1
0
mirror of https://github.com/cc65/cc65.git synced 2025-01-01 03:30:20 +00:00

Fix for Issue #1075 and #1077.

This commit is contained in:
acqn 2020-07-15 20:22:28 +08:00 committed by Oliver Schmidt
parent ba48dfe65d
commit 2108489523
12 changed files with 598 additions and 260 deletions

View File

@ -98,7 +98,7 @@ void Assignment (ExprDesc* Expr)
if (UseReg) {
PushAddr (Expr);
} else {
ED_MakeRVal (Expr);
ED_MarkExprAsRVal (Expr);
LoadExpr (CF_NONE, Expr);
g_push (CF_PTR | CF_UNSIGNED, 0);
}
@ -127,7 +127,7 @@ void Assignment (ExprDesc* Expr)
} else {
/* We will use memcpy. Push the address of the rhs */
ED_MakeRVal (&Expr2);
ED_MarkExprAsRVal (&Expr2);
LoadExpr (CF_NONE, &Expr2);
/* Push the address (or whatever is in ax in case of errors) */
@ -264,5 +264,5 @@ void Assignment (ExprDesc* Expr)
}
/* Value is still in primary and not an lvalue */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
}

View File

@ -100,6 +100,11 @@ static const char* GetLabelName (unsigned Flags, uintptr_t Label, long Offs)
/* Create the correct label name */
switch (Flags & CF_ADDRMASK) {
case CF_IMM:
/* Immediate constant values */
xsprintf (Buf, sizeof (Buf), "$%04X", (unsigned)((Offs) & 0xFFFF));
break;
case CF_STATIC:
/* Static memory cell */
if (Offs) {

View File

@ -81,11 +81,12 @@
#define CF_TEST 0x0080 /* Test value */
#define CF_FIXARGC 0x0100 /* Function has fixed arg count */
#define CF_FORCECHAR 0x0200 /* Handle chars as chars, not ints */
#define CF_REG 0x0800 /* Value is in primary register */
/* Type of static address */
#define CF_ADDRMASK 0xF000 /* Type of address */
#define CF_STATIC 0x0000 /* Static local */
#define CF_ADDRMASK 0xFC00 /* Type of address */
#define CF_IMM 0x0000 /* Value is pure rvalue and has no address */
#define CF_REG 0x0400 /* Value is in primary register */
#define CF_STATIC 0x0800 /* Static local */
#define CF_EXTERNAL 0x1000 /* Static external */
#define CF_ABSOLUTE 0x2000 /* Numeric absolute address */
#define CF_LOCAL 0x4000 /* Auto variable */

View File

@ -1773,9 +1773,14 @@ static void DefineData (ExprDesc* Expr)
{
switch (ED_GetLoc (Expr)) {
case E_LOC_NONE:
/* Immediate numeric value with no storage */
g_defdata (CF_IMM | TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
break;
case E_LOC_ABS:
/* Absolute: numeric address or const */
g_defdata (TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
/* Absolute numeric address */
g_defdata (CF_ABSOLUTE | TypeOf(Expr->Type) | CF_CONST, Expr->IVal, 0);
break;
case E_LOC_GLOBAL:

View File

@ -83,6 +83,7 @@ static unsigned GlobalModeFlags (const ExprDesc* Expr)
/* Return the addressing mode flags for the given expression */
{
switch (ED_GetLoc (Expr)) {
case E_LOC_NONE: return CF_IMM;
case E_LOC_ABS: return CF_ABSOLUTE;
case E_LOC_GLOBAL: return CF_EXTERNAL;
case E_LOC_STATIC: return CF_STATIC;
@ -183,7 +184,7 @@ static unsigned typeadjust (ExprDesc* lhs, ExprDesc* rhs, int NoPush)
/* Generate type adjustment code if needed */
ltype = TypeOf (lhst);
if (ED_IsLocAbs (lhs)) {
if (ED_IsLocNone (lhs)) {
ltype |= CF_CONST;
}
if (NoPush) {
@ -191,7 +192,7 @@ static unsigned typeadjust (ExprDesc* lhs, ExprDesc* rhs, int NoPush)
ltype |= CF_REG;
}
rtype = TypeOf (rhst);
if (ED_IsLocAbs (rhs)) {
if (ED_IsLocNone (rhs)) {
rtype |= CF_CONST;
}
flags = g_typeadjust (ltype, rtype);
@ -506,7 +507,7 @@ static void FunctionCall (ExprDesc* Expr)
** the pointer into the primary and mark it as an expression.
*/
LoadExpr (CF_NONE, Expr);
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
/* Remember the code position */
GetCodePos (&Mark);
@ -646,7 +647,7 @@ static void FunctionCall (ExprDesc* Expr)
}
/* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type);
}
@ -663,7 +664,7 @@ static void Primary (ExprDesc* E)
/* Character and integer constants. */
if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
E->IVal = CurTok.IVal;
E->Flags = E_LOC_ABS | E_RTYPE_RVAL;
E->Flags = E_LOC_NONE | E_RTYPE_RVAL;
E->Type = CurTok.Type;
NextToken ();
return;
@ -672,7 +673,7 @@ static void Primary (ExprDesc* E)
/* Floating point constant */
if (CurTok.Tok == TOK_FCONST) {
E->FVal = CurTok.FVal;
E->Flags = E_LOC_ABS | E_RTYPE_RVAL;
E->Flags = E_LOC_NONE | E_RTYPE_RVAL;
E->Type = CurTok.Type;
NextToken ();
return;
@ -716,7 +717,7 @@ static void Primary (ExprDesc* E)
NextToken ();
Entry = AddLabelSym (CurTok.Ident, SC_REF | SC_GOTO_IND);
/* output its label */
E->Flags = E_RTYPE_RVAL | E_LOC_STATIC;
E->Flags = E_RTYPE_RVAL | E_LOC_STATIC | E_ADDRESS_OF;
E->Name = Entry->V.L.Label;
E->Type = PointerTo (type_void);
NextToken ();
@ -756,7 +757,7 @@ static void Primary (ExprDesc* E)
/* Check for legal symbol types */
if ((Sym->Flags & SC_CONST) == SC_CONST) {
/* Enum or some other numeric constant */
E->Flags = E_LOC_ABS | E_RTYPE_RVAL;
E->Flags = E_LOC_NONE | E_RTYPE_RVAL;
E->IVal = Sym->V.ConstVal;
} else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
/* Function */
@ -797,12 +798,12 @@ static void Primary (ExprDesc* E)
/* We've made all variables lvalues above. However, this is
** not always correct: An array is actually the address of its
** first element, which is a rvalue, and a function is a
** first element, which is an rvalue, and a function is an
** rvalue, too, because we cannot store anything in a function.
** So fix the flags depending on the type.
*/
if (IsTypeArray (E->Type) || IsTypeFunc (E->Type)) {
ED_MakeRVal (E);
ED_AddrExpr (E);
}
} else {
@ -845,7 +846,7 @@ static void Primary (ExprDesc* E)
/* String literal */
E->LVal = UseLiteral (CurTok.SVal);
E->Type = GetCharArrayType (GetLiteralSize (CurTok.SVal));
E->Flags = E_LOC_LITERAL | E_RTYPE_RVAL;
E->Flags = E_LOC_LITERAL | E_RTYPE_RVAL | E_ADDRESS_OF;
E->IVal = 0;
E->Name = GetLiteralLabel (CurTok.SVal);
NextToken ();
@ -854,7 +855,7 @@ static void Primary (ExprDesc* E)
case TOK_ASM:
/* ASM statement */
AsmStatement ();
E->Flags = E_LOC_EXPR | E_RTYPE_RVAL;
E->Flags = E_RTYPE_RVAL;
E->Type = type_void;
break;
@ -912,12 +913,11 @@ static void ArrayRef (ExprDesc* Expr)
/* We can apply a special treatment for arrays that have a const base
** address. This is true for most arrays and will produce a lot better
** code. Check if this is a const base address.
** code. Check if this is a "quasi-const base" address.
*/
ConstBaseAddr = ED_IsRVal (Expr) &&
(ED_IsLocConst (Expr) || ED_IsLocStack (Expr));
ConstBaseAddr = ED_IsRVal (Expr) && ED_IsLocQuasiConst (Expr);
/* If we have a constant base, we delay the address fetch */
/* If we have a quasi-const base address, we delay the address fetch */
GetCodePos (&Mark1);
if (!ConstBaseAddr) {
/* Get a pointer to the array into the primary */
@ -984,7 +984,7 @@ static void ArrayRef (ExprDesc* Expr)
/* If the subscript is a bit-field, load it and make it an rvalue */
if (ED_IsBitField (&Subscript)) {
LoadExpr (CF_NONE, &Subscript);
ED_MakeRValExpr (&Subscript);
ED_FinalizeRValLoad (&Subscript);
}
/* Check if the subscript is constant absolute value */
@ -1015,25 +1015,21 @@ static void ArrayRef (ExprDesc* Expr)
** already in Expr. If the base address was a constant, we can even
** remove the code that loaded the address into the primary.
*/
if (IsTypeArray (Expr->Type)) {
/* Adjust the offset */
Expr->IVal += Subscript.IVal;
} else {
if (!IsTypeArray (Expr->Type)) {
/* It's a pointer, so we do have to load it into the primary
** first (if it's not already there).
*/
if (ConstBaseAddr || ED_IsLVal (Expr)) {
if (!ConstBaseAddr && ED_IsLVal (Expr)) {
LoadExpr (CF_NONE, Expr);
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
}
/* Use the offset */
Expr->IVal = Subscript.IVal;
}
/* Adjust the offset */
Expr->IVal += Subscript.IVal;
} else {
/* Scale the rhs value according to the element type */
@ -1106,7 +1102,7 @@ static void ArrayRef (ExprDesc* Expr)
** subscript was not scaled, that is, if this was a byte array
** or pointer.
*/
if ((ED_IsLocConst (&Subscript) || ED_IsLocStack (&Subscript)) &&
if (ED_IsLocQuasiConst (&Subscript) &&
CheckedSizeOf (ElementType) == SIZEOF_CHAR) {
unsigned Flags;
@ -1131,12 +1127,13 @@ static void ArrayRef (ExprDesc* Expr)
}
} else {
if (ED_IsLocAbs (Expr)) {
if (ED_IsLocNone (Expr) ||
(ED_IsLocAbs (Expr) && ED_IsAddrExpr (Expr))) {
/* Constant numeric address. Just add it */
g_inc (CF_INT, Expr->IVal);
} else if (ED_IsLocStack (Expr)) {
/* Base address is a local variable address */
if (IsTypeArray (Expr->Type)) {
if (ED_IsAddrExpr (Expr)) {
g_addaddr_local (CF_INT, Expr->IVal);
} else {
g_addlocal (CF_PTR, Expr->IVal);
@ -1144,7 +1141,7 @@ static void ArrayRef (ExprDesc* Expr)
} else {
/* Base address is a static variable address */
unsigned Flags = CF_INT | GlobalModeFlags (Expr);
if (ED_IsRVal (Expr)) {
if (ED_IsAddrExpr (Expr)) {
/* Add the address of the location */
g_addaddr_static (Flags, Expr->Name, Expr->IVal);
} else {
@ -1153,27 +1150,27 @@ static void ArrayRef (ExprDesc* Expr)
}
}
}
}
/* The result is an expression in the primary */
ED_MakeRValExpr (Expr);
/* The pointer is an rvalue in the primary */
ED_FinalizeRValLoad (Expr);
}
/* Result is of element type */
/* The result is usually an lvalue expression of element type referenced in
** the primary, unless it's an array which is a rare case. We can just
** assume the usual case first, and change it later if necessary.
*/
ED_IndExpr (Expr);
Expr->Type = ElementType;
/* An array element is actually a variable. So the rules for variables
** with respect to the reference type apply: If it's an array, it is
** a rvalue, otherwise it's an lvalue. (A function would also be a rvalue,
** but an array cannot contain functions).
/* An array element is actually a variable. So the rules for variables with
** respect to the reference type apply: If it's an array, it is virtually
** an rvalue address, otherwise it's an lvalue reference. (A function would
** also be an rvalue address, but an array cannot contain functions).
*/
if (IsTypeArray (Expr->Type)) {
ED_MakeRVal (Expr);
} else {
ED_MakeLVal (Expr);
ED_AddrExpr (Expr);
}
/* Consume the closing bracket */
@ -1210,16 +1207,26 @@ static void StructRef (ExprDesc* Expr)
return;
}
/* If we have a struct pointer that is an lvalue and not already in the
** primary, load it now.
*/
if (ED_IsLVal (Expr) && IsTypePtr (Expr->Type)) {
if (IsTypePtr (Expr->Type)) {
/* If we have a struct pointer that is an lvalue and not already in the
** primary, load its content now.
*/
if (!ED_IsConst (Expr)) {
/* Load into the primary */
LoadExpr (CF_NONE, Expr);
/* Load into the primary */
/* Clear the offset */
Expr->IVal = 0;
}
/* Dereference the expression */
ED_IndExpr (Expr);
} else if (!ED_IsLocQuasiConst (Expr) && !ED_IsLocPrimaryOrExpr (Expr)) {
/* Load the base address into the primary (and use it as a reference
** later) if it's not quasi-const or in the primary already.
*/
LoadExpr (CF_NONE, Expr);
/* Make it an lvalue expression */
ED_MakeLValExpr (Expr);
}
/* The type is the type of the field plus any qualifiers from the struct */
@ -1235,8 +1242,8 @@ static void StructRef (ExprDesc* Expr)
FinalType->C |= Q;
}
/* A struct is usually an lvalue. If not, it is a struct in the primary
** register.
/* A struct is usually an lvalue. If not, it is a struct referenced in the
** primary register, which is likely to be returned from a function.
*/
if (ED_IsRVal (Expr) && ED_IsLocExpr (Expr) && !IsTypePtr (Expr->Type)) {
@ -1289,13 +1296,12 @@ static void StructRef (ExprDesc* Expr)
/* An struct member is actually a variable. So the rules for variables
** with respect to the reference type apply: If it's an array, it is
** a rvalue, otherwise it's an lvalue. (A function would also be a rvalue,
** but a struct field cannot be a function).
** virtually an rvalue address, otherwise it's an lvalue reference. (A
** function would also be an rvalue address, but a struct field cannot
** contain functions).
*/
if (IsTypeArray (Expr->Type)) {
ED_MakeRVal (Expr);
} else {
ED_MakeLVal (Expr);
ED_AddrExpr (Expr);
}
/* Make the expression a bit field if necessary */
@ -1391,7 +1397,7 @@ void Store (ExprDesc* Expr, const Type* StoreType)
switch (ED_GetLoc (Expr)) {
case E_LOC_ABS:
/* Absolute: numeric address or const */
/* Absolute numeric addressed variable */
g_putstatic (Flags, Expr->IVal, 0);
break;
@ -1421,10 +1427,14 @@ void Store (ExprDesc* Expr, const Type* StoreType)
break;
case E_LOC_EXPR:
/* An expression in the primary register */
/* An expression referenced in the primary register */
g_putind (Flags, Expr->IVal);
break;
case E_LOC_NONE:
/* We may get here as a result of previous compiler errors */
break;
default:
Internal ("Invalid location in Store(): 0x%04X", ED_GetLoc (Expr));
}
@ -1466,7 +1476,7 @@ static void PreInc (ExprDesc* Expr)
switch (ED_GetLoc (Expr)) {
case E_LOC_ABS:
/* Absolute: numeric address or const */
/* Absolute numeric addressed variable */
g_addeqstatic (Flags, Expr->IVal, 0, Val);
break;
@ -1497,7 +1507,7 @@ static void PreInc (ExprDesc* Expr)
break;
case E_LOC_EXPR:
/* An expression in the primary register */
/* An expression referenced in the primary register */
g_addeqind (Flags, Expr->IVal, Val);
break;
@ -1506,7 +1516,7 @@ static void PreInc (ExprDesc* Expr)
}
/* Result is an expression, no reference */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
}
@ -1542,7 +1552,7 @@ static void PreDec (ExprDesc* Expr)
switch (ED_GetLoc (Expr)) {
case E_LOC_ABS:
/* Absolute: numeric address or const */
/* Absolute numeric addressed variable */
g_subeqstatic (Flags, Expr->IVal, 0, Val);
break;
@ -1582,7 +1592,7 @@ static void PreDec (ExprDesc* Expr)
}
/* Result is an expression, no reference */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
}
@ -1638,7 +1648,7 @@ static void PostInc (ExprDesc* Expr)
}
/* The result is always an expression, no reference */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
}
@ -1694,7 +1704,7 @@ static void PostDec (ExprDesc* Expr)
}
/* The result is always an expression, no reference */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
}
@ -1741,8 +1751,8 @@ static void UnaryOp (ExprDesc* Expr)
default: Internal ("Unexpected token: %d", Tok);
}
/* The result is a rvalue in the primary */
ED_MakeRValExpr (Expr);
/* The result is an rvalue in the primary */
ED_FinalizeRValLoad (Expr);
}
}
@ -1776,7 +1786,7 @@ void hie10 (ExprDesc* Expr)
Expr->IVal = !Expr->IVal;
} else {
g_bneg (TypeOf (Expr->Type));
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
ED_TestDone (Expr); /* bneg will set cc */
}
break;
@ -1784,13 +1794,14 @@ void hie10 (ExprDesc* Expr)
case TOK_STAR:
NextToken ();
ExprWithCheck (hie10, Expr);
if (ED_IsLVal (Expr) || !(ED_IsLocConst (Expr) || ED_IsLocStack (Expr))) {
/* Not a const, load it into the primary and make it a
if (ED_IsLVal (Expr) || !ED_IsLocQuasiConst (Expr)) {
/* Not a const, load the pointer into the primary and make it a
** calculated value.
*/
LoadExpr (CF_NONE, Expr);
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
}
/* If the expression is already a pointer to function, the
** additional dereferencing operator must be ignored. A function
** itself is represented as "pointer to function", so any number
@ -1799,7 +1810,7 @@ void hie10 (ExprDesc* Expr)
*/
if (IsTypeFuncPtr (Expr->Type) || IsTypeFunc (Expr->Type)) {
/* Expression not storable */
ED_MakeRVal (Expr);
ED_MarkExprAsRVal (Expr);
} else {
if (IsClassPtr (Expr->Type)) {
Expr->Type = Indirect (Expr->Type);
@ -1810,8 +1821,8 @@ void hie10 (ExprDesc* Expr)
** address -- it already is the location of the first element.
*/
if (!IsTypeArray (Expr->Type)) {
/* The * operator yields an lvalue */
ED_MakeLVal (Expr);
/* The * operator yields an lvalue reference */
ED_IndExpr (Expr);
}
}
break;
@ -1831,8 +1842,8 @@ void hie10 (ExprDesc* Expr)
Expr->Flags &= ~E_BITFIELD;
}
Expr->Type = PointerTo (Expr->Type);
/* The & operator yields an rvalue */
ED_MakeRVal (Expr);
/* The & operator yields an rvalue address */
ED_AddrExpr (Expr);
}
break;
@ -2067,8 +2078,8 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */
/* Generate code */
Gen->Func (type, Expr->IVal);
/* We have a rvalue in the primary now */
ED_MakeRValExpr (Expr);
/* We have an rvalue in the primary now */
ED_FinalizeRValLoad (Expr);
} else {
@ -2100,8 +2111,8 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */
/* Generate code */
Gen->Func (type, Expr2.IVal);
/* We have a rvalue in the primary now */
ED_MakeRValExpr (Expr);
/* We have an rvalue in the primary now */
ED_FinalizeRValLoad (Expr);
}
}
}
@ -2441,7 +2452,7 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */
GenFunc (flags, Expr2.IVal);
/* The result is an rvalue in the primary */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
}
/* Result type is always int */
@ -2534,7 +2545,7 @@ static void parseadd (ExprDesc* Expr)
rhst = Expr2.Type;
/* Setup flags */
if (ED_IsLocAbs (Expr)) {
if (ED_IsLocNone (Expr)) {
/* A numerical constant */
flags |= CF_CONST;
} else {
@ -2549,7 +2560,7 @@ static void parseadd (ExprDesc* Expr)
/* Operate on pointers, result type is a pointer */
flags |= CF_PTR;
/* Generate the code for the add */
if (ED_GetLoc (Expr) == E_LOC_ABS) {
if (ED_GetLoc (Expr) == E_LOC_NONE) {
/* Numeric constant */
g_inc (flags, Expr->IVal);
} else {
@ -2569,7 +2580,7 @@ static void parseadd (ExprDesc* Expr)
** not a numeric constant, and the scale factor is not one
** (no scaling), we must take the long way over the stack.
*/
if (ED_IsLocAbs (Expr)) {
if (ED_IsLocNone (Expr)) {
/* Numeric constant, scale lhs */
Expr->IVal *= ScaleFactor;
/* Generate the code for the add */
@ -2588,7 +2599,7 @@ static void parseadd (ExprDesc* Expr)
/* Integer addition */
flags |= typeadjust (Expr, &Expr2, 1);
/* Generate the code for the add */
if (ED_IsLocAbs (Expr)) {
if (ED_IsLocNone (Expr)) {
/* Numeric constant */
g_inc (flags, Expr->IVal);
} else {
@ -2601,8 +2612,8 @@ static void parseadd (ExprDesc* Expr)
flags = CF_INT;
}
/* Result is a rvalue in primary register */
ED_MakeRValExpr (Expr);
/* Result is an rvalue in primary register */
ED_FinalizeRValLoad (Expr);
}
} else {
@ -2692,8 +2703,8 @@ static void parseadd (ExprDesc* Expr)
}
/* Result is a rvalue in primary register */
ED_MakeRValExpr (Expr);
/* Result is an rvalue in primary register */
ED_FinalizeRValLoad (Expr);
}
/* Condition codes not set */
@ -2825,8 +2836,8 @@ static void parsesub (ExprDesc* Expr)
g_scale (flags, -rscale);
}
/* Result is a rvalue in the primary register */
ED_MakeRValExpr (Expr);
/* Result is an rvalue in the primary register */
ED_FinalizeRValLoad (Expr);
ED_MarkAsUntested (Expr);
}
@ -2860,8 +2871,8 @@ static void parsesub (ExprDesc* Expr)
** the lhs is const, we have to remove this mark, since this is no
** longer true, lhs is on stack instead.
*/
if (ED_IsLocAbs (Expr)) {
ED_MakeRValExpr (Expr);
if (ED_IsLocNone (Expr)) {
ED_FinalizeRValLoad (Expr);
}
/* Adjust operand types */
flags = typeadjust (Expr, &Expr2, 0);
@ -2879,8 +2890,8 @@ static void parsesub (ExprDesc* Expr)
g_scale (flags, -rscale);
}
/* Result is a rvalue in the primary register */
ED_MakeRValExpr (Expr);
/* Result is an rvalue in the primary register */
ED_FinalizeRValLoad (Expr);
ED_MarkAsUntested (Expr);
}
}
@ -3070,7 +3081,7 @@ static void hieAnd (ExprDesc* Expr, unsigned TrueLab, int* BoolOp)
g_defcodelabel (FalseLab);
/* The result is an rvalue in primary */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
ED_TestDone (Expr); /* Condition codes are set */
}
}
@ -3133,7 +3144,7 @@ static void hieOr (ExprDesc *Expr)
}
/* The result is an rvalue in primary */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
ED_TestDone (Expr); /* Condition codes are set */
}
@ -3189,7 +3200,7 @@ static void hieQuest (ExprDesc* Expr)
if (!IsTypeVoid (Expr2.Type)) {
/* Load it into the primary */
LoadExpr (CF_NONE, &Expr2);
ED_MakeRValExpr (&Expr2);
ED_FinalizeRValLoad (&Expr2);
Expr2.Type = PtrConversion (Expr2.Type);
}
@ -3212,7 +3223,7 @@ static void hieQuest (ExprDesc* Expr)
if (!IsTypeVoid (Expr3.Type)) {
/* Load it into the primary */
LoadExpr (CF_NONE, &Expr3);
ED_MakeRValExpr (&Expr3);
ED_FinalizeRValLoad (&Expr3);
Expr3.Type = PtrConversion (Expr3.Type);
}
@ -3278,7 +3289,7 @@ static void hieQuest (ExprDesc* Expr)
g_defcodelabel (TrueLab);
/* Setup the target expression */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
Expr->Type = ResultType;
}
}
@ -3294,7 +3305,7 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op)
int MustScale;
/* op= can only be used with lvalues */
if (!ED_IsLVal (Expr)) {
if (ED_IsRVal (Expr)) {
Error ("Invalid lvalue in assignment");
return;
}
@ -3396,7 +3407,7 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op)
Gen->Func (g_typeadjust (flags, TypeOf (Expr2.Type)), 0);
}
Store (Expr, 0);
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
}
@ -3410,7 +3421,7 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
int MustScale;
/* We're currently only able to handle some adressing modes */
/* We're currently only able to handle some addressing modes */
if (ED_GetLoc (Expr) == E_LOC_EXPR || ED_GetLoc (Expr) == E_LOC_PRIMARY) {
/* Use generic routine */
opeq (Gen, Expr, Op);
@ -3487,7 +3498,7 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
switch (ED_GetLoc (Expr)) {
case E_LOC_ABS:
/* Absolute: numeric address or const */
/* Absolute numeric addressed variable */
if (Gen->Tok == TOK_PLUS_ASSIGN) {
g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
} else {
@ -3536,8 +3547,8 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
Internal ("Invalid location in Store(): 0x%04X", ED_GetLoc (Expr));
}
/* Expression is a rvalue in the primary now */
ED_MakeRValExpr (Expr);
/* Expression is an rvalue in the primary now */
ED_FinalizeRValLoad (Expr);
}

View File

@ -80,6 +80,39 @@ void ED_MakeBitField (ExprDesc* Expr, unsigned BitOffs, unsigned BitWidth)
#if !defined(HAVE_INLINE)
int ED_IsLocQuasiConst (const ExprDesc* Expr)
/* Return true if the expression is a constant location of some sort or on the
** stack.
*/
{
return ED_IsLocConst (Expr) || ED_IsLocStack (Expr);
}
#endif
#if !defined(HAVE_INLINE)
int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
{
return ED_IsLocPrimary (Expr) || ED_IsLocExpr (Expr);
}
#endif
#if !defined(HAVE_INLINE)
int ED_IsIndExpr (const ExprDesc* Expr)
/* Check if the expression is a reference to its value */
{
return (Expr->Flags & E_ADDRESS_OF) == 0 &&
!ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr);
}
#endif
void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End)
/* Set the code range for this expression */
{
@ -115,8 +148,9 @@ const char* ED_GetLabelName (const ExprDesc* Expr, long Offs)
/* Generate a label depending on the location */
switch (ED_GetLoc (Expr)) {
case E_LOC_NONE:
case E_LOC_ABS:
/* Absolute: numeric address or const */
/* Absolute numeric addressed variable */
SB_Printf (&Buf, "$%04X", (int)(Offs & 0xFFFF));
break;
@ -168,11 +202,11 @@ int ED_GetStackOffs (const ExprDesc* Expr, int Offs)
ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type)
/* Make Expr an absolute const with the given value and type. */
/* Replace Expr with an absolute const with the given value and type */
{
Expr->Sym = 0;
Expr->Type = Type;
Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL | (Expr->Flags & E_HAVE_MARKS);
Expr->Flags = E_LOC_NONE | E_RTYPE_RVAL | (Expr->Flags & E_HAVE_MARKS);
Expr->Name = 0;
Expr->IVal = Value;
Expr->FVal = FP_D_Make (0.0);
@ -182,11 +216,11 @@ ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type)
ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value)
/* Make Expr a constant integer expression with the given value */
/* Replace Expr with a constant integer expression with the given value */
{
Expr->Sym = 0;
Expr->Type = type_int;
Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL | (Expr->Flags & E_HAVE_MARKS);
Expr->Flags = E_LOC_NONE | E_RTYPE_RVAL | (Expr->Flags & E_HAVE_MARKS);
Expr->Name = 0;
Expr->IVal = Value;
Expr->FVal = FP_D_Make (0.0);
@ -195,14 +229,13 @@ ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value)
ExprDesc* ED_MakeRValExpr (ExprDesc* Expr)
/* Convert Expr into a rvalue which is in the primary register without an
** offset.
*/
ExprDesc* ED_FinalizeRValLoad (ExprDesc* Expr)
/* Finalize the result of LoadExpr to be an rvalue in the primary register */
{
Expr->Sym = 0;
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET);
Expr->Flags |= (E_LOC_EXPR | E_RTYPE_RVAL);
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_ADDRESS_OF);
Expr->Flags &= ~(E_NEED_TEST | E_CC_SET);
Expr->Flags |= (E_LOC_PRIMARY | E_RTYPE_RVAL);
Expr->Name = 0;
Expr->IVal = 0; /* No offset */
Expr->FVal = FP_D_Make (0.0);
@ -211,18 +244,106 @@ ExprDesc* ED_MakeRValExpr (ExprDesc* Expr)
ExprDesc* ED_MakeLValExpr (ExprDesc* Expr)
/* Convert Expr into a lvalue which is in the primary register without an
** offset.
ExprDesc* ED_AddrExpr (ExprDesc* Expr)
/* Take address of Expr. The result is always an rvalue */
{
switch (Expr->Flags & E_MASK_LOC) {
case E_LOC_NONE:
Error ("Cannot get the address of a numeric constant");
break;
case E_LOC_EXPR:
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE);
Expr->Flags |= E_LOC_PRIMARY | E_RTYPE_RVAL;
break;
default:
if ((Expr->Flags & E_ADDRESS_OF) == 0) {
Expr->Flags &= ~E_MASK_RTYPE;
Expr->Flags |= E_ADDRESS_OF | E_RTYPE_RVAL;
} else {
/* Due to the way we handle arrays, this may happen if we take
** the address of a pointer to an array element.
*/
if (!IsTypePtr (Expr->Type)) {
Error ("Cannot get the address of an address");
}
Expr->Flags &= ~E_MASK_RTYPE;
Expr->Flags |= E_RTYPE_RVAL;
}
break;
}
return Expr;
}
ExprDesc* ED_IndExpr (ExprDesc* Expr)
/* Dereference Expr */
{
switch (Expr->Flags & E_MASK_LOC) {
case E_LOC_NONE:
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE);
Expr->Flags |= E_LOC_ABS | E_RTYPE_LVAL;
break;
case E_LOC_PRIMARY:
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE);
Expr->Flags |= E_LOC_EXPR | E_RTYPE_LVAL;
break;
default:
if ((Expr->Flags & E_ADDRESS_OF) != 0) {
Expr->Flags &= ~(E_MASK_RTYPE | E_ADDRESS_OF);
Expr->Flags |= E_RTYPE_LVAL;
} else {
/* Due to the limitation of LoadExpr, this may happen after we
** have loaded the value from a referenced address, in which
** case the content in the primary no longer refers to the
** original address. We simply mark this as E_LOC_EXPR so that
** some info about the original location can be retained.
** If it's really meant to dereference a "pointer value", it
** should be done in two steps where the pointervalue should
** be the manually loaded first before a call into this, and
** the offset should be manually cleared somewhere outside.
*/
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE);
Expr->Flags |= E_LOC_EXPR | E_RTYPE_LVAL;
}
break;
}
return Expr;
}
#if !defined(HAVE_INLINE)
int ED_IsAbs (const ExprDesc* Expr)
/* Return true if the expression denotes a numeric value or address. */
{
return (Expr->Flags & (E_MASK_LOC)) == (E_LOC_NONE) ||
(Expr->Flags & (E_MASK_LOC|E_ADDRESS_OF)) == (E_LOC_ABS|E_ADDRESS_OF);
}
#endif
#if !defined(HAVE_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.
*/
{
Expr->Sym = 0;
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET);
Expr->Flags |= (E_LOC_EXPR | E_RTYPE_LVAL);
Expr->Name = 0;
Expr->IVal = 0; /* No offset */
Expr->FVal = FP_D_Make (0.0);
return Expr;
return ED_IsRVal (Expr) && ED_IsAbs (Expr);
}
#endif
int ED_IsConstAbsInt (const ExprDesc* Expr)
/* Return true if the expression is a constant (numeric) integer. */
{
return ED_IsConstAbs (Expr) && IsClassInt (Expr->Type);
}
@ -233,16 +354,27 @@ int ED_IsConst (const ExprDesc* Expr)
** similar.
*/
{
return ED_IsRVal (Expr) && (Expr->Flags & E_LOC_CONST) != 0;
return (Expr->Flags & E_MASK_LOC) == E_LOC_NONE || ED_IsConstAddr (Expr);
}
int ED_IsConstAbsInt (const ExprDesc* Expr)
/* Return true if the expression is a constant (numeric) integer. */
int ED_IsConstAddr (const ExprDesc* Expr)
/* Return true if the expression denotes a constant address of some sort. This
** can be the address of a global variable (maybe with offset) or similar.
*/
{
return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL) &&
IsClassInt (Expr->Type);
return ED_IsAddrExpr (Expr) && ED_IsLocConst (Expr);
}
int ED_IsQuasiConstAddr (const ExprDesc* Expr)
/* Return true if the expression denotes a quasi-constant address of some sort.
** This can be a constant address or a stack variable address.
*/
{
return ED_IsAddrExpr (Expr) && ED_IsLocQuasiConst (Expr);
}
@ -251,7 +383,7 @@ int ED_IsNullPtr (const ExprDesc* Expr)
/* Return true if the given expression is a NULL pointer constant */
{
return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE|E_BITFIELD)) ==
(E_LOC_ABS|E_RTYPE_RVAL) &&
(E_LOC_NONE|E_RTYPE_RVAL) &&
Expr->IVal == 0 &&
IsClassInt (Expr->Type);
}
@ -293,6 +425,11 @@ void PrintExprDesc (FILE* F, ExprDesc* E)
Flags = E->Flags;
Sep = '(';
fprintf (F, "Flags: 0x%04X ", Flags);
if ((Flags & E_MASK_LOC) == E_LOC_NONE) {
fprintf (F, "%cE_LOC_NONE", Sep);
Flags &= ~E_LOC_NONE;
Sep = ',';
}
if (Flags & E_LOC_ABS) {
fprintf (F, "%cE_LOC_ABS", Sep);
Flags &= ~E_LOC_ABS;
@ -353,6 +490,11 @@ void PrintExprDesc (FILE* F, ExprDesc* E)
Flags &= ~E_CC_SET;
Sep = ',';
}
if (Flags & E_ADDRESS_OF) {
fprintf (F, "%cE_ADDRESS_OF", Sep);
Flags &= ~E_ADDRESS_OF;
Sep = ',';
}
if (Flags) {
fprintf (F, "%c,0x%04X", Sep, Flags);
Sep = ',';

View File

@ -59,22 +59,57 @@
/* Defines for the flags field of the expression descriptor */
enum {
/* Location: Where is the value we're talking about? */
/* Location: Where is the value we're talking about?
**
** Remarks:
** - E_LOC_<else> refers to any other than E_LOC_NONE and E_LOC_PRIMARY.
** - E_LOC_EXPR can be regarded as a generalized E_LOC_<else>.
** - E_LOC_NONE can be regarded as E_LOC_PRIMARY + E_ADDRESS_OF unless
** remarked otherwise (see below).
** - An E_LOC_NONE value is not considered to be an "address".
** - ref-load doesn't change the location, while rval-load puts into the
** primary register a "temporary" that is the straight integer rvalue or
** a "delegate" to the real rvalue somewhere else.
** - ref-load doesn't change the rval/lval category of the expression,
** while rval-load converts it to an rvalue if it wasn't.
** - In practice, ref-load is unimplemented, and can be simulated with
** adding E_ADDRESS_OF temporaily through LoadExpr + FinalizeLoad,
** whilst val-load is done with LoadExpr + FinalizeRValLoad.
**
** E_LOC_NONE -- ref-load -> + E_LOADED (int rvalue)
** E_LOC_PRIMARY -- ref-load -> + E_LOADED (unchanged)
** E_LOC_<else> -- ref-load -> + E_LOADED (reference lvalue)
** + E_ADDRESS_OF -- ref-load -> + E_LOADED (address rvalue)
** E_LOC_NONE -- val-load -> E_LOC_PRIMARY (int rvalue)
** E_LOC_PRIMARY -- val-load -> E_LOC_PRIMARY (unchanged)
** E_LOC_<else> -- val-load -> E_LOC_PRIMARY (rvalue/delegate)
** + E_ADDRESS_OF -- val-load -> E_LOC_PRIMARY (address rvalue)
** E_LOC_NONE -- take address -> (error)
** E_LOC_PRIMARY -- take address -> + E_ADDRESS_OF (or error)
** E_LOC_EXPR -- take address -> E_LOC_PRIMARY (address)
** E_LOC_<else> -- take address -> + E_ADDRESS_OF (address)
** + E_ADDRESS_OF -- take address -> (error)
** E_LOC_NONE -- dereference -> E_LOC_ABS (lvalue reference)
** E_LOC_PRIMARY -- dereference -> E_LOC_EXPR (lvalue reference)
** E_LOC_<else> -- dereference -> E_LOC_EXPR (pointed-to-value, must load)
** + E_ADDRESS_OF -- dereference -> (lvalue reference)
*/
E_MASK_LOC = 0x00FF,
E_LOC_ABS = 0x0001, /* Absolute: numeric address or const */
E_LOC_NONE = 0x0000, /* Pure rvalue with no storage */
E_LOC_ABS = 0x0001, /* Absolute numeric addressed variable */
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_PRIMARY = 0x0020, /* Temporary in primary register */
E_LOC_EXPR = 0x0040, /* A location that the primary register points to */
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_CONST = E_LOC_NONE | E_LOC_ABS | E_LOC_GLOBAL | E_LOC_STATIC |
E_LOC_REGISTER | E_LOC_LITERAL,
/* Reference? */
/* lvalue/rvalue in C language's sense */
E_MASK_RTYPE = 0x0100,
E_RTYPE_RVAL = 0x0000,
E_RTYPE_LVAL = 0x0100,
@ -88,6 +123,10 @@ enum {
E_HAVE_MARKS = 0x1000, /* Code marks are valid */
E_LOADED = 0x4000, /* Expression is loaded in primary */
E_ADDRESS_OF = 0x8000, /* Expression is the address of the lvalue */
};
/* Forward */
@ -135,8 +174,18 @@ INLINE int ED_GetLoc (const ExprDesc* Expr)
#endif
#if defined(HAVE_INLINE)
INLINE int ED_IsLocAbs (const ExprDesc* Expr)
INLINE int ED_IsLocNone (const ExprDesc* Expr)
/* Return true if the expression is an absolute value */
{
return (Expr->Flags & E_MASK_LOC) == E_LOC_NONE;
}
#else
# define ED_IsLocNone(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_NONE)
#endif
#if defined(HAVE_INLINE)
INLINE int ED_IsLocAbs (const ExprDesc* Expr)
/* Return true if the expression is referenced with an absolute address */
{
return (Expr->Flags & E_MASK_LOC) == E_LOC_ABS;
}
@ -151,7 +200,7 @@ INLINE int ED_IsLocRegister (const ExprDesc* Expr)
return (Expr->Flags & E_MASK_LOC) == E_LOC_REGISTER;
}
#else
# define ED_IsLocRegister(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_REGISTER)
# define ED_IsLocRegister(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_REGISTER)
#endif
#if defined(HAVE_INLINE)
@ -198,50 +247,25 @@ INLINE int ED_IsLocLiteral (const ExprDesc* Expr)
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;
return ((Expr)->Flags & E_MASK_LOC & ~E_LOC_CONST) == 0;
}
#else
# define ED_IsLocConst(Expr) (((Expr)->Flags & E_LOC_CONST) != 0)
# define ED_IsLocConst(Expr) (((Expr)->Flags & E_MASK_LOC & ~E_LOC_CONST) == 0)
#endif
#if defined(HAVE_INLINE)
INLINE int ED_IsLVal (const ExprDesc* Expr)
/* Return true if the expression is a reference */
INLINE int ED_IsLocQuasiConst (const ExprDesc* Expr)
/* Return true if the expression is a constant location of some sort or on the
** stack.
*/
{
return (Expr->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL;
return ED_IsLocConst (Expr) || ED_IsLocStack (Expr);
}
#else
# 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_MASK_RTYPE) == E_RTYPE_RVAL;
}
#else
# define ED_IsRVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_MakeLVal (ExprDesc* Expr)
/* Make the expression a lvalue. */
{
Expr->Flags |= E_RTYPE_LVAL;
}
#else
# define ED_MakeLVal(Expr) do { (Expr)->Flags |= E_RTYPE_LVAL; } while (0)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_MakeRVal (ExprDesc* Expr)
/* Make the expression a rvalue. */
{
Expr->Flags &= ~E_RTYPE_LVAL;
}
#else
# define ED_MakeRVal(Expr) do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0)
int ED_IsLocQuasiConst (const ExprDesc* Expr);
/* Return true if the expression denotes a constant address of some sort. This
** can be the address of a global variable (maybe with offset) or similar.
*/
#endif
#if defined(HAVE_INLINE)
@ -308,6 +332,52 @@ INLINE void ED_MarkAsUntested (ExprDesc* Expr)
# define ED_MarkAsUntested(Expr) do { (Expr)->Flags &= ~E_CC_SET; } while (0)
#endif
#if defined(HAVE_INLINE)
INLINE int ED_IsLoaded (const ExprDesc* Expr)
/* Check if the expression is loaded.
** NOTE: This is currently unused and not working due to code complexity.
*/
{
return (Expr->Flags & E_LOADED) != 0;
}
#else
# define ED_IsLoaded(Expr) (((Expr)->Flags & E_LOADED) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
{
return ED_IsLocPrimary (Expr) || ED_IsLocExpr (Expr);
}
#else
int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr);
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
#endif
#if defined(HAVE_INLINE)
INLINE int ED_IsAddrExpr (const ExprDesc* Expr)
/* Check if the expression is taken address of instead of its value.
*/
{
return (Expr->Flags & E_ADDRESS_OF) != 0;
}
#else
# define ED_IsAddrExpr(Expr) (((Expr)->Flags & E_ADDRESS_OF) != 0)
#endif
#if defined(HAVE_INLINE)
INLINE int ED_IsIndExpr (const ExprDesc* Expr)
/* Check if the expression is a reference to its value */
{
return (Expr->Flags & E_ADDRESS_OF) == 0 &&
!ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr);
}
#else
int ED_IsIndExpr (const ExprDesc* Expr);
/* Check if the expression is a reference to its value */
#endif
void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End);
/* Set the code range for this expression */
@ -326,26 +396,79 @@ int ED_GetStackOffs (const ExprDesc* Expr, int Offs);
*/
ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type);
/* Make Expr an absolute const with the given value and type. */
/* Replace Expr with 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 */
/* Replace Expr with an constant integer 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_FinalizeRValLoad (ExprDesc* Expr);
/* Finalize the result of LoadExpr to be an rvalue in the primary register */
ExprDesc* ED_MakeLValExpr (ExprDesc* Expr);
/* Convert Expr into a lvalue which is in the primary register without an
** offset.
*/
#if defined(HAVE_INLINE)
INLINE int ED_IsLVal (const ExprDesc* Expr)
/* Return true if the expression is a reference */
{
return ((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL;
}
#else
# define ED_IsLVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL)
#endif
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_IsRVal (const ExprDesc* Expr)
/* Return true if the expression is an rvalue */
{
return ((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL;
}
#else
# define ED_IsRVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_MarkExprAsLVal (ExprDesc* Expr)
/* Mark the expression as an lvalue.
** HINT: Consider using ED_IndExpr instead of this, unless you know what
** consequence there will be, as there are both a big part in the code
** assuming rvalue = const and a big part assuming rvalue = address.
*/
{
Expr->Flags |= E_RTYPE_LVAL;
}
#else
# define ED_MarkExprAsLVal(Expr) do { (Expr)->Flags |= E_RTYPE_LVAL; } while (0)
#endif
#if defined(HAVE_INLINE)
INLINE void ED_MarkExprAsRVal (ExprDesc* Expr)
/* Mark the expression as an rvalue.
** HINT: Consider using ED_AddrExpr instead of this, unless you know what
** consequence there will be, as there are both a big part in the code
** assuming rvalue = const and a big part assuming rvalue = address.
*/
{
Expr->Flags &= ~E_RTYPE_LVAL;
}
#else
# define ED_MarkExprAsRVal(Expr) do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0)
#endif
ExprDesc* ED_AddrExpr (ExprDesc* Expr);
/* Take address of Expr */
ExprDesc* ED_IndExpr (ExprDesc* Expr);
/* Dereference Expr */
#if defined(HAVE_INLINE)
INLINE int ED_IsAbs (const ExprDesc* Expr)
/* Return true if the expression denotes a numeric value or address. */
{
return (Expr->Flags & (E_MASK_LOC)) == (E_LOC_NONE) ||
(Expr->Flags & (E_MASK_LOC|E_ADDRESS_OF)) == (E_LOC_ABS|E_ADDRESS_OF);
}
#else
int ED_IsAbs (const ExprDesc* Expr);
/* Return true if the expression denotes a numeric value or address. */
#endif
#if defined(HAVE_INLINE)
INLINE int ED_IsConstAbs (const ExprDesc* Expr)
@ -353,16 +476,34 @@ INLINE int ED_IsConstAbs (const ExprDesc* Expr)
** a numeric constant, cast to any type.
*/
{
return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL);
return ED_IsRVal (Expr) && ED_IsAbs (Expr);
}
#else
# define ED_IsConstAbs(E) \
(((E)->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL))
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.
*/
#endif
int ED_IsConstAbsInt (const ExprDesc* Expr);
/* Return true if the expression is a constant (numeric) integer. */
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.
*/
int ED_IsConstAddr (const ExprDesc* Expr);
/* Return true if the expression denotes a constant address of some sort. This
** can be the address of a global variable (maybe with offset) or similar.
*/
int ED_IsQuasiConstAddr (const ExprDesc* Expr);
/* Return true if the expression denotes a quasi-constant address of some sort.
** This can be a constant address or a stack variable address.
*/
int ED_IsNullPtr (const ExprDesc* Expr);
/* Return true if the given expression is a NULL pointer constant */

View File

@ -48,14 +48,14 @@
static void LoadConstant (unsigned Flags, ExprDesc* Expr)
/* Load the primary register with some constant value. */
static void LoadAddress (unsigned Flags, ExprDesc* Expr)
/* Load the primary register with some address value. */
{
switch (ED_GetLoc (Expr)) {
case E_LOC_ABS:
/* Number constant */
g_getimmed (Flags | TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
/* Numberic address */
g_getimmed (Flags | CF_IMM | CF_CONST, Expr->IVal, 0);
break;
case E_LOC_GLOBAL:
@ -83,25 +83,38 @@ static void LoadConstant (unsigned Flags, ExprDesc* Expr)
g_leasp (Expr->IVal);
break;
case E_LOC_EXPR:
if (Expr->IVal != 0) {
/* We have an expression in the primary plus a constant
** offset. Adjust the value in the primary accordingly.
*/
g_inc (Flags | CF_CONST, Expr->IVal);
}
break;
default:
Internal ("Unknown constant type: %04X", Expr->Flags);
Internal ("Unknown address type: %04X", Expr->Flags);
}
}
void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
/* Load an expression into the primary register if it is not already there. */
/* Load an expression into the primary register if it is not already there.
** Note: This function can't modify the content in Expr since there are many
** instances of the "GetCodePos + LoadExpr (maybe indirectly) + RemoveCode"
** code pattern here and there which assumes that Expr should be unchanged,
** unfortunately.
*/
{
if (ED_IsLVal (Expr)) {
if (!ED_IsAddrExpr (Expr)) {
/* Dereferenced lvalue. If this is a bit field its type is unsigned.
** But if the field is completely contained in the lower byte, we will
** throw away the high byte anyway and may therefore load just the
** low byte.
/* Lvalue. If this is a bit field its type is unsigned. But if the
** field is completely contained in the lower byte, we will throw away
** the high byte anyway and may therefore load just the low byte.
*/
if (ED_IsBitField (Expr)) {
Flags |= (Expr->BitOffs + Expr->BitWidth <= CHAR_BITS)? CF_CHAR : CF_INT;
Flags |= (Expr->BitOffs + Expr->BitWidth <= CHAR_BITS) ? CF_CHAR : CF_INT;
Flags |= CF_UNSIGNED;
} else {
Flags |= TypeOf (Expr->Type);
@ -110,10 +123,16 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
Flags |= CF_TEST;
}
/* Load the content of Expr */
switch (ED_GetLoc (Expr)) {
case E_LOC_NONE:
/* Immediate number constant */
g_getimmed (Flags | CF_IMM | TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
break;
case E_LOC_ABS:
/* Absolute: numeric address or const */
/* Absolute numeric addressed variable */
g_getstatic (Flags | CF_ABSOLUTE, Expr->IVal, 0);
break;
@ -139,7 +158,15 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
break;
case E_LOC_PRIMARY:
/* The primary register - just test if necessary */
/* The primary register */
if (Expr->IVal != 0) {
/* We have an expression in the primary plus a constant
** offset. Adjust the value in the primary accordingly.
*/
g_inc (Flags | CF_CONST, Expr->IVal);
/* We might want to clear the offset, but we can't */
}
if (Flags & CF_TEST) {
g_test (Flags);
}
@ -148,6 +175,13 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
case E_LOC_EXPR:
/* Reference to address in primary with offset in Expr */
g_getind (Flags, Expr->IVal);
/* Since the content in primary is now overwritten with the
** dereference value, we might want to change the expression
** loc to E_LOC_PRIMARY as well. That way we could be able to
** call this function as many times as we want. Unfortunately,
** we can't.
*/
break;
default:
@ -173,24 +207,14 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
ED_TestDone (Expr);
} else {
/* An rvalue */
if (ED_IsLocExpr (Expr)) {
if (Expr->IVal != 0) {
/* We have an expression in the primary plus a constant
** offset. Adjust the value in the primary accordingly.
*/
Flags |= TypeOf (Expr->Type);
g_inc (Flags | CF_CONST, Expr->IVal);
}
} else {
/* Constant of some sort, load it into the primary */
LoadConstant (Flags, Expr);
}
/* An address */
Flags |= CF_INT | CF_UNSIGNED;
/* Constant of some sort, load it into the primary */
LoadAddress (Flags, Expr);
/* Are we testing this value? */
if (ED_NeedsTest (Expr)) {
/* Yes, force a test */
Flags |= TypeOf (Expr->Type);
g_test (Flags);
ED_TestDone (Expr);
}

View File

@ -260,7 +260,7 @@ static void ParseAutoDecl (Declaration* Decl)
Flags |= CF_CONST;
} else {
LoadExpr (CF_NONE, &Expr);
ED_MakeRVal (&Expr);
ED_MarkExprAsRVal (&Expr);
}
/* Push the value */

View File

@ -173,8 +173,8 @@ void ShiftExpr (struct ExprDesc* Expr)
goto Next;
}
/* If we're shifting an integer or unsigned to the right, the
** lhs has a const address, and the shift count is larger than 8,
/* If we're shifting an integer or unsigned to the right, the lhs
** has a quasi-const address, and the shift count is larger than 8,
** we can load just the high byte as a char with the correct
** signedness, and reduce the shift count by 8. If the remaining
** shift count is zero, we're done.
@ -182,7 +182,7 @@ void ShiftExpr (struct ExprDesc* Expr)
if (Tok == TOK_SHR &&
IsTypeInt (Expr->Type) &&
ED_IsLVal (Expr) &&
(ED_IsLocConst (Expr) || ED_IsLocStack (Expr)) &&
ED_IsLocQuasiConst (Expr) &&
Expr2.IVal >= 8) {
Type* OldType;
@ -227,8 +227,8 @@ void ShiftExpr (struct ExprDesc* Expr)
}
MakeRVal:
/* We have a rvalue in the primary now */
ED_MakeRValExpr (Expr);
/* We have an rvalue in the primary now */
ED_FinalizeRValLoad (Expr);
Next:
/* Set the type of the result */

View File

@ -343,7 +343,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
** address calculation could overflow in the linker.
*/
int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) &&
!(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
!(ED_IsLocNone (&Arg2.Expr) && Arg2.Expr.IVal < 256);
/* Calculate the real stack offset */
Offs = ED_GetStackOffs (&Arg1.Expr, 0);
@ -421,7 +421,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
** address calculation could overflow in the linker.
*/
int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) &&
!(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
!(ED_IsLocNone (&Arg1.Expr) && Arg1.Expr.IVal < 256);
/* Calculate the real stack offset */
Offs = ED_GetStackOffs (&Arg2.Expr, 0);
@ -520,7 +520,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
AddCodeLine ("lda ptr1");
/* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type);
/* Bail out, no need for further processing */
@ -529,7 +529,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
}
/* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type);
ExitPoint:
@ -743,7 +743,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
AddCodeLine ("lda ptr1");
/* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type);
/* Bail out, no need for further processing */
@ -752,7 +752,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
}
/* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type);
ExitPoint:
@ -955,7 +955,7 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
}
/* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type);
/* We expect the closing brace */
@ -1069,7 +1069,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
** address calculation could overflow in the linker.
*/
int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) &&
!(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
!(ED_IsLocNone (&Arg1.Expr) && Arg1.Expr.IVal < 256);
/* Calculate the real stack offset */
int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
@ -1116,7 +1116,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
** address calculation could overflow in the linker.
*/
int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) &&
!(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
!(ED_IsLocNone (&Arg2.Expr) && Arg2.Expr.IVal < 256);
/* Calculate the real stack offset */
int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
@ -1153,7 +1153,7 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
}
/* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type);
ExitPoint:
@ -1250,7 +1250,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
AddCodeLine ("tya");
/* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
Expr->Type = type_size_t;
/* Bail out, no need for further processing */
@ -1279,7 +1279,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
AddCodeLine ("ldx #$00");
/* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
Expr->Type = type_size_t;
/* Bail out, no need for further processing */
@ -1304,7 +1304,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
AddCodeLine ("tya");
/* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
Expr->Type = type_size_t;
/* Bail out, no need for further processing */
@ -1333,7 +1333,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
AddCodeLine ("tya");
/* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
Expr->Type = type_size_t;
/* Bail out, no need for further processing */
@ -1348,7 +1348,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
AddCodeLine ("jsr _%s", Func_strlen);
/* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
Expr->Type = type_size_t;
ExitPoint:

View File

@ -70,7 +70,7 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType)
** conversion void -> void.
*/
if (IsTypeVoid (NewType)) {
ED_MakeRVal (Expr); /* Never an lvalue */
ED_MarkExprAsRVal (Expr); /* Never an lvalue */
goto ExitPoint;
}
@ -105,10 +105,10 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType)
g_typecast (TypeOf (NewType), TypeOf (OldType) | CF_FORCECHAR);
/* Value is now in primary and an rvalue */
ED_MakeRValExpr (Expr);
ED_FinalizeRValLoad (Expr);
}
} else if (ED_IsLocAbs (Expr)) {
} else if (ED_IsConstAbs (Expr)) {
/* A cast of a constant numeric value to another type. Be sure
** to handle sign extension correctly.
@ -136,6 +136,15 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType)
}
}
/* Do the integer constant <-> absolute address conversion if necessary */
if (IsClassPtr (NewType)) {
Expr->Flags &= ~E_LOC_NONE;
Expr->Flags |= E_LOC_ABS | E_ADDRESS_OF;
} else if (IsClassInt (NewType)) {
Expr->Flags &= ~(E_LOC_ABS | E_ADDRESS_OF);
Expr->Flags |= E_LOC_NONE;
}
} else {
/* The value is not a constant. If the sizes of the types are
@ -150,8 +159,8 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType)
/* Emit typecast code. */
g_typecast (TypeOf (NewType), TypeOf (OldType) | CF_FORCECHAR);
/* Value is now a rvalue in the primary */
ED_MakeRValExpr (Expr);
/* Value is now an rvalue in the primary */
ED_FinalizeRValLoad (Expr);
}
}