Work on better type casts - not yet finished
git-svn-id: svn://svn.cc65.org/cc65/trunk@1476 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
117
src/cc65/expr.c
117
src/cc65/expr.c
@@ -31,6 +31,7 @@
|
|||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "stdfunc.h"
|
#include "stdfunc.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
|
#include "typecast.h"
|
||||||
#include "typecmp.h"
|
#include "typecmp.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
|
||||||
@@ -86,9 +87,6 @@ static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or };
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int hie10 (ExprDesc* lval);
|
|
||||||
/* Handle ++, --, !, unary - etc. */
|
|
||||||
|
|
||||||
static int expr (int (*func) (ExprDesc*), ExprDesc *lval);
|
static int expr (int (*func) (ExprDesc*), ExprDesc *lval);
|
||||||
/* Expression parser; func is either hie0 or hie1. */
|
/* Expression parser; func is either hie0 or hie1. */
|
||||||
|
|
||||||
@@ -501,7 +499,7 @@ void exprhs (unsigned flags, int k, ExprDesc *lval)
|
|||||||
f = lval->Flags;
|
f = lval->Flags;
|
||||||
if (k) {
|
if (k) {
|
||||||
/* Dereferenced lvalue */
|
/* Dereferenced lvalue */
|
||||||
flags |= TypeOf (lval->Type);
|
flags |= TypeOf (lval->Type);
|
||||||
if (lval->Test & E_FORCETEST) {
|
if (lval->Test & E_FORCETEST) {
|
||||||
flags |= CF_TEST;
|
flags |= CF_TEST;
|
||||||
lval->Test &= ~E_FORCETEST;
|
lval->Test &= ~E_FORCETEST;
|
||||||
@@ -529,10 +527,11 @@ void exprhs (unsigned flags, int k, ExprDesc *lval)
|
|||||||
/* Constant of some sort, load it into the primary */
|
/* Constant of some sort, load it into the primary */
|
||||||
lconst (flags, lval);
|
lconst (flags, lval);
|
||||||
}
|
}
|
||||||
if (lval->Test & E_FORCETEST) { /* we testing this value? */
|
/* Are we testing this value? */
|
||||||
/* debug... */
|
if (lval->Test & E_FORCETEST) {
|
||||||
|
/* Yes, force a test */
|
||||||
flags |= TypeOf (lval->Type);
|
flags |= TypeOf (lval->Type);
|
||||||
g_test (flags); /* yes, force a test */
|
g_test (flags);
|
||||||
lval->Test &= ~E_FORCETEST;
|
lval->Test &= ~E_FORCETEST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1234,7 +1233,7 @@ static int arrayref (int k, ExprDesc* lval)
|
|||||||
/* Constant numeric address. Just add it */
|
/* Constant numeric address. Just add it */
|
||||||
g_inc (CF_INT | CF_UNSIGNED, lval->ConstVal);
|
g_inc (CF_INT | CF_UNSIGNED, lval->ConstVal);
|
||||||
} else if (lflags == E_MLOCAL) {
|
} else if (lflags == E_MLOCAL) {
|
||||||
/* Base address is a local variable address */
|
/* Base address is a local variable address */
|
||||||
if (IsTypeArray (tptr1)) {
|
if (IsTypeArray (tptr1)) {
|
||||||
g_addaddr_local (CF_INT, lval->ConstVal);
|
g_addaddr_local (CF_INT, lval->ConstVal);
|
||||||
} else {
|
} else {
|
||||||
@@ -1291,8 +1290,8 @@ static int structref (int k, ExprDesc* lval)
|
|||||||
flags = lval->Flags & ~E_MCTYPE;
|
flags = lval->Flags & ~E_MCTYPE;
|
||||||
if (flags == E_MCONST ||
|
if (flags == E_MCONST ||
|
||||||
(k == 0 && (flags == E_MLOCAL ||
|
(k == 0 && (flags == E_MLOCAL ||
|
||||||
(flags & E_MGLOBAL) != 0 ||
|
(flags & E_MGLOBAL) != 0 ||
|
||||||
lval->Flags == E_MEOFFS))) {
|
lval->Flags == E_MEOFFS))) {
|
||||||
lval->ConstVal += Field->V.Offs;
|
lval->ConstVal += Field->V.Offs;
|
||||||
} else {
|
} else {
|
||||||
if ((flags & E_MEXPR) == 0 || k != 0) {
|
if ((flags & E_MEXPR) == 0 || k != 0) {
|
||||||
@@ -1490,7 +1489,7 @@ static void pre_incdec (ExprDesc* lval, void (*inc) (unsigned, unsigned long))
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void post_incdec (ExprDesc *lval, int k, void (*inc) (unsigned, unsigned long))
|
static void post_incdec (ExprDesc* lval, int k, void (*inc) (unsigned, unsigned long))
|
||||||
/* Handle i-- and i++ */
|
/* Handle i-- and i++ */
|
||||||
{
|
{
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
@@ -1564,99 +1563,7 @@ static void unaryop (int tok, ExprDesc* lval)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int typecast (ExprDesc* lval)
|
int hie10 (ExprDesc* lval)
|
||||||
/* Handle an explicit cast */
|
|
||||||
{
|
|
||||||
int k;
|
|
||||||
type Type[MAXTYPELEN];
|
|
||||||
|
|
||||||
/* Skip the left paren */
|
|
||||||
NextToken ();
|
|
||||||
|
|
||||||
/* Read the type */
|
|
||||||
ParseType (Type);
|
|
||||||
|
|
||||||
/* Closing paren */
|
|
||||||
ConsumeRParen ();
|
|
||||||
|
|
||||||
/* Read the expression we have to cast */
|
|
||||||
k = hie10 (lval);
|
|
||||||
|
|
||||||
/* If the expression is a function, treat it as pointer-to-function */
|
|
||||||
if (IsTypeFunc (lval->Type)) {
|
|
||||||
lval->Type = PointerTo (lval->Type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for a constant on the right side */
|
|
||||||
if (k == 0 && lval->Flags == E_MCONST) {
|
|
||||||
|
|
||||||
/* A cast of a constant to something else. If the new type is an int,
|
|
||||||
* be sure to handle the size extension correctly. If the new type is
|
|
||||||
* not an int, the cast is implementation specific anyway, so leave
|
|
||||||
* the value alone.
|
|
||||||
*/
|
|
||||||
if (IsClassInt (Type)) {
|
|
||||||
|
|
||||||
/* Get the current and new size of the value */
|
|
||||||
unsigned OldBits = CheckedSizeOf (lval->Type) * 8;
|
|
||||||
unsigned NewBits = CheckedSizeOf (Type) * 8;
|
|
||||||
|
|
||||||
/* Check if the new datatype will have a smaller range */
|
|
||||||
if (NewBits <= OldBits) {
|
|
||||||
|
|
||||||
/* Cut the value to the new size */
|
|
||||||
lval->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits));
|
|
||||||
|
|
||||||
/* If the new type is signed, sign extend the value */
|
|
||||||
if (!IsSignUnsigned (Type)) {
|
|
||||||
lval->ConstVal |= ((~0L) << NewBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Sign extend the value if needed */
|
|
||||||
if (!IsSignUnsigned (lval->Type) && !IsSignUnsigned (Type)) {
|
|
||||||
if (lval->ConstVal & (0x01UL << (OldBits-1))) {
|
|
||||||
lval->ConstVal |= ((~0L) << OldBits);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Not a constant. Be sure to ignore casts to void */
|
|
||||||
if (!IsTypeVoid (Type)) {
|
|
||||||
|
|
||||||
/* If the size does not change, leave the value alone. Otherwise,
|
|
||||||
* we have to load the value into the primary and generate code to
|
|
||||||
* cast the value in the primary register.
|
|
||||||
*/
|
|
||||||
if (SizeOf (Type) != SizeOf (lval->Type)) {
|
|
||||||
|
|
||||||
/* Load the value into the primary */
|
|
||||||
exprhs (CF_NONE, k, lval);
|
|
||||||
|
|
||||||
/* Emit typecast code */
|
|
||||||
g_typecast (TypeOf (Type), TypeOf (lval->Type));
|
|
||||||
|
|
||||||
/* Value is now in primary */
|
|
||||||
lval->Flags = E_MEXPR;
|
|
||||||
k = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In any case, use the new type */
|
|
||||||
lval->Type = TypeDup (Type);
|
|
||||||
|
|
||||||
/* Done */
|
|
||||||
return k;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int hie10 (ExprDesc* lval)
|
|
||||||
/* Handle ++, --, !, unary - etc. */
|
/* Handle ++, --, !, unary - etc. */
|
||||||
{
|
{
|
||||||
int k;
|
int k;
|
||||||
@@ -1747,7 +1654,7 @@ static int hie10 (ExprDesc* lval)
|
|||||||
default:
|
default:
|
||||||
if (istypeexpr ()) {
|
if (istypeexpr ()) {
|
||||||
/* A cast */
|
/* A cast */
|
||||||
return typecast (lval);
|
return TypeCast (lval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,9 @@ void boolexpr (ExprDesc* lval);
|
|||||||
void test (unsigned label, int cond);
|
void test (unsigned label, int cond);
|
||||||
/* Generate code to perform test and jump if false. */
|
/* Generate code to perform test and jump if false. */
|
||||||
|
|
||||||
|
int hie10 (ExprDesc* lval);
|
||||||
|
/* Handle ++, --, !, unary - etc. */
|
||||||
|
|
||||||
int hie1 (ExprDesc* lval);
|
int hie1 (ExprDesc* lval);
|
||||||
/* Parse first level of expression hierarchy. */
|
/* Parse first level of expression hierarchy. */
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ OBJS = anonname.o \
|
|||||||
symentry.o \
|
symentry.o \
|
||||||
symtab.o \
|
symtab.o \
|
||||||
textseg.o \
|
textseg.o \
|
||||||
|
typecast.o \
|
||||||
typecmp.o \
|
typecmp.o \
|
||||||
util.o
|
util.o
|
||||||
|
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ OBJS = anonname.obj \
|
|||||||
symentry.obj \
|
symentry.obj \
|
||||||
symtab.obj \
|
symtab.obj \
|
||||||
textseg.obj \
|
textseg.obj \
|
||||||
|
typecast.obj \
|
||||||
typecmp.obj \
|
typecmp.obj \
|
||||||
util.obj
|
util.obj
|
||||||
|
|
||||||
@@ -209,6 +210,7 @@ FILE swstmt.obj
|
|||||||
FILE symentry.obj
|
FILE symentry.obj
|
||||||
FILE symtab.obj
|
FILE symtab.obj
|
||||||
FILE textseg.obj
|
FILE textseg.obj
|
||||||
|
FILE typecast.obj
|
||||||
FILE typecmp.obj
|
FILE typecmp.obj
|
||||||
FILE util.obj
|
FILE util.obj
|
||||||
LIBRARY ..\common\common.lib
|
LIBRARY ..\common\common.lib
|
||||||
|
|||||||
212
src/cc65/typecast.c
Normal file
212
src/cc65/typecast.c
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* typecast.c */
|
||||||
|
/* */
|
||||||
|
/* Handle type casts */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* (C) 2002 Ullrich von Bassewitz */
|
||||||
|
/* Wacholderweg 14 */
|
||||||
|
/* D-70597 Stuttgart */
|
||||||
|
/* EMail: uz@cc65.org */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
/* warranty. In no event will the authors be held liable for any damages */
|
||||||
|
/* arising from the use of this software. */
|
||||||
|
/* */
|
||||||
|
/* Permission is granted to anyone to use this software for any purpose, */
|
||||||
|
/* including commercial applications, and to alter it and redistribute it */
|
||||||
|
/* freely, subject to the following restrictions: */
|
||||||
|
/* */
|
||||||
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||||
|
/* claim that you wrote the original software. If you use this software */
|
||||||
|
/* in a product, an acknowledgment in the product documentation would be */
|
||||||
|
/* appreciated but is not required. */
|
||||||
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||||
|
/* be misrepresented as being the original software. */
|
||||||
|
/* 3. This notice may not be removed or altered from any source */
|
||||||
|
/* distribution. */
|
||||||
|
/* */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* cc65 */
|
||||||
|
#include "codegen.h"
|
||||||
|
#include "datatype.h"
|
||||||
|
#include "declare.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "expr.h"
|
||||||
|
#include "scanner.h"
|
||||||
|
#include "typecast.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Code */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int TypeCast (ExprDesc* lval)
|
||||||
|
/* Handle an explicit cast. The function returns true if the resulting
|
||||||
|
* expression is an lvalue and false if not.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
type* OldType;
|
||||||
|
type NewType[MAXTYPELEN];
|
||||||
|
unsigned OldSize;
|
||||||
|
unsigned NewSize;
|
||||||
|
|
||||||
|
/* Skip the left paren */
|
||||||
|
NextToken ();
|
||||||
|
|
||||||
|
/* Read the type */
|
||||||
|
ParseType (NewType);
|
||||||
|
|
||||||
|
/* Closing paren */
|
||||||
|
ConsumeRParen ();
|
||||||
|
|
||||||
|
/* Read the expression we have to cast */
|
||||||
|
k = hie10 (lval);
|
||||||
|
|
||||||
|
/* If the expression is a function, treat it as pointer-to-function */
|
||||||
|
if (IsTypeFunc (lval->Type)) {
|
||||||
|
lval->Type = PointerTo (lval->Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remember the old type and use the new one */
|
||||||
|
OldType = lval->Type;
|
||||||
|
lval->Type = TypeDup (NewType);
|
||||||
|
|
||||||
|
/* If we're casting to void, we're done. Note: This does also cover a cast
|
||||||
|
* void -> void.
|
||||||
|
*/
|
||||||
|
if (IsTypeVoid (NewType)) {
|
||||||
|
return 0; /* Never an lvalue */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't allow casts from void to something else. The new type is already
|
||||||
|
* set which should avoid more errors, but code will not get generated
|
||||||
|
* because of the error.
|
||||||
|
*/
|
||||||
|
if (IsTypeVoid (OldType)) {
|
||||||
|
Error ("Cannot cast from `void' to something else");
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the sizes of the types. Since we've excluded void types, checking
|
||||||
|
* for known sizes makes sense here.
|
||||||
|
*/
|
||||||
|
OldSize = CheckedSizeOf (OldType);
|
||||||
|
NewSize = CheckedSizeOf (NewType);
|
||||||
|
|
||||||
|
/* Is this a cast of something into an integer? */
|
||||||
|
if (IsClassInt (NewType)) {
|
||||||
|
|
||||||
|
/* lvalue? */
|
||||||
|
if (k != 0) {
|
||||||
|
|
||||||
|
/* We have an lvalue. If the new size is smaller than the new one,
|
||||||
|
* we don't need to do anything. The compiler will generate code
|
||||||
|
* to load only the portion of the value that is actually needed.
|
||||||
|
* This works only on a little endian architecture, but that's
|
||||||
|
* what we support.
|
||||||
|
* If both sizes are equal, do also leave the value alone.
|
||||||
|
* If the new size is larger, we must convert the value.
|
||||||
|
*/
|
||||||
|
if (NewSize > OldSize) {
|
||||||
|
/* Load the value into the primary */
|
||||||
|
exprhs (CF_NONE, k, lval);
|
||||||
|
|
||||||
|
/* Emit typecast code */
|
||||||
|
g_typecast (TypeOf (OldType), TypeOf (NewType));
|
||||||
|
|
||||||
|
/* Value is now in primary */
|
||||||
|
lval->Flags = E_MEXPR;
|
||||||
|
k = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* We have an rvalue. Check for a constant. */
|
||||||
|
if (lval->Flags == E_MCONST) {
|
||||||
|
|
||||||
|
/* A cast of a constant to an integer. Be sure to handle sign
|
||||||
|
* extension correctly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Get the current and new size of the value */
|
||||||
|
unsigned OldBits = OldSize * 8;
|
||||||
|
unsigned NewBits = NewSize * 8;
|
||||||
|
|
||||||
|
/* Check if the new datatype will have a smaller range */
|
||||||
|
if (NewBits <= OldBits) {
|
||||||
|
|
||||||
|
/* Cut the value to the new size */
|
||||||
|
lval->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits));
|
||||||
|
|
||||||
|
/* If the new type is signed, sign extend the value */
|
||||||
|
if (!IsSignUnsigned (NewType)) {
|
||||||
|
lval->ConstVal |= ((~0L) << NewBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Sign extend the value if needed */
|
||||||
|
if (!IsSignUnsigned (OldType) && !IsSignUnsigned (NewType)) {
|
||||||
|
if (lval->ConstVal & (0x01UL << (OldBits-1))) {
|
||||||
|
lval->ConstVal |= ((~0L) << OldBits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* The value is not a constant. If the sizes of the types are
|
||||||
|
* not equal, add conversion code. Be sure to convert chars
|
||||||
|
* correctly.
|
||||||
|
*/
|
||||||
|
if (OldSize != NewSize) {
|
||||||
|
|
||||||
|
/* Load the value into the primary */
|
||||||
|
exprhs (CF_NONE, k, lval);
|
||||||
|
|
||||||
|
/* Emit typecast code. ### CHARS */
|
||||||
|
g_typecast (TypeOf (OldType), TypeOf (NewType));
|
||||||
|
|
||||||
|
/* Value is now in primary */
|
||||||
|
lval->Flags = E_MEXPR;
|
||||||
|
k = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* All other stuff is handled equally */
|
||||||
|
if (NewSize != OldSize) {
|
||||||
|
/* Load the value into the primary */
|
||||||
|
exprhs (CF_NONE, k, lval);
|
||||||
|
|
||||||
|
/* Emit typecast code */
|
||||||
|
g_typecast (TypeOf (OldType), TypeOf (NewType));
|
||||||
|
|
||||||
|
/* Value is now in primary */
|
||||||
|
lval->Flags = E_MEXPR;
|
||||||
|
k = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Done */
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
58
src/cc65/typecast.h
Normal file
58
src/cc65/typecast.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* typecast.h */
|
||||||
|
/* */
|
||||||
|
/* Handle type casts */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* (C) 2002 Ullrich von Bassewitz */
|
||||||
|
/* Wacholderweg 14 */
|
||||||
|
/* D-70597 Stuttgart */
|
||||||
|
/* EMail: uz@cc65.org */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
/* warranty. In no event will the authors be held liable for any damages */
|
||||||
|
/* arising from the use of this software. */
|
||||||
|
/* */
|
||||||
|
/* Permission is granted to anyone to use this software for any purpose, */
|
||||||
|
/* including commercial applications, and to alter it and redistribute it */
|
||||||
|
/* freely, subject to the following restrictions: */
|
||||||
|
/* */
|
||||||
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||||
|
/* claim that you wrote the original software. If you use this software */
|
||||||
|
/* in a product, an acknowledgment in the product documentation would be */
|
||||||
|
/* appreciated but is not required. */
|
||||||
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||||
|
/* be misrepresented as being the original software. */
|
||||||
|
/* 3. This notice may not be removed or altered from any source */
|
||||||
|
/* distribution. */
|
||||||
|
/* */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TYPECAST_H
|
||||||
|
#define TYPECAST_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Code */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int TypeCast (ExprDesc* lval);
|
||||||
|
/* Handle an explicit cast. The function returns true if the resulting
|
||||||
|
* expression is an lvalue and false if not.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* End of typecast.h */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user