SymEntry* Entry;
/* Output the global data segment */
- CHECK (CS_GetEntryCount (CS->Code) == 0);
+ CHECK (!HaveGlobalCode ());
OutputSegments (CS, F);
/* Output all global or referenced functions */
/* */
/* */
/* */
-/* (C) 2002 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
+/* (C) 2002-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
#include "error.h"
#include "expr.h"
#include "typecmp.h"
+#include "typeconv.h"
#include "assignment.h"
-void Assignment (ExprDesc* lval)
+int Assignment (ExprDesc* lval)
/* Parse an assignment */
{
int k;
if (UseReg) {
PushAddr (lval);
} else {
- exprhs (0, 0, lval);
+ exprhs (0, 0, lval);
g_push (CF_PTR | CF_UNSIGNED, 0);
}
} else {
- /* Get the address on stack if needed */
- PushAddr (lval);
+ /* Get the address on stack if needed */
+ PushAddr (lval);
- /* Get the expression on the right of the '=' into the primary */
- if (evalexpr (CF_NONE, hie1, &lval2) == 0) {
- /* Constant expression. Adjust the types */
- assignadjust (ltype, &lval2);
- /* Put the value into the primary register */
- exprhs (CF_NONE, 0, &lval2);
- } else {
- /* Expression is not constant and already in the primary */
- assignadjust (ltype, &lval2);
- }
+ /* Read the expression on the right side of the '=' */
+ k = hie1 (&lval2);
+
+ /* Do type conversion if necessary */
+ k = TypeConversion (&lval2, k, ltype);
+
+ /* If necessary, load the value into the primary register */
+ exprhs (CF_NONE, k, &lval2);
/* Generate a store instruction */
Store (lval, 0);
}
- /* Value is still in primary */
+ /* Value is still in primary and not an lvalue */
lval->Flags = E_MEXPR;
+ return 0;
}
/* */
/* */
/* */
-/* (C) 2002 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
+/* (C) 2002-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
-void Assignment (ExprDesc* lval);
+int Assignment (ExprDesc* lval);
/* Parse an assignment */
#include "anonname.h"
#include "codegen.h"
#include "datatype.h"
+#include "declare.h"
#include "declattr.h"
#include "error.h"
#include "expr.h"
#include "pragma.h"
#include "scanner.h"
#include "symtab.h"
-#include "declare.h"
+#include "typeconv.h"
static unsigned ParseScalarInit (type* T)
/* Parse initializaton for scalar data types. Return the number of data bytes. */
{
- static const unsigned long Masks[] = {
- 0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL
- };
- unsigned BraceCount;
ExprDesc ED;
- /* Get the size of the expected type */
- unsigned Size = SizeOf (T);
- CHECK (Size > 0 && Size <= sizeof(Masks)/sizeof(Masks[0]));
-
/* Optional opening brace */
- BraceCount = OpeningCurlyBraces (0);
+ unsigned BraceCount = OpeningCurlyBraces (0);
/* We warn if an initializer for a scalar contains braces, because this is
* quite unusual and often a sign for some problem in the input.
Warning ("Braces around scalar initializer");
}
- /* Expression */
+ /* Get the expression and convert it to the target type */
ConstExpr (&ED);
- if ((ED.Flags & E_MCTYPE) == E_TCONST) {
- /* Make the const value the correct size */
- ED.ConstVal &= Masks[Size-1];
- }
- assignadjust (T, &ED);
+ TypeConversion (&ED, 0, T);
/* Output the data */
DefineData (&ED);
ClosingCurlyBraces (BraceCount);
/* Done */
- return Size;
+ return SizeOf (T);
}
/* Make the const value the correct size */
ED.ConstVal &= 0xFFFF;
}
- assignadjust (T, &ED);
+ TypeConversion (&ED, 0, T);
/* Output the data */
DefineData (&ED);
unsigned ParseInit (type* T)
/* Parse initialization of variables. Return the number of data bytes. */
{
- return ParseInitInternal (T, !ANSI);
+ /* Parse the initialization */
+ unsigned Size = ParseInitInternal (T, !ANSI);
+
+ /* The initialization may not generate code on global level, because code
+ * outside function scope will never get executed.
+ */
+ if (HaveGlobalCode ()) {
+ Error ("Non constant initializers");
+ RemoveGlobalCode ();
+ }
+
+ /* Return the size needed for the initialization */
+ return Size;
}
#include "scanner.h"
#include "stdfunc.h"
#include "symtab.h"
-#include "typecast.h"
#include "typecmp.h"
+#include "typeconv.h"
#include "expr.h"
-static int hie0 (ExprDesc *lval);
+int hie0 (ExprDesc *lval);
/* Parse comma operator. */
static int expr (int (*func) (ExprDesc*), ExprDesc *lval);
-unsigned assignadjust (type* lhst, ExprDesc* rhs)
-/* Adjust the type of the right hand expression so that it can be assigned to
- * the type on the left hand side. This function is used for assignment and
- * for converting parameters in a function call. It returns the code generator
- * flags for the operation. The type string of the right hand side will be
- * set to the type of the left hand side.
- */
-{
- /* Get the type of the right hand side. Treat function types as
- * pointer-to-function
- */
- type* rhst = rhs->Type;
- if (IsTypeFunc (rhst)) {
- rhst = PointerTo (rhst);
- }
-
- /* After calling this function, rhs will have the type of the lhs */
- rhs->Type = lhst;
-
- /* First, do some type checking */
- if (IsTypeVoid (lhst) || IsTypeVoid (rhst)) {
- /* If one of the sides are of type void, output a more apropriate
- * error message.
- */
- Error ("Illegal type");
- } else if (IsClassInt (lhst)) {
- if (IsClassPtr (rhst)) {
- /* Pointer -> int conversion */
- Warning ("Converting pointer to integer without a cast");
- } else if (IsClassInt (rhst)) {
- /* Convert the rhs to the type of the lhs. */
- unsigned flags = TypeOf (rhst);
- if (rhs->Flags == E_MCONST) {
- flags |= CF_CONST;
- }
- return g_typecast (TypeOf (lhst), flags);
- } else {
- Error ("Incompatible types");
- }
- } else if (IsClassPtr (lhst)) {
- if (IsClassPtr (rhst)) {
- /* Pointer to pointer assignment is valid, if:
- * - both point to the same types, or
- * - the rhs pointer is a void pointer, or
- * - the lhs pointer is a void pointer.
- */
- if (!IsTypeVoid (Indirect (lhst)) && !IsTypeVoid (Indirect (rhst))) {
- /* Compare the types */
- switch (TypeCmp (lhst, rhst)) {
-
- case TC_INCOMPATIBLE:
- Error ("Incompatible pointer types");
- break;
-
- case TC_QUAL_DIFF:
- Error ("Pointer types differ in type qualifiers");
- break;
-
- default:
- /* Ok */
- break;
- }
- }
- } else if (IsClassInt (rhst)) {
- /* Int to pointer assignment is valid only for constant zero */
- if (rhs->Flags != E_MCONST || rhs->ConstVal != 0) {
- Warning ("Converting integer to pointer without a cast");
- }
- } else if (IsTypeFuncPtr (lhst) && IsTypeFunc(rhst)) {
- /* Assignment of function to function pointer is allowed, provided
- * that both functions have the same parameter list.
- */
- if (TypeCmp (Indirect (lhst), rhst) < TC_EQUAL) {
- Error ("Incompatible types");
- }
- } else {
- Error ("Incompatible types");
- }
- } else {
- Error ("Incompatible types");
- }
-
- /* Return an int value in all cases where the operands are not both ints */
- return CF_INT;
-}
-
-
-
void DefineData (ExprDesc* Expr)
/* Output a data definition for the given expression */
{
* convert the actual argument to the type needed.
*/
if (!Ellipsis) {
- /* Promote the argument if needed */
- assignadjust (Param->Type, &lval);
+ /* Convert the argument to the parameter type if needed */
+ TypeConversion (&lval, 0, Param->Type);
/* If we have a prototype, chars may be pushed as chars */
Flags |= CF_FORCECHAR;
-static int hie0 (ExprDesc *lval)
+int hie0 (ExprDesc *lval)
/* Parse comma operator. */
{
- int k;
-
- k = hie1 (lval);
+ int k = hie1 (lval);
while (CurTok.Tok == TOK_COMMA) {
NextToken ();
k = hie1 (lval);
* if not.
*/
-unsigned assignadjust (type* lhst, ExprDesc* rhs);
-/* Adjust the type of the right hand expression so that it can be assigned to
- * the type on the left hand side. This function is used for assignment and
- * for converting parameters in a function call. It returns the code generator
- * flags for the operation.
- */
-
void exprhs (unsigned flags, int k, ExprDesc *lval);
/* Put the result of an expression into the primary register */
* is NULL, use lval->Type instead.
*/
-void expression1 (ExprDesc* lval);
-/* Evaluate an expression on level 1 (no comma operator) and put it into
- * the primary register
- */
-
-void expression (ExprDesc* lval);
-/* Evaluate an expression and put it into the primary register */
+int hie0 (ExprDesc *lval);
+/* Parse comma operator. */
int evalexpr (unsigned flags, int (*f) (ExprDesc*), ExprDesc* lval);
/* Will evaluate an expression via the given function. If the result is a
* primary register and 1 is returned.
*/
+void expression1 (ExprDesc* lval);
+/* Evaluate an expression on level 1 (no comma operator) and put it into
+ * the primary register
+ */
+
+void expression (ExprDesc* lval);
+/* Evaluate an expression and put it into the primary register */
+
void ConstExpr (ExprDesc* lval);
/* Get a constant value */
#include "expr.h"
#include "function.h"
#include "global.h"
-#include "symtab.h"
#include "locals.h"
+#include "symtab.h"
+#include "typeconv.h"
* symbol data, which is the offset of the variable in the register bank.
*/
{
- unsigned Flags;
unsigned InitLabel;
/* Determine if this is a compound variable */
/* Parse the initialization generating a memory image of the
* data in the RODATA segment. The function does return the size
- * of the initialization data, which may be greater than the
- * actual size of the type, if the type is a structure with a
+ * of the initialization data, which may be greater than the
+ * actual size of the type, if the type is a structure with a
* flexible array member that has been initialized. Since we must
* know the size of the data in advance for register variables,
* we cannot allow that here.
} else {
- /* Setup the type flags for the assignment */
- Flags = CF_NONE;
- if (Size == SIZEOF_CHAR) {
- Flags |= CF_FORCECHAR;
- }
+ /* Parse the expression */
+ int k = hie1 (InitExprDesc (&lval));
- /* Get the expression into the primary */
- if (evalexpr (Flags, hie1, &lval) == 0) {
- /* Constant expression. Adjust the types */
- assignadjust (Decl->Type, &lval);
- Flags |= CF_CONST;
- /* Load it into the primary */
- exprhs (Flags, 0, &lval);
- } else {
- /* Expression is not constant and in the primary */
- assignadjust (Decl->Type, &lval);
- }
+ /* Convert it to the target type */
+ k = TypeConversion (&lval, k, Decl->Type);
+
+ /* Load the value into the primary */
+ exprhs (CF_NONE, k, &lval);
/* Store the value into the variable */
- Flags |= CF_REGVAR;
- g_putstatic (Flags | TypeOf (Decl->Type), Reg, 0);
+ g_putstatic (CF_REGVAR | TypeOf (Decl->Type), Reg, 0);
}
} else {
+ int k;
+
/* Allocate previously reserved local space */
F_AllocLocalSpace (CurrentFunc);
/* Setup the type flags for the assignment */
Flags = (Size == SIZEOF_CHAR)? CF_FORCECHAR : CF_NONE;
- /* Get the expression into the primary */
- if (evalexpr (Flags, hie1, &lval) == 0) {
- /* Constant expression. Adjust the types */
- assignadjust (Decl->Type, &lval);
- Flags |= CF_CONST;
+ /* Parse the expression */
+ k = hie1 (InitExprDesc (&lval));
+
+ /* Convert it to the target type */
+ k = TypeConversion (&lval, k, Decl->Type);
+
+ /* If the value is not const, load it into the primary.
+ * Otherwise pass the information to the code generator.
+ */
+ if (k != 0 || lval.Flags != E_MCONST) {
+ exprhs (CF_NONE, k, &lval);
+ k = 0;
} else {
- /* Expression is not constant and in the primary */
- assignadjust (Decl->Type, &lval);
+ Flags |= CF_CONST;
}
/* Push the value */
} else {
- /* Setup the type flags for the assignment */
- Flags = (Size == SIZEOF_CHAR)? CF_FORCECHAR : CF_NONE;
+ /* Parse the expression */
+ int k = hie1 (InitExprDesc (&lval));
- /* Get the expression into the primary */
- if (evalexpr (Flags, hie1, &lval) == 0) {
- /* Constant expression. Adjust the types */
- assignadjust (Decl->Type, &lval);
- Flags |= CF_CONST;
- /* Load it into the primary */
- exprhs (Flags, 0, &lval);
- } else {
- /* Expression is not constant and in the primary */
- assignadjust (Decl->Type, &lval);
- }
+ /* Convert it to the target type */
+ k = TypeConversion (&lval, k, Decl->Type);
- /* Store the value into the variable */
- g_putstatic (Flags | TypeOf (Decl->Type), SymData, 0);
+ /* Load the value into the primary */
+ exprhs (CF_NONE, k, &lval);
+ /* Store the value into the variable */
+ g_putstatic (TypeOf (Decl->Type), SymData, 0);
}
/* Mark the variable as referenced */
symentry.o \
symtab.o \
textseg.o \
- typecast.o \
typecmp.o \
+ typeconv.o \
util.o
LIBS = $(COMMON)/common.a
symentry.obj \
symtab.obj \
textseg.obj \
- typecast.obj \
typecmp.obj \
+ typeconv.obj \
util.obj
LIBS = ..\common\common.lib
+int HaveGlobalCode (void)
+/* Return true if the global code segment contains entries (which is an error) */
+{
+ return (CS_GetEntryCount (GS->Code) > 0);
+}
+
+
+
+void RemoveGlobalCode (void)
+/* Remove all code from the global code segment. Used for error recovery. */
+{
+ CS_DelEntries (GS->Code, 0, CS_GetEntryCount (GS->Code));
+}
+
+
+
void OutputSegments (const Segments* S, FILE* F)
/* Output the given segments to the file */
{
void AddDataLine (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Add a line of data to the current data segment */
+int HaveGlobalCode (void);
+/* Return true if the global code segment contains entries (which is an error) */
+
+void RemoveGlobalCode (void);
+/* Remove all code from the global code segment. Used for error recovery. */
+
void OutputSegments (const Segments* S, FILE* F);
/* Output the given segments to the file */
#include "litpool.h"
#include "scanner.h"
#include "stdfunc.h"
+#include "typeconv.h"
-static unsigned ParseArg (type* Type, ExprDesc* pval)
+static unsigned ParseArg (type* Type, ExprDesc* Arg)
/* Parse one argument but do not push it onto the stack. Return the code
* generator flags needed to do the actual push.
*/
{
- unsigned CFlags;
- unsigned Flags;
+ /* We have a prototype, so chars may be pushed as chars */
+ unsigned Flags = CF_FORCECHAR;
- /* Do some optimization: If we have a constant value to push,
- * use a special function that may optimize.
- */
- CFlags = CF_NONE;
- if (CheckedSizeOf (Type) == 1) {
- CFlags = CF_FORCECHAR;
- }
- Flags = CF_NONE;
- if (evalexpr (CFlags, hie1, pval) == 0) {
- /* A constant value */
- Flags |= CF_CONST;
- }
+ /* Read the expression we're going to pass to the function */
+ int k = hie1 (InitExprDesc (Arg));
- /* Promote the argument if needed */
- assignadjust (Type, pval);
+ /* Convert this expression to the expected type */
+ k = TypeConversion (Arg, k, Type);
- /* We have a prototype, so chars may be pushed as chars */
- Flags |= CF_FORCECHAR;
+ /* If the value is not a constant, load it into the primary */
+ if (k != 0 || Arg->Flags != E_MCONST) {
+
+ /* Load into the primary */
+ exprhs (CF_NONE, k, Arg);
+ k = 0;
+
+ } else {
+
+ /* Remember that we have a constant value */
+ Flags |= CF_CONST;
+
+ }
/* Use the type of the argument for the push */
- return (Flags | TypeOf (pval->Type));
+ return (Flags | TypeOf (Arg->Type));
}
ExprDesc* lval attribute ((unused)))
/* Handle the strlen function */
{
- static type ParamType[] = { T_PTR, T_SCHAR, T_END };
-
- ExprDesc Param;
- unsigned CodeFlags;
+ static type ParamType[] = { T_PTR, T_SCHAR, T_END };
+ int k;
+ ExprDesc Param;
+ unsigned CodeFlags;
unsigned long ParamName;
- /* Fetch the parameter */
- int k = hie1 (InitExprDesc (&Param));
-
/* Setup the argument type string */
ParamType[1] = GetDefaultChar () | T_QUAL_CONST;
- /* Convert the parameter type to the type needed, check for mismatches */
- assignadjust (ParamType, &Param);
+ /* Fetch the parameter and convert it to the type needed */
+ k = TypeConversion (&Param, hie1 (InitExprDesc (&Param)), ParamType);
/* Check if the parameter is a constant array of some type, or a numeric
* address cast to a pointer.
#include "swstmt.h"
#include "symtab.h"
#include "stmt.h"
+#include "typeconv.h"
* error message if not found (plus some error recovery). If PendingToken is
* NULL, it will the skip the token, otherwise it will store one to
* PendingToken.
- * This function is a special version of CheckTok with the addition of the
+ * This function is a special version of CheckTok with the addition of the
* error recovery.
*/
{
int HaveToken = (CurTok.Tok == TOK_SEMI);
if (!HaveToken) {
- Error ("`;' expected");
+ Error ("`;' expected");
/* Try to be smart about errors */
if (CurTok.Tok == TOK_COLON || CurTok.Tok == TOK_COMMA) {
HaveToken = 1;
static void ReturnStatement (void)
/* Handle the 'return' statement */
{
- ExprDesc lval;
+ ExprDesc Expr;
+ int k;
NextToken ();
if (CurTok.Tok != TOK_SEMI) {
Error ("Returning a value in function with return type void");
}
- /* Evaluate the return expression. Result will be in primary */
- expression (&lval);
+ /* Evaluate the return expression */
+ k = hie0 (InitExprDesc (&Expr));
- /* Convert the return value to the type of the function result */
+ /* Ignore the return expression if the function returns void */
if (!F_HasVoidReturn (CurrentFunc)) {
- assignadjust (F_GetReturnType (CurrentFunc), &lval);
+
+ /* Convert the return value to the type of the function result */
+ TypeConversion (&Expr, k, F_GetReturnType (CurrentFunc));
+
+ /* Load the value into the primary */
+ exprhs (CF_NONE, k, &Expr);
}
} else if (!F_HasVoidReturn (CurrentFunc) && !F_HasOldStyleIntRet (CurrentFunc)) {
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* typecast.c */
-/* */
-/* Handle type casts */
-/* */
-/* */
-/* */
-/* (C) 2002 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* 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 the expression is an array, treat it as pointer to first element.
- */
- if (IsTypeFunc (lval->Type)) {
- lval->Type = PointerTo (lval->Type);
- } else if (IsTypeArray (lval->Type)) {
- lval->Type = ArrayToPtr (lval->Type);
- }
-
- /* Remember the old type */
- OldType = lval->Type;
-
- /* If we're casting to void, we're done. Note: This does also cover a cast
- * void -> void.
- */
- if (IsTypeVoid (NewType)) {
- k = 0; /* Never an lvalue */
- goto ExitPoint;
- }
-
- /* Don't allow casts from void to something else. */
- if (IsTypeVoid (OldType)) {
- Error ("Cannot cast from `void' to something else");
- goto ExitPoint;
- }
-
- /* 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 it
- * has a larger range, things are ok, since the value is
- * internally already represented by a long.
- */
- 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)) {
- if (lval->ConstVal & (0x01UL << (NewBits-1))) {
- lval->ConstVal |= ((~0L) << NewBits);
- }
- }
- }
-
- } 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. */
- g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
-
- /* 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) | CF_FORCECHAR);
-
- /* Value is now in primary */
- lval->Flags = E_MEXPR;
- k = 0;
- }
- }
-
-ExitPoint:
- /* The expression has always the new type */
- ReplaceType (lval, NewType);
-
- /* Done */
- return k;
-}
-
-
-
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* 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
-
-
-
-/* cc65 */
-#include "exprdesc.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
-
-
-
--- /dev/null
+/*****************************************************************************/
+/* */
+/* typeconv.c */
+/* */
+/* Handle type conversions */
+/* */
+/* */
+/* */
+/* (C) 2002-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* 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 "typecmp.h"
+#include "typeconv.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+static void DoPtrConversions (ExprDesc* Expr)
+/* If the expression is a function, convert it to pointer to function.
+ * If the expression is an array, convert it to pointer to first element.
+ */
+{
+ if (IsTypeFunc (Expr->Type)) {
+ Expr->Type = PointerTo (Expr->Type);
+ } else if (IsTypeArray (Expr->Type)) {
+ Expr->Type = ArrayToPtr (Expr->Type);
+ }
+}
+
+
+
+static int DoConversion (ExprDesc* Expr, int k, type* NewType)
+/* Emit code to convert the given expression to a new type. */
+{
+ type* OldType;
+ unsigned OldSize;
+ unsigned NewSize;
+
+
+ /* Remember the old type */
+ OldType = Expr->Type;
+
+ /* If we're converting to void, we're done. Note: This does also cover a
+ * conversion void -> void.
+ */
+ if (IsTypeVoid (NewType)) {
+ k = 0; /* Never an lvalue */
+ goto ExitPoint;
+ }
+
+ /* Don't allow casts from void to something else. */
+ if (IsTypeVoid (OldType)) {
+ Error ("Cannot convert from `void' to something else");
+ goto ExitPoint;
+ }
+
+ /* 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);
+
+ /* 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, Expr);
+
+ /* Emit typecast code */
+ g_typecast (TypeOf (OldType), TypeOf (NewType));
+
+ /* Value is now in primary */
+ Expr->Flags = E_MEXPR;
+ k = 0;
+ }
+
+ } else {
+
+ /* We have an rvalue. Check for a constant. */
+ if (Expr->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 it
+ * has a larger range, things are ok, since the value is
+ * internally already represented by a long.
+ */
+ if (NewBits <= OldBits) {
+
+ /* Cut the value to the new size */
+ Expr->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits));
+
+ /* If the new type is signed, sign extend the value */
+ if (!IsSignUnsigned (NewType)) {
+ if (Expr->ConstVal & (0x01UL << (NewBits-1))) {
+ Expr->ConstVal |= ((~0L) << NewBits);
+ }
+ }
+ }
+
+ } 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, Expr);
+
+ /* Emit typecast code. */
+ g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
+
+ /* Value is now in primary */
+ Expr->Flags = E_MEXPR;
+ k = 0;
+ }
+ }
+ }
+
+ExitPoint:
+ /* The expression has always the new type */
+ ReplaceType (Expr, NewType);
+
+ /* Done */
+ return k;
+}
+
+
+
+int TypeConversion (ExprDesc* Expr, int k, type* NewType)
+/* Do an automatic conversion of the given expression to the new type. Output
+ * warnings or errors where this automatic conversion is suspicious or
+ * impossible.
+ */
+{
+ /* Get the type of the right hand side. Treat function types as
+ * pointer-to-function
+ */
+ DoPtrConversions (Expr);
+
+ /* First, do some type checking */
+ if (IsTypeVoid (NewType) || IsTypeVoid (Expr->Type)) {
+ /* If one of the sides are of type void, output a more apropriate
+ * error message.
+ */
+ Error ("Illegal type");
+ return k;
+ }
+
+ /* Handle conversions to int type */
+ if (IsClassInt (NewType)) {
+ if (IsClassPtr (Expr->Type)) {
+ /* Pointer -> int conversion */
+ Warning ("Converting pointer to integer without a cast");
+ } else if (!IsClassInt (Expr->Type)) {
+ Error ("Incompatible types");
+ } else {
+ /* Convert the rhs to the type of the lhs. */
+ k = DoConversion (Expr, k, NewType);
+ }
+ return k;
+ }
+
+ /* Handle conversions to pointer type */
+ if (IsClassPtr (NewType)) {
+ if (IsClassPtr (Expr->Type)) {
+ /* Pointer to pointer assignment is valid, if:
+ * - both point to the same types, or
+ * - the rhs pointer is a void pointer, or
+ * - the lhs pointer is a void pointer.
+ */
+ if (!IsTypeVoid (Indirect (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) {
+ /* Compare the types */
+ switch (TypeCmp (NewType, Expr->Type)) {
+
+ case TC_INCOMPATIBLE:
+ Error ("Incompatible pointer types");
+ return k;
+
+ case TC_QUAL_DIFF:
+ Error ("Pointer types differ in type qualifiers");
+ return k;
+
+ default:
+ /* Ok */
+ break;
+ }
+ }
+ } else if (IsClassInt (Expr->Type)) {
+ /* Int to pointer assignment is valid only for constant zero */
+ if (Expr->Flags != E_MCONST || Expr->ConstVal != 0) {
+ Warning ("Converting integer to pointer without a cast");
+ }
+ } else if (IsTypeFuncPtr (NewType) && IsTypeFunc(Expr->Type)) {
+ /* Assignment of function to function pointer is allowed, provided
+ * that both functions have the same parameter list.
+ */
+ if (TypeCmp (Indirect (NewType), Expr->Type) < TC_EQUAL) {
+ Error ("Incompatible types");
+ return k;
+ }
+ } else {
+ Error ("Incompatible types");
+ return k;
+ }
+
+ /* If we come here, the conversion is ok, convert and return the result */
+ return DoConversion (Expr, k, NewType);
+
+ }
+
+ /* Invalid automatic conversion */
+ Error ("Incompatible types");
+ return k;
+}
+
+
+
+int TypeCast (ExprDesc* Expr)
+/* Handle an explicit cast. The function returns true if the resulting
+ * expression is an lvalue and false if not.
+ */
+{
+ int k;
+ type NewType[MAXTYPELEN];
+
+ /* Skip the left paren */
+ NextToken ();
+
+ /* Read the type */
+ ParseType (NewType);
+
+ /* Closing paren */
+ ConsumeRParen ();
+
+ /* Read the expression we have to cast */
+ k = hie10 (Expr);
+
+ /* Convert functions and arrays to "pointer to" object */
+ DoPtrConversions (Expr);
+
+ /* Convert the value and return the result. */
+ return DoConversion (Expr, k, NewType);
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* typeconv.h */
+/* */
+/* Handle type conversions */
+/* */
+/* */
+/* */
+/* (C) 2002-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* 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 TYPECONV_H
+#define TYPECONV_H
+
+
+
+/* cc65 */
+#include "exprdesc.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+int TypeConversion (ExprDesc* Expr, int k, type* NewType);
+/* Do an automatic conversion of the given expression to the new type. Output
+ * warnings or errors where this automatic conversion is suspicious or
+ * impossible.
+ */
+
+int TypeCast (ExprDesc* Expr);
+/* Handle an explicit cast. The function returns true if the resulting
+ * expression is an lvalue and false if not.
+ */
+
+
+
+/* End of typeconv.h */
+#endif
+
+
+