--- /dev/null
+/*****************************************************************************/
+/* */
+/* assignment.c */
+/* */
+/* Parse assignments */
+/* */
+/* */
+/* */
+/* (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 "error.h"
+#include "expr.h"
+#include "typecmp.h"
+#include "assignment.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void Assignment (ExprDesc* lval)
+/* Parse an assignment */
+{
+ int k;
+ ExprDesc lval2;
+ type* ltype = lval->Type;
+
+
+ /* Check for assignment to const */
+ if (IsQualConst (ltype)) {
+ Error ("Assignment to const");
+ }
+
+ /* cc65 does not have full support for handling structs by value. Since
+ * assigning structs is one of the more useful operations from this
+ * family, allow it here.
+ */
+ if (IsClassStruct (ltype)) {
+
+ /* Get the size of the left hand side. */
+ unsigned Size = SizeOf (ltype);
+
+ /* If the size is that of a basic type (char, int, long), we will copy
+ * the struct using the primary register, otherwise we use memcpy. In
+ * the former case, push the address only if really needed.
+ */
+ int UseReg = 1;
+ type* stype;
+ switch (Size) {
+ case SIZEOF_CHAR: stype = type_uchar; break;
+ case SIZEOF_INT: stype = type_uint; break;
+ case SIZEOF_LONG: stype = type_ulong; break;
+ default: stype = ltype; UseReg = 0; break;
+ }
+ if (UseReg) {
+ PushAddr (lval);
+ } else {
+ exprhs (0, 0, lval);
+ g_push (CF_PTR | CF_UNSIGNED, 0);
+ }
+
+ /* Get the expression on the right of the '=' into the primary */
+ k = hie1 (&lval2);
+
+ /* Check for equality of the structs */
+ if (TypeCmp (ltype, lval2.Type) < TC_STRICT_COMPATIBLE) {
+ Error ("Incompatible types");
+ }
+
+ /* Check if the right hand side is an lvalue */
+ if (k) {
+ /* We have an lvalue. Do we copy using the primary? */
+ if (UseReg) {
+ /* Just use the replacement type */
+ lval2.Type = stype;
+
+ /* Load the value into the primary */
+ exprhs (CF_FORCECHAR, k, &lval2);
+
+ /* Store it into the new location */
+ Store (lval, stype);
+
+ } else {
+
+ /* We will use memcpy. Push the address of the rhs */
+ exprhs (0, 0, &lval2);
+
+ /* Push the address (or whatever is in ax in case of errors) */
+ g_push (CF_PTR | CF_UNSIGNED, 0);
+
+ /* Load the size of the struct into the primary */
+ g_getimmed (CF_INT | CF_UNSIGNED | CF_CONST, CheckedSizeOf (ltype), 0);
+
+ /* Call the memcpy function */
+ g_call (CF_FIXARGC, "memcpy", 4);
+ }
+
+ } else {
+
+ /* We have an rvalue. This can only happen if a function returns
+ * a struct, since there is no other way to generate an expression
+ * that as a struct as an rvalue result. We allow only 1, 2, and 4
+ * byte sized structs and do direct assignment.
+ */
+ if (UseReg) {
+ /* Do the store */
+ Store (lval, stype);
+ } else {
+ /* Print a diagnostic */
+ Error ("Structs of this size are not supported");
+ /* Adjust the stack so we won't run in an internal error later */
+ pop (CF_PTR);
+ }
+
+ }
+
+ } else {
+
+ /* 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);
+ }
+
+ /* Generate a store instruction */
+ Store (lval, 0);
+
+ }
+
+ /* Value is still in primary */
+ lval->Flags = E_MEXPR;
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* assignment.h */
+/* */
+/* Parse assignments */
+/* */
+/* */
+/* */
+/* (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 ASSIGNMENT_H
+#define ASSIGNMENT_H
+
+
+
+/* cc65 */
+#include "exprdesc.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void Assignment (ExprDesc* lval);
+/* Parse an assignment */
+
+
+
+/* End of assignment.h */
+#endif
+
+
+
/* Type elements needed for Encode/Decode */
#define DECODE_SIZE 5
+/* Sizes */
+#define SIZEOF_CHAR 1
+#define SIZEOF_INT 2
+#define SIZEOF_LONG 4
+
/* Predefined type strings */
extern type type_uchar [];
extern type type_int [];
#include "asmcode.h"
#include "asmlabel.h"
#include "asmstmt.h"
+#include "assignment.h"
#include "codegen.h"
-#include "datatype.h"
#include "declare.h"
#include "error.h"
#include "funcdesc.h"
-static void lconst (unsigned Flags, ExprDesc* Expr)
+static void LoadConstant (unsigned Flags, ExprDesc* Expr)
/* Load the primary register with some constant value. */
{
switch (Expr->Flags & E_MCTYPE) {
-static void PushAddr (ExprDesc* lval)
+void PushAddr (ExprDesc* lval)
/* If the expression contains an address that was somehow evaluated,
* push this address on the stack. This is a helper function for all
* sorts of implicit or explicit assignment functions where the lvalue
{
/* Get the address on stack if needed */
if (lval->Flags != E_MREG && (lval->Flags & E_MEXPR)) {
- /* Push the address (always a pointer) */
- g_push (CF_PTR, 0);
+ /* Push the address (always a pointer) */
+ g_push (CF_PTR, 0);
}
}
-static void MakeConstIntExpr (ExprDesc* Expr, long Value)
-/* Make Expr a constant integer expression with the given value */
-{
- Expr->Flags = E_MCONST;
- Expr->Type = type_int;
- Expr->ConstVal = Value;
-}
-
-
-
void ConstSubExpr (int (*F) (ExprDesc*), ExprDesc* Expr)
/* Will evaluate an expression via the given function. If the result is not
* a constant, a diagnostic will be printed, and the value is replaced by
if (F (Expr) != 0 || Expr->Flags != E_MCONST) {
Error ("Constant expression expected");
/* To avoid any compiler errors, make the expression a valid const */
- MakeConstIntExpr (Expr, 1);
+ MakeConstIntExpr (Expr, 1);
}
}
g_inc (flags | CF_CONST, lval->ConstVal);
} else if ((f & E_MEXPR) == 0) {
/* Constant of some sort, load it into the primary */
- lconst (flags, lval);
+ LoadConstant (flags, lval);
}
/* Are we testing this value? */
if (lval->Test & E_FORCETEST) {
-static void store (ExprDesc* lval)
-/* Store primary reg into this reference */
+void Store (ExprDesc* lval, const type* StoreType)
+/* Store the primary register into the location denoted by lval. If StoreType
+ * is given, use this type when storing instead of lval->Type. If StoreType
+ * is NULL, use lval->Type instead.
+ */
{
- int f;
- unsigned flags;
+ unsigned Flags;
- f = lval->Flags;
- flags = TypeOf (lval->Type);
+ unsigned f = lval->Flags;
+
+ /* If StoreType was not given, use lval->Type instead */
+ if (StoreType == 0) {
+ StoreType = lval->Type;
+ }
+
+ /* Get the code generator flags */
+ Flags = TypeOf (StoreType);
if (f & E_MGLOBAL) {
- flags |= GlobalModeFlags (f);
+ Flags |= GlobalModeFlags (f);
if (lval->Test) {
- /* Just testing */
- flags |= CF_TEST;
- }
+ /* Just testing */
+ Flags |= CF_TEST;
+ }
/* Generate code */
- g_putstatic (flags, lval->Name, lval->ConstVal);
+ g_putstatic (Flags, lval->Name, lval->ConstVal);
} else if (f & E_MLOCAL) {
- g_putlocal (flags, lval->ConstVal, 0);
+ /* Store an auto variable */
+ g_putlocal (Flags, lval->ConstVal, 0);
} else if (f == E_MEOFFS) {
- g_putind (flags, lval->ConstVal);
+ /* Store indirect with offset */
+ g_putind (Flags, lval->ConstVal);
} else if (f != E_MREG) {
if (f & E_MEXPR) {
- g_putind (flags, 0);
+ /* Indirect without offset */
+ g_putind (Flags, 0);
} else {
/* Store into absolute address */
- g_putstatic (flags | CF_ABSOLUTE, lval->ConstVal, 0);
+ g_putstatic (Flags | CF_ABSOLUTE, lval->ConstVal, 0);
}
}
inc (flags, val);
/* Store the result back */
- store (lval);
+ Store (lval, 0);
} else {
}
/* Store the result back */
- store (lval);
+ Store (lval, 0);
/* Restore the original value */
g_restore (flags | CF_FORCECHAR);
/* Adjust the types of the operands if needed */
Gen->Func (g_typeadjust (flags, TypeOf (lval2.Type)), 0);
}
- store (lval);
+ Store (lval, 0);
lval->Flags = E_MEXPR;
}
-static void Assignment (ExprDesc* lval)
-/* Parse an assignment */
-{
- int k;
- ExprDesc lval2;
- unsigned flags;
- type* ltype = lval->Type;
-
- /* Check for assignment to const */
- if (IsQualConst (ltype)) {
- Error ("Assignment to const");
- }
-
- /* cc65 does not have full support for handling structs by value. Since
- * assigning structs is one of the more useful operations from this
- * family, allow it here.
- */
- if (IsClassStruct (ltype)) {
-
- /* Bring the address of the lhs into the primary and push it */
- exprhs (0, 0, lval);
- g_push (CF_PTR | CF_UNSIGNED, 0);
-
- /* Get the expression on the right of the '=' into the primary */
- k = hie1 (&lval2);
- if (k) {
- /* Get the address */
- exprhs (0, 0, &lval2);
- }
-
- /* Push the address (or whatever is in ax in case of errors) */
- g_push (CF_PTR | CF_UNSIGNED, 0);
-
- /* Check for equality of the structs */
- if (TypeCmp (ltype, lval2.Type) < TC_STRICT_COMPATIBLE) {
- Error ("Incompatible types");
- }
-
- /* Load the size of the struct into the primary */
- g_getimmed (CF_INT | CF_UNSIGNED | CF_CONST, CheckedSizeOf (ltype), 0);
-
- /* Call the memcpy function */
- g_call (CF_FIXARGC, "memcpy", 4);
-
- } else {
-
- /* Get the address on stack if needed */
- PushAddr (lval);
-
- /* No struct, setup flags for the load */
-#if 0
- /* Generates wrong code!!! ### */
- flags = CheckedSizeOf (ltype) == 1? CF_FORCECHAR : CF_NONE;
-#else
- flags = CF_NONE;
-#endif
-
- /* Get the expression on the right of the '=' into the primary */
- if (evalexpr (flags, hie1, &lval2) == 0) {
- /* Constant expression. Adjust the types */
- assignadjust (ltype, &lval2);
- /* Put the value into the primary register */
- lconst (flags, &lval2);
- } else {
- /* Expression is not constant and already in the primary */
- assignadjust (ltype, &lval2);
- }
-
- /* Generate a store instruction */
- store (lval);
-
- }
-
- /* Value is still in primary */
- lval->Flags = E_MEXPR;
-}
-
-
-
int hie1 (ExprDesc* lval)
/* Parse first level of expression hierarchy. */
{
+/* cc65 */
#include "datatype.h"
+#include "exprdesc.h"
/*****************************************************************************/
-/* data */
+/* code */
/*****************************************************************************/
-/* Defines for the flags field of the expression descriptor */
-#define E_MREG 0x0110U /* Special: Expression is primary register */
-#define E_MGLOBAL 0x0080U /* Reference to static variable */
-#define E_MLOCAL 0x0040U /* Reference to local variable (stack offset) */
-#define E_MCONST 0x0020U /* Constant value */
-#define E_MEXPR 0x0010U /* Result is in primary register */
-#define E_MEOFFS 0x0011U /* Base is in primary register, const offset */
-
-#define E_MCTYPE 0x0007U /* Type of a constant */
-#define E_TCONST 0x0000U /* Constant */
-#define E_TGLAB 0x0001U /* Global label */
-#define E_TLIT 0x0002U /* Literal of some kind */
-#define E_TLOFFS 0x0003U /* Constant stack offset */
-#define E_TLLAB 0x0004U /* Local label */
-#define E_TREGISTER 0x0005U /* Register variable */
-
-/* Defines for the test field of the expression descriptor */
-#define E_CC 0x0001U /* expr has set cond codes apropos result value */
-#define E_FORCETEST 0x0002U /* if expr has NOT set CC, force a test */
-
-/* Describe the result of an expression */
-typedef struct ExprDesc ExprDesc;
-struct ExprDesc {
- struct SymEntry* Sym; /* Symbol table entry if known */
- type* Type; /* Type array of expression */
- long ConstVal;/* Value if expression constant */
- unsigned short Flags;
- unsigned short Test; /* */
- unsigned long Name; /* Name or label number */
-};
-
-
-
-/*****************************************************************************/
-/* code */
-/*****************************************************************************/
-
-
+void PushAddr (ExprDesc* lval);
+/* If the expression contains an address that was somehow evaluated,
+ * push this address on the stack. This is a helper function for all
+ * sorts of implicit or explicit assignment functions where the lvalue
+ * must be saved if it's not constant, before evaluating the rhs.
+ */
void ConstSubExpr (int (*F) (ExprDesc*), ExprDesc* Expr);
/* Will evaluate an expression via the given function. If the result is not
void exprhs (unsigned flags, int k, ExprDesc *lval);
/* Put the result of an expression into the primary register */
+void Store (ExprDesc* lval, const type* StoreType);
+/* Store the primary register into the location denoted by lval. If StoreType
+ * is given, use this type when storing instead of lval->Type. If StoreType
+ * 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
--- /dev/null
+/*****************************************************************************/
+/* */
+/* exprdesc.c */
+/* */
+/* Expression descriptor structure */
+/* */
+/* */
+/* */
+/* (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 "datatype.h"
+#include "symentry.h"
+#include "exprdesc.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void MakeConstIntExpr (ExprDesc* Expr, long Value)
+/* Make Expr a constant integer expression with the given value */
+{
+ Expr->Flags = E_MCONST;
+ Expr->Type = type_int;
+ Expr->ConstVal = Value;
+}
+
+
+
+void PrintExprDesc (FILE* F, ExprDesc* E)
+/* Print an ExprDesc */
+{
+ fprintf (F, "Symbol: %s\n", E->Sym? E->Sym->Name : "(none)");
+ fprintf (F, "Type: ");
+ if (E->Type) {
+ PrintType (F, E->Type);
+ } else {
+ fprintf (F, "(unknown)");
+ }
+ fprintf (F, "\n");
+ fprintf (F, "Value: 0x%08lX\n", E->ConstVal);
+ fprintf (F, "Flags: ");
+ switch (E->Flags & E_MCTYPE) {
+ case E_TCONST: fprintf (F, "E_TCONST "); break;
+ case E_TGLAB: fprintf (F, "E_TGLAB "); break;
+ case E_TLIT: fprintf (F, "E_TLIT "); break;
+ case E_TLOFFS: fprintf (F, "E_TLOFFS "); break;
+ case E_TLLAB: fprintf (F, "E_TLLAB "); break;
+ case E_TREGISTER: fprintf (F, "E_TREGISTER "); break;
+ default: fprintf (F, "0x%02X ", E->Flags & E_MCTYPE); break;
+ }
+ if ((E->Flags & E_MREG) == E_MREG) {
+ fprintf (F, "E_MREG ");
+ } else if ((E->Flags & E_MEOFFS) == E_MEOFFS) {
+ fprintf (F, "E_MEOFFS ");
+ } else if ((E->Flags & E_MEXPR) == E_MEXPR) {
+ fprintf (F, "E_MEXPR ");
+ }
+ if ((E->Flags & E_MGLOBAL) == E_MGLOBAL) {
+ fprintf (F, "E_MGLOBAL ");
+ }
+ if ((E->Flags & E_MLOCAL) == E_MLOCAL) {
+ fprintf (F, "E_MLOCAL ");
+ }
+ if ((E->Flags & E_MCONST) == E_MCONST) {
+ fprintf (F, "E_MCONST ");
+ }
+ fprintf (F, "\n");
+
+ fprintf (F, "Test: ");
+ if (E->Test & E_CC) {
+ fprintf (F, "E_CC ");
+ }
+ if (E->Test & E_FORCETEST) {
+ fprintf (F, "E_FORCETEST ");
+ }
+ fprintf (F, "\n");
+
+ fprintf (F, "Name: 0x%08lX\n", E->Name);
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* exprdesc.h */
+/* */
+/* Expression descriptor structure */
+/* */
+/* */
+/* */
+/* (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 EXPRDESC_H
+#define EXPRDESC_H
+
+
+
+/* cc65 */
+#include "datatype.h"
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* Defines for the flags field of the expression descriptor */
+#define E_MREG 0x0110U /* Special: Expression is primary register */
+#define E_MGLOBAL 0x0080U /* Reference to static variable */
+#define E_MLOCAL 0x0040U /* Reference to local variable (stack offset) */
+#define E_MCONST 0x0020U /* Constant value */
+#define E_MEXPR 0x0010U /* Result is in primary register */
+#define E_MEOFFS 0x0011U /* Base is in primary register, const offset */
+
+#define E_MCTYPE 0x0007U /* Type of a constant */
+#define E_TCONST 0x0000U /* Constant */
+#define E_TGLAB 0x0001U /* Global label */
+#define E_TLIT 0x0002U /* Literal of some kind */
+#define E_TLOFFS 0x0003U /* Constant stack offset */
+#define E_TLLAB 0x0004U /* Local label */
+#define E_TREGISTER 0x0005U /* Register variable */
+
+/* Defines for the test field of the expression descriptor */
+#define E_CC 0x0001U /* expr has set cond codes apropos result value */
+#define E_FORCETEST 0x0002U /* if expr has NOT set CC, force a test */
+
+/* Describe the result of an expression */
+typedef struct ExprDesc ExprDesc;
+struct ExprDesc {
+ struct SymEntry* Sym; /* Symbol table entry if known */
+ type* Type; /* Type array of expression */
+ long ConstVal;/* Value if expression constant */
+ unsigned short Flags;
+ unsigned short Test; /* */
+ unsigned long Name; /* Name or label number */
+};
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void MakeConstIntExpr (ExprDesc* Expr, long Value);
+/* Make Expr a constant integer expression with the given value */
+
+void PrintExprDesc (FILE* F, ExprDesc* Expr);
+/* Print an ExprDesc */
+
+
+
+/* End of exprdesc.h */
+#endif
+
+
+
asmcode.o \
asmlabel.o \
asmstmt.o \
+ assignment.o \
casenode.o \
codeent.o \
codegen.o \
declattr.o \
error.o \
expr.o \
+ exprdesc.o \
exprheap.o \
exprnode.o \
funcdesc.o \
asmcode.obj \
asmlabel.obj \
asmstmt.obj \
+ assignment.obj \
casenode.obj \
codeent.obj \
codegen.obj \
declare.obj \
declattr.obj \
error.obj \
- expr.obj \
+ expr.obj \
+ exprdesc.obj \
exprheap.obj \
exprnode.obj \
funcdesc.obj \
FILE asmcode.obj
FILE asmlabel.obj
FILE asmstmt.obj
+FILE assignment.obj
FILE casenode.obj
FILE codeent.obj
FILE codegen.obj
FILE declattr.obj
FILE error.obj
FILE expr.obj
+FILE exprdesc.obj
FILE exprheap.obj
FILE exprnode.obj
FILE funcdesc.obj
#define TYPECAST_H
+
+/* cc65 */
+#include "exprdesc.h"
+
+
/*****************************************************************************/
/* Code */