1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* exprdesc.h */ |
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 | #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 | #include "inttypes.h" |
47 | |
48 | /* cc65 */ |
49 | #include "asmcode.h" |
50 | #include "datatype.h" |
51 | |
52 | |
53 | |
54 | /*****************************************************************************/ |
55 | /* Data */ |
56 | /*****************************************************************************/ |
57 | |
58 | |
59 | |
60 | /* Defines for the flags field of the expression descriptor */ |
61 | enum { |
62 | /* Location: Where is the value we're talking about? */ |
63 | E_MASK_LOC = 0x00FF, |
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 */ |
72 | |
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, |
76 | |
77 | /* Reference? */ |
78 | E_MASK_RTYPE = 0x0100, |
79 | E_RTYPE_RVAL = 0x0000, |
80 | E_RTYPE_LVAL = 0x0100, |
81 | |
82 | /* Bit-field? */ |
83 | E_BITFIELD = 0x0200, |
84 | |
85 | /* Test */ |
86 | E_NEED_TEST = 0x0400, /* Expression needs a test to set cc */ |
87 | E_CC_SET = 0x0800, /* Condition codes are set */ |
88 | |
89 | E_HAVE_MARKS = 0x1000, /* Code marks are valid */ |
90 | |
91 | }; |
92 | |
93 | /* Forward */ |
94 | struct Literal; |
95 | |
96 | /* Describe the result of an expression */ |
97 | typedef struct ExprDesc ExprDesc; |
98 | struct ExprDesc { |
99 | struct SymEntry* Sym; /* Symbol table entry if known */ |
100 | Type* Type; /* Type array of expression */ |
101 | unsigned Flags; |
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 */ |
106 | |
107 | /* Bit field stuff */ |
108 | unsigned BitOffs; /* Bit offset for bit fields */ |
109 | unsigned BitWidth; /* Bit width for bit fields */ |
110 | |
111 | /* Start and end of generated code */ |
112 | CodeMark Start; |
113 | CodeMark End; |
114 | }; |
115 | |
116 | |
117 | |
118 | /*****************************************************************************/ |
119 | /* Code */ |
120 | /*****************************************************************************/ |
121 | |
122 | |
123 | |
124 | ExprDesc* ED_Init (ExprDesc* Expr); |
125 | /* Initialize an ExprDesc */ |
126 | |
127 | #if defined(HAVE_INLINE) |
128 | INLINE int ED_GetLoc (const ExprDesc* Expr) |
129 | /* Return the location flags from the expression */ |
130 | { |
131 | return (Expr->Flags & E_MASK_LOC); |
132 | } |
133 | #else |
134 | # define ED_GetLoc(Expr) ((Expr)->Flags & E_MASK_LOC) |
135 | #endif |
136 | |
137 | #if defined(HAVE_INLINE) |
138 | INLINE int ED_IsLocAbs (const ExprDesc* Expr) |
139 | /* Return true if the expression is an absolute value */ |
140 | { |
141 | return (Expr->Flags & E_MASK_LOC) == E_LOC_ABS; |
142 | } |
143 | #else |
144 | # define ED_IsLocAbs(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_ABS) |
145 | #endif |
146 | |
147 | #if defined(HAVE_INLINE) |
148 | INLINE int ED_IsLocRegister (const ExprDesc* Expr) |
149 | /* Return true if the expression is located in a register */ |
150 | { |
151 | return (Expr->Flags & E_MASK_LOC) == E_LOC_REGISTER; |
152 | } |
153 | #else |
154 | # define ED_IsLocRegister(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_REGISTER) |
155 | #endif |
156 | |
157 | #if defined(HAVE_INLINE) |
158 | INLINE int ED_IsLocStack (const ExprDesc* Expr) |
159 | /* Return true if the expression is located on the stack */ |
160 | { |
161 | return (Expr->Flags & E_MASK_LOC) == E_LOC_STACK; |
162 | } |
163 | #else |
164 | # define ED_IsLocStack(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_STACK) |
165 | #endif |
166 | |
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 */ |
170 | { |
171 | return (Expr->Flags & E_MASK_LOC) == E_LOC_PRIMARY; |
172 | } |
173 | #else |
174 | # define ED_IsLocPrimary(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_PRIMARY) |
175 | #endif |
176 | |
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 */ |
180 | { |
181 | return (Expr->Flags & E_MASK_LOC) == E_LOC_EXPR; |
182 | } |
183 | #else |
184 | # define ED_IsLocExpr(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_EXPR) |
185 | #endif |
186 | |
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 */ |
190 | { |
191 | return (Expr->Flags & E_MASK_LOC) == E_LOC_LITERAL; |
192 | } |
193 | #else |
194 | # define ED_IsLocLiteral(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_LITERAL) |
195 | #endif |
196 | |
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 */ |
200 | { |
201 | return (Expr->Flags & E_LOC_CONST) != 0; |
202 | } |
203 | #else |
204 | # define ED_IsLocConst(Expr) (((Expr)->Flags & E_LOC_CONST) != 0) |
205 | #endif |
206 | |
207 | #if defined(HAVE_INLINE) |
208 | INLINE int ED_IsLVal (const ExprDesc* Expr) |
209 | /* Return true if the expression is a reference */ |
210 | { |
211 | return (Expr->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL; |
212 | } |
213 | #else |
214 | # define ED_IsLVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL) |
215 | #endif |
216 | |
217 | #if defined(HAVE_INLINE) |
218 | INLINE int ED_IsRVal (const ExprDesc* Expr) |
219 | /* Return true if the expression is a rvalue */ |
220 | { |
221 | return (Expr->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL; |
222 | } |
223 | #else |
224 | # define ED_IsRVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL) |
225 | #endif |
226 | |
227 | #if defined(HAVE_INLINE) |
228 | INLINE void ED_MakeLVal (ExprDesc* Expr) |
229 | /* Make the expression a lvalue. */ |
230 | { |
231 | Expr->Flags |= E_RTYPE_LVAL; |
232 | } |
233 | #else |
234 | # define ED_MakeLVal(Expr) do { (Expr)->Flags |= E_RTYPE_LVAL; } while (0) |
235 | #endif |
236 | |
237 | #if defined(HAVE_INLINE) |
238 | INLINE void ED_MakeRVal (ExprDesc* Expr) |
239 | /* Make the expression a rvalue. */ |
240 | { |
241 | Expr->Flags &= ~E_RTYPE_LVAL; |
242 | } |
243 | #else |
244 | # define ED_MakeRVal(Expr) do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0) |
245 | #endif |
246 | |
247 | #if defined(HAVE_INLINE) |
248 | INLINE int ED_IsBitField (const ExprDesc* Expr) |
249 | /* Return true if the expression is a bit field */ |
250 | { |
251 | return (Expr->Flags & E_BITFIELD) != 0; |
252 | } |
253 | #else |
254 | # define ED_IsBitField(Expr) (((Expr)->Flags & E_BITFIELD) != 0) |
255 | #endif |
256 | |
257 | void ED_MakeBitField (ExprDesc* Expr, unsigned BitOffs, unsigned BitWidth); |
258 | /* Make this expression a bit field expression */ |
259 | |
260 | #if defined(HAVE_INLINE) |
261 | INLINE void ED_MarkForTest (ExprDesc* Expr) |
262 | /* Mark the expression for a test. */ |
263 | { |
264 | Expr->Flags |= E_NEED_TEST; |
265 | } |
266 | #else |
267 | # define ED_MarkForTest(Expr) do { (Expr)->Flags |= E_NEED_TEST; } while (0) |
268 | #endif |
269 | |
270 | #if defined(HAVE_INLINE) |
271 | INLINE int ED_NeedsTest (const ExprDesc* Expr) |
272 | /* Check if the expression needs a test. */ |
273 | { |
274 | return (Expr->Flags & E_NEED_TEST) != 0; |
275 | } |
276 | #else |
277 | # define ED_NeedsTest(Expr) (((Expr)->Flags & E_NEED_TEST) != 0) |
278 | #endif |
279 | |
280 | #if defined(HAVE_INLINE) |
281 | INLINE void ED_TestDone (ExprDesc* Expr) |
282 | /* Mark the expression as tested and condition codes set. */ |
283 | { |
284 | Expr->Flags = (Expr->Flags & ~E_NEED_TEST) | E_CC_SET; |
285 | } |
286 | #else |
287 | # define ED_TestDone(Expr) \ |
288 | do { (Expr)->Flags = ((Expr)->Flags & ~E_NEED_TEST) | E_CC_SET; } while (0) |
289 | #endif |
290 | |
291 | #if defined(HAVE_INLINE) |
292 | INLINE int ED_IsTested (const ExprDesc* Expr) |
293 | /* Check if the expression has set the condition codes. */ |
294 | { |
295 | return (Expr->Flags & E_CC_SET) != 0; |
296 | } |
297 | #else |
298 | # define ED_IsTested(Expr) (((Expr)->Flags & E_CC_SET) != 0) |
299 | #endif |
300 | |
301 | #if defined(HAVE_INLINE) |
302 | INLINE void ED_MarkAsUntested (ExprDesc* Expr) |
303 | /* Mark the expression as not tested (condition codes not set). */ |
304 | { |
305 | Expr->Flags &= ~E_CC_SET; |
306 | } |
307 | #else |
308 | # define ED_MarkAsUntested(Expr) do { (Expr)->Flags &= ~E_CC_SET; } while (0) |
309 | #endif |
310 | |
311 | void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End); |
312 | /* Set the code range for this expression */ |
313 | |
314 | int ED_CodeRangeIsEmpty (const ExprDesc* Expr); |
315 | /* Return true if no code was output for this expression */ |
316 | |
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. |
321 | */ |
322 | |
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. |
326 | */ |
327 | |
328 | ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type); |
329 | /* Make Expr an absolute const with the given value and type. */ |
330 | |
331 | ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value); |
332 | /* Make Expr a constant integer expression with the given value */ |
333 | |
334 | ExprDesc* ED_MakeRValExpr (ExprDesc* Expr); |
335 | /* Convert Expr into a rvalue which is in the primary register without an |
336 | ** offset. |
337 | */ |
338 | |
339 | ExprDesc* ED_MakeLValExpr (ExprDesc* Expr); |
340 | /* Convert Expr into a lvalue which is in the primary register without an |
341 | ** offset. |
342 | */ |
343 | |
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 |
347 | ** similar. |
348 | */ |
349 | |
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. |
354 | */ |
355 | { |
356 | return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL); |
357 | } |
358 | #else |
359 | # define ED_IsConstAbs(E) \ |
360 | (((E)->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL)) |
361 | #endif |
362 | |
363 | int ED_IsConstAbsInt (const ExprDesc* Expr); |
364 | /* Return true if the expression is a constant (numeric) integer. */ |
365 | |
366 | int ED_IsNullPtr (const ExprDesc* Expr); |
367 | /* Return true if the given expression is a NULL pointer constant */ |
368 | |
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. |
372 | */ |
373 | |
374 | void PrintExprDesc (FILE* F, ExprDesc* Expr); |
375 | /* Print an ExprDesc */ |
376 | |
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 */ |
379 | |
380 | |
381 | |
382 | /* End of exprdesc.h */ |
383 | |
384 | #endif |
385 | |