]> git.sur5r.net Git - cc65/blob - src/cc65/exprdesc.c
Renamed ExprDesc.Val to ExprDesc.IVal. Added an FVal field for a floating
[cc65] / src / cc65 / exprdesc.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                exprdesc.c                                 */
4 /*                                                                           */
5 /*                      Expression descriptor structure                      */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002-2004 Ullrich von Bassewitz                                       */
10 /*               Römerstraße 52                                              */
11 /*               D-70794 Filderstadt                                         */
12 /* EMail:        uz@cc65.org                                                 */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 /* common */
37 #include "check.h"
38 #include "xsprintf.h"
39
40 /* cc65 */
41 #include "asmlabel.h"
42 #include "datatype.h"
43 #include "error.h"
44 #include "stackptr.h"
45 #include "symentry.h"
46 #include "exprdesc.h"
47
48
49
50 /*****************************************************************************/
51 /*                                   Code                                    */
52 /*****************************************************************************/
53
54
55
56 ExprDesc* ED_Init (ExprDesc* Expr)
57 /* Initialize an ExprDesc */
58 {
59     Expr->Sym   = 0;
60     Expr->Type  = 0;
61     Expr->Flags = 0;
62     Expr->Name  = 0;
63     Expr->IVal  = 0;
64     Expr->FVal  = 0.0;
65     return Expr;
66 }
67
68
69
70 const char* ED_GetLabelName (const ExprDesc* Expr, long Offs)
71 /* Return the assembler label name of the given expression. Beware: This
72  * function may use a static buffer, so the name may get "lost" on the second
73  * call to the function.
74  */
75 {
76     static char Buf[256];
77
78     /* Expr may have it's own offset, adjust Offs accordingly */
79     Offs += Expr->IVal;
80
81     /* Generate a label depending on the location */
82     switch (ED_GetLoc (Expr)) {
83
84         case E_LOC_ABS:
85             /* Absolute: numeric address or const */
86             xsprintf (Buf, sizeof (Buf), "$%04X", (int)(Offs & 0xFFFF));
87             break;
88
89         case E_LOC_GLOBAL:
90         case E_LOC_STATIC:
91             /* Global or static variable */
92             if (Offs) {
93                 xsprintf (Buf, sizeof (Buf), "%s%+ld",
94                           SymGetAsmName (Expr->Sym), Offs);
95             } else {
96                 xsprintf (Buf, sizeof (Buf), "%s",
97                           SymGetAsmName (Expr->Sym));
98             }
99             break;
100
101         case E_LOC_REGISTER:
102             /* Register variable */
103             xsprintf (Buf, sizeof (Buf), "regbank+%u",
104                       (unsigned)((Offs + Expr->Name) & 0xFFFFU));
105             break;
106
107         case E_LOC_LITERAL:
108             /* Literal in the literal pool */
109             if (Offs) {
110                 xsprintf (Buf, sizeof (Buf), "%s%+ld",
111                           LocalLabelName (Expr->Name), Offs);
112             } else {
113                 xsprintf (Buf, sizeof (Buf), "%s",
114                           LocalLabelName (Expr->Name));
115             }
116             break;
117
118         default:
119             Internal ("Invalid location in ED_GetLabelName: 0x%04X", ED_GetLoc (Expr));
120     }
121
122     /* Return a pointer to the static buffer */
123     return Buf;
124 }
125
126
127
128 int ED_GetStackOffs (const ExprDesc* Expr, int Offs)
129 /* Get the stack offset of an address on the stack in Expr taking into account
130  * an additional offset in Offs.
131  */
132 {
133     PRECONDITION (ED_IsLocStack (Expr));
134     Offs += ((int) Expr->IVal) - StackPtr;
135     CHECK (Offs >= 0);          /* Cannot handle negative stack offsets */
136     return Offs;
137 }
138
139
140
141 ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, type* Type)
142 /* Make Expr an absolute const with the given value and type. */
143 {
144     Expr->Sym   = 0;
145     Expr->Type  = Type;
146     Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL;
147     Expr->Name  = 0;
148     Expr->IVal  = Value;
149     Expr->FVal  = 0.0;
150     return Expr;
151 }
152
153
154
155 ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value)
156 /* Make Expr a constant integer expression with the given value */
157 {
158     Expr->Sym   = 0;
159     Expr->Type  = type_int;
160     Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL;
161     Expr->Name  = 0;
162     Expr->IVal  = Value;
163     Expr->FVal  = 0.0;
164     return Expr;
165 }
166
167
168
169 ExprDesc* ED_MakeRValExpr (ExprDesc* Expr)
170 /* Convert Expr into a rvalue which is in the primary register without an
171  * offset.
172  */
173 {
174     Expr->Sym   = 0;
175     Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_NEED_TEST | E_CC_SET);
176     Expr->Flags |= (E_LOC_EXPR | E_RTYPE_RVAL);
177     Expr->Name  = 0;
178     Expr->IVal  = 0;    /* No offset */
179     Expr->FVal  = 0.0;
180     return Expr;
181 }
182
183
184
185 ExprDesc* ED_MakeLValExpr (ExprDesc* Expr)
186 /* Convert Expr into a lvalue which is in the primary register without an
187  * offset.
188  */
189 {
190     Expr->Sym   = 0;
191     Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_NEED_TEST | E_CC_SET);
192     Expr->Flags |= (E_LOC_EXPR | E_RTYPE_LVAL);
193     Expr->Name  = 0;
194     Expr->IVal  = 0;    /* No offset */
195     Expr->FVal  = 0.0; 
196     return Expr;
197 }
198
199
200
201 int ED_IsConst (const ExprDesc* Expr)
202 /* Return true if the expression denotes a constant of some sort. This can be a
203  * numeric constant, the address of a global variable (maybe with offset) or
204  * similar.
205  */
206 {
207     return ED_IsRVal (Expr) && (Expr->Flags & E_LOC_CONST) != 0;
208 }
209
210
211
212 int ED_IsConstAbs (const ExprDesc* Expr)
213 /* Return true if the expression denotes a constant absolute value. This can be
214  * a numeric constant, cast to any type.
215  */
216 {
217     return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL);
218 }
219
220
221
222 int ED_IsConstAbsInt (const ExprDesc* Expr)
223 /* Return true if the expression is a constant (numeric) integer. */
224 {
225     return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL) &&
226            IsClassInt (Expr->Type);
227 }
228
229
230
231 int ED_IsNullPtr (const ExprDesc* Expr)
232 /* Return true if the given expression is a NULL pointer constant */
233 {
234     return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL) &&
235            Expr->IVal == 0                                                        &&
236            IsClassInt (Expr->Type);
237 }
238
239
240
241 int ED_IsBool (const ExprDesc* Expr)
242 /* Return true of the expression can be treated as a boolean, that is, it can
243  * be an operand to a compare operation.
244  */
245 {
246     /* Either ints, floats, or pointers can be used in a boolean context */
247     return IsClassInt (Expr->Type)   ||
248            IsClassFloat (Expr->Type) ||
249            IsClassPtr (Expr->Type);
250 }
251
252
253
254 void PrintExprDesc (FILE* F, ExprDesc* E)
255 /* Print an ExprDesc */
256 {
257     unsigned Flags;
258     char     Sep;
259
260     fprintf (F, "Symbol:   %s\n", E->Sym? E->Sym->Name : "(none)");
261     if (E->Type) {
262         fprintf (F, "Type:     ");
263         PrintType (F, E->Type);
264         fprintf (F, "\nRaw type: ");
265         PrintRawType (F, E->Type);
266     } else {
267         fprintf (F, "Type:     (unknown)\n"
268                     "Raw type: (unknown)\n");
269     }
270     fprintf (F, "IVal:     0x%08lX\n", E->IVal);
271     fprintf (F, "FVal:     %f\n", E->FVal);
272
273     Flags = E->Flags;
274     Sep   = '(';
275     fprintf (F, "Flags:    0x%04X ", Flags);
276     if (Flags & E_LOC_ABS) {
277         fprintf (F, "%cE_LOC_ABS", Sep);
278         Flags &= ~E_LOC_ABS;
279         Sep = ',';
280     }
281     if (Flags & E_LOC_GLOBAL) {
282         fprintf (F, "%cE_LOC_GLOBAL", Sep);
283         Flags &= ~E_LOC_GLOBAL;
284         Sep = ',';
285     }
286     if (Flags & E_LOC_STATIC) {
287         fprintf (F, "%cE_LOC_STATIC", Sep);
288         Flags &= ~E_LOC_STATIC;
289         Sep = ',';
290     }
291     if (Flags & E_LOC_REGISTER) {
292         fprintf (F, "%cE_LOC_REGISTER", Sep);
293         Flags &= ~E_LOC_REGISTER;
294         Sep = ',';
295     }
296     if (Flags & E_LOC_STACK) {
297         fprintf (F, "%cE_LOC_STACK", Sep);
298         Flags &= ~E_LOC_STACK;
299         Sep = ',';
300     }
301     if (Flags & E_LOC_PRIMARY) {
302         fprintf (F, "%cE_LOC_PRIMARY", Sep);
303         Flags &= ~E_LOC_PRIMARY;
304         Sep = ',';
305     }
306     if (Flags & E_LOC_EXPR) {
307         fprintf (F, "%cE_LOC_EXPR", Sep);
308         Flags &= ~E_LOC_EXPR;
309         Sep = ',';
310     }
311     if (Flags & E_LOC_LITERAL) {
312         fprintf (F, "%cE_LOC_LITERAL", Sep);
313         Flags &= ~E_LOC_LITERAL;
314         Sep = ',';
315     }
316     if (Flags & E_RTYPE_LVAL) {
317         fprintf (F, "%cE_RTYPE_LVAL", Sep);
318         Flags &= ~E_RTYPE_LVAL;
319         Sep = ',';
320     }
321     if (Flags & E_NEED_TEST) {
322         fprintf (F, "%cE_NEED_TEST", Sep);
323         Flags &= ~E_NEED_TEST;
324         Sep = ',';
325     }
326     if (Flags & E_CC_SET) {
327         fprintf (F, "%cE_CC_SET", Sep);
328         Flags &= ~E_CC_SET;
329         Sep = ',';
330     }
331     if (Flags) {
332         fprintf (F, "%c,0x%04X", Sep, Flags);
333         Sep = ',';
334     }
335     if (Sep != '(') {
336         fputc (')', F);
337     }
338     fprintf (F, "\nName:     0x%08lX\n", E->Name);
339 }
340
341
342
343 type* ReplaceType (ExprDesc* Expr, const type* NewType)
344 /* Replace the type of Expr by a copy of Newtype and return the old type string */
345 {
346     type* OldType = Expr->Type;
347     Expr->Type = TypeDup (NewType);
348     return OldType;
349 }
350
351
352