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 /*****************************************************************************/
51 /*****************************************************************************/
53 /*****************************************************************************/
57 ExprDesc* ED_Init (ExprDesc* Expr)
58 /* Initialize an ExprDesc */
65 Expr->FVal = FP_D_Make (0.0);
74 void ED_MakeBitField (ExprDesc* Expr, unsigned BitOffs, unsigned BitWidth)
75 /* Make this expression a bit field expression */
77 Expr->Flags |= E_BITFIELD;
78 Expr->BitOffs = BitOffs;
79 Expr->BitWidth = BitWidth;
84 void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End)
85 /* Set the code range for this expression */
87 Expr->Flags |= E_HAVE_MARKS;
94 int ED_CodeRangeIsEmpty (const ExprDesc* Expr)
95 /* Return true if no code was output for this expression */
97 /* We must have code marks */
98 PRECONDITION (Expr->Flags & E_HAVE_MARKS);
100 return CodeRangeIsEmpty (&Expr->Start, &Expr->End);
105 const char* ED_GetLabelName (const ExprDesc* Expr, long Offs)
106 /* Return the assembler label name of the given expression. Beware: This
107 * function may use a static buffer, so the name may get "lost" on the second
108 * call to the function.
111 static StrBuf Buf = STATIC_STRBUF_INITIALIZER;
113 /* Expr may have it's own offset, adjust Offs accordingly */
116 /* Generate a label depending on the location */
117 switch (ED_GetLoc (Expr)) {
120 /* Absolute: numeric address or const */
121 SB_Printf (&Buf, "$%04X", (int)(Offs & 0xFFFF));
126 /* Global or static variable */
128 SB_Printf (&Buf, "%s%+ld", SymGetAsmName (Expr->Sym), Offs);
130 SB_Printf (&Buf, "%s", SymGetAsmName (Expr->Sym));
135 /* Register variable */
136 SB_Printf (&Buf, "regbank+%u", (unsigned)((Offs + Expr->Name) & 0xFFFFU));
140 /* Literal in the literal pool */
142 SB_Printf (&Buf, "%s%+ld", LocalLabelName (Expr->Name), Offs);
144 SB_Printf (&Buf, "%s", LocalLabelName (Expr->Name));
149 Internal ("Invalid location in ED_GetLabelName: 0x%04X", ED_GetLoc (Expr));
152 /* Return a pointer to the static buffer */
153 return SB_GetConstBuf (&Buf);
158 int ED_GetStackOffs (const ExprDesc* Expr, int Offs)
159 /* Get the stack offset of an address on the stack in Expr taking into account
160 * an additional offset in Offs.
163 PRECONDITION (ED_IsLocStack (Expr));
164 Offs += ((int) Expr->IVal) - StackPtr;
165 CHECK (Offs >= 0); /* Cannot handle negative stack offsets */
171 ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type)
172 /* Make Expr an absolute const with the given value and type. */
176 Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL | (Expr->Flags & E_HAVE_MARKS);
179 Expr->FVal = FP_D_Make (0.0);
185 ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value)
186 /* Make Expr a constant integer expression with the given value */
189 Expr->Type = type_int;
190 Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL | (Expr->Flags & E_HAVE_MARKS);
193 Expr->FVal = FP_D_Make (0.0);
199 ExprDesc* ED_MakeRValExpr (ExprDesc* Expr)
200 /* Convert Expr into a rvalue which is in the primary register without an
205 Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET);
206 Expr->Flags |= (E_LOC_EXPR | E_RTYPE_RVAL);
208 Expr->IVal = 0; /* No offset */
209 Expr->FVal = FP_D_Make (0.0);
215 ExprDesc* ED_MakeLValExpr (ExprDesc* Expr)
216 /* Convert Expr into a lvalue which is in the primary register without an
221 Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET);
222 Expr->Flags |= (E_LOC_EXPR | E_RTYPE_LVAL);
224 Expr->IVal = 0; /* No offset */
225 Expr->FVal = FP_D_Make (0.0);
231 int ED_IsConst (const ExprDesc* Expr)
232 /* Return true if the expression denotes a constant of some sort. This can be a
233 * numeric constant, the address of a global variable (maybe with offset) or
237 return ED_IsRVal (Expr) && (Expr->Flags & E_LOC_CONST) != 0;
242 int ED_IsConstAbsInt (const ExprDesc* Expr)
243 /* Return true if the expression is a constant (numeric) integer. */
245 return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL) &&
246 IsClassInt (Expr->Type);
251 int ED_IsNullPtr (const ExprDesc* Expr)
252 /* Return true if the given expression is a NULL pointer constant */
254 return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE|E_BITFIELD)) ==
255 (E_LOC_ABS|E_RTYPE_RVAL) &&
257 IsClassInt (Expr->Type);
262 int ED_IsBool (const ExprDesc* Expr)
263 /* Return true of the expression can be treated as a boolean, that is, it can
264 * be an operand to a compare operation.
267 /* Either ints, floats, or pointers can be used in a boolean context */
268 return IsClassInt (Expr->Type) ||
269 IsClassFloat (Expr->Type) ||
270 IsClassPtr (Expr->Type);
275 void PrintExprDesc (FILE* F, ExprDesc* E)
276 /* Print an ExprDesc */
281 fprintf (F, "Symbol: %s\n", E->Sym? E->Sym->Name : "(none)");
283 fprintf (F, "Type: ");
284 PrintType (F, E->Type);
285 fprintf (F, "\nRaw type: ");
286 PrintRawType (F, E->Type);
288 fprintf (F, "Type: (unknown)\n"
289 "Raw type: (unknown)\n");
291 fprintf (F, "IVal: 0x%08lX\n", E->IVal);
292 fprintf (F, "FVal: %f\n", FP_D_ToFloat (E->FVal));
296 fprintf (F, "Flags: 0x%04X ", Flags);
297 if (Flags & E_LOC_ABS) {
298 fprintf (F, "%cE_LOC_ABS", Sep);
302 if (Flags & E_LOC_GLOBAL) {
303 fprintf (F, "%cE_LOC_GLOBAL", Sep);
304 Flags &= ~E_LOC_GLOBAL;
307 if (Flags & E_LOC_STATIC) {
308 fprintf (F, "%cE_LOC_STATIC", Sep);
309 Flags &= ~E_LOC_STATIC;
312 if (Flags & E_LOC_REGISTER) {
313 fprintf (F, "%cE_LOC_REGISTER", Sep);
314 Flags &= ~E_LOC_REGISTER;
317 if (Flags & E_LOC_STACK) {
318 fprintf (F, "%cE_LOC_STACK", Sep);
319 Flags &= ~E_LOC_STACK;
322 if (Flags & E_LOC_PRIMARY) {
323 fprintf (F, "%cE_LOC_PRIMARY", Sep);
324 Flags &= ~E_LOC_PRIMARY;
327 if (Flags & E_LOC_EXPR) {
328 fprintf (F, "%cE_LOC_EXPR", Sep);
329 Flags &= ~E_LOC_EXPR;
332 if (Flags & E_LOC_LITERAL) {
333 fprintf (F, "%cE_LOC_LITERAL", Sep);
334 Flags &= ~E_LOC_LITERAL;
337 if (Flags & E_RTYPE_LVAL) {
338 fprintf (F, "%cE_RTYPE_LVAL", Sep);
339 Flags &= ~E_RTYPE_LVAL;
342 if (Flags & E_BITFIELD) {
343 fprintf (F, "%cE_BITFIELD", Sep);
344 Flags &= ~E_BITFIELD;
347 if (Flags & E_NEED_TEST) {
348 fprintf (F, "%cE_NEED_TEST", Sep);
349 Flags &= ~E_NEED_TEST;
352 if (Flags & E_CC_SET) {
353 fprintf (F, "%cE_CC_SET", Sep);
358 fprintf (F, "%c,0x%04X", Sep, Flags);
364 fprintf (F, "\nName: 0x%08lX\n", E->Name);
369 Type* ReplaceType (ExprDesc* Expr, const Type* NewType)
370 /* Replace the type of Expr by a copy of Newtype and return the old type string */
372 Type* OldType = Expr->Type;
373 Expr->Type = TypeDup (NewType);