X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCicode.h;h=d2c69a1f10ef2537ff3b1138dfeb8f7918bffa02;hb=43a9f56ae641cae90edd199d25b234df463b2ff5;hp=3071d614fe415c975a97584d46af32bacc12b0ca;hpb=c819b1e06a731b497ea9e0bfbb6b3b753306a190;p=fw%2Fsdcc diff --git a/src/SDCCicode.h b/src/SDCCicode.h index 3071d614..d2c69a1f 100644 --- a/src/SDCCicode.h +++ b/src/SDCCicode.h @@ -1,25 +1,25 @@ /*------------------------------------------------------------------------- - 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" @@ -27,260 +27,325 @@ #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 ( ); -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 *newiTempOperand (sym_link *, char); +operand *newiTempFromOp (operand *); +iCode *getBuiltinParms (iCode *,int *, operand **); +int isiCodeInFunctionCall (iCode *); /*-----------------------------------------------------------------*/ /* declaration of exported variables */ /*-----------------------------------------------------------------*/ extern char *filename; -int lineno; +extern int lineno; #endif