/*****************************************************************************/
-/* Helper functions */
+/* Helper functions */
/*****************************************************************************/
-void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc *Expr)
+void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr)
/* Call an expression function with checks. */
{
/* Remember the stack pointer */
/* Do some checks if code generation is still constistent */
if (StackPtr != OldSP) {
if (Debug) {
- fprintf (stderr,
- "Code generation messed up!\n"
- "StackPtr is %d, should be %d",
- StackPtr, OldSP);
+ Error ("Code generation messed up: "
+ "StackPtr is %d, should be %d",
+ StackPtr, OldSP);
} else {
- Internal ("StackPtr is %d, should be %d\n", StackPtr, OldSP);
+ Internal ("Code generation messed up: "
+ "StackPtr is %d, should be %d",
+ StackPtr, OldSP);
}
}
}
+void MarkedExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr)
+/* Call an expression function with checks and record start and end of the
+ * generated code.
+ */
+{
+ CodeMark Start, End;
+ GetCodePos (&Start);
+ ExprWithCheck (Func, Expr);
+ GetCodePos (&End);
+ ED_SetCodeRange (Expr, &Start, &End);
+}
+
+
+
static Type* promoteint (Type* lhst, Type* rhst)
/* In an expression with two ints, return the type of the result */
{
+static void WarnConstCompareResult (void)
+/* If the result of a comparison is constant, this is suspicious when not in
+ * preprocessor mode.
+ */
+{
+ if (!Preprocessing) {
+ Warning ("Result of comparison is constant");
+ }
+}
+
+
+
/*****************************************************************************/
/* code */
/*****************************************************************************/
}
} else {
+ /* Check function attributes */
+ if (Expr->Sym && SymHasAttr (Expr->Sym, atNoReturn)) {
+ /* For now, handle as if a return statement was encountered */
+ F_ReturnFound (CurrentFunc);
+ }
+
/* Check for known standard functions and inline them */
if (Expr->Name != 0) {
int StdFunc = FindStdFunc ((const char*) Expr->Name);
/* If we have a pointer on stack, remove it */
if (PtrOnStack) {
- g_space (- (int) sizeofarg (CF_PTR));
+ g_drop (SIZEOF_PTR);
pop (CF_PTR);
}
break;
case TOK_SCONST:
+ case TOK_WCSCONST:
/* String literal */
- E->Type = GetCharArrayType (GetLiteralPoolOffs () - CurTok.IVal);
+ E->LVal = UseLiteral (CurTok.SVal);
+ E->Type = GetCharArrayType (GetLiteralSize (CurTok.SVal));
E->Flags = E_LOC_LITERAL | E_RTYPE_RVAL;
- E->IVal = CurTok.IVal;
- E->Name = LiteralPoolLabel;
+ E->IVal = 0;
+ E->Name = GetLiteralLabel (CurTok.SVal);
NextToken ();
break;
ExprDesc Subscript;
CodeMark Mark1;
CodeMark Mark2;
+ TypeCode Qualifiers;
Type* ElementType;
Type* tptr1;
}
/* TOS now contains ptr to array elements. Get the subscript. */
- ExprWithCheck (hie0, &Subscript);
+ MarkedExprWithCheck (hie0, &Subscript);
/* Check the types of array and subscript. We can either have a
* pointer/array to the left, in which case the subscript must be of an
* Since we do the necessary checking here, we can rely later on the
* correct types.
*/
+ Qualifiers = T_QUAL_NONE;
if (IsClassPtr (Expr->Type)) {
if (!IsClassInt (Subscript.Type)) {
Error ("Array subscript is not an integer");
/* To avoid any compiler errors, make the expression a valid int */
ED_MakeConstAbsInt (&Subscript, 0);
}
+ if (IsTypeArray (Expr->Type)) {
+ Qualifiers = GetQualifier (Expr->Type);
+ }
ElementType = Indirect (Expr->Type);
} else if (IsClassInt (Expr->Type)) {
if (!IsClassPtr (Subscript.Type)) {
* address 0.
*/
ED_MakeConstAbs (&Subscript, 0, GetCharArrayType (1));
+ } else if (IsTypeArray (Subscript.Type)) {
+ Qualifiers = GetQualifier (Subscript.Type);
}
ElementType = Indirect (Subscript.Type);
} else {
ElementType = Indirect (Expr->Type);
}
+ /* The element type has the combined qualifiers from itself and the array,
+ * it is a member of (if any).
+ */
+ if (GetQualifier (ElementType) != (GetQualifier (ElementType) | Qualifiers)) {
+ ElementType = TypeDup (ElementType);
+ ElementType->C |= Qualifiers;
+ }
+
/* If the subscript is a bit-field, load it and make it an rvalue */
if (ED_IsBitField (&Subscript)) {
LoadExpr (CF_NONE, &Subscript);
}
/* Check if the subscript is constant absolute value */
- if (ED_IsConstAbs (&Subscript)) {
+ if (ED_IsConstAbs (&Subscript) && ED_CodeRangeIsEmpty (&Subscript)) {
/* The array subscript is a numeric constant. If we had pushed the
* array base address onto the stack before, we can remove this value,
{
ident Ident;
SymEntry* Field;
+ TypeCode Q;
/* Skip the token and check for an identifier */
NextToken ();
if (CurTok.Tok != TOK_IDENT) {
Error ("Identifier expected");
- Expr->Type = type_int;
+ /* Make the expression an integer at address zero */
+ ED_MakeConstAbs (Expr, 0, type_int);
return;
}
Field = FindStructField (Expr->Type, Ident);
if (Field == 0) {
Error ("Struct/union has no field named `%s'", Ident);
- Expr->Type = type_int;
+ /* Make the expression an integer at address zero */
+ ED_MakeConstAbs (Expr, 0, type_int);
return;
}
/* Set the struct field offset */
Expr->IVal += Field->V.Offs;
- /* The type is now the type of the field */
- Expr->Type = Field->Type;
+ /* The type is the type of the field plus any qualifiers from the struct */
+ if (IsClassStruct (Expr->Type)) {
+ Q = GetQualifier (Expr->Type);
+ } else {
+ Q = GetQualifier (Indirect (Expr->Type));
+ }
+ if (GetQualifier (Field->Type) == (GetQualifier (Field->Type) | Q)) {
+ Expr->Type = Field->Type;
+ } else {
+ Expr->Type = TypeDup (Field->Type);
+ Expr->Type->C |= Q;
+ }
/* 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
}
/* Make the expression a bit field if necessary */
- if ((Field->Flags & SC_BITFIELD) == SC_BITFIELD) {
+ if (SymIsBitField (Field)) {
ED_MakeBitField (Expr, Field->V.B.BitOffs, Field->V.B.BitWidth);
}
}
ED_MakeRValExpr (Expr);
}
/* If the expression is already a pointer to function, the
- * additional dereferencing operator must be ignored.
+ * additional dereferencing operator must be ignored. A function
+ * itself is represented as "pointer to function", so any number
+ * of dereference operators is legal, since the result will
+ * always be converted to "pointer to function".
*/
- if (IsTypeFuncPtr (Expr->Type)) {
+ if (IsTypeFuncPtr (Expr->Type) || IsTypeFunc (Expr->Type)) {
/* Expression not storable */
ED_MakeRVal (Expr);
} else {
}
/* Get the right hand side */
- rconst = (evalexpr (CF_NONE, hienext, &Expr2) == 0);
+ MarkedExprWithCheck (hienext, &Expr2);
+
+ /* Check for a constant expression */
+ rconst = (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2));
+ if (!rconst) {
+ /* Not constant, load into the primary */
+ LoadExpr (CF_NONE, &Expr2);
+ }
/* Check the type of the rhs */
if (!IsClassInt (Expr2.Type)) {
/* Helper function for the compare operators */
{
ExprDesc Expr2;
+ CodeMark Mark0;
CodeMark Mark1;
CodeMark Mark2;
const GenDesc* Gen;
- token_t Tok; /* The operator token */
+ token_t Tok; /* The operator token */
unsigned ltype;
int rconst; /* Operand is a constant */
+ GetCodePos (&Mark0);
hienext (Expr);
while ((Gen = FindGen (CurTok.Tok, Ops)) != 0) {
+ /* Remember the generator function */
+ void (*GenFunc) (unsigned, unsigned long) = Gen->Func;
+
/* Remember the operator token, then skip it */
Tok = CurTok.Tok;
NextToken ();
}
/* Get the right hand side */
- rconst = (evalexpr (CF_NONE, hienext, &Expr2) == 0);
+ MarkedExprWithCheck (hienext, &Expr2);
+
+ /* Check for a constant expression */
+ rconst = (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2));
+ if (!rconst) {
+ /* Not constant, load into the primary */
+ LoadExpr (CF_NONE, &Expr2);
+ }
/* Make sure, the types are compatible */
if (IsClassInt (Expr->Type)) {
/* If the result is constant, this is suspicious when not in
* preprocessor mode.
*/
- if (!Preprocessing) {
- Warning ("Result of comparison is constant");
- }
+ WarnConstCompareResult ();
/* Both operands are constant, remove the generated code */
RemoveCode (&Mark1);
}
}
- } else {
+ } else {
+
+ /* Determine the signedness of the operands */
+ int LeftSigned = IsSignSigned (Expr->Type);
+ int RightSigned = IsSignSigned (Expr2.Type);
/* If the right hand side is constant, and the generator function
* expects the lhs in the primary, remove the push of the primary
}
}
- /* Determine the type of the operation result. If the left
- * operand is of type char and the right is a constant, or
- * if both operands are of type char, we will encode the
- * operation as char operation. Otherwise the default
- * promotions are used.
- */
- if (IsTypeChar (Expr->Type) && (IsTypeChar (Expr2.Type) || rconst)) {
- flags |= CF_CHAR;
- if (IsSignUnsigned (Expr->Type) || IsSignUnsigned (Expr2.Type)) {
- flags |= CF_UNSIGNED;
- }
- if (rconst) {
- flags |= CF_FORCECHAR;
- }
+ /* Determine the type of the operation. */
+ if (IsTypeChar (Expr->Type) && rconst) {
+
+ /* Left side is unsigned char, right side is constant.
+ * Determine the minimum and maximum values
+ */
+ int LeftMin, LeftMax;
+ if (LeftSigned) {
+ LeftMin = -128;
+ LeftMax = 127;
+ } else {
+ LeftMin = 0;
+ LeftMax = 255;
+ }
+ /* An integer value is always represented as a signed in the
+ * ExprDesc structure. This may lead to false results below,
+ * if it is actually unsigned, but interpreted as signed
+ * because of the representation. Fortunately, in this case,
+ * the actual value doesn't matter, since it's always greater
+ * than what can be represented in a char. So correct the
+ * value accordingly.
+ */
+ if (!RightSigned && Expr2.IVal < 0) {
+ /* Correct the value so it is an unsigned. It will then
+ * anyway match one of the cases below.
+ */
+ Expr2.IVal = LeftMax + 1;
+ }
+
+ /* Comparing a char against a constant may have a constant
+ * result.
+ */
+ switch (Tok) {
+
+ case TOK_EQ:
+ if (Expr2.IVal < LeftMin || Expr2.IVal > LeftMax) {
+ ED_MakeConstAbsInt (Expr, 0);
+ WarnConstCompareResult ();
+ RemoveCode (&Mark0);
+ goto Done;
+ }
+ break;
+
+ case TOK_NE:
+ if (Expr2.IVal < LeftMin || Expr2.IVal > LeftMax) {
+ ED_MakeConstAbsInt (Expr, 1);
+ WarnConstCompareResult ();
+ RemoveCode (&Mark0);
+ goto Done;
+ }
+ break;
+
+ case TOK_LT:
+ if (Expr2.IVal <= LeftMin || Expr2.IVal > LeftMax) {
+ ED_MakeConstAbsInt (Expr, Expr2.IVal > LeftMax);
+ WarnConstCompareResult ();
+ RemoveCode (&Mark0);
+ goto Done;
+ }
+ break;
+
+ case TOK_LE:
+ if (Expr2.IVal < LeftMin || Expr2.IVal >= LeftMax) {
+ ED_MakeConstAbsInt (Expr, Expr2.IVal >= LeftMax);
+ WarnConstCompareResult ();
+ RemoveCode (&Mark0);
+ goto Done;
+ }
+ break;
+
+ case TOK_GE:
+ if (Expr2.IVal <= LeftMin || Expr2.IVal > LeftMax) {
+ ED_MakeConstAbsInt (Expr, Expr2.IVal <= LeftMin);
+ WarnConstCompareResult ();
+ RemoveCode (&Mark0);
+ goto Done;
+ }
+ break;
+
+ case TOK_GT:
+ if (Expr2.IVal < LeftMin || Expr2.IVal >= LeftMax) {
+ ED_MakeConstAbsInt (Expr, Expr2.IVal < LeftMin);
+ WarnConstCompareResult ();
+ RemoveCode (&Mark0);
+ goto Done;
+ }
+ break;
+
+ default:
+ Internal ("hie_compare: got token 0x%X\n", Tok);
+ }
+
+ /* If the result is not already constant (as evaluated in the
+ * switch above), we can execute the operation as a char op,
+ * since the right side constant is in a valid range.
+ */
+ flags |= (CF_CHAR | CF_FORCECHAR);
+ if (!LeftSigned) {
+ flags |= CF_UNSIGNED;
+ }
+
+ } else if (IsTypeChar (Expr->Type) && IsTypeChar (Expr2.Type) &&
+ GetSignedness (Expr->Type) == GetSignedness (Expr2.Type)) {
+
+ /* Both are chars with the same signedness. We can encode the
+ * operation as a char operation.
+ */
+ flags |= CF_CHAR;
+ if (rconst) {
+ flags |= CF_FORCECHAR;
+ }
+ if (!LeftSigned) {
+ flags |= CF_UNSIGNED;
+ }
} else {
- unsigned rtype = TypeOf (Expr2.Type) | (flags & CF_CONST);
+ unsigned rtype = TypeOf (Expr2.Type) | (flags & CF_CONST);
flags |= g_typeadjust (ltype, rtype);
}
+ /* If the left side is an unsigned and the right is a constant,
+ * we may be able to change the compares to something more
+ * effective.
+ */
+ if (!LeftSigned && rconst) {
+
+ switch (Tok) {
+
+ case TOK_LT:
+ if (Expr2.IVal == 1) {
+ /* An unsigned compare to one means that the value
+ * must be zero.
+ */
+ GenFunc = g_eq;
+ Expr2.IVal = 0;
+ }
+ break;
+
+ case TOK_LE:
+ if (Expr2.IVal == 0) {
+ /* An unsigned compare to zero means that the value
+ * must be zero.
+ */
+ GenFunc = g_eq;
+ }
+ break;
+
+ case TOK_GE:
+ if (Expr2.IVal == 1) {
+ /* An unsigned compare to one means that the value
+ * must not be zero.
+ */
+ GenFunc = g_ne;
+ Expr2.IVal = 0;
+ }
+ break;
+
+ case TOK_GT:
+ if (Expr2.IVal == 0) {
+ /* An unsigned compare to zero means that the value
+ * must not be zero.
+ */
+ GenFunc = g_ne;
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ }
+
/* Generate code */
- Gen->Func (flags, Expr2.IVal);
+ GenFunc (flags, Expr2.IVal);
/* The result is an rvalue in the primary */
ED_MakeRValExpr (Expr);
/* Result type is always int */
Expr->Type = type_int;
- /* Condition codes are set */
+Done: /* Condition codes are set */
ED_TestDone (Expr);
}
}
/* Both expressions are constants. Check for pointer arithmetic */
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
- /* Left is pointer, right is int, must scale rhs */
+ /* Left is pointer, right is int, must scale rhs */
Expr->IVal += Expr2.IVal * CheckedPSizeOf (lhst);
- /* Result type is a pointer */
+ /* Result type is a pointer */
} else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
- /* Left is int, right is pointer, must scale lhs */
+ /* Left is int, right is pointer, must scale lhs */
Expr->IVal = Expr->IVal * CheckedPSizeOf (rhst) + Expr2.IVal;
- /* Result type is a pointer */
- Expr->Type = Expr2.Type;
+ /* Result type is a pointer */
+ Expr->Type = Expr2.Type;
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
- /* Integer addition */
- Expr->IVal += Expr2.IVal;
- typeadjust (Expr, &Expr2, 1);
+ /* Integer addition */
+ Expr->IVal += Expr2.IVal;
+ typeadjust (Expr, &Expr2, 1);
} else {
/* OOPS */
- Error ("Invalid operands for binary operator `+'");
+ Error ("Invalid operands for binary operator `+'");
}
} else {
g_push (TypeOf (Expr->Type), 0); /* --> stack */
/* Evaluate the rhs */
- if (evalexpr (CF_NONE, hie9, &Expr2) == 0) {
+ MarkedExprWithCheck (hie9, &Expr2);
+
+ /* Check for a constant rhs expression */
+ if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
/* Right hand side is a constant. Get the rhs type */
rhst = Expr2.Type;
} else {
+ /* Not constant, load into the primary */
+ LoadExpr (CF_NONE, &Expr2);
+
/* lhs and rhs are not constant. Get the rhs type. */
rhst = Expr2.Type;
g_push (TypeOf (lhst), 0); /* --> stack */
/* Parse the right hand side */
- if (evalexpr (CF_NONE, hie9, &Expr2) == 0) {
+ MarkedExprWithCheck (hie9, &Expr2);
+
+ /* Check for a constant rhs expression */
+ if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
/* The right hand side is constant. Get the rhs type. */
rhst = Expr2.Type;
/* Do the subtraction */
g_dec (flags | CF_CONST, Expr2.IVal);
- /* If this was a pointer subtraction, we must scale the result */
- if (rscale != 1) {
- g_scale (flags, -rscale);
- }
+ /* If this was a pointer subtraction, we must scale the result */
+ if (rscale != 1) {
+ g_scale (flags, -rscale);
+ }
- /* Result is a rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- ED_MarkAsUntested (Expr);
+ /* Result is a rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ ED_MarkAsUntested (Expr);
- }
+ }
} else {
- /* Right hand side is not constant. Get the rhs type. */
- rhst = Expr2.Type;
+ /* Not constant, load into the primary */
+ LoadExpr (CF_NONE, &Expr2);
+
+ /* Right hand side is not constant. Get the rhs type. */
+ rhst = Expr2.Type;
/* Check for pointer arithmetic */
- if (IsClassPtr (lhst) && IsClassInt (rhst)) {
+ if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */
- g_scale (CF_INT, CheckedPSizeOf (lhst));
- /* Operate on pointers, result type is a pointer */
- flags = CF_PTR;
- } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
- /* Left is pointer, right is pointer, must scale result */
- if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) {
- Error ("Incompatible pointer types");
- } else {
- rscale = CheckedPSizeOf (lhst);
- }
- /* Operate on pointers, result type is an integer */
- flags = CF_PTR;
- Expr->Type = type_int;
+ g_scale (CF_INT, CheckedPSizeOf (lhst));
+ /* Operate on pointers, result type is a pointer */
+ flags = CF_PTR;
+ } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
+ /* Left is pointer, right is pointer, must scale result */
+ if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) {
+ Error ("Incompatible pointer types");
+ } else {
+ rscale = CheckedPSizeOf (lhst);
+ }
+ /* Operate on pointers, result type is an integer */
+ flags = CF_PTR;
+ Expr->Type = type_int;
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer subtraction. If the left hand side descriptor says that
* the lhs is const, we have to remove this mark, since this is no
static void hieAnd (ExprDesc* Expr, unsigned TrueLab, int* BoolOp)
/* Process "exp && exp" */
{
- int lab;
+ int FalseLab;
ExprDesc Expr2;
hie2 (Expr);
*BoolOp = 1;
/* Get a label that we will use for false expressions */
- lab = GetLocalLabel ();
+ FalseLab = GetLocalLabel ();
/* If the expr hasn't set condition codes, set the force-test flag */
if (!ED_IsTested (Expr)) {
LoadExpr (CF_FORCECHAR, Expr);
/* Generate the jump */
- g_falsejump (CF_NONE, lab);
+ g_falsejump (CF_NONE, FalseLab);
/* Parse more boolean and's */
while (CurTok.Tok == TOK_BOOL_AND) {
/* Do short circuit evaluation */
if (CurTok.Tok == TOK_BOOL_AND) {
- g_falsejump (CF_NONE, lab);
+ g_falsejump (CF_NONE, FalseLab);
} else {
/* Last expression - will evaluate to true */
g_truejump (CF_NONE, TrueLab);
}
/* Define the false jump label here */
- g_defcodelabel (lab);
+ g_defcodelabel (FalseLab);
/* The result is an rvalue in primary */
ED_MakeRValExpr (Expr);
static void hieQuest (ExprDesc* Expr)
/* Parse the ternary operator */
{
- int labf;
- int labt;
+ int FalseLab;
+ int TrueLab;
+ CodeMark TrueCodeEnd;
ExprDesc Expr2; /* Expression 2 */
ExprDesc Expr3; /* Expression 3 */
int Expr2IsNULL; /* Expression 2 is a NULL pointer */
ED_MarkForTest (Expr);
}
LoadExpr (CF_NONE, Expr);
- labf = GetLocalLabel ();
- g_falsejump (CF_NONE, labf);
+ FalseLab = GetLocalLabel ();
+ g_falsejump (CF_NONE, FalseLab);
/* Parse second expression. Remember for later if it is a NULL pointer
* expression, then load it into the primary.
ED_MakeRValExpr (&Expr2);
Expr2.Type = PtrConversion (Expr2.Type);
}
- labt = GetLocalLabel ();
+
+ /* Remember the current code position */
+ GetCodePos (&TrueCodeEnd);
+
+ /* Jump around the evaluation of the third expression */
+ TrueLab = GetLocalLabel ();
ConsumeColon ();
- g_jump (labt);
+ g_jump (TrueLab);
/* Jump here if the first expression was false */
- g_defcodelabel (labf);
+ g_defcodelabel (FalseLab);
- /* Parse second expression. Remember for later if it is a NULL pointer
+ /* Parse third expression. Remember for later if it is a NULL pointer
* expression, then load it into the primary.
*/
ExprWithCheck (hie1, &Expr3);
*/
if (IsClassInt (Expr2.Type) && IsClassInt (Expr3.Type)) {
+ CodeMark CvtCodeStart;
+ CodeMark CvtCodeEnd;
+
+
/* Get common type */
ResultType = promoteint (Expr2.Type, Expr3.Type);
/* Convert the third expression to this type if needed */
TypeConversion (&Expr3, ResultType);
- /* Setup a new label so that the expr3 code will jump around
- * the type cast code for expr2.
- */
- labf = GetLocalLabel (); /* Get new label */
- g_jump (labf); /* Jump around code */
-
- /* The jump for expr2 goes here */
- g_defcodelabel (labt);
-
- /* Create the typecast code for expr2 */
+ /* Emit conversion code for the second expression, but remember
+ * where it starts end ends.
+ */
+ GetCodePos (&CvtCodeStart);
TypeConversion (&Expr2, ResultType);
+ GetCodePos (&CvtCodeEnd);
- /* Jump here around the typecase code. */
- g_defcodelabel (labf);
- labt = 0; /* Mark other label as invalid */
+ /* If we had conversion code, move it to the right place */
+ if (!CodeRangeIsEmpty (&CvtCodeStart, &CvtCodeEnd)) {
+ MoveCode (&CvtCodeStart, &CvtCodeEnd, &TrueCodeEnd);
+ }
} else if (IsClassPtr (Expr2.Type) && IsClassPtr (Expr3.Type)) {
/* Must point to same type */
ResultType = Expr2.Type; /* Doesn't matter here */
}
- /* If we don't have the label defined until now, do it */
- if (labt) {
- g_defcodelabel (labt);
- }
+ /* Define the final label */
+ g_defcodelabel (TrueLab);
/* Setup the target expression */
ED_MakeRValExpr (Expr);
-static void opeq (const GenDesc* Gen, ExprDesc* Expr)
+static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op)
/* Process "op=" operators. */
{
ExprDesc Expr2;
g_push (flags, 0);
/* Evaluate the rhs */
- if (evalexpr (CF_NONE, hie1, &Expr2) == 0) {
+ MarkedExprWithCheck (hie1, &Expr2);
+
+ /* The rhs must be an integer (or a float, but we don't support that yet */
+ if (!IsClassInt (Expr2.Type)) {
+ Error ("Invalid right operand for binary operator `%s'", Op);
+ /* Continue. Wrong code will be generated, but the compiler won't
+ * break, so this is the best error recovery.
+ */
+ }
+
+ /* Check for a constant expression */
+ if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
/* The resulting value is a constant. If the generator has the NOPUSH
* flag set, don't push the lhs.
*/
Gen->Func (flags | CF_CONST, Expr2.IVal);
}
} else {
- /* rhs is not constant and already in the primary register */
+
+ /* rhs is not constant. Load into the primary */
+ LoadExpr (CF_NONE, &Expr2);
if (MustScale) {
/* lhs is a pointer, scale rhs */
g_scale (TypeOf (Expr2.Type), CheckedSizeOf (Expr->Type+1));
-static void addsubeq (const GenDesc* Gen, ExprDesc *Expr)
+static void addsubeq (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
/* Process the += and -= operators */
{
ExprDesc Expr2;
/* We're currently only able to handle some adressing modes */
if (ED_GetLoc (Expr) == E_LOC_EXPR || ED_GetLoc (Expr) == E_LOC_PRIMARY) {
/* Use generic routine */
- opeq (Gen, Expr);
+ opeq (Gen, Expr, Op);
return;
}
lflags = 0;
rflags = 0;
- /* Evaluate the rhs */
+ /* Evaluate the rhs. We expect an integer here, since float is not
+ * supported
+ */
hie1 (&Expr2);
+ if (!IsClassInt (Expr2.Type)) {
+ Error ("Invalid right operand for binary operator `%s'", Op);
+ /* Continue. Wrong code will be generated, but the compiler won't
+ * break, so this is the best error recovery.
+ */
+ }
if (ED_IsConstAbs (&Expr2)) {
/* The resulting value is a constant. Scale it. */
if (MustScale) {
break;
case TOK_PLUS_ASSIGN:
- addsubeq (&GenPASGN, Expr);
+ addsubeq (&GenPASGN, Expr, "+=");
break;
case TOK_MINUS_ASSIGN:
- addsubeq (&GenSASGN, Expr);
+ addsubeq (&GenSASGN, Expr, "-=");
break;
case TOK_MUL_ASSIGN:
- opeq (&GenMASGN, Expr);
+ opeq (&GenMASGN, Expr, "*=");
break;
case TOK_DIV_ASSIGN:
- opeq (&GenDASGN, Expr);
+ opeq (&GenDASGN, Expr, "/=");
break;
case TOK_MOD_ASSIGN:
- opeq (&GenMOASGN, Expr);
+ opeq (&GenMOASGN, Expr, "%=");
break;
case TOK_SHL_ASSIGN:
- opeq (&GenSLASGN, Expr);
+ opeq (&GenSLASGN, Expr, "<<=");
break;
case TOK_SHR_ASSIGN:
- opeq (&GenSRASGN, Expr);
+ opeq (&GenSRASGN, Expr, ">>=");
break;
case TOK_AND_ASSIGN:
- opeq (&GenAASGN, Expr);
+ opeq (&GenAASGN, Expr, "&=");
break;
case TOK_XOR_ASSIGN:
- opeq (&GenXOASGN, Expr);
+ opeq (&GenXOASGN, Expr, "^=");
break;
case TOK_OR_ASSIGN:
- opeq (&GenOASGN, Expr);
+ opeq (&GenOASGN, Expr, "|=");
break;
default: