X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fexprdesc.h;h=16322fb09c9cebdf1dde41be84d6e441dd122cd7;hb=7aefd9b4e7b67908b7b3c38b6003c7f1a8d3ee2d;hp=bdae371b80184003d13049dcf5d91ec577d5535a;hpb=878e4f13524e91fbcdc8c97cc461724231339483;p=cc65 diff --git a/src/cc65/exprdesc.h b/src/cc65/exprdesc.h index bdae371b8..16322fb09 100644 --- a/src/cc65/exprdesc.h +++ b/src/cc65/exprdesc.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2002-2004 Ullrich von Bassewitz */ -/* Römerstraße 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2002-2010, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -41,9 +41,11 @@ #include /* common */ +#include "fp.h" #include "inline.h" /* cc65 */ +#include "asmcode.h" #include "datatype.h" @@ -55,118 +57,323 @@ /* Defines for the flags field of the expression descriptor */ -#define E_MREG 0x0110U /* Special: Expression is primary register */ -#define E_MGLOBAL 0x0080U /* Reference to static variable */ -#define E_MLOCAL 0x0040U /* Reference to local variable (stack offset) */ -#define E_MCONST 0x0020U /* Constant value */ -#define E_MEXPR 0x0010U /* Result is in primary register */ -#define E_MEOFFS 0x0011U /* Base is in primary register, const offset */ - -#define E_MCTYPE 0x0007U /* Type of a constant */ -#define E_TCONST 0x0000U /* Constant */ -#define E_TGLAB 0x0001U /* Global label */ -#define E_TLIT 0x0002U /* Literal of some kind */ -#define E_TLOFFS 0x0003U /* Constant stack offset */ -#define E_TLLAB 0x0004U /* Local label */ -#define E_TREGISTER 0x0005U /* Register variable */ - -#define E_RVAL 0x0000U /* Expression node is a value */ -#define E_LVAL 0x1000U /* Expression node is a reference */ - -/* Defines for the test field of the expression descriptor */ -#define E_CC 0x0001U /* expr has set cond codes apropos result value */ -#define E_FORCETEST 0x0002U /* if expr has NOT set CC, force a test */ +enum { + /* Location: Where is the value we're talking about? */ + E_MASK_LOC = 0x00FF, + E_LOC_ABS = 0x0001, /* Absolute: numeric address or const */ + E_LOC_GLOBAL = 0x0002, /* Global variable */ + E_LOC_STATIC = 0x0004, /* Static variable */ + E_LOC_REGISTER = 0x0008, /* Register variable */ + E_LOC_STACK = 0x0010, /* Value on the stack */ + E_LOC_PRIMARY = 0x0020, /* The primary register */ + E_LOC_EXPR = 0x0040, /* An expression in the primary register */ + E_LOC_LITERAL = 0x0080, /* Literal in the literal pool */ + + /* Constant location of some sort (only if rval) */ + E_LOC_CONST = E_LOC_ABS | E_LOC_GLOBAL | E_LOC_STATIC | + E_LOC_REGISTER | E_LOC_LITERAL, + + /* Reference? */ + E_MASK_RTYPE = 0x0100, + E_RTYPE_RVAL = 0x0000, + E_RTYPE_LVAL = 0x0100, + + /* Bit-field? */ + E_BITFIELD = 0x0200, + + /* Test */ + E_NEED_TEST = 0x0400, /* Expression needs a test to set cc */ + E_CC_SET = 0x0800, /* Condition codes are set */ + + E_HAVE_MARKS = 0x1000, /* Code marks are valid */ + +}; + +/* Forward */ +struct Literal; /* Describe the result of an expression */ typedef struct ExprDesc ExprDesc; struct ExprDesc { - struct SymEntry* Sym; /* Symbol table entry if known */ - type* Type; /* Type array of expression */ - long ConstVal;/* Value if expression constant */ - unsigned short Flags; - unsigned short Test; /* */ - unsigned long Name; /* Name or label number */ + struct SymEntry* Sym; /* Symbol table entry if known */ + Type* Type; /* Type array of expression */ + unsigned Flags; + unsigned long Name; /* Name or label number */ + long IVal; /* Integer value if expression constant */ + Double FVal; /* Floating point value */ + struct Literal* LVal; /* Literal value */ + + /* Bit field stuff */ + unsigned BitOffs; /* Bit offset for bit fields */ + unsigned BitWidth; /* Bit width for bit fields */ + + /* Start and end of generated code */ + CodeMark Start; + CodeMark End; }; /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ -#if defined(HAVE_INLINE) -INLINE ExprDesc* InitExprDesc (ExprDesc* Expr) +ExprDesc* ED_Init (ExprDesc* Expr); /* Initialize an ExprDesc */ + +#if defined(HAVE_INLINE) +INLINE int ED_GetLoc (const ExprDesc* Expr) +/* Return the location flags from the expression */ +{ + return (Expr->Flags & E_MASK_LOC); +} +#else +# define ED_GetLoc(Expr) ((Expr)->Flags & E_MASK_LOC) +#endif + +#if defined(HAVE_INLINE) +INLINE int ED_IsLocAbs (const ExprDesc* Expr) +/* Return true if the expression is an absolute value */ +{ + return (Expr->Flags & E_MASK_LOC) == E_LOC_ABS; +} +#else +# define ED_IsLocAbs(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_ABS) +#endif + +#if defined(HAVE_INLINE) +INLINE int ED_IsLocRegister (const ExprDesc* Expr) +/* Return true if the expression is located in a register */ +{ + return (Expr->Flags & E_MASK_LOC) == E_LOC_REGISTER; +} +#else +# define ED_IsLocRegister(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_REGISTER) +#endif + +#if defined(HAVE_INLINE) +INLINE int ED_IsLocStack (const ExprDesc* Expr) +/* Return true if the expression is located on the stack */ { - return memset (Expr, 0, sizeof (*Expr)); + return (Expr->Flags & E_MASK_LOC) == E_LOC_STACK; } #else -# define InitExprDesc(E) memset ((E), 0, sizeof (*(E))) +# define ED_IsLocStack(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_STACK) +#endif + +#if defined(HAVE_INLINE) +INLINE int ED_IsLocPrimary (const ExprDesc* Expr) +/* Return true if the expression is an expression in the register pseudo variable */ +{ + return (Expr->Flags & E_MASK_LOC) == E_LOC_PRIMARY; +} +#else +# define ED_IsLocPrimary(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_PRIMARY) +#endif + +#if defined(HAVE_INLINE) +INLINE int ED_IsLocExpr (const ExprDesc* Expr) +/* Return true if the expression is an expression in the primary */ +{ + return (Expr->Flags & E_MASK_LOC) == E_LOC_EXPR; +} +#else +# define ED_IsLocExpr(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_EXPR) +#endif + +#if defined(HAVE_INLINE) +INLINE int ED_IsLocLiteral (const ExprDesc* Expr) +/* Return true if the expression is a string from the literal pool */ +{ + return (Expr->Flags & E_MASK_LOC) == E_LOC_LITERAL; +} +#else +# define ED_IsLocLiteral(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_LITERAL) +#endif + +#if defined(HAVE_INLINE) +INLINE int ED_IsLocConst (const ExprDesc* Expr) +/* Return true if the expression is a constant location of some sort */ +{ + return (Expr->Flags & E_LOC_CONST) != 0; +} +#else +# define ED_IsLocConst(Expr) (((Expr)->Flags & E_LOC_CONST) != 0) #endif #if defined(HAVE_INLINE) INLINE int ED_IsLVal (const ExprDesc* Expr) /* Return true if the expression is a reference */ { - return (Expr->Flags & E_LVAL) != 0; + return (Expr->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL; } #else -# define ED_IsLVal(Expr) (((Expr)->Flags & E_LVAL) != 0) +# define ED_IsLVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL) #endif #if defined(HAVE_INLINE) INLINE int ED_IsRVal (const ExprDesc* Expr) /* Return true if the expression is a rvalue */ { - return (Expr->Flags & E_LVAL) == 0; + return (Expr->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL; } #else -# define ED_IsRVal(Expr) (((Expr)->Flags & E_LVAL) == 0) +# define ED_IsRVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL) #endif #if defined(HAVE_INLINE) -INLINE int ED_SetValType (ExprDesc* Expr, int Ref) -/* Set the reference flag for an expression and return it (the flag) */ +INLINE void ED_MakeLVal (ExprDesc* Expr) +/* Make the expression a lvalue. */ { - Expr->Flags = Ref? (Expr->Flags | E_LVAL) : (Expr->Flags & ~E_LVAL); - return Ref; + Expr->Flags |= E_RTYPE_LVAL; } #else -/* Beware: Just one occurance of R below, since it may have side effects! */ -# define ED_SetValType(E, R) \ - (((E)->Flags = (R)? ((E)->Flags | E_LVAL) : ((E)->Flags & ~E_LVAL)), \ - ED_IsLVal (E)) +# define ED_MakeLVal(Expr) do { (Expr)->Flags |= E_RTYPE_LVAL; } while (0) #endif #if defined(HAVE_INLINE) -INLINE int ED_MakeLVal (ExprDesc* Expr) -/* Make the expression a lvalue and return true */ +INLINE void ED_MakeRVal (ExprDesc* Expr) +/* Make the expression a rvalue. */ { - return ED_SetValType (Expr, 1); + Expr->Flags &= ~E_RTYPE_LVAL; } #else -# define ED_MakeLVal(Expr) ED_SetValType (Expr, 1) +# define ED_MakeRVal(Expr) do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0) #endif #if defined(HAVE_INLINE) -INLINE int ED_MakeRVal (ExprDesc* Expr) -/* Make the expression a rvalue and return false */ +INLINE int ED_IsBitField (const ExprDesc* Expr) +/* Return true if the expression is a bit field */ { - return ED_SetValType (Expr, 0); + return (Expr->Flags & E_BITFIELD) != 0; } #else -# define ED_MakeRVal(Expr) ED_SetValType (Expr, 0) +# define ED_IsBitField(Expr) (((Expr)->Flags & E_BITFIELD) != 0) #endif -ExprDesc* ED_MakeConstInt (ExprDesc* Expr, long Value); +void ED_MakeBitField (ExprDesc* Expr, unsigned BitOffs, unsigned BitWidth); +/* Make this expression a bit field expression */ + +#if defined(HAVE_INLINE) +INLINE void ED_MarkForTest (ExprDesc* Expr) +/* Mark the expression for a test. */ +{ + Expr->Flags |= E_NEED_TEST; +} +#else +# define ED_MarkForTest(Expr) do { (Expr)->Flags |= E_NEED_TEST; } while (0) +#endif + +#if defined(HAVE_INLINE) +INLINE int ED_NeedsTest (const ExprDesc* Expr) +/* Check if the expression needs a test. */ +{ + return (Expr->Flags & E_NEED_TEST) != 0; +} +#else +# define ED_NeedsTest(Expr) (((Expr)->Flags & E_NEED_TEST) != 0) +#endif + +#if defined(HAVE_INLINE) +INLINE void ED_TestDone (ExprDesc* Expr) +/* Mark the expression as tested and condition codes set. */ +{ + Expr->Flags = (Expr->Flags & ~E_NEED_TEST) | E_CC_SET; +} +#else +# define ED_TestDone(Expr) \ + do { (Expr)->Flags = ((Expr)->Flags & ~E_NEED_TEST) | E_CC_SET; } while (0) +#endif + +#if defined(HAVE_INLINE) +INLINE int ED_IsTested (const ExprDesc* Expr) +/* Check if the expression has set the condition codes. */ +{ + return (Expr->Flags & E_CC_SET) != 0; +} +#else +# define ED_IsTested(Expr) (((Expr)->Flags & E_CC_SET) != 0) +#endif + +#if defined(HAVE_INLINE) +INLINE void ED_MarkAsUntested (ExprDesc* Expr) +/* Mark the expression as not tested (condition codes not set). */ +{ + Expr->Flags &= ~E_CC_SET; +} +#else +# define ED_MarkAsUntested(Expr) do { (Expr)->Flags &= ~E_CC_SET; } while (0) +#endif + +void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End); +/* Set the code range for this expression */ + +int ED_CodeRangeIsEmpty (const ExprDesc* Expr); +/* Return true if no code was output for this expression */ + +const char* ED_GetLabelName (const ExprDesc* Expr, long Offs); +/* Return the assembler label name of the given expression. Beware: This + * function may use a static buffer, so the name may get "lost" on the second + * call to the function. + */ + +int ED_GetStackOffs (const ExprDesc* Expr, int Offs); +/* Get the stack offset of an address on the stack in Expr taking into account + * an additional offset in Offs. + */ + +ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type); +/* Make Expr an absolute const with the given value and type. */ + +ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value); /* Make Expr a constant integer expression with the given value */ +ExprDesc* ED_MakeRValExpr (ExprDesc* Expr); +/* Convert Expr into a rvalue which is in the primary register without an + * offset. + */ + +ExprDesc* ED_MakeLValExpr (ExprDesc* Expr); +/* Convert Expr into a lvalue which is in the primary register without an + * offset. + */ + +int ED_IsConst (const ExprDesc* Expr); +/* Return true if the expression denotes a constant of some sort. This can be a + * numeric constant, the address of a global variable (maybe with offset) or + * similar. + */ + +#if defined(HAVE_INLINE) +INLINE int ED_IsConstAbs (const ExprDesc* Expr) +/* Return true if the expression denotes a constant absolute value. This can be + * a numeric constant, cast to any type. + */ +{ + return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL); +} +#else +# define ED_IsConstAbs(E) \ + (((E)->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL)) +#endif + +int ED_IsConstAbsInt (const ExprDesc* Expr); +/* Return true if the expression is a constant (numeric) integer. */ + +int ED_IsNullPtr (const ExprDesc* Expr); +/* Return true if the given expression is a NULL pointer constant */ + +int ED_IsBool (const ExprDesc* Expr); +/* Return true of the expression can be treated as a boolean, that is, it can + * be an operand to a compare operation. + */ + void PrintExprDesc (FILE* F, ExprDesc* Expr); /* Print an ExprDesc */ -type* ReplaceType (ExprDesc* Expr, const type* NewType); +Type* ReplaceType (ExprDesc* Expr, const Type* NewType); /* Replace the type of Expr by a copy of Newtype and return the old type string */