diff --git a/src/cc65/exprheap.c b/src/cc65/exprheap.c index cd5e49f79..bbf683716 100644 --- a/src/cc65/exprheap.c +++ b/src/cc65/exprheap.c @@ -163,7 +163,7 @@ ExprHeap* PopExprHeap (void) ExprNode* AllocExprNode (nodetype_t NT, type* Type, int LValue) /* Get a new node from the current expression heap */ -{ +{ ExprNode* N; /* Must have a heap */ @@ -205,4 +205,23 @@ void FreeExprNode (ExprNode* N) +void FreeExprTree (ExprNode* N) +/* Free a complete expression tree starting with the current node */ +{ + if (IsBranchNode (N)) { + /* Free the leaf nodes if necessary */ + if ((N->NT & NT_MASK_LIST) == NT_LIST_EXPR) { + unsigned I; + unsigned Count = CollCount (&N->List); + for (I = 0; I < Count; ++I) { + FreeExprNode (CollAt (&N->List, I)); + } + } + } + + /* Free the node itself */ + FreeExprNode (N); +} + + diff --git a/src/cc65/exprheap.h b/src/cc65/exprheap.h index a87d04b54..09c576778 100644 --- a/src/cc65/exprheap.h +++ b/src/cc65/exprheap.h @@ -73,6 +73,9 @@ ExprNode* AllocExprNode (nodetype_t NT, type* Type, int LValue); void FreeExprNode (ExprNode* N); /* Free an expression node from the current expression heap */ +void FreeExprTree (ExprNode* N); +/* Free a complete expression tree starting with the current node */ + /* End of exprheap.h */ diff --git a/src/cc65/exprnode.c b/src/cc65/exprnode.c index 8c3e2c61c..7cf7aa100 100644 --- a/src/cc65/exprnode.c +++ b/src/cc65/exprnode.c @@ -33,6 +33,11 @@ +/* common */ +#include "check.h" + +/* cc65 */ +#include "error.h" #include "exprnode.h" @@ -156,4 +161,321 @@ void SetNodeSym (ExprNode* N, struct SymEntry* Sym) +int IsLeafNode (const ExprNode* E) +/* Return true if this is a leaf node */ +{ + return (E->NT & NT_MASK_LEAF) == NT_LEAF; +} + + + +int IsBranchNode (const ExprNode* E) +/* Return true if this is a branch node */ +{ + return (E->NT & NT_MASK_LEAF) == NT_BRANCH; +} + + + +void DumpExpr (FILE* F, const ExprNode* E) +/* Dump an expression in UPN notation to the given file */ +{ + if (IsLeafNode (E)) { + + /* Operand */ + switch (E->NT) { + + case NT_SYM: + /* Symbol */ + fprintf (F, "SYM "); + break; + + case NT_CONST: + /* A constant of some sort */ + if (IsClassInt (E->Type)) { + fprintf (F, "%0*lX ", SizeOf (E->Type), E->IVal); + } else if (IsClassFloat (E->Type)) { + fprintf (F, "%f ", E->FVal); + } else { + Internal ("Unknown type for NT_CONST"); + } + break; + + case NT_ASM: + /* Inline assembler */ + fprintf (F, "ASM "); + break; + + case NT_REG_A: + /* A register */ + fprintf (F, "REG_A "); + break; + + case NT_REG_X: + /* X register */ + fprintf (F, "REG_X "); + break; + + case NT_REG_Y: + /* Y register */ + fprintf (F, "REG_Y "); + break; + + case NT_REG_AX: + /* AX register */ + fprintf (F, "REG_AX "); + break; + + case NT_REG_EAX: + /* EAX register */ + fprintf (F, "REG_EAX "); + break; + + default: + Internal ("Unknown node type: %04X", E->NT); + break; + + } + + } else { + + unsigned I, Count; + + /* Dump the operands */ + switch (E->NT & NT_MASK_LIST) { + + case NT_LIST_EXPR: + Count = CollCount (&E->List); + for (I = 0; I < Count; ++I) { + DumpExpr (F, CollConstAt (&E->List, I)); + } + break; + + default: + Internal ("Operator with LIST != NT_LIST_EXPR"); + + } + + /* Dump the operator */ + switch (E->NT) { + + case NT_ARRAY_SUBSCRIPT: + /* Array subscript */ + fprintf (F, "[] "); + break; + + case NT_STRUCT_ACCESS: + /* Access of a struct field */ + fprintf (F, ". "); + break; + + case NT_STRUCTPTR_ACCESS: + /* Access via struct ptr */ + fprintf (F, "-> "); + break; + + case NT_FUNCTION_CALL: + /* Call a function */ + fprintf (F, "CALL "); + break; + + case NT_TYPECAST: + /* A cast */ + fprintf (F, "CAST "); + break; + + case NT_ADDRESS: + /* Address operator (&) */ + fprintf (F, "ADDR "); + break; + + case NT_INDIRECT: + /* Indirection operator (*) */ + fprintf (F, "FETCH "); + break; + + case NT_UNARY_MINUS: + /* - */ + fprintf (F, "NEG "); + break; + + case NT_COMPLEMENT: + /* ~ */ + fprintf (F, "~ "); + break; + + case NT_BOOL_NOT: + /* ! */ + fprintf (F, "! "); + break; + + case NT_PLUS: + /* + */ + fprintf (F, "+ "); + break; + + case NT_MINUS: + /* - */ + fprintf (F, "- "); + break; + + case NT_MUL: + /* * */ + fprintf (F, "* "); + break; + + case NT_DIV: + /* / */ + fprintf (F, "/ "); + break; + + case NT_SHL: + /* << */ + fprintf (F, "<< "); + break; + + case NT_SHR: + /* >> */ + fprintf (F, ">> "); + break; + + case NT_AND: + /* & */ + fprintf (F, "& "); + break; + + case NT_OR: + /* | */ + fprintf (F, "| "); + break; + + case NT_XOR: + /* ^ */ + fprintf (F, "^ "); + break; + + case NT_TERNARY: + /* ?: */ + fprintf (F, "?: "); + break; + + case NT_ASSIGN: + /* = */ + fprintf (F, "= "); + break; + + case NT_PLUS_ASSIGN: + /* += */ + fprintf (F, "+= "); + break; + + case NT_MINUS_ASSIGN: + /* -= */ + fprintf (F, "-= "); + break; + + case NT_MUL_ASSIGN: + /* *= */ + fprintf (F, "*= "); + break; + + case NT_DIV_ASSIGN: + /* /= */ + fprintf (F, "/= "); + break; + + case NT_SHL_ASSIGN: + /* <<= */ + fprintf (F, "<<= "); + break; + + case NT_SHR_ASSIGN: + /* >>= */ + fprintf (F, ">>= "); + break; + + case NT_AND_ASSIGN: + /* &= */ + fprintf (F, "&= "); + break; + + case NT_OR_ASSIGN: + /* |= */ + fprintf (F, "|= "); + break; + + case NT_XOR_ASSIGN: + /* ^= */ + fprintf (F, "^= "); + break; + + case NT_PRE_DEC: + /* -- */ + fprintf (F, "<-- "); + break; + + case NT_POST_DEC: + /* -- */ + fprintf (F, "--> "); + break; + + case NT_PRE_INC: + /* ++ */ + fprintf (F, "<++ "); + break; + + case NT_POST_INC: + /* ++ */ + fprintf (F, "++> "); + break; + + case NT_BOOL_OR: + /* || */ + fprintf (F, "|| "); + break; + + case NT_BOOL_AND: + /* && */ + fprintf (F, "&& "); + break; + + case NT_EQ: + /* == */ + fprintf (F, "== "); + break; + + case NT_NE: + /* != */ + fprintf (F, "!= "); + break; + + case NT_LT: + /* < */ + fprintf (F, "< "); + break; + + case NT_LE: + /* <= */ + fprintf (F, "<= "); + break; + + case NT_GT: + /* > */ + fprintf (F, "> "); + break; + + case NT_GE: + /* >= */ + fprintf (F, ">= "); + break; + + default: + Internal ("Unknown node type: %04X", E->NT); + break; + + } + } +} + + diff --git a/src/cc65/exprnode.h b/src/cc65/exprnode.h index bf518c213..30284f350 100644 --- a/src/cc65/exprnode.h +++ b/src/cc65/exprnode.h @@ -76,8 +76,9 @@ typedef enum { NT_MASK_LIST = 0x0300, /* Two bits telling if this is a leaf or a branch */ - NT_BRANCH = 0x4000, /* Branch */ - NT_LEAF = 0x8000, /* Leaf */ + NT_LEAF = 0x0000, /* Leaf */ + NT_BRANCH = 0x8000, /* Branch */ + NT_MASK_LEAF = 0x8000, /* Special node type */ NT_NONE = 0x0000, /* None (invalid) op */ @@ -142,7 +143,9 @@ typedef enum { NT_LT = 0x0037 | NT_BRANCH | NT_LIST_EXPR, /* < */ NT_LE = 0x0038 | NT_BRANCH | NT_LIST_EXPR, /* <= */ NT_GT = 0x0039 | NT_BRANCH | NT_LIST_EXPR, /* > */ - NT_GE = 0x003A | NT_BRANCH | NT_LIST_EXPR /* >= */ + NT_GE = 0x003A | NT_BRANCH | NT_LIST_EXPR, /* >= */ + + NT_MASK_TYPE = 0x00FF } nodetype_t; @@ -224,6 +227,12 @@ struct SymEntry* GetNodeSym (ExprNode* N); void SetNodeSym (ExprNode* N, struct SymEntry* Sym); /* Set the symbol entry in a NT_SYM node */ +int IsLeafNode (const ExprNode* E); +/* Return true if this is a leaf node */ + +int IsBranchNode (const ExprNode* E); +/* Return true if this is a branch node */ + /* End of exprnode.h */ @@ -232,5 +241,3 @@ void SetNodeSym (ExprNode* N, struct SymEntry* Sym); - - diff --git a/src/cc65/parser.c b/src/cc65/parser.c index 1d22b397c..8349aa4fa 100644 --- a/src/cc65/parser.c +++ b/src/cc65/parser.c @@ -543,8 +543,8 @@ static ExprNode* DoFunctionCall (ExprNode* Left) /* Call to non function */ Error (ERR_ILLEGAL_FUNC_CALL); - /* Free the old node */ - FreeExprNode (Left); + /* Free the old tree */ + FreeExprTree (Left); /* Return something safe */ return GetIntNode (0); @@ -759,11 +759,11 @@ static ExprNode* DoUnaryPlusMinus (void) /* Type check */ if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) { - /* Display diagnostic */ + /* Output diagnostic */ Error (ERR_SYNTAX); /* Free the errorneous node */ - FreeExprNode (Op); + FreeExprTree (Op); /* Return something that makes sense later */ return GetIntNode (0); @@ -822,7 +822,7 @@ static ExprNode* DoComplement (void) Error (ERR_OP_NOT_ALLOWED); /* Free the errorneous node */ - FreeExprNode (Op); + FreeExprTree (Op); /* Return something that makes sense later */ return GetIntNode (0); @@ -894,8 +894,8 @@ static ExprNode* DoAddress (void) /* Print diagnostics */ Error (ERR_ILLEGAL_ADDRESS); - /* Free the problematic node */ - FreeExprNode (Op); + /* Free the problematic tree */ + FreeExprTree (Op); /* Return something that is safe later */ Root = AllocExprNode (NT_CONST, PointerTo (type_void), 0); @@ -928,8 +928,8 @@ static ExprNode* DoIndirect (void) /* Print diagnostics */ Error (ERR_ILLEGAL_INDIRECT); - /* Free the problematic node */ - FreeExprNode (Op); + /* Free the problematic tree */ + FreeExprTree (Op); /* Return something that is safe later ### */ return GetIntNode (0); @@ -980,7 +980,7 @@ static ExprNode* DoSizeOf (void) Size = SizeOf (N->Type); /* Free the node */ - FreeExprNode (N); + FreeExprTree (N); } @@ -1021,8 +1021,8 @@ static ExprNode* DoTypeCast (void) } else { - /* Must be casted. Setup the expression tree and return the new node */ - Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE); + /* Must be casted. Setup the expression tree and return the new node */ + Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE); SetLeftNode (Root, Op); return Root; @@ -1049,7 +1049,7 @@ static ExprNode* UnaryExpr (void) case TOK_PLUS: case TOK_MINUS: - return DoUnaryPlusMinus (); + return DoUnaryPlusMinus (); case TOK_COMP: return DoComplement (); @@ -1066,22 +1066,61 @@ static ExprNode* UnaryExpr (void) case TOK_SIZEOF: return DoSizeOf (); - default: - /* Type cast */ - return DoTypeCast (); + default: + /* Type cast */ + return DoTypeCast (); - } + } } else { - /* Call the lower level */ - return PostfixExpr (); + /* Call the lower level */ + return PostfixExpr (); } } +static ExprNode* DoMul (ExprNode* Left) +/* Handle multiplication */ +{ + type TargetType[MAXTYPELEN]; + ExprNode* Right; + ExprNode* Root; + + /* Check the type of the left operand */ + if (!IsClassInt (Left->Type) && !IsClassFloat (Left->Type)) { + MError ("Invalid left operand to binary operator `*'"); + FreeExprTree (Left); + Left = GetIntNode (0); + } + + /* Skip the operator token */ + NextToken (); + + /* Read the right expression */ + Right = UnaryExpr (); + + /* Check the type of the right operand */ + if (!IsClassInt (Right->Type) && !IsClassFloat (Right->Type)) { + MError ("Invalid right operand to binary operator `*'"); + FreeExprTree (Right); + Right = GetIntNode (0); + } + + /* Do minor optimizations ### */ + + /* Make the root node */ + Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE); + SetLeftNode (Root, Left); + SetRightNode (Root, Right); + + return Root; +} + + + static ExprNode* MultExpr (void) /* Handle multiplicative expressions: '*' '/' and '%' */ { @@ -1094,6 +1133,7 @@ static ExprNode* MultExpr (void) switch (CurTok.Tok) { case TOK_MUL: + Root = DoMul (Root); break; case TOK_DIV: @@ -1262,8 +1302,8 @@ static ExprNode* AndExpr (void) Error (ERR_OP_NOT_ALLOWED); /* Remove the unneeded nodes */ - FreeExprNode (Right); - FreeExprNode (Left); + FreeExprTree (Right); + FreeExprTree (Left); /* Create something safe */ Root = GetIntNode (0); @@ -1277,8 +1317,8 @@ static ExprNode* AndExpr (void) int Result = GetBoolRep (Left) & GetBoolRep (Right); /* Remove the unneeded nodes */ - FreeExprNode (Right); - FreeExprNode (Left); + FreeExprTree (Right); + FreeExprTree (Left); /* Create a constant result */ Root = GetIntNode (Result); @@ -1325,8 +1365,8 @@ static ExprNode* XorExpr (void) Error (ERR_OP_NOT_ALLOWED); /* Remove the unneeded nodes */ - FreeExprNode (Right); - FreeExprNode (Left); + FreeExprTree (Right); + FreeExprTree (Left); /* Create something safe */ Root = GetIntNode (0); @@ -1340,8 +1380,8 @@ static ExprNode* XorExpr (void) int Result = GetBoolRep (Left) ^ GetBoolRep (Right); /* Remove the unneeded nodes */ - FreeExprNode (Right); - FreeExprNode (Left); + FreeExprTree (Right); + FreeExprTree (Left); /* Create a constant result */ Root = GetIntNode (Result); @@ -1388,8 +1428,8 @@ static ExprNode* OrExpr (void) Error (ERR_OP_NOT_ALLOWED); /* Remove the unneeded nodes */ - FreeExprNode (Right); - FreeExprNode (Left); + FreeExprTree (Right); + FreeExprTree (Left); /* Create something safe */ Root = GetIntNode (0); @@ -1403,8 +1443,8 @@ static ExprNode* OrExpr (void) int Result = GetBoolRep (Left) | GetBoolRep (Right); /* Remove the unneeded nodes */ - FreeExprNode (Right); - FreeExprNode (Left); + FreeExprTree (Right); + FreeExprTree (Left); /* Create a constant result */ Root = GetIntNode (Result); @@ -1451,8 +1491,8 @@ static ExprNode* BoolAndExpr (void) int Result = GetBoolRep (Left) && GetBoolRep (Right); /* Remove the unneeded nodes */ - FreeExprNode (Right); - FreeExprNode (Left); + FreeExprTree (Right); + FreeExprTree (Left); /* Create a constant result */ Root = GetIntNode (Result); @@ -1499,8 +1539,8 @@ static ExprNode* BoolOrExpr (void) int Result = GetBoolRep (Left) && GetBoolRep (Right); /* Remove the unneeded nodes */ - FreeExprNode (Right); - FreeExprNode (Left); + FreeExprTree (Right); + FreeExprTree (Left); /* Create a constant result */ Root = GetIntNode (Result);