1 /*-------------------------------------------------------------------------
3 SDCCicode.c - intermediate code generation etc.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
27 /*-----------------------------------------------------------------*/
28 /* global variables */
30 set *iCodeChain = NULL ;
41 symbol *returnLabel ; /* function return label */
42 symbol *entryLabel ; /* function entry label */
43 /*-----------------------------------------------------------------*/
44 /* forward definition of some functions */
45 operand *geniCodeDivision (operand *,operand *);
46 operand *geniCodeAssign (operand *,operand *,int);
47 operand *geniCodeArray (operand *,operand *);
48 operand *geniCodeArray2Ptr (operand *);
49 operand *geniCodeRValue (operand *, bool );
50 operand *geniCodeDerefPtr (operand *);
52 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
53 /* forward definition of print functions */
54 PRINTFUNC(picGetValueAtAddr);
55 PRINTFUNC(picSetValueAtAddr);
57 PRINTFUNC(picGeneric);
58 PRINTFUNC(picGenericOne);
64 PRINTFUNC(picJumpTable);
66 PRINTFUNC(picReceive);
68 iCodeTable codeTable[] = {
69 { '!' , "not", picGenericOne , NULL },
70 { '~' , "~" , picGenericOne , NULL },
71 { RRC , "rrc", picGenericOne , NULL },
72 { RLC , "rlc", picGenericOne , NULL },
73 { GETHBIT ,"ghbit", picGenericOne , NULL },
74 { UNARYMINUS , "-" , picGenericOne , NULL },
75 { IPUSH , "push",picGenericOne , NULL },
76 { IPOP , "pop", picGenericOne , NULL },
77 { CALL , "call",picGenericOne , NULL },
78 { PCALL , "pcall",picGenericOne , NULL },
79 { FUNCTION , "proc", picGenericOne , NULL },
80 { ENDFUNCTION ,"eproc", picGenericOne , NULL },
81 { RETURN , "ret", picGenericOne , NULL },
82 { '+' , "+" , picGeneric , NULL },
83 { '-' , "-" , picGeneric , NULL },
84 { '*' , "*" , picGeneric , NULL },
85 { '/' , "/" , picGeneric , NULL },
86 { '%' , "%" , picGeneric , NULL },
87 { '>' , ">" , picGeneric , NULL },
88 { '<' , "<" , picGeneric , NULL },
89 { LE_OP , "<=" , picGeneric , NULL },
90 { GE_OP , ">=" , picGeneric , NULL },
91 { EQ_OP , "==" , picGeneric , NULL },
92 { NE_OP , "!=" , picGeneric , NULL },
93 { AND_OP , "&&" , picGeneric , NULL },
94 { OR_OP , "||" , picGeneric , NULL },
95 { '^' , "^" , picGeneric , NULL },
96 { '|' , "|" , picGeneric , NULL },
97 { BITWISEAND , "&" , picGeneric , NULL },
98 { LEFT_OP , "<<" , picGeneric , NULL },
99 { RIGHT_OP , ">>" , picGeneric , NULL },
100 { GET_VALUE_AT_ADDRESS, "@" , picGetValueAtAddr, NULL },
101 { ADDRESS_OF , "&" , picAddrOf , NULL },
102 { CAST , "<>" , picCast , NULL },
103 { '=' , ":=" , picAssign , NULL },
104 { LABEL , "" , picLabel , NULL },
105 { GOTO , "" , picGoto , NULL },
106 { JUMPTABLE ,"jtab" , picJumpTable , NULL },
107 { IFX , "if" , picIfx , NULL },
108 { INLINEASM , "" , picInline , NULL },
109 { RECEIVE , "recv", picReceive , NULL },
110 { SEND , "send", picGenericOne , NULL }
114 /*-----------------------------------------------------------------*/
115 /* operandName - returns the name of the operand */
116 /*-----------------------------------------------------------------*/
117 int printOperand (operand *op, FILE *file)
132 opetype = getSpec (operandType(op));
133 if (SPEC_NOUN(opetype) == V_FLOAT)
134 fprintf (file,"%g {", SPEC_CVAL(opetype).v_float);
136 fprintf (file,"0x%x {",(int) floatFromVal(op->operand.valOperand));
137 printTypeChain(operandType(op),file);
144 fprintf (file,"%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d}",/*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" ,*/
145 (OP_SYMBOL(op)->rname[0] ? OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name),
147 OP_LIVEFROM(op),OP_LIVETO(op),
148 OP_SYMBOL(op)->stack,
149 op->isaddr, OP_SYMBOL(op)->isreqv,OP_SYMBOL(op)->remat
152 fprintf(file,"{"); printTypeChain(operandType(op),file);
153 if (SPIL_LOC(op) && IS_ITEMP(op))
154 fprintf(file,"}{ sir@ %s",SPIL_LOC(op)->rname);
159 /* if assigned to registers */
160 if (OP_SYMBOL(op)->nRegs) {
161 if (OP_SYMBOL(op)->isspilt) {
162 if (!OP_SYMBOL(op)->remat)
163 if (OP_SYMBOL(op)->usl.spillLoc)
164 fprintf(file,"[%s]",(OP_SYMBOL(op)->usl.spillLoc->rname[0] ?
165 OP_SYMBOL(op)->usl.spillLoc->rname :
166 OP_SYMBOL(op)->usl.spillLoc->name));
168 fprintf(file,"[err]");
170 fprintf(file,"[remat]");
175 for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
176 fprintf(file,"%s ", port->getRegName(OP_SYMBOL(op)->regs[i]));
181 fprintf(file,"%s",(OP_SYMBOL(op)->rname[0] ?
182 OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name));
183 /* if assigned to registers */
184 if (OP_SYMBOL(op)->nRegs && !OP_SYMBOL(op)->isspilt) {
187 for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
188 fprintf(file,"%s ",(OP_SYMBOL(op)->regs[i] ?
189 OP_SYMBOL(op)->regs[i]->name :
198 printTypeChain(op->operand.typeOperand,file);
209 /*-----------------------------------------------------------------*/
210 /* print functions */
211 /*-----------------------------------------------------------------*/
212 PRINTFUNC(picGetValueAtAddr)
215 printOperand (IC_RESULT(ic),of);
218 printOperand (IC_LEFT(ic), of);
224 PRINTFUNC(picSetValueAtAddr)
228 printOperand(IC_LEFT(ic),of);
230 printOperand(IC_RIGHT(ic),of);
237 printOperand(IC_RESULT(ic),of);
238 if (IS_ITEMP(IC_LEFT(ic)))
242 printOperand(IC_LEFT(ic),of);
244 if (IS_ITEMP(IC_LEFT(ic)))
245 fprintf(of," offsetAdd ");
248 printOperand(IC_RIGHT(ic),of);
250 if (IS_ITEMP(IC_LEFT(ic)))
256 PRINTFUNC(picJumpTable)
261 fprintf(of,"%s\t",s);
262 printOperand(IC_JTCOND(ic),of);
264 for ( sym = setFirstItem(IC_JTLABELS(ic)); sym;
265 sym = setNextItem(IC_JTLABELS(ic)))
266 fprintf(of,"\t\t\t%s\n",sym->name);
269 PRINTFUNC(picGeneric)
272 printOperand(IC_RESULT(ic),of);
274 printOperand(IC_LEFT(ic),of);
275 fprintf(of," %s ",s);
276 printOperand(IC_RIGHT(ic),of);
280 PRINTFUNC(picGenericOne)
283 if ( IC_RESULT(ic) ) {
284 printOperand(IC_RESULT(ic),of);
289 fprintf (of,"%s ",s);
290 printOperand(IC_LEFT(ic),of);
293 if (! IC_RESULT(ic) && !IC_LEFT(ic))
302 printOperand(IC_RESULT(ic),of);
304 printOperand(IC_LEFT(ic),of);
305 printOperand(IC_RIGHT(ic),of);
314 if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
317 printOperand(IC_RESULT(ic),of);
319 if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
322 fprintf(of," %s ", s);
323 printOperand (IC_RIGHT(ic),of);
330 fprintf(of," %s($%d) :\n",IC_LABEL(ic)->name,IC_LABEL(ic)->key);
336 fprintf (of," goto %s($%d)\n", IC_LABEL(ic)->name,IC_LABEL(ic)->key);
343 printOperand(IC_COND(ic),of);
346 fprintf (of," == 0 goto %s($%d)\n",IC_FALSE(ic)->name,IC_FALSE(ic)->key);
348 fprintf (of," != 0 goto %s($%d)\n",IC_TRUE(ic)->name,IC_TRUE(ic)->key);
350 fprintf (of,"\tzzgoto %s\n",IC_FALSE(ic)->name);
356 fprintf(of,"%s",IC_INLINE(ic));
359 PRINTFUNC(picReceive)
361 printOperand(IC_RESULT(ic),of);
362 fprintf(of," = %s ",s);
363 printOperand(IC_LEFT(ic),of);
367 /*-----------------------------------------------------------------*/
368 /* piCode - prints one iCode */
369 /*-----------------------------------------------------------------*/
370 int piCode (void *item, FILE *of)
378 icTab = getTableEntry(ic->op) ;
379 fprintf(stdout,"%s(%d:%d:%d:%d:%d)\t",
380 ic->filename,ic->lineno,
381 ic->seq,ic->key,ic->depth,ic->supportRtn);
382 icTab->iCodePrint(of,ic,icTab->printName);
386 /*-----------------------------------------------------------------*/
387 /* printiCChain - prints intermediate code for humans */
388 /*-----------------------------------------------------------------*/
389 void printiCChain (iCode *icChain, FILE *of)
396 for ( loop = icChain ; loop ; loop = loop->next ) {
397 if ((icTab = getTableEntry (loop->op ))) {
398 fprintf(of,"%s(%d:%d:%d:%d:%d)\t",
399 loop->filename,loop->lineno,
400 loop->seq,loop->key,loop->depth,loop->supportRtn);
402 icTab->iCodePrint (of,loop,icTab->printName);
408 /*-----------------------------------------------------------------*/
409 /* newOperand - allocate, init & return a new iCode */
410 /*-----------------------------------------------------------------*/
411 operand *newOperand ()
415 ALLOC(op,sizeof(operand));
421 /*-----------------------------------------------------------------*/
422 /* newiCode - create and return a new iCode entry initialised */
423 /*-----------------------------------------------------------------*/
424 iCode *newiCode (int op, operand *left, operand *right)
428 ALLOC(ic,sizeof(iCode));
430 ic->lineno = lineno ;
431 ic->filename= filename ;
433 ic->level = scopeLevel;
435 ic->key= iCodeKey++ ;
442 /*-----------------------------------------------------------------*/
443 /* newiCode for conditional statements */
444 /*-----------------------------------------------------------------*/
445 iCode *newiCodeCondition (operand *condition,
451 ic = newiCode(IFX,NULL,NULL);
452 IC_COND(ic) = condition ;
453 IC_TRUE(ic) = trueLabel ;
454 IC_FALSE(ic) = falseLabel;
458 /*-----------------------------------------------------------------*/
459 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
460 /*-----------------------------------------------------------------*/
461 iCode *newiCodeLabelGoto (int op, symbol *label)
465 ic = newiCode(op,NULL,NULL);
467 ic->argLabel.label = label ;
469 IC_RIGHT(ic) = NULL ;
470 IC_RESULT(ic) = NULL ;
474 /*-----------------------------------------------------------------*/
475 /* newiTemp - allocate & return a newItemp Variable */
476 /*-----------------------------------------------------------------*/
477 symbol *newiTemp (char *s)
482 sprintf(buffer,"%s",s);
484 sprintf (buffer,"iTemp%d",iTempNum++);
485 itmp = newSymbol (buffer,1);
486 strcpy(itmp->rname,itmp->name);
492 /*-----------------------------------------------------------------*/
493 /* newiTempLabel - creates a temp variable label */
494 /*-----------------------------------------------------------------*/
495 symbol *newiTempLabel (char *s)
499 /* check if this alredy exists */
500 if (s && (itmplbl = findSym(LabelTab, NULL, s)))
504 itmplbl = newSymbol(s,1);
506 sprintf(buffer,"iTempLbl%d",iTempLblNum++);
507 itmplbl = newSymbol(buffer,1);
512 itmplbl->key = labelKey++ ;
513 addSym (LabelTab, itmplbl, itmplbl->name,0,0);
517 /*-----------------------------------------------------------------*/
518 /* newiTempPreheaderLabel - creates a new preheader label */
519 /*-----------------------------------------------------------------*/
520 symbol *newiTempPreheaderLabel()
524 sprintf(buffer,"preHeaderLbl%d",iTempLblNum++);
525 itmplbl = newSymbol(buffer,1);
529 itmplbl->key = labelKey++ ;
530 addSym (LabelTab, itmplbl, itmplbl->name,0,0);
535 /*-----------------------------------------------------------------*/
536 /* initiCode - initialises some iCode related stuff */
537 /*-----------------------------------------------------------------*/
543 /*-----------------------------------------------------------------*/
544 /* copyiCode - make a copy of the iCode given */
545 /*-----------------------------------------------------------------*/
546 iCode *copyiCode (iCode *ic)
548 iCode *nic = newiCode(ic->op,NULL,NULL);
550 nic->lineno = ic->lineno ;
551 nic->filename= ic->filename ;
552 nic->block = ic->block;
553 nic->level = ic->level;
555 /* deal with the special cases first */
558 IC_COND(nic) = operandFromOperand(IC_COND(ic));
559 IC_TRUE(nic) = IC_TRUE(ic);
560 IC_FALSE(nic)= IC_FALSE(ic);
564 IC_JTCOND(nic) = operandFromOperand(IC_JTCOND(ic));
565 IC_JTLABELS(nic) = IC_JTLABELS(ic);
570 IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
571 IC_LEFT(nic) = operandFromOperand(IC_LEFT(ic));
572 IC_ARGS(nic) = IC_ARGS(ic);
576 IC_INLINE(nic) = IC_INLINE(ic);
580 IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
581 IC_LEFT(nic) = operandFromOperand(IC_LEFT(ic));
582 IC_RIGHT(nic)= operandFromOperand(IC_RIGHT(ic));
588 /*-----------------------------------------------------------------*/
589 /* getTableEntry - gets the table entry for the given operator */
590 /*-----------------------------------------------------------------*/
591 iCodeTable *getTableEntry (int oper )
595 for ( i = 0 ; i < (sizeof(codeTable)/sizeof(iCodeTable)); i++ )
596 if (oper == codeTable[i].icode)
597 return &codeTable[i] ;
602 /*-----------------------------------------------------------------*/
603 /* newiTempOperand - new intermediate temp operand */
604 /*-----------------------------------------------------------------*/
605 operand *newiTempOperand (sym_link *type, char throwType)
608 operand *op = newOperand();
612 itmp = newiTemp(NULL);
614 etype = getSpec(type);
616 if (IS_LITERAL(etype) )
619 /* copy the type information */
621 itmp->etype = getSpec (itmp->type = (throwType ? type :
622 copyLinkChain(type)));
623 if (IS_LITERAL(itmp->etype)) {
624 SPEC_SCLS(itmp->etype) = S_REGISTER ;
625 SPEC_OCLS(itmp->etype) = reg;
628 op->operand.symOperand = itmp;
629 op->key = itmp->key = ++operandKey ;
633 /*-----------------------------------------------------------------*/
634 /* operandType - returns the type chain for an operand */
635 /*-----------------------------------------------------------------*/
636 sym_link *operandType (operand *op)
638 /* depending on type of operand */
642 return op->operand.valOperand->type ;
645 return op->operand.symOperand->type ;
648 return op->operand.typeOperand ;
650 werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
651 " operand type not known ");
652 assert (0) ; /* should never come here */
653 /* Just to keep the compiler happy */
654 return (sym_link *)0;
658 /*-----------------------------------------------------------------*/
659 /* isParamterToCall - will return 1 if op is a parameter to args */
660 /*-----------------------------------------------------------------*/
661 int isParameterToCall (value *args, operand *op)
667 isSymbolEqual(op->operand.symOperand,tval->sym))
674 /*-----------------------------------------------------------------*/
675 /* isOperandGlobal - return 1 if operand is a global variable */
676 /*-----------------------------------------------------------------*/
677 int isOperandGlobal ( operand *op )
685 if (op->type == SYMBOL &&
686 (op->operand.symOperand->level == 0 ||
687 IS_STATIC(op->operand.symOperand->etype) ||
688 IS_EXTERN(op->operand.symOperand->etype))
695 /*-----------------------------------------------------------------*/
696 /* isOperandVolatile - return 1 if the operand is volatile */
697 /*-----------------------------------------------------------------*/
698 int isOperandVolatile ( operand *op , bool chkTemp)
703 if (IS_ITEMP(op) && !chkTemp)
706 opetype = getSpec(optype = operandType(op));
708 if (IS_PTR(optype) && DCL_PTR_VOLATILE(optype))
711 if (IS_VOLATILE(opetype))
716 /*-----------------------------------------------------------------*/
717 /* isOperandLiteral - returns 1 if an operand contains a literal */
718 /*-----------------------------------------------------------------*/
719 int isOperandLiteral ( operand *op )
726 opetype = getSpec (operandType(op));
728 if (IS_LITERAL(opetype))
733 /*-----------------------------------------------------------------*/
734 /* isOperandInFarSpace - will return true if operand is in farSpace*/
735 /*-----------------------------------------------------------------*/
736 bool isOperandInFarSpace (operand *op)
746 if (!IS_TRUE_SYMOP(op)) {
748 etype = SPIL_LOC(op)->etype;
754 etype = getSpec(operandType(op));
756 return (IN_FARSPACE(SPEC_OCLS(etype)) ? TRUE : FALSE);
759 /*-----------------------------------------------------------------*/
760 /* isOperandOnStack - will return true if operand is on stack */
761 /*-----------------------------------------------------------------*/
762 bool isOperandOnStack(operand *op)
772 etype = getSpec(operandType(op));
774 return ((IN_STACK(etype)) ? TRUE : FALSE);
777 /*-----------------------------------------------------------------*/
778 /* operandLitValue - literal value of an operand */
779 /*-----------------------------------------------------------------*/
780 double operandLitValue ( operand *op )
782 assert(isOperandLiteral(op));
784 return floatFromVal(op->operand.valOperand);
787 /*-----------------------------------------------------------------*/
788 /* operandOperation - perforoms operations on operands */
789 /*-----------------------------------------------------------------*/
790 operand *operandOperation (operand *left,operand *right,
791 int op, sym_link *type)
793 operand *retval = (operand *)0;
795 assert(isOperandLiteral(left));
797 assert(isOperandLiteral(right));
801 retval = operandFromValue (valCastLiteral(type,
802 operandLitValue(left) +
803 operandLitValue(right)));
806 retval = operandFromValue(valCastLiteral(type,
807 operandLitValue(left) -
808 operandLitValue(right)));
811 retval = operandFromValue(valCastLiteral(type,
812 operandLitValue(left) *
813 operandLitValue(right)));
816 if ((unsigned long) operandLitValue(right) == 0){
817 werror(E_DIVIDE_BY_ZERO);
822 retval = operandFromValue (valCastLiteral(type,
823 operandLitValue(left) /
824 operandLitValue(right)));
827 if ((unsigned long) operandLitValue(right) == 0){
828 werror(E_DIVIDE_BY_ZERO);
832 retval = operandFromLit ((unsigned long) operandLitValue(left) %
833 (unsigned long) operandLitValue(right));
836 retval = operandFromLit ((unsigned long) operandLitValue(left) <<
837 (unsigned long) operandLitValue(right));
840 retval = operandFromLit ((unsigned long) operandLitValue(left) >>
841 (unsigned long) operandLitValue(right));
844 retval = operandFromLit (operandLitValue(left) ==
845 operandLitValue(right));
848 retval = operandFromLit (operandLitValue(left) <
849 operandLitValue(right));
852 retval = operandFromLit (operandLitValue(left) <=
853 operandLitValue(right));
856 retval = operandFromLit (operandLitValue(left) !=
857 operandLitValue(right));
860 retval = operandFromLit (operandLitValue(left) >
861 operandLitValue(right));
864 retval = operandFromLit (operandLitValue(left) >=
865 operandLitValue(right));
868 retval = operandFromLit ((unsigned long) operandLitValue(left) &
869 (unsigned long) operandLitValue(right));
872 retval = operandFromLit ((unsigned long) operandLitValue(left) |
873 (unsigned long) operandLitValue(right));
876 retval = operandFromLit ((unsigned long) operandLitValue(left) ^
877 (unsigned long) operandLitValue(right));
880 retval = operandFromLit (operandLitValue(left) &&
881 operandLitValue(right));
884 retval = operandFromLit (operandLitValue(left) ||
885 operandLitValue(right));
889 long i = operandLitValue(left);
891 retval = operandFromLit ((i >> (getSize(operandType(left))*8 - 1)) |
897 long i = operandLitValue(left);
899 retval = operandFromLit ((i << (getSize(operandType(left))*8 - 1)) |
905 retval = operandFromLit(-1 * operandLitValue(left));
909 retval = operandFromLit(~ ((long) operandLitValue(left)));
913 retval = operandFromLit(! operandLitValue(left));
917 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
918 " operandOperation invalid operator ");
926 /*-----------------------------------------------------------------*/
927 /* isOperandEqual - compares two operand & return 1 if they r = */
928 /*-----------------------------------------------------------------*/
929 int isOperandEqual (operand *left, operand *right)
931 /* if the pointers are equal then they are equal */
935 /* if either of them null then false */
936 if ( !left || !right)
939 if (left->type != right->type)
942 if (IS_SYMOP(left) && IS_SYMOP(right))
943 return left->key == right->key ;
945 /* if types are the same */
946 switch (left->type) {
948 return isSymbolEqual(left->operand.symOperand,
949 right->operand.symOperand);
951 return (floatFromVal(left->operand.valOperand) ==
952 floatFromVal(right->operand.valOperand));
954 if (checkType(left->operand.typeOperand,
955 right->operand.typeOperand) == 1)
962 /*-----------------------------------------------------------------*/
963 /* isiCodeEqual - comapres two iCodes are returns true if yes */
964 /*-----------------------------------------------------------------*/
965 int isiCodeEqual (iCode *left, iCode *right)
967 /* if the same pointer */
971 /* if either of them null */
975 /* if operand are the same */
976 if ( left->op == right->op ) {
978 /* compare all the elements depending on type */
979 if (left->op != IFX ) {
980 if (!isOperandEqual(IC_LEFT(left),IC_LEFT(right)))
982 if (!isOperandEqual(IC_RIGHT(left),IC_RIGHT(right)))
986 if (!isOperandEqual(IC_COND(left),IC_COND(right)))
988 if (!isSymbolEqual (IC_TRUE(left),IC_TRUE(right)))
990 if (!isSymbolEqual(IC_FALSE(left),IC_FALSE(right)))
998 /*-----------------------------------------------------------------*/
999 /* newiTempFromOp - create a temp Operand with same attributes */
1000 /*-----------------------------------------------------------------*/
1001 operand *newiTempFromOp (operand *op)
1011 nop = newiTempOperand(operandType(op),TRUE);
1012 nop->isaddr = op->isaddr ;
1013 nop->isvolatile = op->isvolatile ;
1014 nop->isGlobal = op->isGlobal ;
1015 nop->isLiteral= op->isLiteral ;
1016 nop->noSpilLoc= op->noSpilLoc;
1017 nop->usesDefs = op->usesDefs;
1018 nop->isParm = op->isParm;
1019 nop->parmBytes = op->parmBytes;
1023 /*-----------------------------------------------------------------*/
1024 /* operand from operand - creates an operand holder for the type */
1025 /*-----------------------------------------------------------------*/
1026 operand *operandFromOperand (operand *op)
1033 nop->type = op->type;
1034 nop->isaddr = op->isaddr ;
1035 nop->key = op->key ;
1036 nop->isvolatile = op->isvolatile ;
1037 nop->isGlobal = op->isGlobal ;
1038 nop->isLiteral= op->isLiteral ;
1039 nop->noSpilLoc= op->noSpilLoc;
1040 nop->usesDefs = op->usesDefs;
1041 nop->isParm = op->isParm;
1042 nop->parmBytes = op->parmBytes;
1044 switch (nop->type) {
1046 nop->operand.symOperand = op->operand.symOperand ;
1049 nop->operand.valOperand = op->operand.valOperand;
1052 nop->operand.typeOperand = op->operand.typeOperand ;
1059 /*-----------------------------------------------------------------*/
1060 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1061 /*-----------------------------------------------------------------*/
1062 operand *opFromOpWithDU (operand *op, bitVect *defs, bitVect *uses)
1064 operand *nop = operandFromOperand(op);
1066 if (nop->type == SYMBOL) {
1067 OP_SYMBOL(nop)->defs = bitVectCopy(defs);
1068 OP_SYMBOL(nop)->uses = bitVectCopy(uses);
1074 /*-----------------------------------------------------------------*/
1075 /* operandFromSymbol - creates an operand from a symbol */
1076 /*-----------------------------------------------------------------*/
1077 operand *operandFromSymbol (symbol *sym)
1082 /* if the symbol's type is a literal */
1083 /* then it is an enumerator type */
1084 if (IS_LITERAL(sym->etype) && SPEC_ENUM(sym->etype))
1085 return operandFromValue (valFromType(sym->etype));
1088 sym->key = ++operandKey ;
1090 /* if this an implicit variable, means struct/union */
1091 /* member so just return it */
1092 if (sym->implicit || IS_FUNC(sym->type)) {
1095 op->operand.symOperand = sym;
1096 op->key = sym->key ;
1097 op->isvolatile = isOperandVolatile(op,TRUE);
1098 op->isGlobal = isOperandGlobal(op);
1099 op->parmBytes = sym->argStack;
1103 /* under the following conditions create a
1104 register equivalent for a local symbol */
1105 if (sym->level && sym->etype && SPEC_OCLS(sym->etype) &&
1106 (IN_FARSPACE(SPEC_OCLS(sym->etype)) && (!IS_DS390_PORT)) &&
1107 options.stackAuto == 0)
1110 if (!IS_AGGREGATE(sym->type) && /* not an aggregate */
1111 !IS_FUNC(sym->type) && /* not a function */
1112 !sym->_isparm && /* not a parameter */
1113 sym->level && /* is a local variable */
1114 !sym->addrtaken && /* whose address has not been taken */
1115 !sym->reqv && /* does not already have a register euivalence */
1116 !IS_VOLATILE(sym->etype) && /* not declared as volatile */
1117 !IS_STATIC(sym->etype) && /* and not declared static */
1118 !sym->islbl && /* not a label */
1119 ok && /* farspace check */
1120 !IS_BITVAR(sym->etype) /* not a bit variable */
1123 /* we will use it after all optimizations
1124 and before liveRange calculation */
1125 sym->reqv = newiTempOperand(sym->type,0);
1126 sym->reqv->key = sym->key ;
1127 OP_SYMBOL(sym->reqv)->key = sym->key;
1128 OP_SYMBOL(sym->reqv)->isreqv = 1;
1129 OP_SYMBOL(sym->reqv)->islocal = 1;
1130 SPIL_LOC(sym->reqv) = sym;
1133 if (!IS_AGGREGATE(sym->type)) {
1136 op->operand.symOperand = sym;
1139 op->isvolatile = isOperandVolatile(op,TRUE);
1140 op->isGlobal = isOperandGlobal(op);
1141 op->isPtr = IS_PTR(operandType(op));
1142 op->isParm = sym->_isparm ;
1147 /* itemp = &[_symbol] */
1149 ic = newiCode(ADDRESS_OF,newOperand(),NULL);
1150 IC_LEFT(ic)->type = SYMBOL ;
1151 IC_LEFT(ic)->operand.symOperand = sym ;
1152 IC_LEFT(ic)->key = sym->key;
1153 (IC_LEFT(ic))->isvolatile = isOperandVolatile(IC_LEFT(ic),TRUE);
1154 (IC_LEFT(ic))->isGlobal = isOperandGlobal(IC_LEFT(ic));
1155 IC_LEFT(ic)->isPtr = IS_PTR(operandType(IC_LEFT(ic)));
1158 IC_RESULT(ic) = newiTempOperand(sym->type,0);
1159 if (IS_ARRAY(sym->type)) {
1160 IC_RESULT(ic) = geniCodeArray2Ptr (IC_RESULT(ic));
1161 IC_RESULT(ic)->isaddr = 0;
1163 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(sym->type));
1165 IC_RESULT(ic)->operand.symOperand->args = sym->args;
1169 return IC_RESULT(ic) ;
1172 /*-----------------------------------------------------------------*/
1173 /* operandFromValue - creates an operand from value */
1174 /*-----------------------------------------------------------------*/
1175 operand *operandFromValue (value *val)
1179 /* if this is a symbol then do the symbol thing */
1181 return operandFromSymbol (val->sym);
1183 /* this is not a symbol */
1186 op->operand.valOperand = val ;
1187 op->isLiteral = isOperandLiteral(op);
1191 /*-----------------------------------------------------------------*/
1192 /* operandFromLink - operand from typeChain */
1193 /*-----------------------------------------------------------------*/
1194 operand *operandFromLink (sym_link *type)
1198 /* operand from sym_link */
1204 op->operand.typeOperand = copyLinkChain(type);
1208 /*-----------------------------------------------------------------*/
1209 /* operandFromLit - makes an operand from a literal value */
1210 /*-----------------------------------------------------------------*/
1211 operand *operandFromLit ( float i)
1213 return operandFromValue (valueFromLit (i));
1216 /*-----------------------------------------------------------------*/
1217 /* operandFromAst - creates an operand from an ast */
1218 /*-----------------------------------------------------------------*/
1219 operand *operandFromAst ( ast *tree )
1225 /* depending on type do */
1226 switch (tree->type ) {
1228 return ast2iCode (tree) ;
1232 return operandFromValue(tree->opval.val) ;
1236 return operandFromLink (tree->opval.lnk) ;
1240 /* Just to keep the comiler happy */
1241 return (operand *)0;
1244 /*-----------------------------------------------------------------*/
1245 /* setOperandType - sets the operand's type to the given type */
1246 /*-----------------------------------------------------------------*/
1247 void setOperandType (operand *op, sym_link *type)
1249 /* depending on the type of operand */
1253 op->operand.valOperand->etype =
1254 getSpec( op->operand.valOperand->type =
1255 copyLinkChain (type )) ;
1259 if (op->operand.symOperand->isitmp )
1260 op->operand.symOperand->etype =
1261 getSpec( op->operand.symOperand->type =
1262 copyLinkChain (type )) ;
1264 werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
1265 "attempt to modify type of source");
1269 op->operand.typeOperand = copyLinkChain (type);
1275 /*-----------------------------------------------------------------*/
1276 /* perform "usual unary conversions" */
1277 /*-----------------------------------------------------------------*/
1278 operand *usualUnaryConversions(operand *op)
1280 if (IS_INTEGRAL(operandType(op)))
1282 if (getSize(operandType(op)) < INTSIZE)
1285 return geniCodeCast(INTTYPE,op,TRUE);
1291 /*-----------------------------------------------------------------*/
1292 /* perform "usual binary conversions" */
1293 /*-----------------------------------------------------------------*/
1294 sym_link * usualBinaryConversions(operand **op1, operand **op2)
1296 if (!options.ANSIint)
1298 /* "Classic" SDCC behavior. */
1300 sym_link *rtype = operandType(*op2);
1301 sym_link *ltype = operandType(*op1);
1303 ctype = computeType(ltype,rtype);
1304 *op1 = geniCodeCast(ctype,*op1,TRUE);
1305 *op2= geniCodeCast(ctype,*op2,TRUE);
1310 *op1 = usualUnaryConversions(*op1);
1311 *op2 = usualUnaryConversions(*op2);
1313 /* Try to make the two operands of the same type, following
1314 * the "usual binary conversions" promotion rules.
1316 * NB: floating point types are not yet properly handled; we
1317 * follow the "classic" behavior.
1320 if (IS_FLOAT(operandType(*op1)) || IS_FLOAT(operandType(*op2)))
1322 return newFloatLink();
1325 if (!IS_INTEGRAL(operandType(*op1)) || !IS_INTEGRAL(operandType(*op2)))
1327 /* if either is not an integer type, we're done. */
1328 return copyLinkChain(operandType(*op1)); /* Punt! we should never get here. */
1331 /* If either is an unsigned long, make sure both are. */
1332 if (SPEC_USIGN(operandType(*op1)) && IS_LONG(operandType(*op1)))
1334 if (!SPEC_USIGN(operandType(*op2)) || !IS_LONG(operandType(*op2)))
1336 *op2 = geniCodeCast(ULONGTYPE,*op2,TRUE);
1338 return copyLinkChain(operandType(*op1));
1341 if (SPEC_USIGN(operandType(*op2)) && IS_LONG(operandType(*op2)))
1343 if (!SPEC_USIGN(operandType(*op1)) || !IS_LONG(operandType(*op1)))
1345 *op1 = geniCodeCast(ULONGTYPE,*op1,TRUE);
1347 return copyLinkChain(operandType(*op2));
1350 /* Next, if one is long and the other is int (signed or un),
1351 * cast both to long.
1353 * Note that because in our environment a long can hold all
1354 * the values of an unsigned int, the "long/unsigned int" pair
1355 * in the ANSI conversion table is unnecessary; this test
1356 * handles that case implicitly.
1358 if (IS_LONG(operandType(*op1)))
1360 /* NB: because of the unary conversions, op2 cannot
1361 * be smaller than int. Therefore, if it is not
1362 * long, it is a regular int.
1364 if (!IS_LONG(operandType(*op2)))
1366 *op2 = geniCodeCast(LONGTYPE,*op2,TRUE);
1368 return copyLinkChain(operandType(*op1));
1371 if (IS_LONG(operandType(*op2)))
1373 /* NB: because of the unary conversions, op2 cannot
1374 * be smaller than int. Therefore, if it is not
1375 * long, it is a regular int.
1377 if (!IS_LONG(operandType(*op1)))
1379 *op1 = geniCodeCast(LONGTYPE,*op1,TRUE);
1381 return copyLinkChain(operandType(*op2));
1384 /* All right, neither is long; they must both be integers.
1386 * Only remaining issue is signed vs. unsigned; if one is unsigned
1387 * and the other isn't, convert both to unsigned.
1389 if (SPEC_USIGN(operandType(*op1)))
1391 if (!SPEC_USIGN(operandType(*op2)))
1393 *op2 = geniCodeCast(UINTTYPE,*op2,TRUE);
1395 return copyLinkChain(operandType(*op1));
1398 if (SPEC_USIGN(operandType(*op2)))
1400 if (!SPEC_USIGN(operandType(*op1)))
1402 *op1 = geniCodeCast(UINTTYPE,*op1,TRUE);
1404 return copyLinkChain(operandType(*op2));
1408 return copyLinkChain(operandType(*op1));
1412 /*-----------------------------------------------------------------*/
1413 /* geniCodeValueAtAddress - generate intermeditate code for value */
1415 /*-----------------------------------------------------------------*/
1416 operand *geniCodeRValue (operand *op, bool force)
1419 sym_link *type = operandType(op);
1420 sym_link *etype= getSpec(type);
1422 /* if this is an array & already */
1423 /* an address then return this */
1424 if (IS_AGGREGATE(type) ||
1425 (IS_PTR(type) && !force && !op->isaddr))
1426 return operandFromOperand(op);
1428 /* if this is not an address then must be */
1429 /* rvalue already so return this one */
1433 /* if this is not a temp symbol then */
1434 if (!IS_ITEMP(op) &&
1436 !IN_FARSPACE(SPEC_OCLS(etype))) {
1437 op = operandFromOperand(op);
1442 if (IS_SPEC(type) &&
1443 IS_TRUE_SYMOP(op) &&
1444 !IN_FARSPACE(SPEC_OCLS(etype))) {
1445 op = operandFromOperand(op);
1450 ic = newiCode(GET_VALUE_AT_ADDRESS,op,NULL);
1451 if (IS_PTR(type) && op->isaddr && force)
1454 type = copyLinkChain(type);
1456 IC_RESULT(ic) = newiTempOperand (type,1);
1457 IC_RESULT(ic)->isaddr = 0;
1459 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1461 /* if the right is a symbol */
1462 if (op->type == SYMBOL)
1463 IC_RESULT(ic)->operand.symOperand->args =
1464 op->operand.symOperand->args ;
1467 return IC_RESULT(ic) ;
1470 /*-----------------------------------------------------------------*/
1471 /* geniCodeCast - changes the value from one type to another */
1472 /*-----------------------------------------------------------------*/
1473 operand *geniCodeCast (sym_link *type, operand *op, bool implicit)
1477 sym_link *opetype = getSpec(optype = operandType(op));
1480 /* one of them has size zero then error */
1481 if (IS_VOID(optype)) {
1482 werror(E_CAST_ZERO);
1486 /* if the operand is already the desired type then do nothing */
1487 if ( checkType (type,optype) == 1)
1490 /* if this is a literal then just change the type & return */
1491 if (IS_LITERAL(opetype) && op->type == VALUE && !IS_PTR(type) && !IS_PTR(optype))
1492 return operandFromValue(valCastLiteral(type,
1493 operandLitValue(op)));
1495 /* if casting to some pointer type &&
1496 the destination is not a generic pointer
1497 then give a warning : (only for implicit casts)*/
1498 if (IS_PTR(optype) && implicit &&
1499 (DCL_TYPE(optype) != DCL_TYPE(type)) &&
1501 werror(E_INCOMPAT_CAST);
1502 werror(E_CONTINUE,"from type '");
1503 printTypeChain(optype,stderr);fprintf(stderr,"' to type '");
1504 printTypeChain(type,stderr);fprintf(stderr,"'\n");
1507 /* if they are the same size create an assignment */
1508 if (getSize(type) == getSize(optype) &&
1509 !IS_BITFIELD(type) &&
1511 !IS_FLOAT(optype) &&
1512 ((IS_SPEC(type) && IS_SPEC(optype)) ||
1513 (!IS_SPEC(type) && !IS_SPEC(optype)))) {
1515 ic = newiCode('=',NULL,op);
1516 IC_RESULT(ic) = newiTempOperand(type,0);
1517 SPIL_LOC(IC_RESULT(ic)) =
1518 (IS_TRUE_SYMOP(op) ? OP_SYMBOL(op) : NULL);
1519 IC_RESULT(ic)->isaddr = 0;
1521 ic = newiCode(CAST,operandFromLink(type),
1522 geniCodeRValue(op,FALSE));
1524 IC_RESULT(ic)= newiTempOperand(type,0);
1527 /* preserve the storage class & output class */
1528 /* of the original variable */
1529 restype = getSpec(operandType(IC_RESULT(ic)));
1530 SPEC_SCLS(restype) = SPEC_SCLS(opetype);
1531 SPEC_OCLS(restype) = SPEC_OCLS(opetype);
1534 return IC_RESULT(ic) ;
1537 /*-----------------------------------------------------------------*/
1538 /* geniCodeLabel - will create a Label */
1539 /*-----------------------------------------------------------------*/
1540 void geniCodeLabel (symbol *label)
1544 ic = newiCodeLabelGoto(LABEL,label);
1548 /*-----------------------------------------------------------------*/
1549 /* geniCodeGoto - will create a Goto */
1550 /*-----------------------------------------------------------------*/
1551 void geniCodeGoto (symbol *label)
1555 ic = newiCodeLabelGoto(GOTO,label);
1559 /*-----------------------------------------------------------------*/
1560 /* geniCodeMultiply - gen intermediate code for multiplication */
1561 /*-----------------------------------------------------------------*/
1562 operand *geniCodeMultiply (operand *left, operand *right)
1569 /* if they are both literal then we know the result */
1570 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1571 return operandFromValue (valMult(left->operand.valOperand,
1572 right->operand.valOperand));
1574 resType = usualBinaryConversions(&left, &right);
1576 /* if the right is a literal & power of 2 */
1577 /* then make it a left shift */
1578 if (IS_LITERAL(retype) && !IS_FLOAT(letype) &&
1579 (p2 = powof2 ((unsigned long)floatFromVal(right->operand.valOperand))))
1580 ic = newiCode(LEFT_OP, left,operandFromLit(p2)); /* left shift */
1582 ic = newiCode('*',left,right); /* normal multiplication */
1583 /* if the size left or right > 1 then support routine */
1584 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1588 IC_RESULT(ic) = newiTempOperand(resType,1);
1591 return IC_RESULT(ic) ;
1594 /*-----------------------------------------------------------------*/
1595 /* geniCodeDivision - gen intermediate code for division */
1596 /*-----------------------------------------------------------------*/
1597 operand *geniCodeDivision (operand *left, operand *right)
1602 sym_link *rtype = operandType(right);
1603 sym_link *retype= getSpec(rtype);
1604 sym_link *ltype = operandType(left);
1605 sym_link *letype= getSpec(ltype);
1607 resType = usualBinaryConversions(&left, &right);
1609 /* if the right is a literal & power of 2 */
1610 /* then make it a right shift */
1611 if (IS_LITERAL(retype) &&
1612 !IS_FLOAT(letype) &&
1613 (p2 = powof2 ((unsigned long)
1614 floatFromVal(right->operand.valOperand))))
1615 ic = newiCode(RIGHT_OP, left,operandFromLit(p2)); /* right shift */
1617 ic = newiCode('/',left,right); /* normal division */
1618 /* if the size left or right > 1 then support routine */
1619 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1622 IC_RESULT(ic) = newiTempOperand(resType,0);
1625 return IC_RESULT(ic) ;
1627 /*-----------------------------------------------------------------*/
1628 /* geniCodeModulus - gen intermediate code for modulus */
1629 /*-----------------------------------------------------------------*/
1630 operand *geniCodeModulus (operand *left, operand *right)
1636 /* if they are both literal then we know the result */
1637 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1638 return operandFromValue (valMod(left->operand.valOperand,
1639 right->operand.valOperand));
1641 resType = usualBinaryConversions(&left, &right);
1643 /* now they are the same size */
1644 ic = newiCode('%',left,right);
1646 /* if the size left or right > 1 then support routine */
1647 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1649 IC_RESULT(ic) = newiTempOperand(resType,0);
1652 return IC_RESULT(ic) ;
1655 /*-----------------------------------------------------------------*/
1656 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1657 /*-----------------------------------------------------------------*/
1658 operand *geniCodePtrPtrSubtract (operand *left, operand *right)
1664 /* if they are both literals then */
1665 if (IS_LITERAL(letype) && IS_LITERAL(retype)) {
1666 result = operandFromValue (valMinus(left->operand.valOperand,
1667 right->operand.valOperand));
1671 ic = newiCode('-',left,right);
1673 IC_RESULT(ic) = result = newiTempOperand(newIntLink(),1);
1677 return geniCodeDivision (result,
1678 operandFromLit(getSize(ltype->next)));
1681 /*-----------------------------------------------------------------*/
1682 /* geniCodeSubtract - generates code for subtraction */
1683 /*-----------------------------------------------------------------*/
1684 operand *geniCodeSubtract (operand *left, operand *right)
1691 /* if they both pointers then */
1692 if ((IS_PTR(ltype) || IS_ARRAY(ltype)) &&
1693 (IS_PTR(rtype) || IS_ARRAY(rtype)))
1694 return geniCodePtrPtrSubtract (left,right);
1696 /* if they are both literal then we know the result */
1697 if (IS_LITERAL(letype) && IS_LITERAL(retype)
1698 && left->isLiteral && right->isLiteral)
1699 return operandFromValue (valMinus(left->operand.valOperand,
1700 right->operand.valOperand));
1702 /* if left is an array or pointer */
1703 if ( IS_PTR(ltype) || IS_ARRAY(ltype) ) {
1704 isarray = left->isaddr ;
1705 right = geniCodeMultiply (right,
1706 operandFromLit(getSize(ltype->next)));
1707 resType = copyLinkChain(IS_ARRAY(ltype) ? ltype->next : ltype);
1709 else { /* make them the same size */
1710 resType = usualBinaryConversions(&left, &right);
1713 ic = newiCode('-',left,right);
1715 IC_RESULT(ic)= newiTempOperand(resType,1);
1716 IC_RESULT(ic)->isaddr = (isarray ? 1 : 0);
1718 /* if left or right is a float */
1719 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1723 return IC_RESULT(ic) ;
1726 /*-----------------------------------------------------------------*/
1727 /* geniCodeAdd - generates iCode for addition */
1728 /*-----------------------------------------------------------------*/
1729 operand *geniCodeAdd (operand *left, operand *right )
1737 /* if left is an array then array access */
1738 if (IS_ARRAY(ltype))
1739 return geniCodeArray (left,right);
1741 /* if the right side is LITERAL zero */
1742 /* return the left side */
1743 if (IS_LITERAL(retype) && right->isLiteral && !floatFromVal(valFromType(retype)))
1746 /* if left is literal zero return right */
1747 if (IS_LITERAL(letype) && left->isLiteral && !floatFromVal(valFromType(letype)))
1750 /* if left is an array or pointer then size */
1751 if (IS_PTR(ltype)) {
1753 isarray = left->isaddr;
1755 operandFromLit(getSize(ltype->next));
1756 if (getSize(ltype) > 1 && (getSize(rtype) < INTSIZE))
1758 right = geniCodeCast(INTTYPE,right,TRUE);
1760 right = geniCodeMultiply (right ,size);
1762 resType = copyLinkChain(ltype);
1764 else { /* make them the same size */
1765 resType = usualBinaryConversions(&left, &right);
1768 /* if they are both literals then we know */
1769 if (IS_LITERAL(letype) && IS_LITERAL(retype)
1770 && left->isLiteral && right->isLiteral)
1771 return operandFromValue (valPlus(valFromType(letype),
1772 valFromType(retype)));
1774 ic = newiCode('+',left,right);
1776 IC_RESULT(ic) = newiTempOperand(resType,1);
1777 IC_RESULT(ic)->isaddr = ( isarray ? 1 : 0);
1779 /* if left or right is a float then support
1781 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1786 return IC_RESULT(ic) ;
1790 /*-----------------------------------------------------------------*/
1791 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1792 /*-----------------------------------------------------------------*/
1793 sym_link *aggrToPtr ( sym_link *type, bool force)
1799 if (IS_PTR(type) && !force)
1802 etype = getSpec(type);
1806 /* if the output class is generic */
1807 if ((DCL_TYPE(ptype) = PTR_TYPE(SPEC_OCLS(etype))) == CPOINTER)
1808 DCL_PTR_CONST(ptype) = port->mem.code_ro;
1810 /* if the variable was declared a constant */
1811 /* then the pointer points to a constant */
1812 if (IS_CONSTANT(etype) )
1813 DCL_PTR_CONST(ptype) = 1;
1815 /* the variable was volatile then pointer to volatile */
1816 if (IS_VOLATILE(etype))
1817 DCL_PTR_VOLATILE(ptype) = 1;
1821 /*-----------------------------------------------------------------*/
1822 /* geniCodeArray2Ptr - array to pointer */
1823 /*-----------------------------------------------------------------*/
1824 operand *geniCodeArray2Ptr (operand *op)
1826 sym_link *optype = operandType(op);
1827 sym_link *opetype = getSpec(optype);
1829 /* set the pointer depending on the storage class */
1830 if ((DCL_TYPE(optype) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1831 DCL_PTR_CONST(optype) = port->mem.code_ro;
1834 /* if the variable was declared a constant */
1835 /* then the pointer points to a constant */
1836 if (IS_CONSTANT(opetype) )
1837 DCL_PTR_CONST(optype) = 1;
1839 /* the variable was volatile then pointer to volatile */
1840 if (IS_VOLATILE(opetype))
1841 DCL_PTR_VOLATILE(optype) = 1;
1847 /*-----------------------------------------------------------------*/
1848 /* geniCodeArray - array access */
1849 /*-----------------------------------------------------------------*/
1850 operand *geniCodeArray (operand *left,operand *right)
1853 sym_link *ltype = operandType(left);
1855 if (IS_PTR(ltype)) {
1856 if (IS_PTR(ltype->next) && left->isaddr)
1858 left = geniCodeRValue(left,FALSE);
1860 return geniCodeDerefPtr(geniCodeAdd(left,right));
1864 right = usualUnaryConversions(right);
1865 right = geniCodeMultiply(right,
1866 operandFromLit(getSize(ltype->next)));
1868 /* we can check for limits here */
1869 if (isOperandLiteral(right) &&
1872 (operandLitValue(right)/getSize(ltype->next)) >= DCL_ELEM(ltype)) {
1873 werror(E_ARRAY_BOUND);
1874 right = operandFromLit(0);
1877 ic = newiCode('+',left,right);
1879 IC_RESULT(ic) = newiTempOperand(((IS_PTR(ltype) &&
1880 !IS_AGGREGATE(ltype->next) &&
1881 !IS_PTR(ltype->next))
1882 ? ltype : ltype->next),0);
1884 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(ltype->next));
1886 return IC_RESULT(ic) ;
1889 /*-----------------------------------------------------------------*/
1890 /* geniCodeStruct - generates intermediate code for structres */
1891 /*-----------------------------------------------------------------*/
1892 operand *geniCodeStruct (operand *left, operand *right, bool islval)
1895 sym_link *type = operandType(left);
1896 sym_link *etype = getSpec(type);
1898 symbol *element = getStructElement(SPEC_STRUCT(etype),
1899 right->operand.symOperand);
1901 /* add the offset */
1902 ic = newiCode('+',left,operandFromLit(element->offset));
1904 IC_RESULT(ic) = newiTempOperand(element->type,0);
1906 /* preserve the storage & output class of the struct */
1907 /* as well as the volatile attribute */
1908 retype = getSpec(operandType(IC_RESULT(ic)));
1909 SPEC_SCLS(retype) = SPEC_SCLS(etype);
1910 SPEC_OCLS(retype) = SPEC_OCLS(etype);
1911 SPEC_VOLATILE(retype) |= SPEC_VOLATILE(etype);
1913 if (IS_PTR(element->type))
1914 setOperandType(IC_RESULT(ic),aggrToPtr(operandType(IC_RESULT(ic)),TRUE));
1916 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(element->type));
1920 return (islval ? IC_RESULT(ic) : geniCodeRValue(IC_RESULT(ic),TRUE));
1923 /*-----------------------------------------------------------------*/
1924 /* geniCodePostInc - generate int code for Post increment */
1925 /*-----------------------------------------------------------------*/
1926 operand *geniCodePostInc (operand *op)
1930 sym_link *optype = operandType(op);
1932 operand *rv = (IS_ITEMP(op) ?
1933 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1935 sym_link *rvtype = operandType(rv);
1938 /* if this is not an address we have trouble */
1939 if ( ! op->isaddr ) {
1940 werror (E_LVALUE_REQUIRED,"++");
1944 rOp = newiTempOperand(rvtype,0);
1950 geniCodeAssign(rOp,rv,0);
1952 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1953 ic = newiCode('+',rv,operandFromLit(size));
1954 IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
1957 geniCodeAssign(op,result,0);
1963 /*-----------------------------------------------------------------*/
1964 /* geniCodePreInc - generate code for preIncrement */
1965 /*-----------------------------------------------------------------*/
1966 operand *geniCodePreInc (operand *op)
1969 sym_link *optype = operandType(op);
1970 operand *rop = (IS_ITEMP(op) ?
1971 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1973 sym_link *roptype = operandType(rop);
1977 if ( ! op->isaddr ) {
1978 werror(E_LVALUE_REQUIRED,"++");
1983 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1984 ic = newiCode('+',rop,operandFromLit(size));
1985 IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
1989 return geniCodeAssign(op,result,0) ;
1992 /*-----------------------------------------------------------------*/
1993 /* geniCodePostDec - generates code for Post decrement */
1994 /*-----------------------------------------------------------------*/
1995 operand *geniCodePostDec (operand *op)
1999 sym_link *optype = operandType(op);
2001 operand *rv = (IS_ITEMP(op) ?
2002 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
2004 sym_link *rvtype = operandType(rv);
2007 /* if this is not an address we have trouble */
2008 if ( ! op->isaddr ) {
2009 werror (E_LVALUE_REQUIRED,"++");
2013 rOp = newiTempOperand(rvtype,0);
2019 geniCodeAssign(rOp,rv,0);
2021 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
2022 ic = newiCode('-',rv,operandFromLit(size));
2023 IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
2026 geniCodeAssign(op,result,0);
2032 /*-----------------------------------------------------------------*/
2033 /* geniCodePreDec - generate code for pre decrement */
2034 /*-----------------------------------------------------------------*/
2035 operand *geniCodePreDec (operand *op)
2038 sym_link *optype = operandType(op);
2039 operand *rop = (IS_ITEMP(op) ?
2040 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
2042 sym_link *roptype = operandType(rop);
2046 if ( ! op->isaddr ) {
2047 werror(E_LVALUE_REQUIRED,"++");
2052 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
2053 ic = newiCode('-',rop,operandFromLit(size));
2054 IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
2058 return geniCodeAssign(op,result,0) ;
2062 /*-----------------------------------------------------------------*/
2063 /* geniCodeBitwise - gen int code for bitWise operators */
2064 /*-----------------------------------------------------------------*/
2065 operand *geniCodeBitwise (operand *left, operand *right,
2066 int oper, sym_link *resType)
2070 left = geniCodeCast(resType,left,TRUE);
2071 right= geniCodeCast(resType,right,TRUE);
2073 ic = newiCode(oper,left,right);
2074 IC_RESULT(ic) = newiTempOperand(resType,0);
2077 return IC_RESULT(ic) ;
2080 /*-----------------------------------------------------------------*/
2081 /* geniCodeAddressOf - gens icode for '&' address of operator */
2082 /*-----------------------------------------------------------------*/
2083 operand *geniCodeAddressOf (operand *op)
2087 sym_link *optype = operandType(op);
2088 sym_link *opetype= getSpec(optype);
2090 /* lvalue check already done in decorateType */
2091 /* this must be a lvalue */
2092 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2093 /* werror (E_LVALUE_REQUIRED,"&"); */
2098 p->class = DECLARATOR ;
2100 /* set the pointer depending on the storage class */
2101 if ((DCL_TYPE(p) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
2102 DCL_PTR_CONST(p) = port->mem.code_ro;
2104 /* make sure we preserve the const & volatile */
2105 if (IS_CONSTANT(opetype))
2106 DCL_PTR_CONST(p) = 1;
2108 if (IS_VOLATILE(opetype))
2109 DCL_PTR_VOLATILE(p) = 1;
2111 p->next = copyLinkChain(optype);
2113 /* if already a temp */
2115 setOperandType (op,p);
2120 /* other wise make this of the type coming in */
2121 ic = newiCode(ADDRESS_OF,op,NULL);
2122 IC_RESULT(ic) = newiTempOperand(p,1);
2123 IC_RESULT(ic)->isaddr = 0;
2125 return IC_RESULT(ic);
2127 /*-----------------------------------------------------------------*/
2128 /* setOClass - sets the output class depending on the pointer type */
2129 /*-----------------------------------------------------------------*/
2130 void setOClass (sym_link *ptr, sym_link *spec)
2132 switch (DCL_TYPE(ptr)) {
2134 SPEC_OCLS(spec) = data ;
2138 SPEC_OCLS(spec) = generic;
2142 SPEC_OCLS(spec) = xdata ;
2146 SPEC_OCLS(spec) = code ;
2150 SPEC_OCLS(spec) = idata;
2154 SPEC_OCLS(spec) = xstack;
2158 SPEC_OCLS(spec) = eeprom;
2167 /*-----------------------------------------------------------------*/
2168 /* geniCodeDerefPtr - dereference pointer with '*' */
2169 /*-----------------------------------------------------------------*/
2170 operand *geniCodeDerefPtr (operand *op)
2172 sym_link *rtype , *retype ;
2173 sym_link *optype = operandType(op);
2175 /* if this is a pointer then generate the rvalue */
2176 if (IS_PTR(optype)) {
2177 if (IS_TRUE_SYMOP(op)) {
2179 op = geniCodeRValue(op,TRUE);
2182 op = geniCodeRValue(op,TRUE);
2185 /* now get rid of the pointer part */
2186 if (lvaluereq && IS_ITEMP(op) )
2188 retype = getSpec(rtype = copyLinkChain(optype)) ;
2192 retype = getSpec(rtype = copyLinkChain(optype->next)) ;
2195 /* if this is a pointer then outputclass needs 2b updated */
2197 setOClass(optype,retype);
2199 op->isGptr = IS_GENPTR(optype);
2201 /* if the pointer was declared as a constant */
2202 /* then we cannot allow assignment to the derefed */
2203 if (IS_PTR_CONST(optype))
2204 SPEC_CONST(retype) = 1;
2206 op->isaddr = (IS_PTR(rtype) ||
2213 op = geniCodeRValue(op,TRUE);
2215 setOperandType(op,rtype);
2220 /*-----------------------------------------------------------------*/
2221 /* geniCodeUnaryMinus - does a unary minus of the operand */
2222 /*-----------------------------------------------------------------*/
2223 operand *geniCodeUnaryMinus (operand *op)
2226 sym_link *optype = operandType(op);
2228 if (IS_LITERAL(optype))
2229 return operandFromLit(- floatFromVal(op->operand.valOperand));
2231 ic = newiCode(UNARYMINUS,op,NULL);
2232 IC_RESULT(ic) = newiTempOperand(optype,0);
2234 return IC_RESULT(ic);
2237 /*-----------------------------------------------------------------*/
2238 /* geniCodeLeftShift - gen i code for left shift */
2239 /*-----------------------------------------------------------------*/
2240 operand *geniCodeLeftShift (operand *left, operand *right)
2244 /* Note that we don't use the usual binary conversions for the
2245 * shift operations, in accordance with our ANSI friends.
2247 if (options.ANSIint)
2249 right = usualUnaryConversions(right);
2250 left = usualUnaryConversions(left);
2253 ic = newiCode(LEFT_OP,left,right);
2254 IC_RESULT(ic) = newiTempOperand(operandType(left),0);
2256 return IC_RESULT(ic) ;
2259 /*-----------------------------------------------------------------*/
2260 /* geniCodeRightShift - gen i code for right shift */
2261 /*-----------------------------------------------------------------*/
2262 operand *geniCodeRightShift (operand *left, operand *right)
2266 /* Note that we don't use the usual binary conversions for the
2267 * shift operations, in accordance with our ANSI friends.
2269 if (options.ANSIint)
2271 right = usualUnaryConversions(right);
2272 left = usualUnaryConversions(left);
2275 ic = newiCode(RIGHT_OP,left,right);
2276 IC_RESULT(ic) = newiTempOperand(operandType(left),0);
2278 return IC_RESULT(ic) ;
2281 #if defined(__BORLANDC__) || defined(_MSC_VER)
2282 #define LONG_LONG __int64
2284 #define LONG_LONG long long
2287 /*-----------------------------------------------------------------*/
2288 /* geniCodeLogic- logic code */
2289 /*-----------------------------------------------------------------*/
2290 operand *geniCodeLogic (operand *left, operand *right, int op )
2294 sym_link *rtype = operandType(right);
2295 sym_link *ltype = operandType(left);
2297 /* left is integral type and right is literal then
2298 check if the literal value is within bounds */
2299 if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2300 int nbits = bitsForType(ltype);
2301 long v = operandLitValue(right);
2303 if (v > ((LONG_LONG) 1 << nbits) && v > 0)
2304 werror(W_CONST_RANGE," compare operation ");
2307 ctype = usualBinaryConversions(&left, &right);
2309 ic = newiCode(op,left,right);
2310 IC_RESULT(ic) = newiTempOperand (newCharLink(),1);
2312 /* if comparing anything greater than one byte
2313 and not a '==' || '!=' || '&&' || '||' (these
2315 if (getSize(ctype) > 1 &&
2323 return IC_RESULT(ic);
2326 /*-----------------------------------------------------------------*/
2327 /* geniCodeUnary - for a a generic unary operation */
2328 /*-----------------------------------------------------------------*/
2329 operand *geniCodeUnary (operand *op, int oper )
2331 iCode *ic = newiCode (oper,op,NULL);
2333 IC_RESULT(ic)= newiTempOperand(operandType(op),0);
2335 return IC_RESULT(ic) ;
2338 /*-----------------------------------------------------------------*/
2339 /* geniCodeConditional - geniCode for '?' ':' operation */
2340 /*-----------------------------------------------------------------*/
2341 operand *geniCodeConditional (ast *tree)
2344 symbol *falseLabel = newiTempLabel(NULL);
2345 symbol *exitLabel = newiTempLabel(NULL);
2346 operand *cond = ast2iCode(tree->left);
2347 operand *true, *false , *result;
2349 ic = newiCodeCondition(geniCodeRValue(cond,FALSE),
2353 true = ast2iCode(tree->right->left);
2355 /* move the value to a new Operand */
2356 result = newiTempOperand(operandType(true),0);
2357 geniCodeAssign(result,geniCodeRValue(true,FALSE),0);
2359 /* generate an unconditional goto */
2360 geniCodeGoto(exitLabel);
2362 /* now for the right side */
2363 geniCodeLabel(falseLabel);
2365 false = ast2iCode(tree->right->right);
2366 geniCodeAssign(result,geniCodeRValue(false,FALSE),0);
2368 /* create the exit label */
2369 geniCodeLabel(exitLabel);
2374 /*-----------------------------------------------------------------*/
2375 /* geniCodeAssign - generate code for assignment */
2376 /*-----------------------------------------------------------------*/
2377 operand *geniCodeAssign (operand *left, operand *right, int nosupdate)
2380 sym_link *ltype = operandType(left);
2381 sym_link *rtype = operandType(right);
2383 if (!left->isaddr && !IS_ITEMP(left)) {
2384 werror(E_LVALUE_REQUIRED,"assignment");
2388 /* left is integral type and right is literal then
2389 check if the literal value is within bounds */
2390 if (IS_INTEGRAL(ltype) && right->type == VALUE && IS_LITERAL(rtype)) {
2391 int nbits = bitsForType(ltype);
2392 long v = operandLitValue(right);
2394 if (v > ((LONG_LONG)1 << nbits) && v > 0)
2395 werror(W_CONST_RANGE," = operation");
2398 /* if the left & right type don't exactly match */
2399 /* if pointer set then make sure the check is
2400 done with the type & not the pointer */
2401 /* then cast rights type to left */
2403 /* first check the type for pointer assignement */
2404 if (left->isaddr && IS_PTR(ltype) && IS_ITEMP(left) &&
2405 checkType(ltype,rtype)<0) {
2406 if (checkType(ltype->next,rtype) < 0)
2407 right = geniCodeCast(ltype->next,right,TRUE);
2409 if (checkType(ltype,rtype) < 0 )
2410 right = geniCodeCast(ltype,right,TRUE);
2412 /* if left is a true symbol & ! volatile
2413 create an assignment to temporary for
2414 the right & then assign this temporary
2415 to the symbol this is SSA . isn't it simple
2416 and folks have published mountains of paper on it */
2417 if (IS_TRUE_SYMOP(left) &&
2418 !isOperandVolatile(left,FALSE) &&
2419 isOperandGlobal(left)) {
2422 if (IS_TRUE_SYMOP(right))
2423 sym = OP_SYMBOL(right);
2424 ic = newiCode('=',NULL,right);
2425 IC_RESULT(ic) = right = newiTempOperand(ltype,0);
2426 SPIL_LOC(right) = sym ;
2430 ic = newiCode('=',NULL,right);
2431 IC_RESULT(ic) = left;
2434 /* if left isgptr flag is set then support
2435 routine will be required */
2439 ic->nosupdate = nosupdate;
2443 /*-----------------------------------------------------------------*/
2444 /* geniCodeSEParms - generate code for side effecting fcalls */
2445 /*-----------------------------------------------------------------*/
2446 static void geniCodeSEParms (ast *parms)
2451 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2452 geniCodeSEParms (parms->left) ;
2453 geniCodeSEParms (parms->right);
2457 /* hack don't like this but too lazy to think of
2459 if (IS_ADDRESS_OF_OP(parms))
2460 parms->left->lvalue = 1;
2462 if (IS_CAST_OP(parms) &&
2463 IS_PTR(parms->ftype) &&
2464 IS_ADDRESS_OF_OP(parms->right))
2465 parms->right->left->lvalue = 1;
2467 parms->opval.oprnd =
2468 geniCodeRValue(ast2iCode (parms),FALSE);
2470 parms->type = EX_OPERAND ;
2473 /*-----------------------------------------------------------------*/
2474 /* geniCodeParms - generates parameters */
2475 /*-----------------------------------------------------------------*/
2476 static void geniCodeParms ( ast *parms , int *stack, sym_link *fetype, symbol *func)
2484 /* if this is a param node then do the left & right */
2485 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2486 geniCodeParms (parms->left, stack,fetype,func) ;
2487 geniCodeParms (parms->right, stack,fetype,func);
2491 /* get the parameter value */
2492 if (parms->type == EX_OPERAND)
2493 pval = parms->opval.oprnd ;
2495 /* maybe this else should go away ?? */
2496 /* hack don't like this but too lazy to think of
2498 if (IS_ADDRESS_OF_OP(parms))
2499 parms->left->lvalue = 1;
2501 if (IS_CAST_OP(parms) &&
2502 IS_PTR(parms->ftype) &&
2503 IS_ADDRESS_OF_OP(parms->right))
2504 parms->right->left->lvalue = 1;
2506 pval = geniCodeRValue(ast2iCode (parms),FALSE);
2509 /* if register parm then make it a send */
2510 if (((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
2511 IS_REGPARM(parms->etype)) && !func->hasVargs ) {
2512 ic = newiCode(SEND,pval,NULL);
2515 /* now decide whether to push or assign */
2516 if (!(options.stackAuto || IS_RENT(fetype))) {
2519 operand *top = operandFromSymbol(parms->argSym);
2520 geniCodeAssign(top,pval,1);
2523 sym_link *p = operandType(pval);
2525 ic = newiCode(IPUSH,pval,NULL);
2527 /* update the stack adjustment */
2528 *stack += getSize(IS_AGGREGATE(p)? aggrToPtr(p,FALSE):p);
2535 /*-----------------------------------------------------------------*/
2536 /* geniCodeCall - generates temp code for calling */
2537 /*-----------------------------------------------------------------*/
2538 operand *geniCodeCall (operand *left, ast *parms)
2542 sym_link *type, *etype;
2545 /* take care of parameters with side-effecting
2546 function calls in them, this is required to take care
2547 of overlaying function parameters */
2548 geniCodeSEParms ( parms );
2550 /* first the parameters */
2551 geniCodeParms ( parms , &stack , getSpec(operandType(left)), OP_SYMBOL(left));
2553 /* now call : if symbol then pcall */
2555 ic = newiCode(PCALL,left,NULL);
2557 ic = newiCode(CALL,left,NULL);
2559 IC_ARGS(ic) = left->operand.symOperand->args ;
2560 type = copyLinkChain(operandType(left)->next);
2561 etype = getSpec(type);
2562 SPEC_EXTR(etype) = 0;
2563 IC_RESULT(ic) = result = newiTempOperand(type,1);
2567 /* stack adjustment after call */
2568 left->parmBytes = stack;
2573 /*-----------------------------------------------------------------*/
2574 /* geniCodeReceive - generate intermediate code for "receive" */
2575 /*-----------------------------------------------------------------*/
2576 static void geniCodeReceive (value *args)
2578 /* for all arguments that are passed in registers */
2581 if (IS_REGPARM(args->etype)) {
2582 operand *opr = operandFromValue(args);
2584 symbol *sym = OP_SYMBOL(opr);
2587 /* we will use it after all optimizations
2588 and before liveRange calculation */
2589 if (!sym->addrtaken && !IS_VOLATILE(sym->etype)) {
2591 if (IN_FARSPACE(SPEC_OCLS(sym->etype)) &&
2592 options.stackAuto == 0 &&
2595 opl = newiTempOperand(args->type,0);
2597 sym->reqv->key = sym->key ;
2598 OP_SYMBOL(sym->reqv)->key = sym->key;
2599 OP_SYMBOL(sym->reqv)->isreqv = 1;
2600 OP_SYMBOL(sym->reqv)->islocal= 0;
2601 SPIL_LOC(sym->reqv) = sym;
2605 ic = newiCode(RECEIVE,NULL,NULL);
2606 currFunc->recvSize = getSize(sym->etype);
2607 IC_RESULT(ic) = opr;
2615 /*-----------------------------------------------------------------*/
2616 /* geniCodeFunctionBody - create the function body */
2617 /*-----------------------------------------------------------------*/
2618 void geniCodeFunctionBody (ast *tree)
2625 /* reset the auto generation */
2631 func = ast2iCode(tree->left);
2632 fetype = getSpec(operandType(func));
2634 savelineno = lineno;
2635 lineno = OP_SYMBOL(func)->lineDef;
2636 /* create an entry label */
2637 geniCodeLabel(entryLabel);
2638 lineno = savelineno;
2640 /* create a proc icode */
2641 ic = newiCode(FUNCTION,func,NULL);
2642 /* if the function has parmas then */
2643 /* save the parameters information */
2644 ic->argLabel.args = tree->values.args ;
2645 ic->lineno = OP_SYMBOL(func)->lineDef;
2649 /* for all parameters that are passed
2650 on registers add a "receive" */
2651 geniCodeReceive( tree->values.args );
2653 /* generate code for the body */
2654 ast2iCode(tree->right);
2656 /* create a label for return */
2657 geniCodeLabel(returnLabel);
2659 /* now generate the end proc */
2660 ic = newiCode(ENDFUNCTION,func,NULL);
2665 /*-----------------------------------------------------------------*/
2666 /* geniCodeReturn - gen icode for 'return' statement */
2667 /*-----------------------------------------------------------------*/
2668 void geniCodeReturn (operand *op)
2672 /* if the operand is present force an rvalue */
2674 op = geniCodeRValue(op,FALSE);
2676 ic = newiCode(RETURN,op,NULL);
2680 /*-----------------------------------------------------------------*/
2681 /* geniCodeIfx - generates code for extended if statement */
2682 /*-----------------------------------------------------------------*/
2683 void geniCodeIfx (ast *tree)
2686 operand *condition = ast2iCode(tree->left);
2689 /* if condition is null then exit */
2693 condition = geniCodeRValue(condition,FALSE);
2695 cetype = getSpec(operandType(condition));
2696 /* if the condition is a literal */
2697 if (IS_LITERAL(cetype)) {
2698 if (floatFromVal(condition->operand.valOperand)) {
2699 if (tree->trueLabel)
2700 geniCodeGoto(tree->trueLabel);
2705 if (tree->falseLabel)
2706 geniCodeGoto (tree->falseLabel);
2713 if ( tree->trueLabel ) {
2714 ic = newiCodeCondition(condition,
2719 if ( tree->falseLabel)
2720 geniCodeGoto(tree->falseLabel);
2723 ic = newiCodeCondition (condition,
2730 ast2iCode(tree->right);
2733 /*-----------------------------------------------------------------*/
2734 /* geniCodeJumpTable - tries to create a jump table for switch */
2735 /*-----------------------------------------------------------------*/
2736 int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
2738 int min = 0 ,max = 0, t, cnt = 0;
2743 set *labels = NULL ;
2745 if (!tree || !caseVals)
2748 /* the criteria for creating a jump table is */
2749 /* all integer numbers between the maximum & minimum must */
2750 /* be present , the maximum value should not exceed 255 */
2751 min = max = (int)floatFromVal(vch = caseVals);
2752 sprintf(buffer,"_case_%d_%d",
2753 tree->values.switchVals.swNum,
2755 addSet(&labels,newiTempLabel(buffer));
2757 /* if there is only one case value then no need */
2758 if (!(vch = vch->next ))
2762 if (((t = (int)floatFromVal(vch)) - max) != 1)
2764 sprintf(buffer,"_case_%d_%d",
2765 tree->values.switchVals.swNum,
2767 addSet(&labels,newiTempLabel(buffer));
2773 /* if the number of case statements <= 2 then */
2774 /* it is not economical to create the jump table */
2775 /* since two compares are needed for boundary conditions */
2776 if ((! optimize.noJTabBoundary && cnt <= 2) || max > (255/3))
2779 if ( tree->values.switchVals.swDefault )
2780 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2782 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2784 falseLabel = newiTempLabel (buffer);
2786 /* so we can create a jumptable */
2787 /* first we rule out the boundary conditions */
2788 /* if only optimization says so */
2789 if ( ! optimize.noJTabBoundary ) {
2790 sym_link *cetype = getSpec(operandType(cond));
2791 /* no need to check the lower bound if
2792 the condition is unsigned & minimum value is zero */
2793 if (!( min == 0 && SPEC_USIGN(cetype))) {
2794 boundary = geniCodeLogic (cond,operandFromLit(min),'<');
2795 ic = newiCodeCondition (boundary,falseLabel,NULL);
2799 /* now for upper bounds */
2800 boundary = geniCodeLogic(cond,operandFromLit(max),'>');
2801 ic = newiCodeCondition (boundary,falseLabel,NULL);
2805 /* if the min is not zero then we no make it zero */
2807 cond = geniCodeSubtract(cond,operandFromLit(min));
2808 setOperandType(cond, UCHARTYPE);
2811 /* now create the jumptable */
2812 ic = newiCode(JUMPTABLE,NULL,NULL);
2813 IC_JTCOND(ic) = cond;
2814 IC_JTLABELS(ic) = labels;
2819 /*-----------------------------------------------------------------*/
2820 /* geniCodeSwitch - changes a switch to a if statement */
2821 /*-----------------------------------------------------------------*/
2822 void geniCodeSwitch (ast *tree)
2825 operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
2826 value *caseVals = tree->values.switchVals.swVals ;
2827 symbol *trueLabel , *falseLabel;
2829 /* if we can make this a jump table */
2830 if ( geniCodeJumpTable (cond,caseVals,tree) )
2831 goto jumpTable ; /* no need for the comparison */
2833 /* for the cases defined do */
2836 operand *compare = geniCodeLogic (cond,
2837 operandFromValue(caseVals),
2840 sprintf(buffer,"_case_%d_%d",
2841 tree->values.switchVals.swNum,
2842 (int) floatFromVal(caseVals));
2843 trueLabel = newiTempLabel(buffer);
2845 ic = newiCodeCondition(compare,trueLabel,NULL);
2847 caseVals = caseVals->next;
2852 /* if default is present then goto break else break */
2853 if ( tree->values.switchVals.swDefault )
2854 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2856 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2858 falseLabel = newiTempLabel (buffer);
2859 geniCodeGoto(falseLabel);
2862 ast2iCode(tree->right);
2865 /*-----------------------------------------------------------------*/
2866 /* geniCodeInline - intermediate code for inline assembler */
2867 /*-----------------------------------------------------------------*/
2868 static void geniCodeInline (ast *tree)
2872 ic = newiCode(INLINEASM,NULL,NULL);
2873 IC_INLINE(ic) = tree->values.inlineasm;
2877 /*-----------------------------------------------------------------*/
2878 /* ast2iCode - creates an icodeList from an ast */
2879 /*-----------------------------------------------------------------*/
2880 operand *ast2iCode (ast *tree)
2882 operand *left = NULL;
2883 operand *right= NULL;
2888 /* set the global variables for filename & line number */
2889 if ( tree->filename )
2890 filename = tree->filename ;
2892 lineno = tree->lineno ;
2894 block = tree->block ;
2896 scopeLevel = tree->level;
2898 if (tree->type == EX_VALUE )
2899 return operandFromValue(tree->opval.val);
2901 if (tree->type == EX_LINK )
2902 return operandFromLink (tree->opval.lnk);
2904 /* if we find a nullop */
2905 if (tree->type == EX_OP &&
2906 ( tree->opval.op == NULLOP ||
2907 tree->opval.op == BLOCK )) {
2908 ast2iCode (tree->left);
2909 ast2iCode (tree->right);
2913 /* special cases for not evaluating */
2914 if ( tree->opval.op != ':' &&
2915 tree->opval.op != '?' &&
2916 tree->opval.op != CALL &&
2917 tree->opval.op != IFX &&
2918 tree->opval.op != LABEL &&
2919 tree->opval.op != GOTO &&
2920 tree->opval.op != SWITCH &&
2921 tree->opval.op != FUNCTION &&
2922 tree->opval.op != INLINEASM ) {
2924 if (IS_ASSIGN_OP(tree->opval.op) ||
2925 IS_DEREF_OP(tree) ||
2926 (tree->opval.op == '&' && !tree->right) ||
2927 tree->opval.op == PTR_OP) {
2929 if ((IS_ARRAY_OP(tree->left) && IS_ARRAY_OP(tree->left->left)) ||
2930 (IS_DEREF_OP(tree) && IS_ARRAY_OP(tree->left)))
2932 int olvr = lvaluereq ;
2934 left = operandFromAst(tree->left);
2935 lvaluereq = olvr - 1;
2937 left = operandFromAst(tree->left);
2940 if (IS_DEREF_OP(tree) && IS_DEREF_OP(tree->left))
2941 left = geniCodeRValue(left,TRUE);
2943 left = operandFromAst(tree->left);
2945 if (tree->opval.op == INC_OP ||
2946 tree->opval.op == DEC_OP) {
2948 right= operandFromAst(tree->right);
2951 right= operandFromAst(tree->right);
2955 /* now depending on the type of operand */
2956 /* this will be a biggy */
2957 switch (tree->opval.op) {
2959 case '[' : /* array operation */
2961 sym_link *ltype = operandType(left);
2962 left= geniCodeRValue (left,IS_PTR(ltype->next) ? TRUE : FALSE);
2963 right=geniCodeRValue (right,TRUE);
2966 return geniCodeArray (left,right);
2968 case '.' : /* structure dereference */
2969 if (IS_PTR(operandType(left)))
2970 left = geniCodeRValue(left,TRUE);
2972 left = geniCodeRValue(left,FALSE);
2974 return geniCodeStruct (left,right,tree->lvalue);
2976 case PTR_OP: /* structure pointer dereference */
2979 pType = operandType(left);
2980 left = geniCodeRValue(left,TRUE);
2982 setOClass (pType,getSpec(operandType(left)));
2985 return geniCodeStruct (left, right,tree->lvalue);
2987 case INC_OP: /* increment operator */
2989 return geniCodePostInc (left);
2991 return geniCodePreInc (right);
2993 case DEC_OP: /* decrement operator */
2995 return geniCodePostDec (left);
2997 return geniCodePreDec (right);
2999 case '&' : /* bitwise and or address of operator */
3000 if ( right ) { /* this is a bitwise operator */
3001 left= geniCodeRValue(left,FALSE);
3002 right= geniCodeRValue(right,FALSE);
3003 return geniCodeBitwise (left,right,BITWISEAND,tree->ftype);
3005 return geniCodeAddressOf (left);
3007 case '|': /* bitwise or & xor */
3009 return geniCodeBitwise (geniCodeRValue(left,FALSE),
3010 geniCodeRValue(right,FALSE),
3015 return geniCodeDivision (geniCodeRValue(left,FALSE),
3016 geniCodeRValue(right,FALSE));
3019 return geniCodeModulus (geniCodeRValue(left,FALSE),
3020 geniCodeRValue(right,FALSE));
3023 return geniCodeMultiply (geniCodeRValue(left,FALSE),
3024 geniCodeRValue(right,FALSE));
3026 return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
3030 return geniCodeSubtract (geniCodeRValue(left,FALSE),
3031 geniCodeRValue(right,FALSE));
3033 return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
3037 return geniCodeAdd (geniCodeRValue(left,FALSE),
3038 geniCodeRValue(right,FALSE));
3040 return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
3043 return geniCodeLeftShift (geniCodeRValue(left,FALSE),
3044 geniCodeRValue(right,FALSE));
3047 return geniCodeRightShift (geniCodeRValue(left,FALSE),
3048 geniCodeRValue(right,FALSE));
3050 return geniCodeCast (operandType(left),
3051 geniCodeRValue(right,FALSE),FALSE);
3057 return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
3061 operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
3062 setOperandType(op, UCHARTYPE);
3073 return geniCodeLogic (geniCodeRValue(left,FALSE),
3074 geniCodeRValue(right,FALSE),
3077 return geniCodeConditional (tree);
3080 return operandFromLit(getSize(tree->right->ftype));
3084 sym_link *rtype = operandType(right);
3085 sym_link *ltype = operandType(left);
3086 if (IS_PTR(rtype) && IS_ITEMP(right)
3087 && right->isaddr && checkType(rtype->next,ltype)==1)
3088 right = geniCodeRValue(right,TRUE);
3090 right = geniCodeRValue(right,FALSE);
3092 geniCodeAssign (left,right,0);
3097 geniCodeAssign(left,
3098 geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
3100 geniCodeRValue(right,FALSE)),0);
3104 geniCodeAssign(left,
3105 geniCodeDivision(geniCodeRValue(operandFromOperand(left),
3107 geniCodeRValue(right,FALSE)),0);
3110 geniCodeAssign(left,
3111 geniCodeModulus(geniCodeRValue(operandFromOperand(left),
3113 geniCodeRValue(right,FALSE)),0);
3116 sym_link *rtype = operandType(right);
3117 sym_link *ltype = operandType(left);
3118 if (IS_PTR(rtype) && IS_ITEMP(right)
3119 && right->isaddr && checkType(rtype->next,ltype)==1)
3120 right = geniCodeRValue(right,TRUE);
3122 right = geniCodeRValue(right,FALSE);
3125 return geniCodeAssign(left,
3126 geniCodeAdd (geniCodeRValue(operandFromOperand(left),
3132 sym_link *rtype = operandType(right);
3133 sym_link *ltype = operandType(left);
3134 if (IS_PTR(rtype) && IS_ITEMP(right)
3135 && right->isaddr && checkType(rtype->next,ltype)==1) {
3136 right = geniCodeRValue(right,TRUE);
3139 right = geniCodeRValue(right,FALSE);
3142 geniCodeAssign (left,
3143 geniCodeSubtract(geniCodeRValue(operandFromOperand(left),
3149 geniCodeAssign (left,
3150 geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
3152 geniCodeRValue(right,FALSE)),0);
3155 geniCodeAssign(left,
3156 geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
3158 geniCodeRValue(right,FALSE)),0);
3161 geniCodeAssign (left,
3162 geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
3164 geniCodeRValue(right,FALSE),
3166 operandType(left)),0);
3169 geniCodeAssign (left,
3170 geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
3172 geniCodeRValue(right,FALSE),
3174 operandType(left)),0);
3177 geniCodeAssign (left,
3178 geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
3180 geniCodeRValue(right,FALSE),
3182 operandType(left)),0);
3184 return geniCodeRValue(right,FALSE);
3187 return geniCodeCall (ast2iCode(tree->left),
3190 geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
3191 return ast2iCode (tree->right);
3194 geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
3195 return ast2iCode (tree->right);
3198 geniCodeFunctionBody ( tree );
3202 geniCodeReturn (right);
3210 geniCodeSwitch (tree);
3214 geniCodeInline (tree);
3221 /*-----------------------------------------------------------------*/
3222 /* reverseICChain - gets from the list and creates a linkedlist */
3223 /*-----------------------------------------------------------------*/
3224 iCode *reverseiCChain ()
3226 iCode *loop = NULL ;
3227 iCode *prev = NULL ;
3229 while ((loop = getSet(&iCodeChain))) {
3240 /*-----------------------------------------------------------------*/
3241 /* iCodeFromAst - given an ast will convert it to iCode */
3242 /*-----------------------------------------------------------------*/
3243 iCode *iCodeFromAst ( ast *tree )
3245 returnLabel = newiTempLabel("_return");
3246 entryLabel = newiTempLabel("_entry") ;
3248 return reverseiCChain ();