/*-------------------------------------------------------------------------
- SDCCicode.h - intermediate code generation etc.
+ SDCCicode.h - intermediate code generation etc.
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
+
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
- what you give them. Help stamp out software-hoarding!
+ what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
#include "SDCCbitv.h"
#include "SDCCset.h"
#define LRTYPE LRFTYPE LRETYPE
#define IS_ITEMP(op) (IS_SYMOP(op) && op->operand.symOperand->isitmp == 1)
#define IS_PARM(op) (IS_SYMOP(op) && op->operand.symOperand->_isparm)
-#define IS_ITEMPLBL(op) (IS_ITEMP(op) && op->operand.symOperand->isilbl == 1);
+#define IS_ITEMPLBL(op) (IS_ITEMP(op) && op->operand.symOperand->isilbl == 1)
#define IS_OP_VOLATILE(op) (IS_SYMOP(op) && op->isvolatile)
#define IS_OP_LITERAL(op) (op && op->isLiteral)
#define IS_OP_GLOBAL(op) (IS_SYMOP(op) && op->isGlobal)
/* typedef for operand */
typedef struct operand
{
- OPTYPE type; /* type of operand */
- unsigned int isaddr:1; /* is an address */
- unsigned int isvolatile:1; /* is a volatile operand */
- unsigned int isGlobal:1; /* is a global operand */
- unsigned int isPtr:1; /* is assigned a pointer */
- unsigned int isGptr:1; /* is a generic pointer */
- unsigned int isParm:1; /* is a parameter */
- unsigned int isLiteral:1; /* operand is literal */
-
- unsigned key;
+ OPTYPE type; /* type of operand */
+ unsigned int isaddr:1; /* is an address */
+ unsigned int aggr2ptr:2; /* 1: must change aggregate to pointer to aggregate */
+ /* 2: aggregate has been changed to pointer to aggregate */
+ unsigned int isvolatile:1; /* is a volatile operand */
+ unsigned int isGlobal:1; /* is a global operand */
+ unsigned int isPtr:1; /* is assigned a pointer */
+ unsigned int isGptr:1; /* is a generic pointer */
+ unsigned int isParm:1; /* is a parameter */
+ unsigned int isLiteral:1; /* operand is literal */
+
+ int key;
union
{
- struct symbol *symOperand; /* operand is of type symbol */
- struct value *valOperand; /* operand is of type value */
- struct sym_link *typeOperand; /* operand is of type typechain */
+ struct symbol *symOperand; /* operand is of type symbol */
+ struct value *valOperand; /* operand is of type value */
+ struct sym_link *typeOperand; /* operand is of type typechain */
}
operand;
- bitVect *usesDefs; /* which definitions are used by this */
- struct asmop *aop; /* asm op for this operand */
+ bitVect *usesDefs; /* which definitions are used by this */
+ struct asmop *aop; /* asm op for this operand */
}
operand;
-extern operand *validateOpType(operand *op,
- const char *macro,
- const char *args,
- OPTYPE type,
- const char *file,
- unsigned line);
+extern operand *validateOpType(operand *op,
+ const char *macro,
+ const char *args,
+ OPTYPE type,
+ const char *file,
+ unsigned line);
-#define OP_SYMBOL(op) validateOpType(op, "OP_SYMBOL", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand
-#define OP_VALUE(op) validateOpType(op, "OP_VALUE", #op, VALUE, __FILE__, __LINE__)->operand.valOperand
+#define OP_SYMBOL(op) validateOpType(op, "OP_SYMBOL", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand
+#define OP_VALUE(op) validateOpType(op, "OP_VALUE", #op, VALUE, __FILE__, __LINE__)->operand.valOperand
#define OP_SYM_TYPE(op) validateOpType(op, "OP_SYM_TYPE", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->type
#define OP_SYM_ETYPE(op) validateOpType(op, "OP_SYM_ETYPE", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->etype
#define SPIL_LOC(op) validateOpType(op, "SPIL_LOC", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->usl.spillLoc
#define IC_COND(x) (x)->ulrrcnd.cnd.condition
#define IC_TRUE(x) (x)->ulrrcnd.cnd.trueLabel
#define IC_FALSE(x) (x)->ulrrcnd.cnd.falseLabel
-#define IC_LABEL(x) (x)->argLabel.label
-// jwk #define IC_ARGS(x) (x)->argLabel.args
+#define IC_LABEL(x) (x)->label
#define IC_JTCOND(x) (x)->ulrrcnd.jmpTab.condition
#define IC_JTLABELS(x) (x)->ulrrcnd.jmpTab.labels
#define IC_INLINE(x) (x)->inlineAsm
typedef struct iCode
{
- unsigned int op; /* operation defined */
- int key; /* running key for this iCode */
- int seq; /* sequence number within routine */
- short depth; /* loop depth of this iCode */
- short level; /* scope level */
- short block; /* sequential block number */
- unsigned nosupdate:1; /* don't update spillocation with this */
- unsigned generated:1; /* code generated for this one */
- unsigned parmPush:1; /* parameter push Vs spill push */
- unsigned supportRtn:1; /* will cause a call to a support routine */
- unsigned regsSaved:1; /* registers have been saved */
- unsigned bankSaved:1; /* register bank has been saved */
+ unsigned int op; /* operation defined */
+ int key; /* running key for this iCode */
+ int seq; /* sequence number within routine */
+ int seqPoint; /* sequence point */
+ short depth; /* loop depth of this iCode */
+ short level; /* scope level */
+ short block; /* sequential block number */
+ unsigned nosupdate:1; /* don't update spillocation with this */
+ unsigned generated:1; /* code generated for this one */
+ unsigned parmPush:1; /* parameter push Vs spill push */
+ unsigned supportRtn:1; /* will cause a call to a support routine */
+ unsigned regsSaved:1; /* registers have been saved */
+ unsigned bankSaved:1; /* register bank has been saved */
unsigned builtinSEND:1; /* SEND for parameter of builtin function */
- struct iCode *next; /* next in chain */
- struct iCode *prev; /* previous in chain */
- set *movedFrom; /* if this iCode gets moved to another block */
- bitVect *rlive; /* ranges that are live at this point */
- int defKey; /* key for the operand being defined */
- bitVect *uses; /* vector of key of used symbols */
- bitVect *rUsed; /* registers used by this instruction */
- bitVect *rMask; /* registers in use during this instruction */
+ struct iCode *next; /* next in chain */
+ struct iCode *prev; /* previous in chain */
+ set *movedFrom; /* if this iCode gets moved to another block */
+ bitVect *rlive; /* ranges that are live at this point */
+ int defKey; /* key for the operand being defined */
+ bitVect *uses; /* vector of key of used symbols */
+ bitVect *rUsed; /* registers used by this instruction */
+ bitVect *rMask; /* registers in use during this instruction */
union
{
- struct
- {
- operand *left; /* left if any */
- operand *right; /* right if any */
- operand *result; /* result of this op */
- }
- lrr;
-
- struct
- {
- operand *condition; /* if this is a conditional */
- symbol *trueLabel; /* true for conditional */
- symbol *falseLabel; /* false for conditional */
- }
- cnd;
-
- struct
- {
- operand *condition; /* condition for the jump */
- set *labels; /* ordered set of labels */
- }
- jmpTab;
+ struct
+ {
+ operand *left; /* left if any */
+ operand *right; /* right if any */
+ operand *result; /* result of this op */
+ }
+ lrr;
+
+ struct
+ {
+ operand *condition; /* if this is a conditional */
+ symbol *trueLabel; /* true for conditional */
+ symbol *falseLabel; /* false for conditional */
+ }
+ cnd;
+
+ struct
+ {
+ operand *condition; /* condition for the jump */
+ set *labels; /* ordered set of labels */
+ }
+ jmpTab;
}
ulrrcnd;
- union
- {
- symbol *label; /* for a goto statement */
- // jwk value *args; /* for a function */
- }
- argLabel;
+ symbol *label; /* for a goto statement */
- char *inlineAsm; /* pointer to inline assembler code */
+ char *inlineAsm; /* pointer to inline assembler code */
literalList *arrayInitList; /* point to array initializer list. */
- int lineno; /* file & lineno for debug information */
+ int lineno; /* file & lineno for debug information */
char *filename;
-
- int parmBytes; /* if call/pcall, count of parameter bytes
- on stack */
- int argreg; /* argument regno for SEND/RECEIVE */
+
+ int parmBytes; /* if call/pcall, count of parameter bytes
+ on stack */
+ int argreg; /* argument regno for SEND/RECEIVE */
int eBBlockNum; /* belongs to which eBBlock */
+ char riu; /* after ralloc, the registers in use */
+ struct ast * tree; /* ast node for this iCode (if not NULL) */
}
iCode;
{
int icode;
char *printName;
- void (*iCodePrint) (FILE *, iCode *, char *);
+ void (*iCodePrint) (struct dbuf_s *, iCode *, char *);
iCode *(*iCodeCopy) (iCode *);
}
iCodeTable;
/* useful macros */
-#define SKIP_IC2(x) (x->op == GOTO || \
- x->op == LABEL || \
- x->op == FUNCTION || \
- x->op == INLINEASM || \
- x->op == ENDFUNCTION )
-
-#define SKIP_IC1(x) (x->op == CALL || \
- SKIP_IC2(x) )
-
-#define SKIP_IC(x) (x->op == PCALL || \
- x->op == IPUSH || \
- x->op == IPOP || \
- x->op == JUMPTABLE || \
- x->op == RECEIVE || \
- x->op == ARRAYINIT || \
- SKIP_IC1(x)|| \
- x->op == SEND )
-
-#define SKIP_IC3(x) (SKIP_IC2(x) || \
- x->op == JUMPTABLE )
+#define SKIP_IC2(x) (x->op == GOTO || \
+ x->op == LABEL || \
+ x->op == FUNCTION || \
+ x->op == INLINEASM || \
+ x->op == ENDFUNCTION )
+
+#define SKIP_IC1(x) (x->op == CALL || \
+ SKIP_IC2(x) )
+
+#define SKIP_IC(x) (x->op == PCALL || \
+ x->op == IPUSH || \
+ x->op == IPOP || \
+ x->op == JUMPTABLE || \
+ x->op == RECEIVE || \
+ x->op == ARRAYINIT || \
+ SKIP_IC1(x) || \
+ x->op == CRITICAL || \
+ x->op == ENDCRITICAL || \
+ x->op == SEND )
+
+#define SKIP_IC3(x) (SKIP_IC2(x) || \
+ x->op == JUMPTABLE )
#define IS_CONDITIONAL(x) (x->op == EQ_OP || \
- x->op == '<' || \
- x->op == '>' || \
- x->op == LE_OP || \
- x->op == GE_OP || \
- x->op == NE_OP )
+ x->op == '<' || \
+ x->op == '>' || \
+ x->op == LE_OP || \
+ x->op == GE_OP || \
+ x->op == NE_OP )
#define IS_TRUE_SYMOP(op) (op && IS_SYMOP(op) && !IS_ITEMP(op))
#define POINTER_SET(ic) ( ic && ic->op == '=' \
- && IS_ITEMP(IC_RESULT(ic)) \
+ && (IS_ITEMP(IC_RESULT(ic)) || IS_OP_LITERAL(IC_RESULT(ic)))\
&& IC_RESULT(ic)->isaddr )
#define POINTER_GET(ic) ( ic && ic->op == GET_VALUE_AT_ADDRESS \
- && (IS_ITEMP(IC_LEFT(ic)) || IS_OP_LITERAL(IC_LEFT(ic)))\
- && IC_LEFT(ic)->isaddr )
+ && (IS_ITEMP(IC_LEFT(ic)) || IS_OP_LITERAL(IC_LEFT(ic)))\
+ && IC_LEFT(ic)->isaddr )
#define IS_ARITHMETIC_OP(x) (x && (x->op == '+' || \
- x->op == '-' || \
- x->op == '/' || \
- x->op == '*' || \
- x->op == '%'))
+ x->op == '-' || \
+ x->op == '/' || \
+ x->op == '*' || \
+ x->op == '%'))
#define IS_BITWISE_OP(x) (x && (x->op == BITWISEAND || \
x->op == '|' || \
x->op == '^'))
+#define IS_ASSOCIATIVE(x) (x && (x->op == EQ_OP || \
+ x->op == NE_OP || \
+ x->op == '+' || \
+ x->op == '*' || \
+ x->op == BITWISEAND || \
+ x->op == '|' || \
+ x->op == '^'))
+
#define ASSIGNMENT(ic) ( ic && ic->op == '=')
#define ASSIGN_SYM_TO_ITEMP(ic) (ic && ic->op == '=' && \
- IS_TRUE_SYMOP(IC_RIGHT(ic)) && \
+ IS_TRUE_SYMOP(IC_RIGHT(ic)) && \
IS_ITEMP(IC_RESULT(ic)))
#define ASSIGN_ITEMP_TO_SYM(ic) (ic && ic->op == '=' && \
- IS_TRUE_SYMOP(IC_RESULT(ic)) && \
+ IS_TRUE_SYMOP(IC_RESULT(ic)) && \
IS_ITEMP(IC_RIGHT(ic)))
#define ASSIGN_ITEMP_TO_ITEMP(ic) (ic && ic->op == '=' &&\
- !POINTER_SET(ic) &&\
- IS_ITEMP(IC_RIGHT(ic)) &&\
- IS_ITEMP(IC_RESULT(ic)))
+ !POINTER_SET(ic) &&\
+ IS_ITEMP(IC_RIGHT(ic)) &&\
+ IS_ITEMP(IC_RESULT(ic)))
#define ADD_SUBTRACT_ITEMP(ic) (ic && (ic->op == '+' || ic->op == '-') && \
- IS_ITEMP(IC_RESULT(ic)) && \
- ( ( IS_ITEMP(IC_LEFT(ic)) ) || ( IS_SYMOP(IC_LEFT(ic)) ) ) && \
+ IS_ITEMP(IC_RESULT(ic)) && \
+ ( ( IS_ITEMP(IC_LEFT(ic)) ) || ( IS_SYMOP(IC_LEFT(ic)) ) ) && \
IS_OP_LITERAL(IC_RIGHT(ic)))
#define ASSIGNMENT_TO_SELF(ic) (!POINTER_SET(ic) && !POINTER_GET(ic) && \
- ic->op == '=' && IC_RESULT(ic)->key == IC_RIGHT(ic)->key )
+ ic->op == '=' && IC_RESULT(ic)->key == IC_RIGHT(ic)->key )
#define IS_CAST_ICODE(ic) (ic && ic->op == CAST)
#define SET_ISADDR(op,v) {op = operandFromOperand(op); op->isaddr = v;}
#define SET_RESULT_RIGHT(ic) {SET_ISADDR(IC_RIGHT(ic),0); SET_ISADDR(IC_RESULT(ic),0);}
#define IS_ASSIGN_ICODE(ic) (ASSIGNMENT(ic) && !POINTER_SET(ic))
-#if 0 // this causes too much, extremely difficult to find, bugs
- #define OP_DEFS(op) op->operand.symOperand->defs
- #define OP_USES(op) op->operand.symOperand->uses
-#else
- struct bitVect *OP_DEFS(struct operand *);
- struct bitVect *OP_DEFS_SET(struct operand *, struct bitVect *);
- struct bitVect *OP_USES(struct operand *);
- struct bitVect *OP_USES_SET(struct operand *, struct bitVect *);
-#endif
+#define OP_DEFS(op) validateOpType(op, "OP_DEFS", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->defs
+#define OP_USES(op) validateOpType(op, "OP_USES", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->uses
/*-----------------------------------------------------------------*/
/* forward references for functions */
/*-----------------------------------------------------------------*/
int isOperandGlobal (operand *);
void printiCChain (iCode *, FILE *);
operand *ast2iCode (ast *,int);
-operand *geniCodeCast (sym_link *, operand *, bool);
operand *geniCodePtrPtrSubtract (operand *, operand *);
void initiCode ();
iCode *iCodeFromAst (ast *);
iCode *newiCodeLabelGoto (int, symbol *);
symbol *newiTemp (char *);
symbol *newiTempLabel (char *);
-symbol *newiTempPreheaderLabel ();
+#define LOOPEXITLBL "loopExitLbl"
+symbol *newiTempLoopHeaderLabel (bool);
iCode *newiCode (int, operand *, operand *);
sym_link *operandType (operand *);
+unsigned int operandSize (operand *);
operand *operandFromValue (value *);
operand *operandFromSymbol (symbol *);
+operand *operandFromLink (sym_link *);
sym_link *aggrToPtr (sym_link *, bool);
+int aggrToPtrDclType (sym_link *, bool);
int piCode (void *, FILE *);
+int dbuf_printOperand (operand *, struct dbuf_s *);
int printOperand (operand *, FILE *);
void setOperandType (operand *, sym_link *);
bool isOperandInFarSpace (operand *);
+bool isOperandInPagedSpace (operand *);
bool isOperandInDirSpace (operand *);
bool isOperandInCodeSpace (operand *);
operand *opFromOpWithDU (operand *, bitVect *, bitVect *);
iCode *copyiCode (iCode *);
+operand *newiTempOperand (sym_link *, char);
operand *newiTempFromOp (operand *);
iCode *getBuiltinParms (iCode *,int *, operand **);
+int isiCodeInFunctionCall (iCode *);
/*-----------------------------------------------------------------*/
/* declaration of exported variables */
/*-----------------------------------------------------------------*/