mirror of
https://github.com/cc65/cc65.git
synced 2024-12-25 02:29:52 +00:00
Reusing code from parseadd() for ArrayRef().
Now index[ptr] works in constant expressions. Fixed codegen for cast type in constant expressions. Calls on swapstk in 'i[ptr]' is avoided when possible.
This commit is contained in:
parent
f5972dfd08
commit
99c7fe0ada
393
src/cc65/expr.c
393
src/cc65/expr.c
@ -74,11 +74,20 @@ static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or };
|
|||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Helper functions */
|
/* Forward declarations */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void parseadd (ExprDesc* Expr, int DoArrayRef);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Helper functions */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
static unsigned GlobalModeFlags (const ExprDesc* Expr)
|
static unsigned GlobalModeFlags (const ExprDesc* Expr)
|
||||||
/* Return the addressing mode flags for the given expression */
|
/* Return the addressing mode flags for the given expression */
|
||||||
{
|
{
|
||||||
@ -1333,294 +1342,6 @@ static void Primary (ExprDesc* E)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ArrayRef (ExprDesc* Expr)
|
|
||||||
/* Handle an array reference. This function needs a rewrite. */
|
|
||||||
{
|
|
||||||
int ConstBaseAddr;
|
|
||||||
ExprDesc Subscript;
|
|
||||||
CodeMark Mark1;
|
|
||||||
CodeMark Mark2;
|
|
||||||
TypeCode Qualifiers;
|
|
||||||
Type* ElementType;
|
|
||||||
Type* tptr1;
|
|
||||||
|
|
||||||
ED_Init (&Subscript);
|
|
||||||
Subscript.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR;
|
|
||||||
|
|
||||||
/* Skip the bracket */
|
|
||||||
NextToken ();
|
|
||||||
|
|
||||||
/* Get the type of left side */
|
|
||||||
tptr1 = Expr->Type;
|
|
||||||
|
|
||||||
/* 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 "quasi-const base" address.
|
|
||||||
*/
|
|
||||||
ConstBaseAddr = ED_IsRVal (Expr) && ED_IsLocQuasiConst (Expr);
|
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
LoadExpr (CF_NONE, Expr);
|
|
||||||
|
|
||||||
/* Get the array pointer on stack. Do not push more than 16
|
|
||||||
** bit, even if this value is greater, since we cannot handle
|
|
||||||
** other than 16bit stuff when doing indexing.
|
|
||||||
*/
|
|
||||||
GetCodePos (&Mark2);
|
|
||||||
g_push (CF_PTR, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TOS now contains ptr to array elements. Get the 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
|
|
||||||
** integer type, or we have an integer to the left, in which case the
|
|
||||||
** subscript must be a pointer/array.
|
|
||||||
** 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)) {
|
|
||||||
Error ("Subscripted value is neither array nor pointer");
|
|
||||||
/* To avoid compiler errors, make the subscript a char[] at
|
|
||||||
** address 0.
|
|
||||||
*/
|
|
||||||
ED_MakeConstAbs (&Subscript, 0, GetCharArrayType (1));
|
|
||||||
} else if (IsTypeArray (Subscript.Type)) {
|
|
||||||
Qualifiers = GetQualifier (Subscript.Type);
|
|
||||||
}
|
|
||||||
ElementType = Indirect (Subscript.Type);
|
|
||||||
} else {
|
|
||||||
Error ("Cannot subscript");
|
|
||||||
/* To avoid compiler errors, fake both the array and the subscript, so
|
|
||||||
** we can just proceed.
|
|
||||||
*/
|
|
||||||
ED_MakeConstAbs (Expr, 0, GetCharArrayType (1));
|
|
||||||
ED_MakeConstAbsInt (&Subscript, 0);
|
|
||||||
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);
|
|
||||||
ED_FinalizeRValLoad (&Subscript);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make the address of the array element from the base and subscript */
|
|
||||||
if (ED_IsConstAbs (&Subscript) && ED_CodeRangeIsEmpty (&Subscript)) {
|
|
||||||
|
|
||||||
/* The array subscript is a constant. Since we can have the element
|
|
||||||
** address directly as base+offset, we can remove the array address
|
|
||||||
** push onto the stack before if loading subscript doesn't tamper that
|
|
||||||
** address in the primary.
|
|
||||||
*/
|
|
||||||
if (!ConstBaseAddr) {
|
|
||||||
RemoveCode (&Mark2);
|
|
||||||
} else {
|
|
||||||
/* Get an array pointer into the primary */
|
|
||||||
LoadExpr (CF_NONE, Expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsClassPtr (Expr->Type)) {
|
|
||||||
|
|
||||||
/* Lhs is pointer/array. Scale the subscript value according to
|
|
||||||
** the element size.
|
|
||||||
*/
|
|
||||||
Subscript.IVal *= CheckedSizeOf (ElementType);
|
|
||||||
|
|
||||||
/* Remove the address load code */
|
|
||||||
RemoveCode (&Mark1);
|
|
||||||
|
|
||||||
/* In case of an array, we can adjust the offset of the expression
|
|
||||||
** 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)) {
|
|
||||||
|
|
||||||
/* 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)) {
|
|
||||||
LoadExpr (CF_NONE, Expr);
|
|
||||||
ED_FinalizeRValLoad (Expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adjust the offset */
|
|
||||||
Expr->IVal += Subscript.IVal;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Scale the lhs value according to the element type */
|
|
||||||
g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType));
|
|
||||||
|
|
||||||
/* Add the subscript. Since arrays are indexed by integers,
|
|
||||||
** we will ignore the true type of the subscript here and
|
|
||||||
** use always an int. #### Use offset but beware of LoadExpr!
|
|
||||||
*/
|
|
||||||
g_inc (CF_INT | CF_CONST, Subscript.IVal);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Array subscript is not constant. Load it into the primary */
|
|
||||||
GetCodePos (&Mark2);
|
|
||||||
LoadExpr (CF_NONE, &Subscript);
|
|
||||||
|
|
||||||
/* Do scaling */
|
|
||||||
if (IsClassPtr (Expr->Type)) {
|
|
||||||
|
|
||||||
/* Indexing is based on unsigneds, so we will just use the integer
|
|
||||||
** portion of the index (which is in (e)ax, so there's no further
|
|
||||||
** action required).
|
|
||||||
*/
|
|
||||||
g_scale (CF_INT, CheckedSizeOf (ElementType));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Get the int value on top. If we come here, we're sure, both
|
|
||||||
** values are 16 bit (the first one was truncated if necessary
|
|
||||||
** and the second one is a pointer). Note: If ConstBaseAddr is
|
|
||||||
** true, we don't have a value on stack, so to "swap" both, just
|
|
||||||
** push the subscript.
|
|
||||||
*/
|
|
||||||
if (ConstBaseAddr) {
|
|
||||||
g_push (CF_INT, 0);
|
|
||||||
LoadExpr (CF_NONE, Expr);
|
|
||||||
ConstBaseAddr = 0;
|
|
||||||
} else {
|
|
||||||
g_swap (CF_INT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scale it */
|
|
||||||
g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The offset is now in the primary register. It we didn't have a
|
|
||||||
** constant base address for the lhs, the lhs address is already
|
|
||||||
** on stack, and we must add the offset. If the base address was
|
|
||||||
** constant, we call special functions to add the address to the
|
|
||||||
** offset value.
|
|
||||||
*/
|
|
||||||
if (!ConstBaseAddr) {
|
|
||||||
|
|
||||||
/* The array base address is on stack and the subscript is in the
|
|
||||||
** primary. Add both.
|
|
||||||
*/
|
|
||||||
g_add (CF_INT, 0);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* The subscript is in the primary, and the array base address is
|
|
||||||
** in Expr. If the subscript has itself a constant address, it is
|
|
||||||
** often a better idea to reverse again the order of the
|
|
||||||
** evaluation. This will generate better code if the subscript is
|
|
||||||
** a byte sized variable. But beware: This is only possible if the
|
|
||||||
** subscript was not scaled, that is, if this was a byte array
|
|
||||||
** or pointer.
|
|
||||||
*/
|
|
||||||
if (ED_IsLocQuasiConst (&Subscript) &&
|
|
||||||
CheckedSizeOf (ElementType) == SIZEOF_CHAR) {
|
|
||||||
|
|
||||||
unsigned Flags;
|
|
||||||
|
|
||||||
/* Reverse the order of evaluation */
|
|
||||||
if (CheckedSizeOf (Subscript.Type) == SIZEOF_CHAR) {
|
|
||||||
Flags = CF_CHAR;
|
|
||||||
} else {
|
|
||||||
Flags = CF_INT;
|
|
||||||
}
|
|
||||||
RemoveCode (&Mark2);
|
|
||||||
|
|
||||||
/* Get a pointer to the array into the primary. */
|
|
||||||
LoadExpr (CF_NONE, Expr);
|
|
||||||
|
|
||||||
/* Add the variable */
|
|
||||||
if (ED_IsLocStack (&Subscript)) {
|
|
||||||
g_addlocal (Flags, Subscript.IVal);
|
|
||||||
} else {
|
|
||||||
Flags |= GlobalModeFlags (&Subscript);
|
|
||||||
g_addstatic (Flags, Subscript.Name, Subscript.IVal);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
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 (ED_IsAddrExpr (Expr)) {
|
|
||||||
g_addaddr_local (CF_INT, Expr->IVal);
|
|
||||||
} else {
|
|
||||||
g_addlocal (CF_PTR, Expr->IVal);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Base address is a static variable address */
|
|
||||||
unsigned Flags = CF_INT | GlobalModeFlags (Expr);
|
|
||||||
if (ED_IsAddrExpr (Expr)) {
|
|
||||||
/* Add the address of the location */
|
|
||||||
g_addaddr_static (Flags, Expr->Name, Expr->IVal);
|
|
||||||
} else {
|
|
||||||
/* Add the contents of the location */
|
|
||||||
g_addstatic (Flags, Expr->Name, Expr->IVal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The address of the element is an rvalue in the primary */
|
|
||||||
ED_FinalizeRValLoad (Expr);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The final result is usually an lvalue expression of element type
|
|
||||||
** referenced in the primary, unless it is once again an array. 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 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_AddrExpr (Expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Consume the closing bracket */
|
|
||||||
ConsumeRBrack ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void StructRef (ExprDesc* Expr)
|
static void StructRef (ExprDesc* Expr)
|
||||||
/* Process struct/union field after . or ->. */
|
/* Process struct/union field after . or ->. */
|
||||||
{
|
{
|
||||||
@ -1793,7 +1514,7 @@ static void hie11 (ExprDesc *Expr)
|
|||||||
|
|
||||||
case TOK_LBRACK:
|
case TOK_LBRACK:
|
||||||
/* Array reference */
|
/* Array reference */
|
||||||
ArrayRef (Expr);
|
parseadd (Expr, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_LPAREN:
|
case TOK_LPAREN:
|
||||||
@ -3034,10 +2755,11 @@ static void hie9 (ExprDesc *Expr)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void parseadd (ExprDesc* Expr)
|
static void parseadd (ExprDesc* Expr, int DoArrayRef)
|
||||||
/* Parse an expression with the binary plus operator. Expr contains the
|
/* Parse an expression with the binary plus or subscript operator. Expr contains
|
||||||
** unprocessed left hand side of the expression and will contain the
|
** the unprocessed left hand side of the expression and will contain the result
|
||||||
** result of the expression on return.
|
** of the expression on return. If DoArrayRef is zero, this evaluates the binary
|
||||||
|
** plus operation. Otherwise, this evaluates the subscript operation.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ExprDesc Expr2;
|
ExprDesc Expr2;
|
||||||
@ -3052,7 +2774,7 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
ED_Init (&Expr2);
|
ED_Init (&Expr2);
|
||||||
Expr2.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR;
|
Expr2.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR;
|
||||||
|
|
||||||
/* Skip the PLUS token */
|
/* Skip the PLUS or opening bracket token */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Get the left hand side type, initialize operation flags */
|
/* Get the left hand side type, initialize operation flags */
|
||||||
@ -3077,7 +2799,7 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
if (ED_IsQuasiConst (Expr)) {
|
if (ED_IsQuasiConst (Expr)) {
|
||||||
|
|
||||||
/* The left hand side is a constant of some sort. Good. Get rhs */
|
/* The left hand side is a constant of some sort. Good. Get rhs */
|
||||||
ExprWithCheck (hie9, &Expr2);
|
ExprWithCheck (DoArrayRef ? hie0 : hie9, &Expr2);
|
||||||
|
|
||||||
/* Right hand side is constant. Get the rhs type */
|
/* Right hand side is constant. Get the rhs type */
|
||||||
rhst = Expr2.Type;
|
rhst = Expr2.Type;
|
||||||
@ -3094,7 +2816,7 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
lscale = CheckedPSizeOf (rhst);
|
lscale = CheckedPSizeOf (rhst);
|
||||||
/* Operate on pointers, result type is a pointer */
|
/* Operate on pointers, result type is a pointer */
|
||||||
flags = CF_PTR;
|
flags = CF_PTR;
|
||||||
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
} else if (!DoArrayRef && IsClassInt (lhst) && IsClassInt (rhst)) {
|
||||||
/* Integer addition */
|
/* Integer addition */
|
||||||
flags = CF_INT;
|
flags = CF_INT;
|
||||||
} else {
|
} else {
|
||||||
@ -3123,13 +2845,14 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (AddDone) {
|
if (AddDone) {
|
||||||
/* Adjust the result */
|
/* Adjust the result for addition */
|
||||||
|
if (!DoArrayRef) {
|
||||||
if (IsClassPtr (lhst)) {
|
if (IsClassPtr (lhst)) {
|
||||||
/* Result type is a pointer */
|
/* Result type is a pointer */
|
||||||
Expr->Type = PtrConversion (lhst);
|
Expr->Type = lhst;
|
||||||
} else if (IsClassPtr (rhst)) {
|
} else if (IsClassPtr (rhst)) {
|
||||||
/* Result type is a pointer */
|
/* Result type is a pointer */
|
||||||
Expr->Type = PtrConversion (rhst);
|
Expr->Type = rhst;
|
||||||
} else {
|
} else {
|
||||||
/* Limit the calculated value to the range of its type */
|
/* Limit the calculated value to the range of its type */
|
||||||
LimitExprValue (Expr);
|
LimitExprValue (Expr);
|
||||||
@ -3137,6 +2860,7 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
|
|
||||||
/* The result is always an rvalue */
|
/* The result is always an rvalue */
|
||||||
ED_MarkExprAsRVal (Expr);
|
ED_MarkExprAsRVal (Expr);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Decide the order */
|
/* Decide the order */
|
||||||
if (!ED_IsAbs (&Expr2) && rscale > 1) {
|
if (!ED_IsAbs (&Expr2) && rscale > 1) {
|
||||||
@ -3214,7 +2938,7 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
/* Operate on pointers, result type is a pointer */
|
/* Operate on pointers, result type is a pointer */
|
||||||
flags |= CF_PTR;
|
flags |= CF_PTR;
|
||||||
Expr->Type = Expr2.Type;
|
Expr->Type = Expr2.Type;
|
||||||
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
} else if (!DoArrayRef && IsClassInt (lhst) && IsClassInt (rhst)) {
|
||||||
/* Integer addition */
|
/* Integer addition */
|
||||||
flags |= typeadjust (Expr, &Expr2, 1);
|
flags |= typeadjust (Expr, &Expr2, 1);
|
||||||
} else {
|
} else {
|
||||||
@ -3270,8 +2994,6 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
g_add (CF_PTR, 0);
|
g_add (CF_PTR, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Array and function types must be converted to pointer types */
|
|
||||||
Expr->Type = PtrConversion (Expr->Type);
|
|
||||||
|
|
||||||
/* Result is an rvalue in primary register */
|
/* Result is an rvalue in primary register */
|
||||||
ED_FinalizeRValLoad (Expr);
|
ED_FinalizeRValLoad (Expr);
|
||||||
@ -3286,7 +3008,7 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
g_push (flags, 0); /* --> stack */
|
g_push (flags, 0); /* --> stack */
|
||||||
|
|
||||||
/* Evaluate the rhs */
|
/* Evaluate the rhs */
|
||||||
MarkedExprWithCheck (hie9, &Expr2);
|
MarkedExprWithCheck (DoArrayRef ? hie0 : hie9, &Expr2);
|
||||||
|
|
||||||
/* Get the rhs type */
|
/* Get the rhs type */
|
||||||
rhst = Expr2.Type;
|
rhst = Expr2.Type;
|
||||||
@ -3309,7 +3031,7 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
/* Operate on pointers, result type is a pointer */
|
/* Operate on pointers, result type is a pointer */
|
||||||
flags = CF_PTR;
|
flags = CF_PTR;
|
||||||
Expr->Type = Expr2.Type;
|
Expr->Type = Expr2.Type;
|
||||||
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
} else if (!DoArrayRef && IsClassInt (lhst) && IsClassInt (rhst)) {
|
||||||
/* Integer addition */
|
/* Integer addition */
|
||||||
flags = typeadjust (Expr, &Expr2, 1);
|
flags = typeadjust (Expr, &Expr2, 1);
|
||||||
} else {
|
} else {
|
||||||
@ -3356,7 +3078,7 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
/* Operate on pointers, result type is a pointer */
|
/* Operate on pointers, result type is a pointer */
|
||||||
flags = CF_PTR;
|
flags = CF_PTR;
|
||||||
Expr->Type = Expr2.Type;
|
Expr->Type = Expr2.Type;
|
||||||
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
} else if (!DoArrayRef && IsClassInt (lhst) && IsClassInt (rhst)) {
|
||||||
/* Integer addition. Note: Result is never constant.
|
/* Integer addition. Note: Result is never constant.
|
||||||
** Problem here is that typeadjust does not know if the
|
** Problem here is that typeadjust does not know if the
|
||||||
** variable is an rvalue or lvalue, so if both operands
|
** variable is an rvalue or lvalue, so if both operands
|
||||||
@ -3380,19 +3102,70 @@ static void parseadd (ExprDesc* Expr)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Array and function types must be converted to pointer types */
|
|
||||||
Expr->Type = PtrConversion (Expr->Type);
|
|
||||||
|
|
||||||
/* Result is an rvalue in primary register */
|
/* Result is an rvalue in primary register */
|
||||||
ED_FinalizeRValLoad (Expr);
|
ED_FinalizeRValLoad (Expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Deal with array ref */
|
||||||
|
if (DoArrayRef) {
|
||||||
|
TypeCode Qualifiers = T_QUAL_NONE;
|
||||||
|
Type* ElementType;
|
||||||
|
|
||||||
|
/* Check the types of array and subscript */
|
||||||
|
if (IsClassPtr (lhst)) {
|
||||||
|
if (!IsClassInt (rhst)) {
|
||||||
|
Error ("Array subscript is not an integer");
|
||||||
|
ED_MakeConstAbs (Expr, 0, GetCharArrayType (1));
|
||||||
|
} else if (IsTypeArray (lhst)) {
|
||||||
|
Qualifiers = GetQualifier (lhst);
|
||||||
|
}
|
||||||
|
} else if (IsClassInt (lhst)) {
|
||||||
|
if (!IsClassPtr (rhst)) {
|
||||||
|
Error ("Subscripted value is neither array nor pointer");
|
||||||
|
ED_MakeConstAbs (Expr, 0, GetCharArrayType (1));
|
||||||
|
} else if (IsTypeArray (rhst)) {
|
||||||
|
Qualifiers = GetQualifier (rhst);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Error ("Cannot subscript");
|
||||||
|
ED_MakeConstAbs (Expr, 0, GetCharArrayType (1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The element type has the combined qualifiers from itself and the array,
|
||||||
|
** it is a member of (if any).
|
||||||
|
*/
|
||||||
|
ElementType = Indirect (Expr->Type);
|
||||||
|
if (GetQualifier (ElementType) != (GetQualifier (ElementType) | Qualifiers)) {
|
||||||
|
ElementType = TypeDup (ElementType);
|
||||||
|
ElementType->C |= Qualifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The final result is usually an lvalue expression of element type
|
||||||
|
** referenced in the primary, unless it is once again an array. 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 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_AddrExpr (Expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consume the closing bracket */
|
||||||
|
ConsumeRBrack ();
|
||||||
|
} else {
|
||||||
if (AddDone < 0) {
|
if (AddDone < 0) {
|
||||||
Error ("Invalid operands for binary operator '+'");
|
Error ("Invalid operands for binary operator '+'");
|
||||||
} else {
|
} else {
|
||||||
/* Array and function types must be converted to pointer types */
|
/* Array and function types must be converted to pointer types */
|
||||||
Expr->Type = PtrConversion (Expr->Type);
|
Expr->Type = PtrConversion (Expr->Type);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Condition code not set */
|
/* Condition code not set */
|
||||||
ED_MarkAsUntested (Expr);
|
ED_MarkAsUntested (Expr);
|
||||||
@ -3658,7 +3431,7 @@ void hie8 (ExprDesc* Expr)
|
|||||||
ExprWithCheck (hie9, Expr);
|
ExprWithCheck (hie9, Expr);
|
||||||
while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) {
|
while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) {
|
||||||
if (CurTok.Tok == TOK_PLUS) {
|
if (CurTok.Tok == TOK_PLUS) {
|
||||||
parseadd (Expr);
|
parseadd (Expr, 0);
|
||||||
} else {
|
} else {
|
||||||
parsesub (Expr);
|
parsesub (Expr);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user