]> git.sur5r.net Git - cc65/blob - src/cc65/exprdesc.h
First implementation of bit fields.
[cc65] / src / cc65 / exprdesc.h
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                exprdesc.h                                 */
4 /*                                                                           */
5 /*                      Expression descriptor structure                      */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002-2009, 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 #ifndef EXPRDESC_H
37 #define EXPRDESC_H
38
39
40
41 #include <string.h>
42
43 /* common */
44 #include "fp.h"
45 #include "inline.h"
46
47 /* cc65 */
48 #include "datatype.h"
49
50
51
52 /*****************************************************************************/
53 /*                                   Data                                    */
54 /*****************************************************************************/
55
56
57
58 /* Defines for the flags field of the expression descriptor */
59 enum {
60     /* Location: Where is the value we're talking about? */
61     E_MASK_LOC          = 0x00FF,
62     E_LOC_ABS           = 0x0001,       /* Absolute: numeric address or const */
63     E_LOC_GLOBAL        = 0x0002,       /* Global variable */
64     E_LOC_STATIC        = 0x0004,       /* Static variable */
65     E_LOC_REGISTER      = 0x0008,       /* Register variable */
66     E_LOC_STACK         = 0x0010,       /* Value on the stack */
67     E_LOC_PRIMARY       = 0x0020,       /* The primary register */
68     E_LOC_EXPR          = 0x0040,       /* An expression in the primary register */
69     E_LOC_LITERAL       = 0x0080,       /* Literal in the literal pool */
70
71     /* Constant location of some sort (only if rval) */
72     E_LOC_CONST         = E_LOC_ABS | E_LOC_GLOBAL | E_LOC_STATIC |
73                           E_LOC_REGISTER | E_LOC_LITERAL,
74
75     /* Reference? */
76     E_MASK_RTYPE        = 0x0100,
77     E_RTYPE_RVAL        = 0x0000,
78     E_RTYPE_LVAL        = 0x0100,
79
80     /* Bit-field? */
81     E_BITFIELD          = 0x0200,
82
83     /* Test */
84     E_NEED_TEST         = 0x0400,       /* Expression needs a test to set cc */
85     E_CC_SET            = 0x0800        /* Condition codes are set */
86 };
87
88 /* Describe the result of an expression */
89 typedef struct ExprDesc ExprDesc;
90 struct ExprDesc {
91     struct SymEntry*    Sym;            /* Symbol table entry if known */
92     Type*               Type;           /* Type array of expression */
93     unsigned            Flags;
94     unsigned long       Name;           /* Name or label number */
95     long                IVal;           /* Integer value if expression constant */
96     Double              FVal;           /* Floating point value */
97
98     unsigned            BitOffs;        /* Bit offset for bit fields */
99     unsigned            BitWidth;       /* Bit width for bit fields */
100 };
101
102
103
104 /*****************************************************************************/
105 /*                                   Code                                    */
106 /*****************************************************************************/
107
108
109
110 ExprDesc* ED_Init (ExprDesc* Expr);
111 /* Initialize an ExprDesc */
112
113 #if defined(HAVE_INLINE)
114 INLINE int ED_GetLoc (const ExprDesc* Expr)
115 /* Return the location flags from the expression */
116 {
117     return (Expr->Flags & E_MASK_LOC);
118 }
119 #else
120 #  define ED_GetLoc(Expr)       ((Expr)->Flags & E_MASK_LOC)
121 #endif
122
123 #if defined(HAVE_INLINE)
124 INLINE int ED_IsLocAbs (const ExprDesc* Expr)
125 /* Return true if the expression is an absolute value */
126 {
127     return (Expr->Flags & E_MASK_LOC) == E_LOC_ABS;
128 }
129 #else
130 #  define ED_IsLocAbs(Expr)     (((Expr)->Flags & E_MASK_LOC) == E_LOC_ABS)
131 #endif
132
133 #if defined(HAVE_INLINE)
134 INLINE int ED_IsLocRegister (const ExprDesc* Expr)
135 /* Return true if the expression is located in a register */
136 {
137     return (Expr->Flags & E_MASK_LOC) == E_LOC_REGISTER;
138 }
139 #else
140 #  define ED_IsLocRegister(Expr)    (((Expr)->Flags & E_MASK_LOC) == E_LOC_REGISTER)
141 #endif
142
143 #if defined(HAVE_INLINE)
144 INLINE int ED_IsLocStack (const ExprDesc* Expr)
145 /* Return true if the expression is located on the stack */
146 {
147     return (Expr->Flags & E_MASK_LOC) == E_LOC_STACK;
148 }
149 #else
150 #  define ED_IsLocStack(Expr)     (((Expr)->Flags & E_MASK_LOC) == E_LOC_STACK)
151 #endif
152
153 #if defined(HAVE_INLINE)
154 INLINE int ED_IsLocPrimary (const ExprDesc* Expr)
155 /* Return true if the expression is an expression in the register pseudo variable */
156 {
157     return (Expr->Flags & E_MASK_LOC) == E_LOC_PRIMARY;
158 }
159 #else
160 #  define ED_IsLocPrimary(Expr)  (((Expr)->Flags & E_MASK_LOC) == E_LOC_PRIMARY)
161 #endif
162
163 #if defined(HAVE_INLINE)
164 INLINE int ED_IsLocExpr (const ExprDesc* Expr)
165 /* Return true if the expression is an expression in the primary */
166 {
167     return (Expr->Flags & E_MASK_LOC) == E_LOC_EXPR;
168 }
169 #else
170 #  define ED_IsLocExpr(Expr)     (((Expr)->Flags & E_MASK_LOC) == E_LOC_EXPR)
171 #endif
172
173 #if defined(HAVE_INLINE)
174 INLINE int ED_IsLocLiteral (const ExprDesc* Expr)
175 /* Return true if the expression is a string from the literal pool */
176 {
177     return (Expr->Flags & E_MASK_LOC) == E_LOC_LITERAL;
178 }
179 #else
180 #  define ED_IsLocLiteral(Expr)   (((Expr)->Flags & E_MASK_LOC) == E_LOC_LITERAL)
181 #endif
182
183 #if defined(HAVE_INLINE)
184 INLINE int ED_IsLocConst (const ExprDesc* Expr)
185 /* Return true if the expression is a constant location of some sort */
186 {
187     return (Expr->Flags & E_LOC_CONST) != 0;
188 }
189 #else
190 #  define ED_IsLocConst(Expr)  (((Expr)->Flags & E_LOC_CONST) != 0)
191 #endif
192
193 #if defined(HAVE_INLINE)
194 INLINE int ED_IsLVal (const ExprDesc* Expr)
195 /* Return true if the expression is a reference */
196 {
197     return (Expr->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL;
198 }
199 #else
200 #  define ED_IsLVal(Expr)       (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL)
201 #endif
202
203 #if defined(HAVE_INLINE)
204 INLINE int ED_IsRVal (const ExprDesc* Expr)
205 /* Return true if the expression is a rvalue */
206 {
207     return (Expr->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL;
208 }
209 #else
210 #  define ED_IsRVal(Expr)       (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL)
211 #endif
212
213 #if defined(HAVE_INLINE)
214 INLINE void ED_MakeLVal (ExprDesc* Expr)
215 /* Make the expression a lvalue. */
216 {
217     Expr->Flags |= E_RTYPE_LVAL;
218 }
219 #else
220 #  define ED_MakeLVal(Expr)     do { (Expr)->Flags |= E_RTYPE_LVAL; } while (0)
221 #endif
222
223 #if defined(HAVE_INLINE)
224 INLINE void ED_MakeRVal (ExprDesc* Expr)
225 /* Make the expression a rvalue. */
226 {
227     Expr->Flags &= ~E_RTYPE_LVAL;
228 }
229 #else
230 #  define ED_MakeRVal(Expr)     do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0)
231 #endif
232
233 #if defined(HAVE_INLINE)
234 INLINE int ED_IsBitField (const ExprDesc* Expr)
235 /* Return true if the expression is a bit field */
236 {
237     return (Expr->Flags & E_BITFIELD) != 0;
238 }
239 #else
240 #  define ED_IsBitField(Expr)   (((Expr)->Flags & E_BITFIELD) != 0)
241 #endif
242
243 void ED_MakeBitField (ExprDesc* Expr, unsigned BitOffs, unsigned BitWidth);
244 /* Make this expression a bit field expression */
245
246 #if defined(HAVE_INLINE)
247 INLINE void ED_MarkForTest (ExprDesc* Expr)
248 /* Mark the expression for a test. */
249 {
250     Expr->Flags |= E_NEED_TEST;
251 }
252 #else
253 #  define ED_MarkForTest(Expr)  do { (Expr)->Flags |= E_NEED_TEST; } while (0)
254 #endif
255
256 #if defined(HAVE_INLINE)
257 INLINE int ED_NeedsTest (const ExprDesc* Expr)
258 /* Check if the expression needs a test. */
259 {
260     return (Expr->Flags & E_NEED_TEST) != 0;
261 }
262 #else
263 #  define ED_NeedsTest(Expr)    (((Expr)->Flags & E_NEED_TEST) != 0)
264 #endif
265
266 #if defined(HAVE_INLINE)
267 INLINE void ED_TestDone (ExprDesc* Expr)
268 /* Mark the expression as tested and condition codes set. */
269 {
270     Expr->Flags = (Expr->Flags & ~E_NEED_TEST) | E_CC_SET;
271 }
272 #else
273 #  define ED_TestDone(Expr)     \
274     do { (Expr)->Flags = ((Expr)->Flags & ~E_NEED_TEST) | E_CC_SET; } while (0)
275 #endif
276
277 #if defined(HAVE_INLINE)
278 INLINE int ED_IsTested (const ExprDesc* Expr)
279 /* Check if the expression has set the condition codes. */
280 {
281     return (Expr->Flags & E_CC_SET) != 0;
282 }
283 #else
284 #  define ED_IsTested(Expr)   (((Expr)->Flags & E_CC_SET) != 0)
285 #endif
286
287 #if defined(HAVE_INLINE)
288 INLINE void ED_MarkAsUntested (ExprDesc* Expr)
289 /* Mark the expression as not tested (condition codes not set). */
290 {
291     Expr->Flags &= ~E_CC_SET;
292 }
293 #else
294 #  define ED_MarkAsUntested(Expr)   do { (Expr)->Flags &= ~E_CC_SET; } while (0)
295 #endif
296
297 const char* ED_GetLabelName (const ExprDesc* Expr, long Offs);
298 /* Return the assembler label name of the given expression. Beware: This
299  * function may use a static buffer, so the name may get "lost" on the second
300  * call to the function.
301  */
302
303 int ED_GetStackOffs (const ExprDesc* Expr, int Offs);
304 /* Get the stack offset of an address on the stack in Expr taking into account
305  * an additional offset in Offs.
306  */
307
308 ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type);
309 /* Make Expr an absolute const with the given value and type. */
310
311 ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value);
312 /* Make Expr a constant integer expression with the given value */
313
314 ExprDesc* ED_MakeRValExpr (ExprDesc* Expr);
315 /* Convert Expr into a rvalue which is in the primary register without an
316  * offset.
317  */
318
319 ExprDesc* ED_MakeLValExpr (ExprDesc* Expr);
320 /* Convert Expr into a lvalue which is in the primary register without an
321  * offset.
322  */
323
324 int ED_IsConst (const ExprDesc* Expr);
325 /* Return true if the expression denotes a constant of some sort. This can be a
326  * numeric constant, the address of a global variable (maybe with offset) or
327  * similar.
328  */
329
330 #if defined(HAVE_INLINE)
331 INLINE int ED_IsConstAbs (const ExprDesc* Expr)
332 /* Return true if the expression denotes a constant absolute value. This can be
333  * a numeric constant, cast to any type.
334  */
335 {
336     return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL);
337 }
338 #else
339 #  define ED_IsConstAbs(E)      \
340         (((E)->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL))
341 #endif
342
343 int ED_IsConstAbsInt (const ExprDesc* Expr);
344 /* Return true if the expression is a constant (numeric) integer. */
345
346 int ED_IsNullPtr (const ExprDesc* Expr);
347 /* Return true if the given expression is a NULL pointer constant */
348
349 int ED_IsBool (const ExprDesc* Expr);
350 /* Return true of the expression can be treated as a boolean, that is, it can
351  * be an operand to a compare operation.
352  */
353
354 void PrintExprDesc (FILE* F, ExprDesc* Expr);
355 /* Print an ExprDesc */
356
357 Type* ReplaceType (ExprDesc* Expr, const Type* NewType);
358 /* Replace the type of Expr by a copy of Newtype and return the old type string */
359
360
361
362 /* End of exprdesc.h */
363 #endif
364
365
366