mirror of
https://github.com/cc65/cc65.git
synced 2025-01-01 03:30:20 +00:00
parent
ba48dfe65d
commit
2108489523
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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 */
|
||||
|
@ -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:
|
||||
|
231
src/cc65/expr.c
231
src/cc65/expr.c
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 = ',';
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user