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) { if (UseReg) {
PushAddr (Expr); PushAddr (Expr);
} else { } else {
ED_MakeRVal (Expr); ED_MarkExprAsRVal (Expr);
LoadExpr (CF_NONE, Expr); LoadExpr (CF_NONE, Expr);
g_push (CF_PTR | CF_UNSIGNED, 0); g_push (CF_PTR | CF_UNSIGNED, 0);
} }
@@ -127,7 +127,7 @@ void Assignment (ExprDesc* Expr)
} else { } else {
/* We will use memcpy. Push the address of the rhs */ /* We will use memcpy. Push the address of the rhs */
ED_MakeRVal (&Expr2); ED_MarkExprAsRVal (&Expr2);
LoadExpr (CF_NONE, &Expr2); LoadExpr (CF_NONE, &Expr2);
/* Push the address (or whatever is in ax in case of errors) */ /* 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 */ /* 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 */ /* Create the correct label name */
switch (Flags & CF_ADDRMASK) { switch (Flags & CF_ADDRMASK) {
case CF_IMM:
/* Immediate constant values */
xsprintf (Buf, sizeof (Buf), "$%04X", (unsigned)((Offs) & 0xFFFF));
break;
case CF_STATIC: case CF_STATIC:
/* Static memory cell */ /* Static memory cell */
if (Offs) { if (Offs) {

View File

@@ -81,11 +81,12 @@
#define CF_TEST 0x0080 /* Test value */ #define CF_TEST 0x0080 /* Test value */
#define CF_FIXARGC 0x0100 /* Function has fixed arg count */ #define CF_FIXARGC 0x0100 /* Function has fixed arg count */
#define CF_FORCECHAR 0x0200 /* Handle chars as chars, not ints */ #define CF_FORCECHAR 0x0200 /* Handle chars as chars, not ints */
#define CF_REG 0x0800 /* Value is in primary register */
/* Type of static address */ /* Type of static address */
#define CF_ADDRMASK 0xF000 /* Type of address */ #define CF_ADDRMASK 0xFC00 /* Type of address */
#define CF_STATIC 0x0000 /* Static local */ #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_EXTERNAL 0x1000 /* Static external */
#define CF_ABSOLUTE 0x2000 /* Numeric absolute address */ #define CF_ABSOLUTE 0x2000 /* Numeric absolute address */
#define CF_LOCAL 0x4000 /* Auto variable */ #define CF_LOCAL 0x4000 /* Auto variable */

View File

@@ -1773,9 +1773,14 @@ static void DefineData (ExprDesc* Expr)
{ {
switch (ED_GetLoc (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: case E_LOC_ABS:
/* Absolute: numeric address or const */ /* Absolute numeric address */
g_defdata (TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0); g_defdata (CF_ABSOLUTE | TypeOf(Expr->Type) | CF_CONST, Expr->IVal, 0);
break; break;
case E_LOC_GLOBAL: 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 */ /* Return the addressing mode flags for the given expression */
{ {
switch (ED_GetLoc (Expr)) { switch (ED_GetLoc (Expr)) {
case E_LOC_NONE: return CF_IMM;
case E_LOC_ABS: return CF_ABSOLUTE; case E_LOC_ABS: return CF_ABSOLUTE;
case E_LOC_GLOBAL: return CF_EXTERNAL; case E_LOC_GLOBAL: return CF_EXTERNAL;
case E_LOC_STATIC: return CF_STATIC; 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 */ /* Generate type adjustment code if needed */
ltype = TypeOf (lhst); ltype = TypeOf (lhst);
if (ED_IsLocAbs (lhs)) { if (ED_IsLocNone (lhs)) {
ltype |= CF_CONST; ltype |= CF_CONST;
} }
if (NoPush) { if (NoPush) {
@@ -191,7 +192,7 @@ static unsigned typeadjust (ExprDesc* lhs, ExprDesc* rhs, int NoPush)
ltype |= CF_REG; ltype |= CF_REG;
} }
rtype = TypeOf (rhst); rtype = TypeOf (rhst);
if (ED_IsLocAbs (rhs)) { if (ED_IsLocNone (rhs)) {
rtype |= CF_CONST; rtype |= CF_CONST;
} }
flags = g_typeadjust (ltype, rtype); 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. ** the pointer into the primary and mark it as an expression.
*/ */
LoadExpr (CF_NONE, Expr); LoadExpr (CF_NONE, Expr);
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
/* Remember the code position */ /* Remember the code position */
GetCodePos (&Mark); GetCodePos (&Mark);
@@ -646,7 +647,7 @@ static void FunctionCall (ExprDesc* Expr)
} }
/* The function result is an rvalue in the primary register */ /* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type); Expr->Type = GetFuncReturn (Expr->Type);
} }
@@ -663,7 +664,7 @@ static void Primary (ExprDesc* E)
/* Character and integer constants. */ /* Character and integer constants. */
if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) { if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
E->IVal = CurTok.IVal; E->IVal = CurTok.IVal;
E->Flags = E_LOC_ABS | E_RTYPE_RVAL; E->Flags = E_LOC_NONE | E_RTYPE_RVAL;
E->Type = CurTok.Type; E->Type = CurTok.Type;
NextToken (); NextToken ();
return; return;
@@ -672,7 +673,7 @@ static void Primary (ExprDesc* E)
/* Floating point constant */ /* Floating point constant */
if (CurTok.Tok == TOK_FCONST) { if (CurTok.Tok == TOK_FCONST) {
E->FVal = CurTok.FVal; E->FVal = CurTok.FVal;
E->Flags = E_LOC_ABS | E_RTYPE_RVAL; E->Flags = E_LOC_NONE | E_RTYPE_RVAL;
E->Type = CurTok.Type; E->Type = CurTok.Type;
NextToken (); NextToken ();
return; return;
@@ -716,7 +717,7 @@ static void Primary (ExprDesc* E)
NextToken (); NextToken ();
Entry = AddLabelSym (CurTok.Ident, SC_REF | SC_GOTO_IND); Entry = AddLabelSym (CurTok.Ident, SC_REF | SC_GOTO_IND);
/* output its label */ /* 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->Name = Entry->V.L.Label;
E->Type = PointerTo (type_void); E->Type = PointerTo (type_void);
NextToken (); NextToken ();
@@ -756,7 +757,7 @@ static void Primary (ExprDesc* E)
/* Check for legal symbol types */ /* Check for legal symbol types */
if ((Sym->Flags & SC_CONST) == SC_CONST) { if ((Sym->Flags & SC_CONST) == SC_CONST) {
/* Enum or some other numeric constant */ /* 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; E->IVal = Sym->V.ConstVal;
} else if ((Sym->Flags & SC_FUNC) == SC_FUNC) { } else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
/* Function */ /* Function */
@@ -797,12 +798,12 @@ static void Primary (ExprDesc* E)
/* We've made all variables lvalues above. However, this is /* We've made all variables lvalues above. However, this is
** not always correct: An array is actually the address of its ** 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. ** rvalue, too, because we cannot store anything in a function.
** So fix the flags depending on the type. ** So fix the flags depending on the type.
*/ */
if (IsTypeArray (E->Type) || IsTypeFunc (E->Type)) { if (IsTypeArray (E->Type) || IsTypeFunc (E->Type)) {
ED_MakeRVal (E); ED_AddrExpr (E);
} }
} else { } else {
@@ -845,7 +846,7 @@ static void Primary (ExprDesc* E)
/* String literal */ /* String literal */
E->LVal = UseLiteral (CurTok.SVal); E->LVal = UseLiteral (CurTok.SVal);
E->Type = GetCharArrayType (GetLiteralSize (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->IVal = 0;
E->Name = GetLiteralLabel (CurTok.SVal); E->Name = GetLiteralLabel (CurTok.SVal);
NextToken (); NextToken ();
@@ -854,7 +855,7 @@ static void Primary (ExprDesc* E)
case TOK_ASM: case TOK_ASM:
/* ASM statement */ /* ASM statement */
AsmStatement (); AsmStatement ();
E->Flags = E_LOC_EXPR | E_RTYPE_RVAL; E->Flags = E_RTYPE_RVAL;
E->Type = type_void; E->Type = type_void;
break; break;
@@ -912,12 +913,11 @@ static void ArrayRef (ExprDesc* Expr)
/* We can apply a special treatment for arrays that have a const base /* 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 ** 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) && ConstBaseAddr = ED_IsRVal (Expr) && ED_IsLocQuasiConst (Expr);
(ED_IsLocConst (Expr) || ED_IsLocStack (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); GetCodePos (&Mark1);
if (!ConstBaseAddr) { if (!ConstBaseAddr) {
/* Get a pointer to the array into the primary */ /* 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 the subscript is a bit-field, load it and make it an rvalue */
if (ED_IsBitField (&Subscript)) { if (ED_IsBitField (&Subscript)) {
LoadExpr (CF_NONE, &Subscript); LoadExpr (CF_NONE, &Subscript);
ED_MakeRValExpr (&Subscript); ED_FinalizeRValLoad (&Subscript);
} }
/* Check if the subscript is constant absolute value */ /* 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 ** already in Expr. If the base address was a constant, we can even
** remove the code that loaded the address into the primary. ** remove the code that loaded the address into the primary.
*/ */
if (IsTypeArray (Expr->Type)) { if (!IsTypeArray (Expr->Type)) {
/* Adjust the offset */
Expr->IVal += Subscript.IVal;
} else {
/* It's a pointer, so we do have to load it into the primary /* It's a pointer, so we do have to load it into the primary
** first (if it's not already there). ** first (if it's not already there).
*/ */
if (ConstBaseAddr || ED_IsLVal (Expr)) { if (!ConstBaseAddr && ED_IsLVal (Expr)) {
LoadExpr (CF_NONE, 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 { } else {
/* Scale the rhs value according to the element type */ /* 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 ** subscript was not scaled, that is, if this was a byte array
** or pointer. ** or pointer.
*/ */
if ((ED_IsLocConst (&Subscript) || ED_IsLocStack (&Subscript)) && if (ED_IsLocQuasiConst (&Subscript) &&
CheckedSizeOf (ElementType) == SIZEOF_CHAR) { CheckedSizeOf (ElementType) == SIZEOF_CHAR) {
unsigned Flags; unsigned Flags;
@@ -1131,12 +1127,13 @@ static void ArrayRef (ExprDesc* Expr)
} }
} else { } else {
if (ED_IsLocAbs (Expr)) { if (ED_IsLocNone (Expr) ||
(ED_IsLocAbs (Expr) && ED_IsAddrExpr (Expr))) {
/* Constant numeric address. Just add it */ /* Constant numeric address. Just add it */
g_inc (CF_INT, Expr->IVal); g_inc (CF_INT, Expr->IVal);
} else if (ED_IsLocStack (Expr)) { } else if (ED_IsLocStack (Expr)) {
/* Base address is a local variable address */ /* Base address is a local variable address */
if (IsTypeArray (Expr->Type)) { if (ED_IsAddrExpr (Expr)) {
g_addaddr_local (CF_INT, Expr->IVal); g_addaddr_local (CF_INT, Expr->IVal);
} else { } else {
g_addlocal (CF_PTR, Expr->IVal); g_addlocal (CF_PTR, Expr->IVal);
@@ -1144,7 +1141,7 @@ static void ArrayRef (ExprDesc* Expr)
} else { } else {
/* Base address is a static variable address */ /* Base address is a static variable address */
unsigned Flags = CF_INT | GlobalModeFlags (Expr); unsigned Flags = CF_INT | GlobalModeFlags (Expr);
if (ED_IsRVal (Expr)) { if (ED_IsAddrExpr (Expr)) {
/* Add the address of the location */ /* Add the address of the location */
g_addaddr_static (Flags, Expr->Name, Expr->IVal); g_addaddr_static (Flags, Expr->Name, Expr->IVal);
} else { } else {
@@ -1153,27 +1150,27 @@ static void ArrayRef (ExprDesc* Expr)
} }
} }
} }
} }
/* The result is an expression in the primary */ /* The pointer is an rvalue in the primary */
ED_MakeRValExpr (Expr); 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; Expr->Type = ElementType;
/* An array element is actually a variable. So the rules for variables /* An array element is actually a variable. So the rules for variables with
** with respect to the reference type apply: If it's an array, it is ** respect to the reference type apply: If it's an array, it is virtually
** a rvalue, otherwise it's an lvalue. (A function would also be a rvalue, ** an rvalue address, otherwise it's an lvalue reference. (A function would
** but an array cannot contain functions). ** also be an rvalue address, but an array cannot contain functions).
*/ */
if (IsTypeArray (Expr->Type)) { if (IsTypeArray (Expr->Type)) {
ED_MakeRVal (Expr); ED_AddrExpr (Expr);
} else {
ED_MakeLVal (Expr);
} }
/* Consume the closing bracket */ /* Consume the closing bracket */
@@ -1210,16 +1207,26 @@ static void StructRef (ExprDesc* Expr)
return; return;
} }
/* If we have a struct pointer that is an lvalue and not already in the if (IsTypePtr (Expr->Type)) {
** primary, load it now. /* If we have a struct pointer that is an lvalue and not already in the
*/ ** primary, load its content now.
if (ED_IsLVal (Expr) && IsTypePtr (Expr->Type)) { */
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); 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 */ /* 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; FinalType->C |= Q;
} }
/* A struct is usually an lvalue. If not, it is a struct in the primary /* A struct is usually an lvalue. If not, it is a struct referenced in the
** register. ** primary register, which is likely to be returned from a function.
*/ */
if (ED_IsRVal (Expr) && ED_IsLocExpr (Expr) && !IsTypePtr (Expr->Type)) { 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 /* 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 ** 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, ** virtually an rvalue address, otherwise it's an lvalue reference. (A
** but a struct field cannot be a function). ** function would also be an rvalue address, but a struct field cannot
** contain functions).
*/ */
if (IsTypeArray (Expr->Type)) { if (IsTypeArray (Expr->Type)) {
ED_MakeRVal (Expr); ED_AddrExpr (Expr);
} else {
ED_MakeLVal (Expr);
} }
/* Make the expression a bit field if necessary */ /* Make the expression a bit field if necessary */
@@ -1391,7 +1397,7 @@ void Store (ExprDesc* Expr, const Type* StoreType)
switch (ED_GetLoc (Expr)) { switch (ED_GetLoc (Expr)) {
case E_LOC_ABS: case E_LOC_ABS:
/* Absolute: numeric address or const */ /* Absolute numeric addressed variable */
g_putstatic (Flags, Expr->IVal, 0); g_putstatic (Flags, Expr->IVal, 0);
break; break;
@@ -1421,10 +1427,14 @@ void Store (ExprDesc* Expr, const Type* StoreType)
break; break;
case E_LOC_EXPR: case E_LOC_EXPR:
/* An expression in the primary register */ /* An expression referenced in the primary register */
g_putind (Flags, Expr->IVal); g_putind (Flags, Expr->IVal);
break; break;
case E_LOC_NONE:
/* We may get here as a result of previous compiler errors */
break;
default: default:
Internal ("Invalid location in Store(): 0x%04X", ED_GetLoc (Expr)); Internal ("Invalid location in Store(): 0x%04X", ED_GetLoc (Expr));
} }
@@ -1466,7 +1476,7 @@ static void PreInc (ExprDesc* Expr)
switch (ED_GetLoc (Expr)) { switch (ED_GetLoc (Expr)) {
case E_LOC_ABS: case E_LOC_ABS:
/* Absolute: numeric address or const */ /* Absolute numeric addressed variable */
g_addeqstatic (Flags, Expr->IVal, 0, Val); g_addeqstatic (Flags, Expr->IVal, 0, Val);
break; break;
@@ -1497,7 +1507,7 @@ static void PreInc (ExprDesc* Expr)
break; break;
case E_LOC_EXPR: case E_LOC_EXPR:
/* An expression in the primary register */ /* An expression referenced in the primary register */
g_addeqind (Flags, Expr->IVal, Val); g_addeqind (Flags, Expr->IVal, Val);
break; break;
@@ -1506,7 +1516,7 @@ static void PreInc (ExprDesc* Expr)
} }
/* Result is an expression, no reference */ /* 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)) { switch (ED_GetLoc (Expr)) {
case E_LOC_ABS: case E_LOC_ABS:
/* Absolute: numeric address or const */ /* Absolute numeric addressed variable */
g_subeqstatic (Flags, Expr->IVal, 0, Val); g_subeqstatic (Flags, Expr->IVal, 0, Val);
break; break;
@@ -1582,7 +1592,7 @@ static void PreDec (ExprDesc* Expr)
} }
/* Result is an expression, no reference */ /* 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 */ /* 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 */ /* 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); default: Internal ("Unexpected token: %d", Tok);
} }
/* The result is a rvalue in the primary */ /* The result is an rvalue in the primary */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
} }
} }
@@ -1776,7 +1786,7 @@ void hie10 (ExprDesc* Expr)
Expr->IVal = !Expr->IVal; Expr->IVal = !Expr->IVal;
} else { } else {
g_bneg (TypeOf (Expr->Type)); g_bneg (TypeOf (Expr->Type));
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
ED_TestDone (Expr); /* bneg will set cc */ ED_TestDone (Expr); /* bneg will set cc */
} }
break; break;
@@ -1784,13 +1794,14 @@ void hie10 (ExprDesc* Expr)
case TOK_STAR: case TOK_STAR:
NextToken (); NextToken ();
ExprWithCheck (hie10, Expr); ExprWithCheck (hie10, Expr);
if (ED_IsLVal (Expr) || !(ED_IsLocConst (Expr) || ED_IsLocStack (Expr))) { if (ED_IsLVal (Expr) || !ED_IsLocQuasiConst (Expr)) {
/* Not a const, load it into the primary and make it a /* Not a const, load the pointer into the primary and make it a
** calculated value. ** calculated value.
*/ */
LoadExpr (CF_NONE, Expr); LoadExpr (CF_NONE, Expr);
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
} }
/* If the expression is already a pointer to function, the /* If the expression is already a pointer to function, the
** additional dereferencing operator must be ignored. A function ** additional dereferencing operator must be ignored. A function
** itself is represented as "pointer to function", so any number ** 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)) { if (IsTypeFuncPtr (Expr->Type) || IsTypeFunc (Expr->Type)) {
/* Expression not storable */ /* Expression not storable */
ED_MakeRVal (Expr); ED_MarkExprAsRVal (Expr);
} else { } else {
if (IsClassPtr (Expr->Type)) { if (IsClassPtr (Expr->Type)) {
Expr->Type = Indirect (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. ** address -- it already is the location of the first element.
*/ */
if (!IsTypeArray (Expr->Type)) { if (!IsTypeArray (Expr->Type)) {
/* The * operator yields an lvalue */ /* The * operator yields an lvalue reference */
ED_MakeLVal (Expr); ED_IndExpr (Expr);
} }
} }
break; break;
@@ -1831,8 +1842,8 @@ void hie10 (ExprDesc* Expr)
Expr->Flags &= ~E_BITFIELD; Expr->Flags &= ~E_BITFIELD;
} }
Expr->Type = PointerTo (Expr->Type); Expr->Type = PointerTo (Expr->Type);
/* The & operator yields an rvalue */ /* The & operator yields an rvalue address */
ED_MakeRVal (Expr); ED_AddrExpr (Expr);
} }
break; break;
@@ -2067,8 +2078,8 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */
/* Generate code */ /* Generate code */
Gen->Func (type, Expr->IVal); Gen->Func (type, Expr->IVal);
/* We have a rvalue in the primary now */ /* We have an rvalue in the primary now */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
} else { } else {
@@ -2100,8 +2111,8 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */
/* Generate code */ /* Generate code */
Gen->Func (type, Expr2.IVal); Gen->Func (type, Expr2.IVal);
/* We have a rvalue in the primary now */ /* We have an rvalue in the primary now */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
} }
} }
} }
@@ -2441,7 +2452,7 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */
GenFunc (flags, Expr2.IVal); GenFunc (flags, Expr2.IVal);
/* The result is an rvalue in the primary */ /* The result is an rvalue in the primary */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
} }
/* Result type is always int */ /* Result type is always int */
@@ -2534,7 +2545,7 @@ static void parseadd (ExprDesc* Expr)
rhst = Expr2.Type; rhst = Expr2.Type;
/* Setup flags */ /* Setup flags */
if (ED_IsLocAbs (Expr)) { if (ED_IsLocNone (Expr)) {
/* A numerical constant */ /* A numerical constant */
flags |= CF_CONST; flags |= CF_CONST;
} else { } else {
@@ -2549,7 +2560,7 @@ static void parseadd (ExprDesc* Expr)
/* Operate on pointers, result type is a pointer */ /* Operate on pointers, result type is a pointer */
flags |= CF_PTR; flags |= CF_PTR;
/* Generate the code for the add */ /* Generate the code for the add */
if (ED_GetLoc (Expr) == E_LOC_ABS) { if (ED_GetLoc (Expr) == E_LOC_NONE) {
/* Numeric constant */ /* Numeric constant */
g_inc (flags, Expr->IVal); g_inc (flags, Expr->IVal);
} else { } else {
@@ -2569,7 +2580,7 @@ static void parseadd (ExprDesc* Expr)
** not a numeric constant, and the scale factor is not one ** not a numeric constant, and the scale factor is not one
** (no scaling), we must take the long way over the stack. ** (no scaling), we must take the long way over the stack.
*/ */
if (ED_IsLocAbs (Expr)) { if (ED_IsLocNone (Expr)) {
/* Numeric constant, scale lhs */ /* Numeric constant, scale lhs */
Expr->IVal *= ScaleFactor; Expr->IVal *= ScaleFactor;
/* Generate the code for the add */ /* Generate the code for the add */
@@ -2588,7 +2599,7 @@ static void parseadd (ExprDesc* Expr)
/* Integer addition */ /* Integer addition */
flags |= typeadjust (Expr, &Expr2, 1); flags |= typeadjust (Expr, &Expr2, 1);
/* Generate the code for the add */ /* Generate the code for the add */
if (ED_IsLocAbs (Expr)) { if (ED_IsLocNone (Expr)) {
/* Numeric constant */ /* Numeric constant */
g_inc (flags, Expr->IVal); g_inc (flags, Expr->IVal);
} else { } else {
@@ -2601,8 +2612,8 @@ static void parseadd (ExprDesc* Expr)
flags = CF_INT; flags = CF_INT;
} }
/* Result is a rvalue in primary register */ /* Result is an rvalue in primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
} }
} else { } else {
@@ -2692,8 +2703,8 @@ static void parseadd (ExprDesc* Expr)
} }
/* Result is a rvalue in primary register */ /* Result is an rvalue in primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
} }
/* Condition codes not set */ /* Condition codes not set */
@@ -2825,8 +2836,8 @@ static void parsesub (ExprDesc* Expr)
g_scale (flags, -rscale); g_scale (flags, -rscale);
} }
/* Result is a rvalue in the primary register */ /* Result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
ED_MarkAsUntested (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 ** the lhs is const, we have to remove this mark, since this is no
** longer true, lhs is on stack instead. ** longer true, lhs is on stack instead.
*/ */
if (ED_IsLocAbs (Expr)) { if (ED_IsLocNone (Expr)) {
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
} }
/* Adjust operand types */ /* Adjust operand types */
flags = typeadjust (Expr, &Expr2, 0); flags = typeadjust (Expr, &Expr2, 0);
@@ -2879,8 +2890,8 @@ static void parsesub (ExprDesc* Expr)
g_scale (flags, -rscale); g_scale (flags, -rscale);
} }
/* Result is a rvalue in the primary register */ /* Result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
ED_MarkAsUntested (Expr); ED_MarkAsUntested (Expr);
} }
} }
@@ -3070,7 +3081,7 @@ static void hieAnd (ExprDesc* Expr, unsigned TrueLab, int* BoolOp)
g_defcodelabel (FalseLab); g_defcodelabel (FalseLab);
/* The result is an rvalue in primary */ /* The result is an rvalue in primary */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
ED_TestDone (Expr); /* Condition codes are set */ ED_TestDone (Expr); /* Condition codes are set */
} }
} }
@@ -3133,7 +3144,7 @@ static void hieOr (ExprDesc *Expr)
} }
/* The result is an rvalue in primary */ /* The result is an rvalue in primary */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
ED_TestDone (Expr); /* Condition codes are set */ ED_TestDone (Expr); /* Condition codes are set */
} }
@@ -3189,7 +3200,7 @@ static void hieQuest (ExprDesc* Expr)
if (!IsTypeVoid (Expr2.Type)) { if (!IsTypeVoid (Expr2.Type)) {
/* Load it into the primary */ /* Load it into the primary */
LoadExpr (CF_NONE, &Expr2); LoadExpr (CF_NONE, &Expr2);
ED_MakeRValExpr (&Expr2); ED_FinalizeRValLoad (&Expr2);
Expr2.Type = PtrConversion (Expr2.Type); Expr2.Type = PtrConversion (Expr2.Type);
} }
@@ -3212,7 +3223,7 @@ static void hieQuest (ExprDesc* Expr)
if (!IsTypeVoid (Expr3.Type)) { if (!IsTypeVoid (Expr3.Type)) {
/* Load it into the primary */ /* Load it into the primary */
LoadExpr (CF_NONE, &Expr3); LoadExpr (CF_NONE, &Expr3);
ED_MakeRValExpr (&Expr3); ED_FinalizeRValLoad (&Expr3);
Expr3.Type = PtrConversion (Expr3.Type); Expr3.Type = PtrConversion (Expr3.Type);
} }
@@ -3278,7 +3289,7 @@ static void hieQuest (ExprDesc* Expr)
g_defcodelabel (TrueLab); g_defcodelabel (TrueLab);
/* Setup the target expression */ /* Setup the target expression */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Expr->Type = ResultType; Expr->Type = ResultType;
} }
} }
@@ -3294,7 +3305,7 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op)
int MustScale; int MustScale;
/* op= can only be used with lvalues */ /* op= can only be used with lvalues */
if (!ED_IsLVal (Expr)) { if (ED_IsRVal (Expr)) {
Error ("Invalid lvalue in assignment"); Error ("Invalid lvalue in assignment");
return; 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); Gen->Func (g_typeadjust (flags, TypeOf (Expr2.Type)), 0);
} }
Store (Expr, 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; 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) { if (ED_GetLoc (Expr) == E_LOC_EXPR || ED_GetLoc (Expr) == E_LOC_PRIMARY) {
/* Use generic routine */ /* Use generic routine */
opeq (Gen, Expr, Op); opeq (Gen, Expr, Op);
@@ -3487,7 +3498,7 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
switch (ED_GetLoc (Expr)) { switch (ED_GetLoc (Expr)) {
case E_LOC_ABS: case E_LOC_ABS:
/* Absolute: numeric address or const */ /* Absolute numeric addressed variable */
if (Gen->Tok == TOK_PLUS_ASSIGN) { if (Gen->Tok == TOK_PLUS_ASSIGN) {
g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal); g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
} else { } 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)); Internal ("Invalid location in Store(): 0x%04X", ED_GetLoc (Expr));
} }
/* Expression is a rvalue in the primary now */ /* Expression is an rvalue in the primary now */
ED_MakeRValExpr (Expr); 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) void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End)
/* Set the code range for this expression */ /* 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 */ /* Generate a label depending on the location */
switch (ED_GetLoc (Expr)) { switch (ED_GetLoc (Expr)) {
case E_LOC_NONE:
case E_LOC_ABS: case E_LOC_ABS:
/* Absolute: numeric address or const */ /* Absolute numeric addressed variable */
SB_Printf (&Buf, "$%04X", (int)(Offs & 0xFFFF)); SB_Printf (&Buf, "$%04X", (int)(Offs & 0xFFFF));
break; break;
@@ -168,11 +202,11 @@ int ED_GetStackOffs (const ExprDesc* Expr, int Offs)
ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type) 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->Sym = 0;
Expr->Type = Type; 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->Name = 0;
Expr->IVal = Value; Expr->IVal = Value;
Expr->FVal = FP_D_Make (0.0); 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) 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->Sym = 0;
Expr->Type = type_int; 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->Name = 0;
Expr->IVal = Value; Expr->IVal = Value;
Expr->FVal = FP_D_Make (0.0); Expr->FVal = FP_D_Make (0.0);
@@ -195,14 +229,13 @@ ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value)
ExprDesc* ED_MakeRValExpr (ExprDesc* Expr) ExprDesc* ED_FinalizeRValLoad (ExprDesc* Expr)
/* Convert Expr into a rvalue which is in the primary register without an /* Finalize the result of LoadExpr to be an rvalue in the primary register */
** offset.
*/
{ {
Expr->Sym = 0; Expr->Sym = 0;
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET); Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_ADDRESS_OF);
Expr->Flags |= (E_LOC_EXPR | E_RTYPE_RVAL); Expr->Flags &= ~(E_NEED_TEST | E_CC_SET);
Expr->Flags |= (E_LOC_PRIMARY | E_RTYPE_RVAL);
Expr->Name = 0; Expr->Name = 0;
Expr->IVal = 0; /* No offset */ Expr->IVal = 0; /* No offset */
Expr->FVal = FP_D_Make (0.0); Expr->FVal = FP_D_Make (0.0);
@@ -211,18 +244,106 @@ ExprDesc* ED_MakeRValExpr (ExprDesc* Expr)
ExprDesc* ED_MakeLValExpr (ExprDesc* Expr) ExprDesc* ED_AddrExpr (ExprDesc* Expr)
/* Convert Expr into a lvalue which is in the primary register without an /* Take address of Expr. The result is always an rvalue */
** offset. {
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; return ED_IsRVal (Expr) && ED_IsAbs (Expr);
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET); }
Expr->Flags |= (E_LOC_EXPR | E_RTYPE_LVAL); #endif
Expr->Name = 0;
Expr->IVal = 0; /* No offset */
Expr->FVal = FP_D_Make (0.0);
return Expr; 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. ** 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) int ED_IsConstAddr (const ExprDesc* Expr)
/* Return true if the expression is a constant (numeric) integer. */ /* 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) && return ED_IsAddrExpr (Expr) && ED_IsLocConst (Expr);
IsClassInt (Expr->Type); }
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 true if the given expression is a NULL pointer constant */
{ {
return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE|E_BITFIELD)) == 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 && Expr->IVal == 0 &&
IsClassInt (Expr->Type); IsClassInt (Expr->Type);
} }
@@ -293,6 +425,11 @@ void PrintExprDesc (FILE* F, ExprDesc* E)
Flags = E->Flags; Flags = E->Flags;
Sep = '('; Sep = '(';
fprintf (F, "Flags: 0x%04X ", Flags); 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) { if (Flags & E_LOC_ABS) {
fprintf (F, "%cE_LOC_ABS", Sep); fprintf (F, "%cE_LOC_ABS", Sep);
Flags &= ~E_LOC_ABS; Flags &= ~E_LOC_ABS;
@@ -353,6 +490,11 @@ void PrintExprDesc (FILE* F, ExprDesc* E)
Flags &= ~E_CC_SET; Flags &= ~E_CC_SET;
Sep = ','; Sep = ',';
} }
if (Flags & E_ADDRESS_OF) {
fprintf (F, "%cE_ADDRESS_OF", Sep);
Flags &= ~E_ADDRESS_OF;
Sep = ',';
}
if (Flags) { if (Flags) {
fprintf (F, "%c,0x%04X", Sep, Flags); fprintf (F, "%c,0x%04X", Sep, Flags);
Sep = ','; Sep = ',';

View File

@@ -59,22 +59,57 @@
/* Defines for the flags field of the expression descriptor */ /* Defines for the flags field of the expression descriptor */
enum { 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_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_GLOBAL = 0x0002, /* Global variable */
E_LOC_STATIC = 0x0004, /* Static variable */ E_LOC_STATIC = 0x0004, /* Static variable */
E_LOC_REGISTER = 0x0008, /* Register variable */ E_LOC_REGISTER = 0x0008, /* Register variable */
E_LOC_STACK = 0x0010, /* Value on the stack */ E_LOC_STACK = 0x0010, /* Value on the stack */
E_LOC_PRIMARY = 0x0020, /* The primary register */ E_LOC_PRIMARY = 0x0020, /* Temporary in primary register */
E_LOC_EXPR = 0x0040, /* An expression in the primary register */ E_LOC_EXPR = 0x0040, /* A location that the primary register points to */
E_LOC_LITERAL = 0x0080, /* Literal in the literal pool */ E_LOC_LITERAL = 0x0080, /* Literal in the literal pool */
/* Constant location of some sort (only if rval) */ /* 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, E_LOC_REGISTER | E_LOC_LITERAL,
/* Reference? */ /* lvalue/rvalue in C language's sense */
E_MASK_RTYPE = 0x0100, E_MASK_RTYPE = 0x0100,
E_RTYPE_RVAL = 0x0000, E_RTYPE_RVAL = 0x0000,
E_RTYPE_LVAL = 0x0100, E_RTYPE_LVAL = 0x0100,
@@ -88,6 +123,10 @@ enum {
E_HAVE_MARKS = 0x1000, /* Code marks are valid */ 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 */ /* Forward */
@@ -135,8 +174,18 @@ INLINE int ED_GetLoc (const ExprDesc* Expr)
#endif #endif
#if defined(HAVE_INLINE) #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 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; 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; return (Expr->Flags & E_MASK_LOC) == E_LOC_REGISTER;
} }
#else #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 #endif
#if defined(HAVE_INLINE) #if defined(HAVE_INLINE)
@@ -198,50 +247,25 @@ INLINE int ED_IsLocLiteral (const ExprDesc* Expr)
INLINE int ED_IsLocConst (const ExprDesc* Expr) INLINE int ED_IsLocConst (const ExprDesc* Expr)
/* Return true if the expression is a constant location of some sort */ /* 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 #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 #endif
#if defined(HAVE_INLINE) #if defined(HAVE_INLINE)
INLINE int ED_IsLVal (const ExprDesc* Expr) INLINE int ED_IsLocQuasiConst (const ExprDesc* Expr)
/* Return true if the expression is a reference */ /* 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 #else
# define ED_IsLVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL) int ED_IsLocQuasiConst (const ExprDesc* Expr);
#endif /* 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.
#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)
#endif #endif
#if defined(HAVE_INLINE) #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) # define ED_MarkAsUntested(Expr) do { (Expr)->Flags &= ~E_CC_SET; } while (0)
#endif #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); void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End);
/* Set the code range for this expression */ /* 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); 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); 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); ExprDesc* ED_FinalizeRValLoad (ExprDesc* Expr);
/* Convert Expr into a rvalue which is in the primary register without an /* Finalize the result of LoadExpr to be an rvalue in the primary register */
** offset.
*/
ExprDesc* ED_MakeLValExpr (ExprDesc* Expr); #if defined(HAVE_INLINE)
/* Convert Expr into a lvalue which is in the primary register without an INLINE int ED_IsLVal (const ExprDesc* Expr)
** offset. /* 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); #if defined(HAVE_INLINE)
/* Return true if the expression denotes a constant of some sort. This can be a INLINE int ED_IsRVal (const ExprDesc* Expr)
** numeric constant, the address of a global variable (maybe with offset) or /* Return true if the expression is an rvalue */
** similar. {
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) #if defined(HAVE_INLINE)
INLINE int ED_IsConstAbs (const ExprDesc* Expr) 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. ** 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 #else
# define ED_IsConstAbs(E) \ int ED_IsConstAbs (const ExprDesc* Expr);
(((E)->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL)) /* Return true if the expression denotes a constant absolute value. This can be
** a numeric constant, cast to any type.
*/
#endif #endif
int ED_IsConstAbsInt (const ExprDesc* Expr); int ED_IsConstAbsInt (const ExprDesc* Expr);
/* Return true if the expression is a constant (numeric) integer. */ /* 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); int ED_IsNullPtr (const ExprDesc* Expr);
/* Return true if the given expression is a NULL pointer constant */ /* Return true if the given expression is a NULL pointer constant */

View File

@@ -48,14 +48,14 @@
static void LoadConstant (unsigned Flags, ExprDesc* Expr) static void LoadAddress (unsigned Flags, ExprDesc* Expr)
/* Load the primary register with some constant value. */ /* Load the primary register with some address value. */
{ {
switch (ED_GetLoc (Expr)) { switch (ED_GetLoc (Expr)) {
case E_LOC_ABS: case E_LOC_ABS:
/* Number constant */ /* Numberic address */
g_getimmed (Flags | TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0); g_getimmed (Flags | CF_IMM | CF_CONST, Expr->IVal, 0);
break; break;
case E_LOC_GLOBAL: case E_LOC_GLOBAL:
@@ -83,25 +83,38 @@ static void LoadConstant (unsigned Flags, ExprDesc* Expr)
g_leasp (Expr->IVal); g_leasp (Expr->IVal);
break; 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: default:
Internal ("Unknown constant type: %04X", Expr->Flags); Internal ("Unknown address type: %04X", Expr->Flags);
} }
} }
void LoadExpr (unsigned Flags, struct ExprDesc* Expr) 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. /* Lvalue. If this is a bit field its type is unsigned. But if the
** But if the field is completely contained in the lower byte, we will ** field is completely contained in the lower byte, we will throw away
** throw away the high byte anyway and may therefore load just the ** the high byte anyway and may therefore load just the low byte.
** low byte.
*/ */
if (ED_IsBitField (Expr)) { 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; Flags |= CF_UNSIGNED;
} else { } else {
Flags |= TypeOf (Expr->Type); Flags |= TypeOf (Expr->Type);
@@ -110,10 +123,16 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
Flags |= CF_TEST; Flags |= CF_TEST;
} }
/* Load the content of Expr */
switch (ED_GetLoc (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: case E_LOC_ABS:
/* Absolute: numeric address or const */ /* Absolute numeric addressed variable */
g_getstatic (Flags | CF_ABSOLUTE, Expr->IVal, 0); g_getstatic (Flags | CF_ABSOLUTE, Expr->IVal, 0);
break; break;
@@ -139,7 +158,15 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
break; break;
case E_LOC_PRIMARY: 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) { if (Flags & CF_TEST) {
g_test (Flags); g_test (Flags);
} }
@@ -148,6 +175,13 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
case E_LOC_EXPR: case E_LOC_EXPR:
/* Reference to address in primary with offset in Expr */ /* Reference to address in primary with offset in Expr */
g_getind (Flags, Expr->IVal); 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; break;
default: default:
@@ -173,24 +207,14 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
ED_TestDone (Expr); ED_TestDone (Expr);
} else { } else {
/* An rvalue */ /* An address */
if (ED_IsLocExpr (Expr)) { Flags |= CF_INT | CF_UNSIGNED;
if (Expr->IVal != 0) { /* Constant of some sort, load it into the primary */
/* We have an expression in the primary plus a constant LoadAddress (Flags, Expr);
** 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);
}
/* Are we testing this value? */ /* Are we testing this value? */
if (ED_NeedsTest (Expr)) { if (ED_NeedsTest (Expr)) {
/* Yes, force a test */ /* Yes, force a test */
Flags |= TypeOf (Expr->Type);
g_test (Flags); g_test (Flags);
ED_TestDone (Expr); ED_TestDone (Expr);
} }

View File

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

View File

@@ -173,8 +173,8 @@ void ShiftExpr (struct ExprDesc* Expr)
goto Next; goto Next;
} }
/* If we're shifting an integer or unsigned to the right, the /* If we're shifting an integer or unsigned to the right, the lhs
** lhs has a const address, and the shift count is larger than 8, ** 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 ** we can load just the high byte as a char with the correct
** signedness, and reduce the shift count by 8. If the remaining ** signedness, and reduce the shift count by 8. If the remaining
** shift count is zero, we're done. ** shift count is zero, we're done.
@@ -182,7 +182,7 @@ void ShiftExpr (struct ExprDesc* Expr)
if (Tok == TOK_SHR && if (Tok == TOK_SHR &&
IsTypeInt (Expr->Type) && IsTypeInt (Expr->Type) &&
ED_IsLVal (Expr) && ED_IsLVal (Expr) &&
(ED_IsLocConst (Expr) || ED_IsLocStack (Expr)) && ED_IsLocQuasiConst (Expr) &&
Expr2.IVal >= 8) { Expr2.IVal >= 8) {
Type* OldType; Type* OldType;
@@ -227,8 +227,8 @@ void ShiftExpr (struct ExprDesc* Expr)
} }
MakeRVal: MakeRVal:
/* We have a rvalue in the primary now */ /* We have an rvalue in the primary now */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Next: Next:
/* Set the type of the result */ /* 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. ** address calculation could overflow in the linker.
*/ */
int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) && 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 */ /* Calculate the real stack offset */
Offs = ED_GetStackOffs (&Arg1.Expr, 0); 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. ** address calculation could overflow in the linker.
*/ */
int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) && 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 */ /* Calculate the real stack offset */
Offs = ED_GetStackOffs (&Arg2.Expr, 0); Offs = ED_GetStackOffs (&Arg2.Expr, 0);
@@ -520,7 +520,7 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
AddCodeLine ("lda ptr1"); AddCodeLine ("lda ptr1");
/* The function result is an rvalue in the primary register */ /* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type); Expr->Type = GetFuncReturn (Expr->Type);
/* Bail out, no need for further processing */ /* 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 */ /* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type); Expr->Type = GetFuncReturn (Expr->Type);
ExitPoint: ExitPoint:
@@ -743,7 +743,7 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
AddCodeLine ("lda ptr1"); AddCodeLine ("lda ptr1");
/* The function result is an rvalue in the primary register */ /* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type); Expr->Type = GetFuncReturn (Expr->Type);
/* Bail out, no need for further processing */ /* 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 */ /* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type); Expr->Type = GetFuncReturn (Expr->Type);
ExitPoint: 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 */ /* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type); Expr->Type = GetFuncReturn (Expr->Type);
/* We expect the closing brace */ /* 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. ** address calculation could overflow in the linker.
*/ */
int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) && 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 */ /* Calculate the real stack offset */
int Offs = ED_GetStackOffs (&Arg2.Expr, 0); 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. ** address calculation could overflow in the linker.
*/ */
int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) && 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 */ /* Calculate the real stack offset */
int Offs = ED_GetStackOffs (&Arg1.Expr, 0); 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 */ /* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Expr->Type = GetFuncReturn (Expr->Type); Expr->Type = GetFuncReturn (Expr->Type);
ExitPoint: ExitPoint:
@@ -1250,7 +1250,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
AddCodeLine ("tya"); AddCodeLine ("tya");
/* The function result is an rvalue in the primary register */ /* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Expr->Type = type_size_t; Expr->Type = type_size_t;
/* Bail out, no need for further processing */ /* Bail out, no need for further processing */
@@ -1279,7 +1279,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
AddCodeLine ("ldx #$00"); AddCodeLine ("ldx #$00");
/* The function result is an rvalue in the primary register */ /* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Expr->Type = type_size_t; Expr->Type = type_size_t;
/* Bail out, no need for further processing */ /* Bail out, no need for further processing */
@@ -1304,7 +1304,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
AddCodeLine ("tya"); AddCodeLine ("tya");
/* The function result is an rvalue in the primary register */ /* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Expr->Type = type_size_t; Expr->Type = type_size_t;
/* Bail out, no need for further processing */ /* Bail out, no need for further processing */
@@ -1333,7 +1333,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
AddCodeLine ("tya"); AddCodeLine ("tya");
/* The function result is an rvalue in the primary register */ /* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Expr->Type = type_size_t; Expr->Type = type_size_t;
/* Bail out, no need for further processing */ /* 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); AddCodeLine ("jsr _%s", Func_strlen);
/* The function result is an rvalue in the primary register */ /* The function result is an rvalue in the primary register */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
Expr->Type = type_size_t; Expr->Type = type_size_t;
ExitPoint: ExitPoint:

View File

@@ -70,7 +70,7 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType)
** conversion void -> void. ** conversion void -> void.
*/ */
if (IsTypeVoid (NewType)) { if (IsTypeVoid (NewType)) {
ED_MakeRVal (Expr); /* Never an lvalue */ ED_MarkExprAsRVal (Expr); /* Never an lvalue */
goto ExitPoint; goto ExitPoint;
} }
@@ -105,10 +105,10 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType)
g_typecast (TypeOf (NewType), TypeOf (OldType) | CF_FORCECHAR); g_typecast (TypeOf (NewType), TypeOf (OldType) | CF_FORCECHAR);
/* Value is now in primary and an rvalue */ /* 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 /* A cast of a constant numeric value to another type. Be sure
** to handle sign extension correctly. ** 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 { } else {
/* The value is not a constant. If the sizes of the types are /* 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. */ /* Emit typecast code. */
g_typecast (TypeOf (NewType), TypeOf (OldType) | CF_FORCECHAR); g_typecast (TypeOf (NewType), TypeOf (OldType) | CF_FORCECHAR);
/* Value is now a rvalue in the primary */ /* Value is now an rvalue in the primary */
ED_MakeRValExpr (Expr); ED_FinalizeRValLoad (Expr);
} }
} }