1 /*****************************************************************************/
5 /* Expression descriptor structure */
9 /* (C) 2002-2010, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
54 /*****************************************************************************/
56 /*****************************************************************************/
60 /* Defines for the flags field of the expression descriptor */
62 /* Location: Where is the value we're talking about? */
64 E_LOC_ABS = 0x0001, /* Absolute: numeric address or const */
65 E_LOC_GLOBAL = 0x0002, /* Global variable */
66 E_LOC_STATIC = 0x0004, /* Static variable */
67 E_LOC_REGISTER = 0x0008, /* Register variable */
68 E_LOC_STACK = 0x0010, /* Value on the stack */
69 E_LOC_PRIMARY = 0x0020, /* The primary register */
70 E_LOC_EXPR = 0x0040, /* An expression in the primary register */
71 E_LOC_LITERAL = 0x0080, /* Literal in the literal pool */
73 /* Constant location of some sort (only if rval) */
74 E_LOC_CONST = E_LOC_ABS | E_LOC_GLOBAL | E_LOC_STATIC |
75 E_LOC_REGISTER | E_LOC_LITERAL,
78 E_MASK_RTYPE = 0x0100,
79 E_RTYPE_RVAL = 0x0000,
80 E_RTYPE_LVAL = 0x0100,
86 E_NEED_TEST = 0x0400, /* Expression needs a test to set cc */
87 E_CC_SET = 0x0800, /* Condition codes are set */
89 E_HAVE_MARKS = 0x1000, /* Code marks are valid */
96 /* Describe the result of an expression */
97 typedef struct ExprDesc ExprDesc;
99 struct SymEntry* Sym; /* Symbol table entry if known */
100 Type* Type; /* Type array of expression */
102 uintptr_t Name; /* Name pointer or label number */
103 long IVal; /* Integer value if expression constant */
104 Double FVal; /* Floating point value */
105 struct Literal* LVal; /* Literal value */
107 /* Bit field stuff */
108 unsigned BitOffs; /* Bit offset for bit fields */
109 unsigned BitWidth; /* Bit width for bit fields */
111 /* Start and end of generated code */
118 /*****************************************************************************/
120 /*****************************************************************************/
124 ExprDesc* ED_Init (ExprDesc* Expr);
125 /* Initialize an ExprDesc */
127 #if defined(HAVE_INLINE)
128 INLINE int ED_GetLoc (const ExprDesc* Expr)
129 /* Return the location flags from the expression */
131 return (Expr->Flags & E_MASK_LOC);
134 # define ED_GetLoc(Expr) ((Expr)->Flags & E_MASK_LOC)
137 #if defined(HAVE_INLINE)
138 INLINE int ED_IsLocAbs (const ExprDesc* Expr)
139 /* Return true if the expression is an absolute value */
141 return (Expr->Flags & E_MASK_LOC) == E_LOC_ABS;
144 # define ED_IsLocAbs(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_ABS)
147 #if defined(HAVE_INLINE)
148 INLINE int ED_IsLocRegister (const ExprDesc* Expr)
149 /* Return true if the expression is located in a register */
151 return (Expr->Flags & E_MASK_LOC) == E_LOC_REGISTER;
154 # define ED_IsLocRegister(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_REGISTER)
157 #if defined(HAVE_INLINE)
158 INLINE int ED_IsLocStack (const ExprDesc* Expr)
159 /* Return true if the expression is located on the stack */
161 return (Expr->Flags & E_MASK_LOC) == E_LOC_STACK;
164 # define ED_IsLocStack(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_STACK)
167 #if defined(HAVE_INLINE)
168 INLINE int ED_IsLocPrimary (const ExprDesc* Expr)
169 /* Return true if the expression is an expression in the register pseudo variable */
171 return (Expr->Flags & E_MASK_LOC) == E_LOC_PRIMARY;
174 # define ED_IsLocPrimary(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_PRIMARY)
177 #if defined(HAVE_INLINE)
178 INLINE int ED_IsLocExpr (const ExprDesc* Expr)
179 /* Return true if the expression is an expression in the primary */
181 return (Expr->Flags & E_MASK_LOC) == E_LOC_EXPR;
184 # define ED_IsLocExpr(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_EXPR)
187 #if defined(HAVE_INLINE)
188 INLINE int ED_IsLocLiteral (const ExprDesc* Expr)
189 /* Return true if the expression is a string from the literal pool */
191 return (Expr->Flags & E_MASK_LOC) == E_LOC_LITERAL;
194 # define ED_IsLocLiteral(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_LITERAL)
197 #if defined(HAVE_INLINE)
198 INLINE int ED_IsLocConst (const ExprDesc* Expr)
199 /* Return true if the expression is a constant location of some sort */
201 return (Expr->Flags & E_LOC_CONST) != 0;
204 # define ED_IsLocConst(Expr) (((Expr)->Flags & E_LOC_CONST) != 0)
207 #if defined(HAVE_INLINE)
208 INLINE int ED_IsLVal (const ExprDesc* Expr)
209 /* Return true if the expression is a reference */
211 return (Expr->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL;
214 # define ED_IsLVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL)
217 #if defined(HAVE_INLINE)
218 INLINE int ED_IsRVal (const ExprDesc* Expr)
219 /* Return true if the expression is a rvalue */
221 return (Expr->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL;
224 # define ED_IsRVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL)
227 #if defined(HAVE_INLINE)
228 INLINE void ED_MakeLVal (ExprDesc* Expr)
229 /* Make the expression a lvalue. */
231 Expr->Flags |= E_RTYPE_LVAL;
234 # define ED_MakeLVal(Expr) do { (Expr)->Flags |= E_RTYPE_LVAL; } while (0)
237 #if defined(HAVE_INLINE)
238 INLINE void ED_MakeRVal (ExprDesc* Expr)
239 /* Make the expression a rvalue. */
241 Expr->Flags &= ~E_RTYPE_LVAL;
244 # define ED_MakeRVal(Expr) do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0)
247 #if defined(HAVE_INLINE)
248 INLINE int ED_IsBitField (const ExprDesc* Expr)
249 /* Return true if the expression is a bit field */
251 return (Expr->Flags & E_BITFIELD) != 0;
254 # define ED_IsBitField(Expr) (((Expr)->Flags & E_BITFIELD) != 0)
257 void ED_MakeBitField (ExprDesc* Expr, unsigned BitOffs, unsigned BitWidth);
258 /* Make this expression a bit field expression */
260 #if defined(HAVE_INLINE)
261 INLINE void ED_MarkForTest (ExprDesc* Expr)
262 /* Mark the expression for a test. */
264 Expr->Flags |= E_NEED_TEST;
267 # define ED_MarkForTest(Expr) do { (Expr)->Flags |= E_NEED_TEST; } while (0)
270 #if defined(HAVE_INLINE)
271 INLINE int ED_NeedsTest (const ExprDesc* Expr)
272 /* Check if the expression needs a test. */
274 return (Expr->Flags & E_NEED_TEST) != 0;
277 # define ED_NeedsTest(Expr) (((Expr)->Flags & E_NEED_TEST) != 0)
280 #if defined(HAVE_INLINE)
281 INLINE void ED_TestDone (ExprDesc* Expr)
282 /* Mark the expression as tested and condition codes set. */
284 Expr->Flags = (Expr->Flags & ~E_NEED_TEST) | E_CC_SET;
287 # define ED_TestDone(Expr) \
288 do { (Expr)->Flags = ((Expr)->Flags & ~E_NEED_TEST) | E_CC_SET; } while (0)
291 #if defined(HAVE_INLINE)
292 INLINE int ED_IsTested (const ExprDesc* Expr)
293 /* Check if the expression has set the condition codes. */
295 return (Expr->Flags & E_CC_SET) != 0;
298 # define ED_IsTested(Expr) (((Expr)->Flags & E_CC_SET) != 0)
301 #if defined(HAVE_INLINE)
302 INLINE void ED_MarkAsUntested (ExprDesc* Expr)
303 /* Mark the expression as not tested (condition codes not set). */
305 Expr->Flags &= ~E_CC_SET;
308 # define ED_MarkAsUntested(Expr) do { (Expr)->Flags &= ~E_CC_SET; } while (0)
311 void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End);
312 /* Set the code range for this expression */
314 int ED_CodeRangeIsEmpty (const ExprDesc* Expr);
315 /* Return true if no code was output for this expression */
317 const char* ED_GetLabelName (const ExprDesc* Expr, long Offs);
318 /* Return the assembler label name of the given expression. Beware: This
319 ** function may use a static buffer, so the name may get "lost" on the second
320 ** call to the function.
323 int ED_GetStackOffs (const ExprDesc* Expr, int Offs);
324 /* Get the stack offset of an address on the stack in Expr taking into account
325 ** an additional offset in Offs.
328 ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type);
329 /* Make Expr an absolute const with the given value and type. */
331 ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value);
332 /* Make Expr a constant integer expression with the given value */
334 ExprDesc* ED_MakeRValExpr (ExprDesc* Expr);
335 /* Convert Expr into a rvalue which is in the primary register without an
339 ExprDesc* ED_MakeLValExpr (ExprDesc* Expr);
340 /* Convert Expr into a lvalue which is in the primary register without an
344 int ED_IsConst (const ExprDesc* Expr);
345 /* Return true if the expression denotes a constant of some sort. This can be a
346 ** numeric constant, the address of a global variable (maybe with offset) or
350 #if defined(HAVE_INLINE)
351 INLINE int ED_IsConstAbs (const ExprDesc* Expr)
352 /* Return true if the expression denotes a constant absolute value. This can be
353 ** a numeric constant, cast to any type.
356 return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL);
359 # define ED_IsConstAbs(E) \
360 (((E)->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL))
363 int ED_IsConstAbsInt (const ExprDesc* Expr);
364 /* Return true if the expression is a constant (numeric) integer. */
366 int ED_IsNullPtr (const ExprDesc* Expr);
367 /* Return true if the given expression is a NULL pointer constant */
369 int ED_IsBool (const ExprDesc* Expr);
370 /* Return true of the expression can be treated as a boolean, that is, it can
371 ** be an operand to a compare operation.
374 void PrintExprDesc (FILE* F, ExprDesc* Expr);
375 /* Print an ExprDesc */
377 Type* ReplaceType (ExprDesc* Expr, const Type* NewType);
378 /* Replace the type of Expr by a copy of Newtype and return the old type string */
382 /* End of exprdesc.h */