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