X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCicode.h;h=d2c69a1f10ef2537ff3b1138dfeb8f7918bffa02;hb=HEAD;hp=a6f656a67606500c01a8aed4b5bf8d6fd5805852;hpb=54f886ab573f40c4356bbc4dc97c4196da96871b;p=fw%2Fsdcc diff --git a/src/SDCCicode.h b/src/SDCCicode.h index a6f656a6..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" @@ -49,6 +49,9 @@ typedef enum 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 sym_link *ltype = operandType(left), \ @@ -58,48 +61,59 @@ OPTYPE; #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; + 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); + +#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 @@ -107,77 +121,79 @@ operand; #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_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 */ - 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 */ + 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; + 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; + 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 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; @@ -186,83 +202,99 @@ typedef struct icodeFuncTable { 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 || \ - 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 */ /*-----------------------------------------------------------------*/ @@ -271,8 +303,7 @@ bool isOperandOnStack (operand *); int isOperandVolatile (operand *, bool); int isOperandGlobal (operand *); void printiCChain (iCode *, FILE *); -operand *ast2iCode (ast *); -operand *geniCodeCast (sym_link *, operand *, bool); +operand *ast2iCode (ast *,int); operand *geniCodePtrPtrSubtract (operand *, operand *); void initiCode (); iCode *iCodeFromAst (ast *); @@ -282,25 +313,36 @@ iCodeTable *getTableEntry (int); int isOperandLiteral (operand *); operand *operandOperation (operand *, operand *, int, sym_link *); double operandLitValue (operand *); -operand *operandFromLit (float); +operand *operandFromLit (double); operand *operandFromOperand (operand *); int isParameterToCall (value *, operand *); 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 */ /*-----------------------------------------------------------------*/