1 /*****************************************************************************/
5 /* Expression descriptor structure */
9 /* (C) 2002-2004 Ullrich von Bassewitz */
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 /*****************************************************************************/
50 /*****************************************************************************/
52 /*****************************************************************************/
56 ExprDesc* ED_Init (ExprDesc* Expr)
57 /* Initialize an ExprDesc */
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.
78 /* Expr may have it's own offset, adjust Offs accordingly */
81 /* Generate a label depending on the location */
82 switch (ED_GetLoc (Expr)) {
85 /* Absolute: numeric address or const */
86 xsprintf (Buf, sizeof (Buf), "$%04X", (int)(Offs & 0xFFFF));
91 /* Global or static variable */
93 xsprintf (Buf, sizeof (Buf), "%s%+ld",
94 SymGetAsmName (Expr->Sym), Offs);
96 xsprintf (Buf, sizeof (Buf), "%s",
97 SymGetAsmName (Expr->Sym));
102 /* Register variable */
103 xsprintf (Buf, sizeof (Buf), "regbank+%u",
104 (unsigned)((Offs + Expr->Name) & 0xFFFFU));
108 /* Literal in the literal pool */
110 xsprintf (Buf, sizeof (Buf), "%s%+ld",
111 LocalLabelName (Expr->Name), Offs);
113 xsprintf (Buf, sizeof (Buf), "%s",
114 LocalLabelName (Expr->Name));
119 Internal ("Invalid location in ED_GetLabelName: 0x%04X", ED_GetLoc (Expr));
122 /* Return a pointer to the static buffer */
128 int ED_GetStackOffs (const ExprDesc* Expr, int Offs)
129 /* Get the stack offset of an address on the stack in Expr taking into account
130 * an additional offset in Offs.
133 PRECONDITION (ED_IsLocStack (Expr));
134 Offs += ((int) Expr->Val) - StackPtr;
135 CHECK (Offs >= 0); /* Cannot handle negative stack offsets */
141 ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, type* Type)
142 /* Make Expr an absolute const with the given value and type. */
147 Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL;
155 ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value)
156 /* Make Expr a constant integer expression with the given value */
159 Expr->Type = type_int;
161 Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL;
169 ExprDesc* ED_MakeRValExpr (ExprDesc* Expr)
170 /* Convert Expr into a rvalue which is in the primary register without an
175 Expr->Val = 0; /* No offset */
176 Expr->Flags = (Expr->Flags & ~(E_MASK_LOC|E_MASK_RTYPE)) | (E_LOC_EXPR|E_RTYPE_RVAL);
184 ExprDesc* ED_MakeLValExpr (ExprDesc* Expr)
185 /* Convert Expr into a lvalue which is in the primary register without an
190 Expr->Val = 0; /* No offset */
191 Expr->Flags = (Expr->Flags & ~(E_MASK_LOC|E_MASK_RTYPE)) | (E_LOC_EXPR|E_RTYPE_LVAL);
199 int ED_IsConst (const ExprDesc* Expr)
200 /* Return true if the expression denotes a constant of some sort. This can be a
201 * numeric constant, the address of a global variable (maybe with offset) or
205 return ED_IsRVal (Expr) && (Expr->Flags & E_LOC_CONST) != 0;
210 int ED_IsConstAbs (const ExprDesc* Expr)
211 /* Return true if the expression denotes a constant absolute value. This can be
212 * a numeric constant, cast to any type.
215 return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL);
220 int ED_IsConstAbsInt (const ExprDesc* Expr)
221 /* Return true if the expression is a constant (numeric) integer. */
223 return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL) &&
224 IsClassInt (Expr->Type);
229 int ED_IsNullPtr (const ExprDesc* Expr)
230 /* Return true if the given expression is a NULL pointer constant */
232 return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL) &&
234 IsClassInt (Expr->Type);
239 int ED_IsBool (const ExprDesc* Expr)
240 /* Return true of the expression can be treated as a boolean, that is, it can
241 * be an operand to a compare operation.
244 /* Either ints, floats, or pointers can be used in a boolean context */
245 return IsClassInt (Expr->Type) ||
246 IsClassFloat (Expr->Type) ||
247 IsClassPtr (Expr->Type);
252 void PrintExprDesc (FILE* F, ExprDesc* E)
253 /* Print an ExprDesc */
258 fprintf (F, "Symbol: %s\n", E->Sym? E->Sym->Name : "(none)");
260 fprintf (F, "Type: ");
261 PrintType (F, E->Type);
262 fprintf (F, "\nRaw type: ");
263 PrintRawType (F, E->Type);
265 fprintf (F, "Type: (unknown)\n"
266 "Raw type: (unknown)\n");
268 fprintf (F, "Value: 0x%08lX\n", E->Val);
272 fprintf (F, "Flags: 0x%04X ", Flags);
273 if (Flags & E_LOC_ABS) {
274 fprintf (F, "%cE_LOC_ABS", Sep);
278 if (Flags & E_LOC_GLOBAL) {
279 fprintf (F, "%cE_LOC_GLOBAL", Sep);
280 Flags &= ~E_LOC_GLOBAL;
283 if (Flags & E_LOC_STATIC) {
284 fprintf (F, "%cE_LOC_STATIC", Sep);
285 Flags &= ~E_LOC_STATIC;
288 if (Flags & E_LOC_REGISTER) {
289 fprintf (F, "%cE_LOC_REGISTER", Sep);
290 Flags &= ~E_LOC_REGISTER;
293 if (Flags & E_LOC_STACK) {
294 fprintf (F, "%cE_LOC_STACK", Sep);
295 Flags &= ~E_LOC_STACK;
298 if (Flags & E_LOC_PRIMARY) {
299 fprintf (F, "%cE_LOC_PRIMARY", Sep);
300 Flags &= ~E_LOC_PRIMARY;
303 if (Flags & E_LOC_EXPR) {
304 fprintf (F, "%cE_LOC_EXPR", Sep);
305 Flags &= ~E_LOC_EXPR;
308 if (Flags & E_LOC_LITERAL) {
309 fprintf (F, "%cE_LOC_LITERAL", Sep);
310 Flags &= ~E_LOC_LITERAL;
313 if (Flags & E_RTYPE_LVAL) {
314 fprintf (F, "%cE_RTYPE_LVAL", Sep);
315 Flags &= ~E_RTYPE_LVAL;
319 fprintf (F, "%c,0x%04X", Sep, Flags);
327 fprintf (F, "\nTest: ");
328 if (E->Test & E_CC) {
329 fprintf (F, "E_CC ");
331 if (E->Test & E_FORCETEST) {
332 fprintf (F, "E_FORCETEST ");
335 fprintf (F, "\nName: 0x%08lX\n", E->Name);
340 type* ReplaceType (ExprDesc* Expr, const type* NewType)
341 /* Replace the type of Expr by a copy of Newtype and return the old type string */
343 type* OldType = Expr->Type;
344 Expr->Type = TypeDup (NewType);