/*-------------------------------------------------------------------------
- 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"
#ifndef SDCCICODE_H
#define SDCCICODE_H 1
-extern symbol *returnLabel ;
-extern symbol *entryLabel ;
-extern int iCodeKey ;
-extern int operandKey ;
-
-enum {
- CONDITIONAL = 0 ,
- EXPRESSION ,
- STATEMENT ,
- LEAF };
-
-typedef enum {
- SYMBOL =1,
- VALUE ,
- TYPE
-} OPTYPE;
+extern symbol *returnLabel;
+extern symbol *entryLabel;
+extern int iCodeKey;
+extern int operandKey;
+
+enum
+ {
+ CONDITIONAL = 0,
+ EXPRESSION,
+ STATEMENT,
+ LEAF
+ };
+
+typedef enum
+ {
+ SYMBOL = 1,
+ VALUE,
+ TYPE
+ }
+OPTYPE;
#define IS_SYMOP(op) (op && op->type == SYMBOL)
+#define IS_VALOP(op) (op && op->type == VALUE)
+#define IS_TYPOP(op) (op && op->type == TYPE)
+
#define ADDTOCHAIN(x) addSetHead(&iCodeChain,x)
-#define LRFTYPE link *ltype = operandType(left), \
+#define LRFTYPE sym_link *ltype = operandType(left), \
*rtype = operandType(right) ;
-#define LRETYPE link *letype= getSpec(ltype) , \
+#define LRETYPE sym_link *letype= getSpec(ltype) , \
*retype= getSpec(rtype);
#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)
#define IS_OP_POINTER(op) (IS_SYMOP(op) && op->isPtr)
#define IS_OP_PARM(op) (IS_SYMOP(op) && op->isParm)
-#define OP_SYMBOL(op) op->operand.symOperand
-#define OP_SYM_TYPE(op) op->operand.symOperand->type
-#define OP_SYM_ETYPE(op) op->operand.symOperand->etype
-#define SPIL_LOC(op) op->operand.symOperand->usl.spillLoc
-#define OP_LIVEFROM(op) op->operand.symOperand->liveFrom
-#define OP_LIVETO(op) op->operand.symOperand->liveTo
-#define OP_REQV(op) op->operand.symOperand->reqv
#define OP_ISLIVE_FCALL(op) (IS_ITEMP(op) && OP_SYMBOL(op)->isLiveFcall)
+#define SYM_SPIL_LOC(sym) sym->usl.spillLoc
/* 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 int noSpilLoc:1 ; /* cannot be assigned a spil location */
-
- unsigned key ;
- int parmBytes;
- union {
- struct symbol *symOperand ; /* operand is of type symbol */
- struct value *valOperand ; /* operand is of type value */
- struct link *typeOperand; /* operand is of type typechain */
- } operand ;
-
- bitVect *usesDefs; /* which definitions are used by this */
- struct asmop *aop ; /* asm op for this operand */
-} operand ;
-
-/* definition for intermediate code */
-#define IC_RESULT(x) x->ulrrcnd.lrr.result
-#define IC_LEFT(x) x->ulrrcnd.lrr.left
-#define IC_RIGHT(x) x->ulrrcnd.lrr.right
-#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
-#define IC_ARGS(x) x->argLabel.args
-#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 */
-
- 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 ;
-
- } ulrrcnd;
-
- union {
- symbol *label ; /* for a goto statement */
- value *args ;
- } argLabel ;
-
- char *inlineAsm ; /* pointer to inline assembler code */
-
- int lineno ; /* file & lineno for debug information */
- char *filename ;
-} iCode ;
+typedef struct operand
+ {
+ 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 */
+ }
+ 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);
+
+#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 OP_LIVEFROM(op) validateOpType(op, "OP_LIVEFROM", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->liveFrom
+#define OP_LIVETO(op) validateOpType(op, "OP_LIVETO", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->liveTo
+#define OP_REQV(op) validateOpType(op, "OP_REQV", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->reqv
+
+/* definition for intermediate code */
+#define IC_RESULT(x) (x)->ulrrcnd.lrr.result
+#define IC_LEFT(x) (x)->ulrrcnd.lrr.left
+#define IC_RIGHT(x) (x)->ulrrcnd.lrr.right
+#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)->label
+#define IC_JTCOND(x) (x)->ulrrcnd.jmpTab.condition
+#define IC_JTLABELS(x) (x)->ulrrcnd.jmpTab.labels
+#define IC_INLINE(x) (x)->inlineAsm
+#define IC_ARRAYILIST(x) (x)->arrayInitList
+
+typedef struct iCode
+ {
+ 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 */
+ 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;
+
+ }
+ ulrrcnd;
+
+ symbol *label; /* for a goto statement */
+
+ char *inlineAsm; /* pointer to inline assembler code */
+ literalList *arrayInitList; /* point to array initializer list. */
+
+ 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 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;
/* various functions associated to iCode */
-typedef struct icodeFuncTable
-{
- int icode ;
- char *printName ;
- void (*iCodePrint)(FILE *,iCode *,char *) ;
- iCode * (*iCodeCopy)(iCode *) ;
-} iCodeTable ;
+typedef struct icodeFuncTable
+ {
+ int icode;
+ char *printName;
+ 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 || \
- SKIP_IC1(x)|| \
- x->op == SEND )
+#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))
-#define OP_DEFS(op) op->operand.symOperand->defs
-#define OP_USES(op) op->operand.symOperand->uses
+#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 */
/*-----------------------------------------------------------------*/
-iCode *reverseiCChain ( );
-bool isOperandOnStack (operand *);
-int isOperandVolatile (operand *,bool);
-int isOperandGlobal (operand *);
-void printiCChain ( iCode * , FILE *);
-operand *ast2iCode ( ast *);
-operand *geniCodeCast ( link *, operand *,bool);
+iCode *reverseiCChain ();
+bool isOperandOnStack (operand *);
+int isOperandVolatile (operand *, bool);
+int isOperandGlobal (operand *);
+void printiCChain (iCode *, FILE *);
+operand *ast2iCode (ast *,int);
operand *geniCodePtrPtrSubtract (operand *, operand *);
-void initiCode ();
-iCode *iCodeFromAst ( ast * );
-int isiCodeEqual ( iCode *,iCode *) ;
-int isOperandEqual ( operand *, operand *);
-iCodeTable *getTableEntry (int );
-int isOperandLiteral (operand *);
-operand *operandOperation (operand *,operand *,int,link *);
-double operandLitValue ( operand * );
-operand *operandFromLit (float);
-operand *operandFromOperand(operand *);
-int isParameterToCall (value *,operand *);
-iCode *newiCodeLabelGoto (int , symbol *);
-symbol *newiTemp(char *);
-symbol *newiTempLabel (char *);
-symbol *newiTempPreheaderLabel ();
-iCode *newiCode (int, operand *, operand *);
-link *operandType(operand *);
+void initiCode ();
+iCode *iCodeFromAst (ast *);
+int isiCodeEqual (iCode *, iCode *);
+int isOperandEqual (operand *, operand *);
+iCodeTable *getTableEntry (int);
+int isOperandLiteral (operand *);
+operand *operandOperation (operand *, operand *, int, sym_link *);
+double operandLitValue (operand *);
+operand *operandFromLit (double);
+operand *operandFromOperand (operand *);
+int isParameterToCall (value *, operand *);
+iCode *newiCodeLabelGoto (int, symbol *);
+symbol *newiTemp (char *);
+symbol *newiTempLabel (char *);
+#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 *);
-link *aggrToPtr ( link *, bool);
-int piCode (void *, FILE * );
-int printOperand (operand *,FILE *);
-void setOperandType (operand *, link *);
-bool isOperandInFarSpace (operand *);
-operand *opFromOpWithDU (operand *,bitVect *,bitVect *);
-iCode *copyiCode (iCode *);
-operand *newiTempFromOp( operand *);
+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 *newiTempFromOp (operand *);
+iCode *getBuiltinParms (iCode *,int *, operand **);
+int isiCodeInFunctionCall (iCode *);
/*-----------------------------------------------------------------*/
/* declaration of exported variables */
/*-----------------------------------------------------------------*/