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 */
61enum {
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 */
94struct Literal;
95
96/* Describe the result of an expression */
97typedef struct ExprDesc ExprDesc;
98struct 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
124ExprDesc* ED_Init (ExprDesc* Expr);
125/* Initialize an ExprDesc */
126
127#if defined(HAVE_INLINE)
128INLINE 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)
138INLINE 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)
148INLINE 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)
158INLINE 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)
168INLINE 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)
178INLINE 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)
188INLINE 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)
198INLINE 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)
208INLINE 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)
218INLINE 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)
228INLINE 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)
238INLINE 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)
248INLINE 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
257void ED_MakeBitField (ExprDesc* Expr, unsigned BitOffs, unsigned BitWidth);
258/* Make this expression a bit field expression */
259
260#if defined(HAVE_INLINE)
261INLINE 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)
271INLINE 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)
281INLINE 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)
292INLINE 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)
302INLINE 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
311void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End);
312/* Set the code range for this expression */
313
314int ED_CodeRangeIsEmpty (const ExprDesc* Expr);
315/* Return true if no code was output for this expression */
316
317const 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
323int 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
328ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type);
329/* Make Expr an absolute const with the given value and type. */
330
331ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value);
332/* Make Expr a constant integer expression with the given value */
333
334ExprDesc* ED_MakeRValExpr (ExprDesc* Expr);
335/* Convert Expr into a rvalue which is in the primary register without an
336** offset.
337*/
338
339ExprDesc* ED_MakeLValExpr (ExprDesc* Expr);
340/* Convert Expr into a lvalue which is in the primary register without an
341** offset.
342*/
343
344int 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)
351INLINE 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
363int ED_IsConstAbsInt (const ExprDesc* Expr);
364/* Return true if the expression is a constant (numeric) integer. */
365
366int ED_IsNullPtr (const ExprDesc* Expr);
367/* Return true if the given expression is a NULL pointer constant */
368
369int 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
374void PrintExprDesc (FILE* F, ExprDesc* Expr);
375/* Print an ExprDesc */
376
377Type* 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