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