1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-09 06:29:38 +00:00

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:
cuz 2002-11-01 15:16:16 +00:00
parent 571ea849d9
commit 5548b6fd56
6 changed files with 288 additions and 105 deletions

View File

@ -31,6 +31,7 @@
#include "scanner.h"
#include "stdfunc.h"
#include "symtab.h"
#include "typecast.h"
#include "typecmp.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);
/* Expression parser; func is either hie0 or hie1. */
@ -501,7 +499,7 @@ void exprhs (unsigned flags, int k, ExprDesc *lval)
f = lval->Flags;
if (k) {
/* Dereferenced lvalue */
flags |= TypeOf (lval->Type);
flags |= TypeOf (lval->Type);
if (lval->Test & E_FORCETEST) {
flags |= CF_TEST;
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 */
lconst (flags, lval);
}
if (lval->Test & E_FORCETEST) { /* we testing this value? */
/* debug... */
/* Are we testing this value? */
if (lval->Test & E_FORCETEST) {
/* Yes, force a test */
flags |= TypeOf (lval->Type);
g_test (flags); /* yes, force a test */
g_test (flags);
lval->Test &= ~E_FORCETEST;
}
}
@ -1234,7 +1233,7 @@ static int arrayref (int k, ExprDesc* lval)
/* Constant numeric address. Just add it */
g_inc (CF_INT | CF_UNSIGNED, lval->ConstVal);
} else if (lflags == E_MLOCAL) {
/* Base address is a local variable address */
/* Base address is a local variable address */
if (IsTypeArray (tptr1)) {
g_addaddr_local (CF_INT, lval->ConstVal);
} else {
@ -1291,8 +1290,8 @@ static int structref (int k, ExprDesc* lval)
flags = lval->Flags & ~E_MCTYPE;
if (flags == E_MCONST ||
(k == 0 && (flags == E_MLOCAL ||
(flags & E_MGLOBAL) != 0 ||
lval->Flags == E_MEOFFS))) {
(flags & E_MGLOBAL) != 0 ||
lval->Flags == E_MEOFFS))) {
lval->ConstVal += Field->V.Offs;
} else {
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++ */
{
unsigned flags;
@ -1564,99 +1563,7 @@ static void unaryop (int tok, ExprDesc* lval)
static int typecast (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)
int hie10 (ExprDesc* lval)
/* Handle ++, --, !, unary - etc. */
{
int k;
@ -1747,7 +1654,7 @@ static int hie10 (ExprDesc* lval)
default:
if (istypeexpr ()) {
/* A cast */
return typecast (lval);
return TypeCast (lval);
}
}

View File

@ -107,6 +107,9 @@ void boolexpr (ExprDesc* lval);
void test (unsigned label, int cond);
/* Generate code to perform test and jump if false. */
int hie10 (ExprDesc* lval);
/* Handle ++, --, !, unary - etc. */
int hie1 (ExprDesc* lval);
/* Parse first level of expression hierarchy. */

View File

@ -81,6 +81,7 @@ OBJS = anonname.o \
symentry.o \
symtab.o \
textseg.o \
typecast.o \
typecmp.o \
util.o

View File

@ -126,6 +126,7 @@ OBJS = anonname.obj \
symentry.obj \
symtab.obj \
textseg.obj \
typecast.obj \
typecmp.obj \
util.obj
@ -209,6 +210,7 @@ FILE swstmt.obj
FILE symentry.obj
FILE symtab.obj
FILE textseg.obj
FILE typecast.obj
FILE typecmp.obj
FILE util.obj
LIBRARY ..\common\common.lib

212
src/cc65/typecast.c Normal file
View 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
View 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