1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-18 07:29:36 +00:00

Move the assignment parser into a separate module.

When assigning structures, copy them using the primary register when the
size is 1, 2, or 4.
When assigning structures, allow structures by value when the size is 1,
2, or 4. These structures are expected to be in the primary register. The
only case when this can happen is by return from function, so this change
makes div() work.


git-svn-id: svn://svn.cc65.org/cc65/trunk@1477 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2002-11-01 21:27:31 +00:00
parent 5548b6fd56
commit 8810e38bb7
10 changed files with 519 additions and 154 deletions

174
src/cc65/assignment.c Normal file
View File

@ -0,0 +1,174 @@
/*****************************************************************************/
/* */
/* 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;
}

61
src/cc65/assignment.h Normal file
View File

@ -0,0 +1,61 @@
/*****************************************************************************/
/* */
/* 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

View File

@ -143,6 +143,11 @@ typedef unsigned short type;
/* 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 [];

View File

@ -18,8 +18,8 @@
#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"
@ -319,7 +319,7 @@ void DefineData (ExprDesc* Expr)
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) {
@ -442,7 +442,7 @@ static int istypeexpr (void)
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
@ -451,23 +451,13 @@ static void PushAddr (ExprDesc* lval)
{
/* 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
@ -479,7 +469,7 @@ void ConstSubExpr (int (*F) (ExprDesc*), ExprDesc* Expr)
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);
}
}
@ -525,7 +515,7 @@ void exprhs (unsigned flags, int k, ExprDesc *lval)
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) {
@ -1370,34 +1360,46 @@ static int hie11 (ExprDesc *lval)
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);
}
}
@ -1442,7 +1444,7 @@ static void pre_incdec (ExprDesc* lval, void (*inc) (unsigned, unsigned long))
inc (flags, val);
/* Store the result back */
store (lval);
Store (lval, 0);
} else {
@ -1518,7 +1520,7 @@ static void post_incdec (ExprDesc* lval, int k, void (*inc) (unsigned, unsigned
}
/* Store the result back */
store (lval);
Store (lval, 0);
/* Restore the original value */
g_restore (flags | CF_FORCECHAR);
@ -2815,7 +2817,7 @@ static void opeq (const GenDesc* Gen, ExprDesc *lval, int k)
/* 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;
}
@ -2920,85 +2922,6 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *lval, int k)
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. */
{

View File

@ -11,54 +11,24 @@
/* 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
@ -77,6 +47,12 @@ unsigned assignadjust (type* lhst, ExprDesc* rhs);
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

112
src/cc65/exprdesc.c Normal file
View File

@ -0,0 +1,112 @@
/*****************************************************************************/
/* */
/* 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);
}

103
src/cc65/exprdesc.h Normal file
View File

@ -0,0 +1,103 @@
/*****************************************************************************/
/* */
/* 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

View File

@ -26,6 +26,7 @@ OBJS = anonname.o \
asmcode.o \
asmlabel.o \
asmstmt.o \
assignment.o \
casenode.o \
codeent.o \
codegen.o \
@ -52,6 +53,7 @@ OBJS = anonname.o \
declattr.o \
error.o \
expr.o \
exprdesc.o \
exprheap.o \
exprnode.o \
funcdesc.o \

View File

@ -71,6 +71,7 @@ OBJS = anonname.obj \
asmcode.obj \
asmlabel.obj \
asmstmt.obj \
assignment.obj \
casenode.obj \
codeent.obj \
codegen.obj \
@ -96,7 +97,8 @@ OBJS = anonname.obj \
declare.obj \
declattr.obj \
error.obj \
expr.obj \
expr.obj \
exprdesc.obj \
exprheap.obj \
exprnode.obj \
funcdesc.obj \
@ -155,6 +157,7 @@ FILE anonname.obj
FILE asmcode.obj
FILE asmlabel.obj
FILE asmstmt.obj
FILE assignment.obj
FILE casenode.obj
FILE codeent.obj
FILE codegen.obj
@ -181,6 +184,7 @@ FILE declare.obj
FILE declattr.obj
FILE error.obj
FILE expr.obj
FILE exprdesc.obj
FILE exprheap.obj
FILE exprnode.obj
FILE funcdesc.obj

View File

@ -37,6 +37,11 @@
#define TYPECAST_H
/* cc65 */
#include "exprdesc.h"
/*****************************************************************************/
/* Code */