]> git.sur5r.net Git - cc65/blob - src/cc65/exprdesc.c
Move the test flags into the Flags bitset of struct ExprDesc
[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->Val   = 0;
62     Expr->Flags = 0;
63     Expr->Name  = 0;
64     return Expr;
65 }
66
67
68
69 const char* ED_GetLabelName (const ExprDesc* Expr, long Offs)
70 /* Return the assembler label name of the given expression. Beware: This
71  * function may use a static buffer, so the name may get "lost" on the second
72  * call to the function.
73  */
74 {
75     static char Buf[256];
76
77     /* Expr may have it's own offset, adjust Offs accordingly */
78     Offs += Expr->Val;
79
80     /* Generate a label depending on the location */
81     switch (ED_GetLoc (Expr)) {
82
83         case E_LOC_ABS:
84             /* Absolute: numeric address or const */
85             xsprintf (Buf, sizeof (Buf), "$%04X", (int)(Offs & 0xFFFF));
86             break;
87
88         case E_LOC_GLOBAL:
89         case E_LOC_STATIC:
90             /* Global or static variable */
91             if (Offs) {
92                 xsprintf (Buf, sizeof (Buf), "%s%+ld",
93                           SymGetAsmName (Expr->Sym), Offs);
94             } else {
95                 xsprintf (Buf, sizeof (Buf), "%s",
96                           SymGetAsmName (Expr->Sym));
97             }
98             break;
99
100         case E_LOC_REGISTER:
101             /* Register variable */
102             xsprintf (Buf, sizeof (Buf), "regbank+%u",
103                       (unsigned)((Offs + Expr->Name) & 0xFFFFU));
104             break;
105
106         case E_LOC_LITERAL:
107             /* Literal in the literal pool */
108             if (Offs) {
109                 xsprintf (Buf, sizeof (Buf), "%s%+ld",
110                           LocalLabelName (Expr->Name), Offs);
111             } else {
112                 xsprintf (Buf, sizeof (Buf), "%s",
113                           LocalLabelName (Expr->Name));
114             }
115             break;
116
117         default:
118             Internal ("Invalid location in ED_GetLabelName: 0x%04X", ED_GetLoc (Expr));
119     }
120
121     /* Return a pointer to the static buffer */
122     return Buf;
123 }
124
125
126
127 int ED_GetStackOffs (const ExprDesc* Expr, int Offs)
128 /* Get the stack offset of an address on the stack in Expr taking into account
129  * an additional offset in Offs.
130  */
131 {
132     PRECONDITION (ED_IsLocStack (Expr));
133     Offs += ((int) Expr->Val) - StackPtr;
134     CHECK (Offs >= 0);          /* Cannot handle negative stack offsets */
135     return Offs;
136 }
137
138
139
140 ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, type* Type)
141 /* Make Expr an absolute const with the given value and type. */
142 {
143     Expr->Sym   = 0;
144     Expr->Type  = Type;
145     Expr->Val   = Value;
146     Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL;
147     Expr->Name  = 0;
148     return Expr;
149 }
150
151
152
153 ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value)
154 /* Make Expr a constant integer expression with the given value */
155 {
156     Expr->Sym   = 0;
157     Expr->Type  = type_int;
158     Expr->Val   = Value;
159     Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL;
160     Expr->Name  = 0;
161     return Expr;
162 }
163
164
165
166 ExprDesc* ED_MakeRValExpr (ExprDesc* Expr)
167 /* Convert Expr into a rvalue which is in the primary register without an
168  * offset.
169  */
170 {
171     Expr->Sym   = 0;
172     Expr->Val   = 0;    /* No offset */
173     Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_NEED_TEST | E_CC_SET);
174     Expr->Flags |= (E_LOC_EXPR | E_RTYPE_RVAL);
175     Expr->Name  = 0;
176     return Expr;
177 }
178
179
180
181 ExprDesc* ED_MakeLValExpr (ExprDesc* Expr)
182 /* Convert Expr into a lvalue which is in the primary register without an
183  * offset.
184  */
185 {
186     Expr->Sym   = 0;
187     Expr->Val   = 0;    /* No offset */
188     Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_NEED_TEST | E_CC_SET);
189     Expr->Flags |= (E_LOC_EXPR | E_RTYPE_LVAL);
190     Expr->Name  = 0;
191     return Expr;
192 }
193
194
195
196 int ED_IsConst (const ExprDesc* Expr)
197 /* Return true if the expression denotes a constant of some sort. This can be a
198  * numeric constant, the address of a global variable (maybe with offset) or
199  * similar.
200  */
201 {
202     return ED_IsRVal (Expr) && (Expr->Flags & E_LOC_CONST) != 0;
203 }
204
205
206
207 int ED_IsConstAbs (const ExprDesc* Expr)
208 /* Return true if the expression denotes a constant absolute value. This can be
209  * a numeric constant, cast to any type.
210  */
211 {
212     return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL);
213 }
214
215
216
217 int ED_IsConstAbsInt (const ExprDesc* Expr)
218 /* Return true if the expression is a constant (numeric) integer. */
219 {
220     return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL) &&
221            IsClassInt (Expr->Type);
222 }
223
224
225
226 int ED_IsNullPtr (const ExprDesc* Expr)
227 /* Return true if the given expression is a NULL pointer constant */
228 {
229     return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL) &&
230            Expr->Val == 0                                                        &&
231            IsClassInt (Expr->Type);
232 }
233
234
235
236 int ED_IsBool (const ExprDesc* Expr)
237 /* Return true of the expression can be treated as a boolean, that is, it can
238  * be an operand to a compare operation.
239  */
240 {
241     /* Either ints, floats, or pointers can be used in a boolean context */
242     return IsClassInt (Expr->Type)   ||
243            IsClassFloat (Expr->Type) ||
244            IsClassPtr (Expr->Type);
245 }
246
247
248
249 void PrintExprDesc (FILE* F, ExprDesc* E)
250 /* Print an ExprDesc */
251 {
252     unsigned Flags;
253     char     Sep;
254
255     fprintf (F, "Symbol:   %s\n", E->Sym? E->Sym->Name : "(none)");
256     if (E->Type) {
257         fprintf (F, "Type:     ");
258         PrintType (F, E->Type);
259         fprintf (F, "\nRaw type: ");
260         PrintRawType (F, E->Type);
261     } else {
262         fprintf (F, "Type:     (unknown)\n"
263                     "Raw type: (unknown)\n");
264     }
265     fprintf (F, "Value:    0x%08lX\n", E->Val);
266
267     Flags = E->Flags;
268     Sep   = '(';
269     fprintf (F, "Flags:    0x%04X ", Flags);
270     if (Flags & E_LOC_ABS) {
271         fprintf (F, "%cE_LOC_ABS", Sep);
272         Flags &= ~E_LOC_ABS;
273         Sep = ',';
274     }
275     if (Flags & E_LOC_GLOBAL) {
276         fprintf (F, "%cE_LOC_GLOBAL", Sep);
277         Flags &= ~E_LOC_GLOBAL;
278         Sep = ',';
279     }
280     if (Flags & E_LOC_STATIC) {
281         fprintf (F, "%cE_LOC_STATIC", Sep);
282         Flags &= ~E_LOC_STATIC;
283         Sep = ',';
284     }
285     if (Flags & E_LOC_REGISTER) {
286         fprintf (F, "%cE_LOC_REGISTER", Sep);
287         Flags &= ~E_LOC_REGISTER;
288         Sep = ',';
289     }
290     if (Flags & E_LOC_STACK) {
291         fprintf (F, "%cE_LOC_STACK", Sep);
292         Flags &= ~E_LOC_STACK;
293         Sep = ',';
294     }
295     if (Flags & E_LOC_PRIMARY) {
296         fprintf (F, "%cE_LOC_PRIMARY", Sep);
297         Flags &= ~E_LOC_PRIMARY;
298         Sep = ',';
299     }
300     if (Flags & E_LOC_EXPR) {
301         fprintf (F, "%cE_LOC_EXPR", Sep);
302         Flags &= ~E_LOC_EXPR;
303         Sep = ',';
304     }
305     if (Flags & E_LOC_LITERAL) {
306         fprintf (F, "%cE_LOC_LITERAL", Sep);
307         Flags &= ~E_LOC_LITERAL;
308         Sep = ',';
309     }
310     if (Flags & E_RTYPE_LVAL) {
311         fprintf (F, "%cE_RTYPE_LVAL", Sep);
312         Flags &= ~E_RTYPE_LVAL;
313         Sep = ',';
314     }
315     if (Flags & E_NEED_TEST) {
316         fprintf (F, "%cE_NEED_TEST", Sep);
317         Flags &= ~E_NEED_TEST;
318         Sep = ',';
319     }
320     if (Flags & E_CC_SET) {
321         fprintf (F, "%cE_CC_SET", Sep);
322         Flags &= ~E_CC_SET;
323         Sep = ',';
324     }
325     if (Flags) {
326         fprintf (F, "%c,0x%04X", Sep, Flags);
327         Sep = ',';
328     }
329     if (Sep != '(') {
330         fputc (')', F);
331     }
332     fprintf (F, "\nName:     0x%08lX\n", E->Name);
333 }
334
335
336
337 type* ReplaceType (ExprDesc* Expr, const type* NewType)
338 /* Replace the type of Expr by a copy of Newtype and return the old type string */
339 {
340     type* OldType = Expr->Type;
341     Expr->Type = TypeDup (NewType);
342     return OldType;
343 }
344
345
346