]> git.sur5r.net Git - cc65/blob - src/cc65/exprdesc.c
Changed the low level type representation from a strung of unsigned short
[cc65] / src / cc65 / exprdesc.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                exprdesc.c                                 */
4 /*                                                                           */
5 /*                      Expression descriptor structure                      */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002-2006 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 "strbuf.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 StrBuf Buf = STATIC_STRBUF_INITIALIZER;
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             SB_Printf (&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                 SB_Printf (&Buf, "%s%+ld", SymGetAsmName (Expr->Sym), Offs);
94             } else {
95                 SB_Printf (&Buf, "%s", SymGetAsmName (Expr->Sym));
96             }
97             break;
98
99         case E_LOC_REGISTER:
100             /* Register variable */
101             SB_Printf (&Buf, "regbank+%u", (unsigned)((Offs + Expr->Name) & 0xFFFFU));
102             break;
103
104         case E_LOC_LITERAL:
105             /* Literal in the literal pool */
106             if (Offs) {
107                 SB_Printf (&Buf, "%s%+ld", LocalLabelName (Expr->Name), Offs);
108             } else {
109                 SB_Printf (&Buf, "%s", LocalLabelName (Expr->Name));
110             }
111             break;
112
113         default:
114             Internal ("Invalid location in ED_GetLabelName: 0x%04X", ED_GetLoc (Expr));
115     }
116
117     /* Return a pointer to the static buffer */
118     return SB_GetConstBuf (&Buf);
119 }
120
121
122
123 int ED_GetStackOffs (const ExprDesc* Expr, int Offs)
124 /* Get the stack offset of an address on the stack in Expr taking into account
125  * an additional offset in Offs.
126  */
127 {
128     PRECONDITION (ED_IsLocStack (Expr));
129     Offs += ((int) Expr->IVal) - StackPtr;
130     CHECK (Offs >= 0);          /* Cannot handle negative stack offsets */
131     return Offs;
132 }
133
134
135
136 ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type)
137 /* Make Expr an absolute const with the given value and type. */
138 {
139     Expr->Sym   = 0;
140     Expr->Type  = Type;
141     Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL;
142     Expr->Name  = 0;
143     Expr->IVal  = Value;
144     Expr->FVal  = 0.0;
145     return Expr;
146 }
147
148
149
150 ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value)
151 /* Make Expr a constant integer expression with the given value */
152 {
153     Expr->Sym   = 0;
154     Expr->Type  = type_int;
155     Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL;
156     Expr->Name  = 0;
157     Expr->IVal  = Value;
158     Expr->FVal  = 0.0;
159     return Expr;
160 }
161
162
163
164 ExprDesc* ED_MakeRValExpr (ExprDesc* Expr)
165 /* Convert Expr into a rvalue which is in the primary register without an
166  * offset.
167  */
168 {
169     Expr->Sym   = 0;
170     Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_NEED_TEST | E_CC_SET);
171     Expr->Flags |= (E_LOC_EXPR | E_RTYPE_RVAL);
172     Expr->Name  = 0;
173     Expr->IVal  = 0;    /* No offset */
174     Expr->FVal  = 0.0;
175     return Expr;
176 }
177
178
179
180 ExprDesc* ED_MakeLValExpr (ExprDesc* Expr)
181 /* Convert Expr into a lvalue which is in the primary register without an
182  * offset.
183  */
184 {
185     Expr->Sym   = 0;
186     Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_NEED_TEST | E_CC_SET);
187     Expr->Flags |= (E_LOC_EXPR | E_RTYPE_LVAL);
188     Expr->Name  = 0;
189     Expr->IVal  = 0;    /* No offset */
190     Expr->FVal  = 0.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_IsConstAbsInt (const ExprDesc* Expr)
208 /* Return true if the expression is a constant (numeric) integer. */
209 {
210     return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL) &&
211            IsClassInt (Expr->Type);
212 }
213
214
215
216 int ED_IsNullPtr (const ExprDesc* Expr)
217 /* Return true if the given expression is a NULL pointer constant */
218 {
219     return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL) &&
220            Expr->IVal == 0                                                        &&
221            IsClassInt (Expr->Type);
222 }
223
224
225
226 int ED_IsBool (const ExprDesc* Expr)
227 /* Return true of the expression can be treated as a boolean, that is, it can
228  * be an operand to a compare operation.
229  */
230 {
231     /* Either ints, floats, or pointers can be used in a boolean context */
232     return IsClassInt (Expr->Type)   ||
233            IsClassFloat (Expr->Type) ||
234            IsClassPtr (Expr->Type);
235 }
236
237
238
239 void PrintExprDesc (FILE* F, ExprDesc* E)
240 /* Print an ExprDesc */
241 {
242     unsigned Flags;
243     char     Sep;
244
245     fprintf (F, "Symbol:   %s\n", E->Sym? E->Sym->Name : "(none)");
246     if (E->Type) {
247         fprintf (F, "Type:     ");
248         PrintType (F, E->Type);
249         fprintf (F, "\nRaw type: ");
250         PrintRawType (F, E->Type);
251     } else {
252         fprintf (F, "Type:     (unknown)\n"
253                     "Raw type: (unknown)\n");
254     }
255     fprintf (F, "IVal:     0x%08lX\n", E->IVal);
256     fprintf (F, "FVal:     %f\n", E->FVal);
257
258     Flags = E->Flags;
259     Sep   = '(';
260     fprintf (F, "Flags:    0x%04X ", Flags);
261     if (Flags & E_LOC_ABS) {
262         fprintf (F, "%cE_LOC_ABS", Sep);
263         Flags &= ~E_LOC_ABS;
264         Sep = ',';
265     }
266     if (Flags & E_LOC_GLOBAL) {
267         fprintf (F, "%cE_LOC_GLOBAL", Sep);
268         Flags &= ~E_LOC_GLOBAL;
269         Sep = ',';
270     }
271     if (Flags & E_LOC_STATIC) {
272         fprintf (F, "%cE_LOC_STATIC", Sep);
273         Flags &= ~E_LOC_STATIC;
274         Sep = ',';
275     }
276     if (Flags & E_LOC_REGISTER) {
277         fprintf (F, "%cE_LOC_REGISTER", Sep);
278         Flags &= ~E_LOC_REGISTER;
279         Sep = ',';
280     }
281     if (Flags & E_LOC_STACK) {
282         fprintf (F, "%cE_LOC_STACK", Sep);
283         Flags &= ~E_LOC_STACK;
284         Sep = ',';
285     }
286     if (Flags & E_LOC_PRIMARY) {
287         fprintf (F, "%cE_LOC_PRIMARY", Sep);
288         Flags &= ~E_LOC_PRIMARY;
289         Sep = ',';
290     }
291     if (Flags & E_LOC_EXPR) {
292         fprintf (F, "%cE_LOC_EXPR", Sep);
293         Flags &= ~E_LOC_EXPR;
294         Sep = ',';
295     }
296     if (Flags & E_LOC_LITERAL) {
297         fprintf (F, "%cE_LOC_LITERAL", Sep);
298         Flags &= ~E_LOC_LITERAL;
299         Sep = ',';
300     }
301     if (Flags & E_RTYPE_LVAL) {
302         fprintf (F, "%cE_RTYPE_LVAL", Sep);
303         Flags &= ~E_RTYPE_LVAL;
304         Sep = ',';
305     }
306     if (Flags & E_NEED_TEST) {
307         fprintf (F, "%cE_NEED_TEST", Sep);
308         Flags &= ~E_NEED_TEST;
309         Sep = ',';
310     }
311     if (Flags & E_CC_SET) {
312         fprintf (F, "%cE_CC_SET", Sep);
313         Flags &= ~E_CC_SET;
314         Sep = ',';
315     }
316     if (Flags) {
317         fprintf (F, "%c,0x%04X", Sep, Flags);
318         Sep = ',';
319     }
320     if (Sep != '(') {
321         fputc (')', F);
322     }
323     fprintf (F, "\nName:     0x%08lX\n", E->Name);
324 }
325
326
327
328 Type* ReplaceType (ExprDesc* Expr, const Type* NewType)
329 /* Replace the type of Expr by a copy of Newtype and return the old type string */
330 {
331     Type* OldType = Expr->Type;
332     Expr->Type = TypeDup (NewType);
333     return OldType;
334 }
335
336
337