/* 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);
}
}
}
+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);
}
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;
* 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);
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;
}
Expr->IVal += Field->V.Offs;
/* The type is the type of the field plus any qualifiers from the struct */
- Q = GetQualifier (Expr->Type);
- if (Q == T_QUAL_NONE) {
+ 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);
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 {
/* 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 ();
/* 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);
}
}