* as const.
*/
unsigned flags = TypeOf (rhst);
- if (rhs->e_flags & E_MCONST) {
+ if (rhs->e_flags == E_MCONST) {
flags |= CF_CONST;
}
return g_typeadjust (TypeOf (lhst) | CF_CONST, flags);
}
} else if (IsClassInt (rhst)) {
/* Int to pointer assignment is valid only for constant zero */
- if ((rhs->e_flags & E_MCONST) == 0 || rhs->e_const != 0) {
+ if (rhs->e_flags != E_MCONST || rhs->e_const != 0) {
Warning ("Converting integer to pointer without a cast");
}
} else if (IsTypeFuncPtr (lhst) && IsTypeFunc(rhst)) {
case E_TLIT:
/* a literal of some kind */
- g_defdata (CF_STATIC, LiteralLabel, lval->e_const);
+ g_defdata (CF_STATIC, LiteralPoolLabel, lval->e_const);
break;
default:
case E_TLIT:
/* Literal string */
- g_getimmed (CF_STATIC, LiteralLabel, lval->e_const);
+ g_getimmed (CF_STATIC, LiteralPoolLabel, lval->e_const);
break;
default:
{
SymEntry* Entry;
- return curtok == TOK_LPAREN && (
- (nxttok >= TOK_FIRSTTYPE && nxttok <= TOK_LASTTYPE) ||
- (nxttok == TOK_CONST) ||
- (nxttok == TOK_IDENT &&
- (Entry = FindSym (NextTok.Ident)) != 0 &&
- IsTypeDef (Entry))
- );
+ return CurTok.Tok == TOK_LPAREN && (
+ (NextTok.Tok >= TOK_FIRSTTYPE && NextTok.Tok <= TOK_LASTTYPE) ||
+ (NextTok.Tok == TOK_CONST) ||
+ (NextTok.Tok == TOK_IDENT &&
+ (Entry = FindSym (NextTok.Ident)) != 0 &&
+ IsTypeDef (Entry)));
}
}
if (lval->e_test & E_FORCETEST) { /* we testing this value? */
/* debug... */
- AddCodeHint ("forcetest");
flags |= TypeOf (lval->e_tptr);
g_test (flags); /* yes, force a test */
lval->e_test &= ~E_FORCETEST;
}
/* Parse the actual parameter list */
- while (curtok != TOK_RPAREN) {
+ while (CurTok.Tok != TOK_RPAREN) {
unsigned CFlags;
unsigned Flags;
- /* Add a hint for the optimizer */
- AddCodeHint ("param:start");
-
/* Count arguments */
++ParamCount;
} else {
unsigned ArgSize = sizeofarg (Flags);
if (FrameSize > 0) {
- /* We have the space already allocated, store in the frame */
- CHECK (FrameSize >= ArgSize);
- FrameSize -= ArgSize;
- FrameOffs -= ArgSize;
- /* Store */
- g_putlocal (Flags | CF_NOKEEP, FrameOffs, lval.e_const);
+ /* We have the space already allocated, store in the frame */
+ CHECK (FrameSize >= ArgSize);
+ FrameSize -= ArgSize;
+ FrameOffs -= ArgSize;
+ /* Store */
+ g_putlocal (Flags | CF_NOKEEP, FrameOffs, lval.e_const);
} else {
/* Push the argument */
- g_push (Flags, lval.e_const);
+ g_push (Flags, lval.e_const);
}
/* Calculate total parameter size */
ParamSize += ArgSize;
}
- /* Add an optimizer hint */
- AddCodeHint ("param:end");
-
/* Check for end of argument list */
- if (curtok != TOK_COMMA) {
+ if (CurTok.Tok != TOK_COMMA) {
break;
}
NextToken ();
Error ("Too few arguments in function call");
}
- /* Return the size of all parameters pushed onto the stack */
- return ParamSize;
+ /* The function returns the size of all parameters pushed onto the stack.
+ * However, if there are parameters missing (which is an error and was
+ * flagged by the compiler) AND a stack frame was preallocated above,
+ * we would loose track of the stackpointer and generate an internal error
+ * later. So we correct the value by the parameters that should have been
+ * pushed to avoid an internal compiler error. Since an error was
+ * generated before, no code will be output anyway.
+ */
+ return ParamSize + FrameSize;
}
ConsumeLParen ();
/* String literal */
- if (curtok != TOK_SCONST) {
+ if (CurTok.Tok != TOK_SCONST) {
Error ("String literal expected");
} else {
- /* Write the string directly into the output, followed by a newline */
- AddCodeLine (GetLiteral (curval));
+
+ /* The string literal may consist of more than one line of assembler
+ * code. Separate the single lines and output the code.
+ */
+ const char* S = GetLiteral (CurTok.IVal);
+ while (*S) {
+
+ /* Allow lines up to 256 bytes */
+ const char* E = strchr (S, '\n');
+ if (E) {
+ /* Found a newline */
+ g_asmcode (S, E-S);
+ S = E+1;
+ } else {
+ int Len = strlen (S);
+ g_asmcode (S, Len);
+ S += Len;
+ }
+ }
/* Reset the string pointer, effectivly clearing the string from the
* string table. Since we're working with one token lookahead, this
* will fail if the next token is also a string token, but that's a
* syntax error anyway, because we expect a right paren.
*/
- ResetLiteralOffs (curval);
+ ResetLiteralPoolOffs (CurTok.IVal);
}
/* Skip the string token */
lval->e_test = 0;
/* Character and integer constants. */
- if (curtok == TOK_ICONST || curtok == TOK_CCONST) {
+ if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
lval->e_flags = E_MCONST | E_TCONST;
- lval->e_tptr = curtype;
- lval->e_const = curval;
+ lval->e_tptr = CurTok.Type;
+ lval->e_const = CurTok.IVal;
NextToken ();
return 0;
}
/* Process parenthesized subexpression by calling the whole parser
* recursively.
*/
- if (curtok == TOK_LPAREN) {
+ if (CurTok.Tok == TOK_LPAREN) {
NextToken ();
memset (lval, 0, sizeof (*lval)); /* Remove any attributes */
k = hie0 (lval);
}
/* Identifier? */
- if (curtok == TOK_IDENT) {
+ if (CurTok.Tok == TOK_IDENT) {
SymEntry* Sym;
ident Ident;
NextToken ();
/* IDENT is either an auto-declared function or an undefined variable. */
- if (curtok == TOK_LPAREN) {
+ if (CurTok.Tok == TOK_LPAREN) {
/* Declare a function returning int. For that purpose, prepare a
* function signature for a function having an empty param list
* and returning int.
}
/* String literal? */
- if (curtok == TOK_SCONST) {
+ if (CurTok.Tok == TOK_SCONST) {
lval->e_flags = E_MCONST | E_TLIT;
- lval->e_const = curval;
- lval->e_tptr = GetCharArrayType (strlen (GetLiteral (curval)));
+ lval->e_const = CurTok.IVal;
+ lval->e_tptr = GetCharArrayType (strlen (GetLiteral (CurTok.IVal)));
NextToken ();
return 0;
}
/* ASM statement? */
- if (curtok == TOK_ASM) {
+ if (CurTok.Tok == TOK_ASM) {
doasm ();
lval->e_tptr = type_void;
lval->e_flags = E_MEXPR;
}
/* __AX__ and __EAX__ pseudo values? */
- if (curtok == TOK_AX || curtok == TOK_EAX) {
- lval->e_tptr = (curtok == TOK_AX)? type_uint : type_ulong;
+ if (CurTok.Tok == TOK_AX || CurTok.Tok == TOK_EAX) {
+ lval->e_tptr = (CurTok.Tok == TOK_AX)? type_uint : type_ulong;
lval->e_flags = E_MREG;
lval->e_test &= ~E_CC;
lval->e_const = 0;
/* Skip the token and check for an identifier */
NextToken ();
- if (curtok != TOK_IDENT) {
+ if (CurTok.Tok != TOK_IDENT) {
Error ("Identifier expected");
lval->e_tptr = type_int;
return 0;
k = primary (lval);
- if (curtok < TOK_LBRACK || curtok > TOK_PTR_REF) {
+ if (CurTok.Tok < TOK_LBRACK || CurTok.Tok > TOK_PTR_REF) {
/* Not for us */
return k;
}
while (1) {
- if (curtok == TOK_LBRACK) {
+ if (CurTok.Tok == TOK_LBRACK) {
/* Array reference */
k = arrayref (k, lval);
- } else if (curtok == TOK_LPAREN) {
+ } else if (CurTok.Tok == TOK_LPAREN) {
/* Function call. Skip the opening parenthesis */
NextToken ();
}
k = 0;
- } else if (curtok == TOK_DOT) {
+ } else if (CurTok.Tok == TOK_DOT) {
if (!IsClassStruct (lval->e_tptr)) {
Error ("Struct expected");
}
k = structref (0, lval);
- } else if (curtok == TOK_PTR_REF) {
+ } else if (CurTok.Tok == TOK_PTR_REF) {
tptr = lval->e_tptr;
if (tptr[0] != T_PTR || (tptr[1] & T_STRUCT) == 0) {
NextToken ();
k = hie10 (lval);
- if (k == 0 && lval->e_flags & E_MCONST) {
+ if (k == 0 && (lval->e_flags & E_MCONST) != 0) {
/* Value is constant */
switch (tok) {
- case TOK_MINUS: lval->e_const = -lval->e_const; break;
+ case TOK_MINUS: lval->e_const = -lval->e_const; break;
case TOK_PLUS: break;
case TOK_COMP: lval->e_const = ~lval->e_const; break;
default: Internal ("Unexpected token: %d", tok);
int k;
type* t;
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_INC:
pre_incdec (lval, g_inc);
case TOK_PLUS:
case TOK_MINUS:
case TOK_COMP:
- unaryop (curtok, lval);
+ unaryop (CurTok.Tok, lval);
return 0;
case TOK_BOOL_NOT:
}
k = hie11 (lval);
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_INC:
post_incdec (lval, k, g_inc);
return 0;
k = hienext (lval);
*UsedGen = 0;
- while ((Gen = FindGen (curtok, ops)) != 0) {
+ while ((Gen = FindGen (CurTok.Tok, ops)) != 0) {
/* Tell the caller that we handled it's ops */
*UsedGen = 1;
}
/* Remember the operator token, then skip it */
- tok = curtok;
+ tok = CurTok.Tok;
NextToken ();
/* Get the lhs on stack */
k = hienext (lval);
- while ((Gen = FindGen (curtok, ops)) != 0) {
+ while ((Gen = FindGen (CurTok.Tok, ops)) != 0) {
/* Remember the operator token, then skip it */
- tok = curtok;
+ tok = CurTok.Tok;
NextToken ();
/* Get the lhs on stack */
flags = 0;
/* Check for constness on both sides */
- if (k == 0 && lval->e_flags == E_MCONST) {
+ if (k == 0 && (lval->e_flags & E_MCONST) != 0) {
/* The left hand side is a constant. Good. Get rhs */
if (evalexpr (CF_NONE, hie9, &lval2) == 0) {
}
/* Result is constant, condition codes not set */
- lval->e_test = E_MCONST;
+ lval->e_test &= ~E_CC;
} else {
rhst = lval2.e_tptr;
/* Check left hand side */
- if (k == 0 && lval->e_flags & E_MCONST) {
+ if (k == 0 && (lval->e_flags & E_MCONST) != 0) {
/* Both sides are constant, remove generated code */
RemoveCode (Mark1);
}
/* Result is constant, condition codes not set */
- lval->e_flags = E_MCONST;
+ /* lval->e_flags = E_MCONST; ### */
lval->e_test &= ~E_CC;
} else {
/* Process + and - binary operators. */
{
int k = hie9 (lval);
- while (curtok == TOK_PLUS || curtok == TOK_MINUS) {
+ while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) {
- if (curtok == TOK_PLUS) {
+ if (CurTok.Tok == TOK_PLUS) {
parseadd (k, lval);
} else {
parsesub (k, lval);
struct expent lval2;
k = hie2 (lval);
- if (curtok == TOK_BOOL_AND) {
+ if (CurTok.Tok == TOK_BOOL_AND) {
/* Tell our caller that we're evaluating a boolean */
*BoolOp = 1;
/* Get a label that we will use for false expressions */
- lab = GetLabel ();
+ lab = GetLocalLabel ();
/* If the expr hasn't set condition codes, set the force-test flag */
if ((lval->e_test & E_CC) == 0) {
g_falsejump (CF_NONE, lab);
/* Parse more boolean and's */
- while (curtok == TOK_BOOL_AND) {
+ while (CurTok.Tok == TOK_BOOL_AND) {
/* Skip the && */
NextToken ();
exprhs (CF_FORCECHAR, k, &lval2);
/* Do short circuit evaluation */
- if (curtok == TOK_BOOL_AND) {
+ if (CurTok.Tok == TOK_BOOL_AND) {
g_falsejump (CF_NONE, lab);
} else {
/* Last expression - will evaluate to true */
}
/* Define the false jump label here */
- g_defloclabel (lab);
+ g_defcodelabel (lab);
/* Define the label */
lval->e_flags = E_MEXPR;
unsigned DoneLab;
/* Get a label */
- TrueLab = GetLabel ();
+ TrueLab = GetLocalLabel ();
/* Call the next level parser */
k = hieAnd (lval, TrueLab, &BoolOp);
/* Any boolean or's? */
- if (curtok == TOK_BOOL_OR) {
+ if (CurTok.Tok == TOK_BOOL_OR) {
/* If the expr hasn't set condition codes, set the force-test flag */
if ((lval->e_test & E_CC) == 0) {
BoolOp = 1;
/* while there's more expr */
- while (curtok == TOK_BOOL_OR) {
+ while (CurTok.Tok == TOK_BOOL_OR) {
/* skip the || */
NextToken ();
*/
#if 0
/* Seems this sometimes generates wrong code */
- if (curtok == TOK_BOOL_OR && !AndOp) {
+ if (CurTok.Tok == TOK_BOOL_OR && !AndOp) {
g_truejump (CF_NONE, TrueLab);
}
#else
/* If we really had boolean ops, generate the end sequence */
if (BoolOp) {
- DoneLab = GetLabel ();
+ DoneLab = GetLocalLabel ();
g_getimmed (CF_INT | CF_CONST, 0, 0); /* Load FALSE */
g_falsejump (CF_NONE, DoneLab);
- g_defloclabel (TrueLab);
+ g_defcodelabel (TrueLab);
g_getimmed (CF_INT | CF_CONST, 1, 0); /* Load TRUE */
- g_defloclabel (DoneLab);
+ g_defcodelabel (DoneLab);
}
return k;
}
k = hieOr (lval);
- if (curtok == TOK_QUEST) {
+ if (CurTok.Tok == TOK_QUEST) {
NextToken ();
if ((lval->e_test & E_CC) == 0) {
/* Condition codes not set, force a test */
lval->e_test |= E_FORCETEST;
}
exprhs (CF_NONE, k, lval);
- labf = GetLabel ();
+ labf = GetLocalLabel ();
g_falsejump (CF_NONE, labf);
/* Parse second and third expression */
expression1 (&lval2);
- labt = GetLabel ();
+ labt = GetLocalLabel ();
ConsumeColon ();
g_jump (labt);
- g_defloclabel (labf);
+ g_defcodelabel (labf);
expression1 (&lval3);
/* Check if any conversions are needed, if so, do them.
/* Setup a new label so that the expr3 code will jump around
* the type cast code for expr2.
*/
- labf = GetLabel (); /* Get new label */
+ labf = GetLocalLabel (); /* Get new label */
Mark1 = GetCodePos (); /* Remember current position */
g_jump (labf); /* Jump around code */
/* The jump for expr2 goes here */
- g_defloclabel (labt);
+ g_defcodelabel (labt);
/* Create the typecast code for expr2 */
Mark2 = GetCodePos (); /* Remember position */
g_typecast (TypeOf (rtype), TypeOf (type2));
- /* If the typecast did not produce code, remove the jump,
- * otherwise output the label.
- */
- if (GetCodePos() == Mark2) {
- RemoveCode (Mark1); /* Remove code */
- } else {
- /* We have typecast code, output label */
- g_defloclabel (labf);
- labt = 0; /* Mark other label as invalid */
- }
+ /* Jump here around the typecase code. */
+ g_defcodelabel (labf);
+ labt = 0; /* Mark other label as invalid */
} else if (IsClassPtr (type2) && IsClassPtr (type3)) {
/* Must point to same type */
/* If we don't have the label defined until now, do it */
if (labt) {
- g_defloclabel (labt);
+ g_defcodelabel (labt);
}
/* Setup the target expression */
/* cc65 does not have full support for handling structs by value. Since
* assigning structs is one of the more useful operations from this
- * familiy, allow it here.
+ * family, allow it here.
*/
if (IsClassStruct (ltype)) {
int k;
k = hieQuest (lval);
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_RPAREN:
case TOK_SEMI:
int k;
k = hie1 (lval);
- while (curtok == TOK_COMMA) {
+ while (CurTok.Tok == TOK_COMMA) {
NextToken ();
k = hie1 (lval);
}
/* Load the value into the primary register */
exprhs (CF_FORCECHAR, k, &lval);
- /* Check for the closing brace */
- ConsumeRParen ();
-
/* Generate the jump */
if (cond) {
g_truejump (CF_NONE, label);
* compiler itself is one big hack...): If a semicolon follows, we
* don't have a statement and may omit the jump.
*/
- if (curtok != TOK_SEMI) {
+ if (CurTok.Tok != TOK_SEMI) {
g_falsejump (CF_NONE, label);
}
}
+
+ /* Check for the closing brace */
+ ConsumeRParen ();
}