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 (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 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 */
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 /* operandLitValue - literal value of an operand */
761 /*-----------------------------------------------------------------*/
762 double operandLitValue ( operand *op )
764 assert(isOperandLiteral(op));
766 return floatFromVal(op->operand.valOperand);
769 /*-----------------------------------------------------------------*/
770 /* operandOperation - perforoms operations on operands */
771 /*-----------------------------------------------------------------*/
772 operand *operandOperation (operand *left,operand *right,
775 operand *retval = (operand *)0;
777 assert(isOperandLiteral(left));
779 assert(isOperandLiteral(right));
783 retval = operandFromValue (valCastLiteral(type,
784 operandLitValue(left) +
785 operandLitValue(right)));
788 retval = operandFromValue(valCastLiteral(type,
789 operandLitValue(left) -
790 operandLitValue(right)));
793 retval = operandFromValue(valCastLiteral(type,
794 operandLitValue(left) *
795 operandLitValue(right)));
798 if ((unsigned long) operandLitValue(right) == 0){
799 werror(E_DIVIDE_BY_ZERO);
804 retval = operandFromValue (valCastLiteral(type,
805 operandLitValue(left) /
806 operandLitValue(right)));
809 if ((unsigned long) operandLitValue(right) == 0){
810 werror(E_DIVIDE_BY_ZERO);
814 retval = operandFromLit ((unsigned long) operandLitValue(left) %
815 (unsigned long) operandLitValue(right));
818 retval = operandFromLit ((unsigned long) operandLitValue(left) <<
819 (unsigned long) operandLitValue(right));
822 retval = operandFromLit ((unsigned long) operandLitValue(left) >>
823 (unsigned long) operandLitValue(right));
826 retval = operandFromLit (operandLitValue(left) ==
827 operandLitValue(right));
830 retval = operandFromLit (operandLitValue(left) <
831 operandLitValue(right));
834 retval = operandFromLit (operandLitValue(left) <=
835 operandLitValue(right));
838 retval = operandFromLit (operandLitValue(left) !=
839 operandLitValue(right));
842 retval = operandFromLit (operandLitValue(left) >
843 operandLitValue(right));
846 retval = operandFromLit (operandLitValue(left) >=
847 operandLitValue(right));
850 retval = operandFromLit ((unsigned long) operandLitValue(left) &
851 (unsigned long) operandLitValue(right));
854 retval = operandFromLit ((unsigned long) operandLitValue(left) |
855 (unsigned long) operandLitValue(right));
858 retval = operandFromLit ((unsigned long) operandLitValue(left) ^
859 (unsigned long) operandLitValue(right));
862 retval = operandFromLit (operandLitValue(left) &&
863 operandLitValue(right));
866 retval = operandFromLit (operandLitValue(left) ||
867 operandLitValue(right));
871 long i = operandLitValue(left);
873 retval = operandFromLit ((i >> (getSize(operandType(left))*8 - 1)) |
879 long i = operandLitValue(left);
881 retval = operandFromLit ((i << (getSize(operandType(left))*8 - 1)) |
887 retval = operandFromLit(-1 * operandLitValue(left));
891 retval = operandFromLit(~ ((long) operandLitValue(left)));
895 retval = operandFromLit(! operandLitValue(left));
899 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
900 " operandOperation invalid operator ");
908 /*-----------------------------------------------------------------*/
909 /* isOperandEqual - compares two operand & return 1 if they r = */
910 /*-----------------------------------------------------------------*/
911 int isOperandEqual (operand *left, operand *right)
913 /* if the pointers are equal then they are equal */
917 /* if either of them null then false */
918 if ( !left || !right)
921 if (left->type != right->type)
924 if (IS_SYMOP(left) && IS_SYMOP(right))
925 return left->key == right->key ;
927 /* if types are the same */
928 switch (left->type) {
930 return isSymbolEqual(left->operand.symOperand,
931 right->operand.symOperand);
933 return (floatFromVal(left->operand.valOperand) ==
934 floatFromVal(right->operand.valOperand));
936 if (checkType(left->operand.typeOperand,
937 right->operand.typeOperand) == 1)
944 /*-----------------------------------------------------------------*/
945 /* isiCodeEqual - comapres two iCodes are returns true if yes */
946 /*-----------------------------------------------------------------*/
947 int isiCodeEqual (iCode *left, iCode *right)
949 /* if the same pointer */
953 /* if either of them null */
957 /* if operand are the same */
958 if ( left->op == right->op ) {
960 /* compare all the elements depending on type */
961 if (left->op != IFX ) {
962 if (!isOperandEqual(IC_LEFT(left),IC_LEFT(right)))
964 if (!isOperandEqual(IC_RIGHT(left),IC_RIGHT(right)))
968 if (!isOperandEqual(IC_COND(left),IC_COND(right)))
970 if (!isSymbolEqual (IC_TRUE(left),IC_TRUE(right)))
972 if (!isSymbolEqual(IC_FALSE(left),IC_FALSE(right)))
980 /*-----------------------------------------------------------------*/
981 /* newiTempFromOp - create a temp Operand with same attributes */
982 /*-----------------------------------------------------------------*/
983 operand *newiTempFromOp (operand *op)
993 nop = newiTempOperand(operandType(op),TRUE);
994 nop->isaddr = op->isaddr ;
995 nop->isvolatile = op->isvolatile ;
996 nop->isGlobal = op->isGlobal ;
997 nop->isLiteral= op->isLiteral ;
998 nop->noSpilLoc= op->noSpilLoc;
999 nop->usesDefs = op->usesDefs;
1000 nop->isParm = op->isParm;
1001 nop->parmBytes = op->parmBytes;
1005 /*-----------------------------------------------------------------*/
1006 /* operand from operand - creates an operand holder for the type */
1007 /*-----------------------------------------------------------------*/
1008 operand *operandFromOperand (operand *op)
1015 nop->type = op->type;
1016 nop->isaddr = op->isaddr ;
1017 nop->key = op->key ;
1018 nop->isvolatile = op->isvolatile ;
1019 nop->isGlobal = op->isGlobal ;
1020 nop->isLiteral= op->isLiteral ;
1021 nop->noSpilLoc= op->noSpilLoc;
1022 nop->usesDefs = op->usesDefs;
1023 nop->isParm = op->isParm;
1024 nop->parmBytes = op->parmBytes;
1026 switch (nop->type) {
1028 nop->operand.symOperand = op->operand.symOperand ;
1031 nop->operand.valOperand = op->operand.valOperand;
1034 nop->operand.typeOperand = op->operand.typeOperand ;
1041 /*-----------------------------------------------------------------*/
1042 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1043 /*-----------------------------------------------------------------*/
1044 operand *opFromOpWithDU (operand *op, bitVect *defs, bitVect *uses)
1046 operand *nop = operandFromOperand(op);
1048 if (nop->type == SYMBOL) {
1049 OP_SYMBOL(nop)->defs = bitVectCopy(defs);
1050 OP_SYMBOL(nop)->uses = bitVectCopy(uses);
1056 /*-----------------------------------------------------------------*/
1057 /* operandFromSymbol - creates an operand from a symbol */
1058 /*-----------------------------------------------------------------*/
1059 operand *operandFromSymbol (symbol *sym)
1064 /* if the symbol's type is a literal */
1065 /* then it is an enumerator type */
1066 if (IS_LITERAL(sym->etype) && SPEC_ENUM(sym->etype))
1067 return operandFromValue (valFromType(sym->etype));
1070 sym->key = ++operandKey ;
1072 /* if this an implicit variable, means struct/union */
1073 /* member so just return it */
1074 if (sym->implicit || IS_FUNC(sym->type)) {
1077 op->operand.symOperand = sym;
1078 op->key = sym->key ;
1079 op->isvolatile = isOperandVolatile(op,TRUE);
1080 op->isGlobal = isOperandGlobal(op);
1081 op->parmBytes = sym->argStack;
1085 /* under the following conditions create a
1086 register equivalent for a local symbol */
1087 if (sym->level && sym->etype && SPEC_OCLS(sym->etype) &&
1088 (IN_FARSPACE(SPEC_OCLS(sym->etype)) && (!IS_DS390_PORT)) &&
1089 options.stackAuto == 0)
1092 if (!IS_AGGREGATE(sym->type) && /* not an aggregate */
1093 !IS_FUNC(sym->type) && /* not a function */
1094 !sym->_isparm && /* not a parameter */
1095 sym->level && /* is a local variable */
1096 !sym->addrtaken && /* whose address has not been taken */
1097 !sym->reqv && /* does not already have a register euivalence */
1098 !IS_VOLATILE(sym->etype) && /* not declared as volatile */
1099 !IS_STATIC(sym->etype) && /* and not declared static */
1100 !sym->islbl && /* not a label */
1101 ok && /* farspace check */
1102 !IS_BITVAR(sym->etype) /* not a bit variable */
1105 /* we will use it after all optimizations
1106 and before liveRange calculation */
1107 sym->reqv = newiTempOperand(sym->type,0);
1108 sym->reqv->key = sym->key ;
1109 OP_SYMBOL(sym->reqv)->key = sym->key;
1110 OP_SYMBOL(sym->reqv)->isreqv = 1;
1111 OP_SYMBOL(sym->reqv)->islocal = 1;
1112 SPIL_LOC(sym->reqv) = sym;
1115 if (!IS_AGGREGATE(sym->type)) {
1118 op->operand.symOperand = sym;
1121 op->isvolatile = isOperandVolatile(op,TRUE);
1122 op->isGlobal = isOperandGlobal(op);
1123 op->isPtr = IS_PTR(operandType(op));
1124 op->isParm = sym->_isparm ;
1129 /* itemp = &[_symbol] */
1131 ic = newiCode(ADDRESS_OF,newOperand(),NULL);
1132 IC_LEFT(ic)->type = SYMBOL ;
1133 IC_LEFT(ic)->operand.symOperand = sym ;
1134 IC_LEFT(ic)->key = sym->key;
1135 (IC_LEFT(ic))->isvolatile = isOperandVolatile(IC_LEFT(ic),TRUE);
1136 (IC_LEFT(ic))->isGlobal = isOperandGlobal(IC_LEFT(ic));
1137 IC_LEFT(ic)->isPtr = IS_PTR(operandType(IC_LEFT(ic)));
1140 IC_RESULT(ic) = newiTempOperand(sym->type,0);
1141 if (IS_ARRAY(sym->type)) {
1142 IC_RESULT(ic) = geniCodeArray2Ptr (IC_RESULT(ic));
1143 IC_RESULT(ic)->isaddr = 0;
1145 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(sym->type));
1147 IC_RESULT(ic)->operand.symOperand->args = sym->args;
1151 return IC_RESULT(ic) ;
1154 /*-----------------------------------------------------------------*/
1155 /* operandFromValue - creates an operand from value */
1156 /*-----------------------------------------------------------------*/
1157 operand *operandFromValue (value *val)
1161 /* if this is a symbol then do the symbol thing */
1163 return operandFromSymbol (val->sym);
1165 /* this is not a symbol */
1168 op->operand.valOperand = val ;
1169 op->isLiteral = isOperandLiteral(op);
1173 /*-----------------------------------------------------------------*/
1174 /* operandFromLink - operand from typeChain */
1175 /*-----------------------------------------------------------------*/
1176 operand *operandFromLink (link *type)
1180 /* operand from link */
1186 op->operand.typeOperand = copyLinkChain(type);
1190 /*-----------------------------------------------------------------*/
1191 /* operandFromLit - makes an operand from a literal value */
1192 /*-----------------------------------------------------------------*/
1193 operand *operandFromLit ( float i)
1195 return operandFromValue (valueFromLit (i));
1198 /*-----------------------------------------------------------------*/
1199 /* operandFromAst - creates an operand from an ast */
1200 /*-----------------------------------------------------------------*/
1201 operand *operandFromAst ( ast *tree )
1207 /* depending on type do */
1208 switch (tree->type ) {
1210 return ast2iCode (tree) ;
1214 return operandFromValue(tree->opval.val) ;
1218 return operandFromLink (tree->opval.lnk) ;
1222 /* Just to keep the comiler happy */
1223 return (operand *)0;
1226 /*-----------------------------------------------------------------*/
1227 /* setOperandType - sets the operand's type to the given type */
1228 /*-----------------------------------------------------------------*/
1229 void setOperandType (operand *op, link *type)
1231 /* depending on the type of operand */
1235 op->operand.valOperand->etype =
1236 getSpec( op->operand.valOperand->type =
1237 copyLinkChain (type )) ;
1241 if (op->operand.symOperand->isitmp )
1242 op->operand.symOperand->etype =
1243 getSpec( op->operand.symOperand->type =
1244 copyLinkChain (type )) ;
1246 werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
1247 "attempt to modify type of source");
1251 op->operand.typeOperand = copyLinkChain (type);
1257 /*-----------------------------------------------------------------*/
1258 /* geniCodeValueAtAddress - generate intermeditate code for value */
1260 /*-----------------------------------------------------------------*/
1261 operand *geniCodeRValue (operand *op, bool force)
1264 link *type = operandType(op);
1265 link *etype= getSpec(type);
1267 /* if this is an array & already */
1268 /* an address then return this */
1269 if (IS_AGGREGATE(type) ||
1270 (IS_PTR(type) && !force && !op->isaddr))
1271 return operandFromOperand(op);
1273 /* if this is not an address then must be */
1274 /* rvalue already so return this one */
1278 /* if this is not a temp symbol then */
1279 if (!IS_ITEMP(op) &&
1281 !IN_FARSPACE(SPEC_OCLS(etype))) {
1282 op = operandFromOperand(op);
1287 if (IS_SPEC(type) &&
1288 IS_TRUE_SYMOP(op) &&
1289 !IN_FARSPACE(SPEC_OCLS(etype))) {
1290 op = operandFromOperand(op);
1295 ic = newiCode(GET_VALUE_AT_ADDRESS,op,NULL);
1296 if (IS_PTR(type) && op->isaddr && force)
1299 type = copyLinkChain(type);
1301 IC_RESULT(ic) = newiTempOperand (type,1);
1302 IC_RESULT(ic)->isaddr = 0;
1304 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1306 /* if the right is a symbol */
1307 if (op->type == SYMBOL)
1308 IC_RESULT(ic)->operand.symOperand->args =
1309 op->operand.symOperand->args ;
1312 return IC_RESULT(ic) ;
1315 /*-----------------------------------------------------------------*/
1316 /* geniCodeCast - changes the value from one type to another */
1317 /*-----------------------------------------------------------------*/
1318 operand *geniCodeCast (link *type, operand *op, bool implicit)
1322 link *opetype = getSpec(optype = operandType(op));
1325 /* one of them has size zero then error */
1326 if (IS_VOID(optype)) {
1327 werror(E_CAST_ZERO);
1331 /* if the operand is already the desired type then do nothing */
1332 if ( checkType (type,optype) == 1)
1335 /* if this is a literal then just change the type & return */
1336 if (IS_LITERAL(opetype) && op->type == VALUE && !IS_PTR(type) && !IS_PTR(optype))
1337 return operandFromValue(valCastLiteral(type,
1338 operandLitValue(op)));
1340 /* if casting to some pointer type &&
1341 the destination is not a generic pointer
1342 then give a warning : (only for implicit casts)*/
1343 if (IS_PTR(optype) && implicit &&
1344 (DCL_TYPE(optype) != DCL_TYPE(type)) &&
1346 werror(E_INCOMPAT_CAST);
1347 werror(E_CONTINUE,"from type '");
1348 printTypeChain(optype,stderr);fprintf(stderr,"' to type '");
1349 printTypeChain(type,stderr);fprintf(stderr,"'\n");
1352 /* if they are the same size create an assignment */
1353 if (getSize(type) == getSize(optype) &&
1354 !IS_BITFIELD(type) &&
1356 !IS_FLOAT(optype) &&
1357 ((IS_SPEC(type) && IS_SPEC(optype)) ||
1358 (!IS_SPEC(type) && !IS_SPEC(optype)))) {
1360 ic = newiCode('=',NULL,op);
1361 IC_RESULT(ic) = newiTempOperand(type,0);
1362 SPIL_LOC(IC_RESULT(ic)) =
1363 (IS_TRUE_SYMOP(op) ? OP_SYMBOL(op) : NULL);
1364 IC_RESULT(ic)->isaddr = 0;
1366 ic = newiCode(CAST,operandFromLink(type),
1367 geniCodeRValue(op,FALSE));
1369 IC_RESULT(ic)= newiTempOperand(type,0);
1372 /* preserve the storage class & output class */
1373 /* of the original variable */
1374 restype = getSpec(operandType(IC_RESULT(ic)));
1375 SPEC_SCLS(restype) = SPEC_SCLS(opetype);
1376 SPEC_OCLS(restype) = SPEC_OCLS(opetype);
1379 return IC_RESULT(ic) ;
1382 /*-----------------------------------------------------------------*/
1383 /* geniCodeLabel - will create a Label */
1384 /*-----------------------------------------------------------------*/
1385 void geniCodeLabel (symbol *label)
1389 ic = newiCodeLabelGoto(LABEL,label);
1393 /*-----------------------------------------------------------------*/
1394 /* geniCodeGoto - will create a Goto */
1395 /*-----------------------------------------------------------------*/
1396 void geniCodeGoto (symbol *label)
1400 ic = newiCodeLabelGoto(GOTO,label);
1404 /*-----------------------------------------------------------------*/
1405 /* geniCodeMultiply - gen intermediate code for multiplication */
1406 /*-----------------------------------------------------------------*/
1407 operand *geniCodeMultiply (operand *left, operand *right)
1414 /* if they are both literal then we know the result */
1415 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1416 return operandFromValue (valMult(left->operand.valOperand,
1417 right->operand.valOperand));
1419 resType = computeType (ltype,rtype) ;
1420 left = geniCodeCast(resType,left,TRUE);
1421 right= geniCodeCast(resType,right,TRUE);
1423 /* if the right is a literal & power of 2 */
1424 /* then make it a left shift */
1425 if (IS_LITERAL(retype) && !IS_FLOAT(letype) &&
1426 (p2 = powof2 ((unsigned long)floatFromVal(right->operand.valOperand))))
1427 ic = newiCode(LEFT_OP, left,operandFromLit(p2)); /* left shift */
1429 ic = newiCode('*',left,right); /* normal multiplication */
1430 /* if the size left or right > 1 then support routine */
1431 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1435 IC_RESULT(ic) = newiTempOperand(resType,1);
1438 return IC_RESULT(ic) ;
1441 /*-----------------------------------------------------------------*/
1442 /* geniCodeDivision - gen intermediate code for division */
1443 /*-----------------------------------------------------------------*/
1444 operand *geniCodeDivision (operand *left, operand *right)
1449 link *rtype = operandType(right);
1450 link *retype= getSpec(rtype);
1451 link *ltype = operandType(left);
1452 link *letype= getSpec(ltype);
1454 resType = computeType (ltype,rtype) ;
1455 left = geniCodeCast(resType,left,TRUE);
1456 right= geniCodeCast(resType,right,TRUE);
1458 /* if the right is a literal & power of 2 */
1459 /* then make it a right shift */
1460 if (IS_LITERAL(retype) &&
1461 !IS_FLOAT(letype) &&
1462 (p2 = powof2 ((unsigned long)
1463 floatFromVal(right->operand.valOperand))))
1464 ic = newiCode(RIGHT_OP, left,operandFromLit(p2)); /* right shift */
1466 ic = newiCode('/',left,right); /* normal division */
1467 /* if the size left or right > 1 then support routine */
1468 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1471 IC_RESULT(ic) = newiTempOperand(resType,0);
1474 return IC_RESULT(ic) ;
1476 /*-----------------------------------------------------------------*/
1477 /* geniCodeModulus - gen intermediate code for modulus */
1478 /*-----------------------------------------------------------------*/
1479 operand *geniCodeModulus (operand *left, operand *right)
1485 /* if they are both literal then we know the result */
1486 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1487 return operandFromValue (valMod(left->operand.valOperand,
1488 right->operand.valOperand));
1490 resType = computeType (ltype,rtype) ;
1491 left = geniCodeCast(resType,left,TRUE);
1492 right= geniCodeCast(resType,right,TRUE);
1494 /* now they are the same size */
1495 ic = newiCode('%',left,right);
1497 /* if the size left or right > 1 then support routine */
1498 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1500 IC_RESULT(ic) = newiTempOperand(resType,0);
1503 return IC_RESULT(ic) ;
1506 /*-----------------------------------------------------------------*/
1507 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1508 /*-----------------------------------------------------------------*/
1509 operand *geniCodePtrPtrSubtract (operand *left, operand *right)
1515 /* if they are both literals then */
1516 if (IS_LITERAL(letype) && IS_LITERAL(retype)) {
1517 result = operandFromValue (valMinus(left->operand.valOperand,
1518 right->operand.valOperand));
1522 ic = newiCode('-',left,right);
1524 IC_RESULT(ic) = result = newiTempOperand(newIntLink(),1);
1528 return geniCodeDivision (result,
1529 operandFromLit(getSize(ltype->next)));
1532 /*-----------------------------------------------------------------*/
1533 /* geniCodeSubtract - generates code for subtraction */
1534 /*-----------------------------------------------------------------*/
1535 operand *geniCodeSubtract (operand *left, operand *right)
1542 /* if they both pointers then */
1543 if ((IS_PTR(ltype) || IS_ARRAY(ltype)) &&
1544 (IS_PTR(rtype) || IS_ARRAY(rtype)))
1545 return geniCodePtrPtrSubtract (left,right);
1547 /* if they are both literal then we know the result */
1548 if (IS_LITERAL(letype) && IS_LITERAL(retype)
1549 && left->isLiteral && right->isLiteral)
1550 return operandFromValue (valMinus(left->operand.valOperand,
1551 right->operand.valOperand));
1553 /* if left is an array or pointer */
1554 if ( IS_PTR(ltype) || IS_ARRAY(ltype) ) {
1555 isarray = left->isaddr ;
1556 right = geniCodeMultiply (right,
1557 operandFromLit(getSize(ltype->next)));
1558 resType = copyLinkChain(IS_ARRAY(ltype) ? ltype->next : ltype);
1560 else { /* make them the same size */
1561 resType = computeType (ltype,rtype) ;
1562 left = geniCodeCast(resType,left,TRUE);
1563 right= geniCodeCast(resType,right,TRUE);
1566 ic = newiCode('-',left,right);
1568 IC_RESULT(ic)= newiTempOperand(resType,1);
1569 IC_RESULT(ic)->isaddr = (isarray ? 1 : 0);
1571 /* if left or right is a float */
1572 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1576 return IC_RESULT(ic) ;
1579 /*-----------------------------------------------------------------*/
1580 /* geniCodeAdd - generates iCode for addition */
1581 /*-----------------------------------------------------------------*/
1582 operand *geniCodeAdd (operand *left, operand *right )
1590 /* if left is an array then array access */
1591 if (IS_ARRAY(ltype))
1592 return geniCodeArray (left,right);
1594 /* if the right side is LITERAL zero */
1595 /* return the left side */
1596 if (IS_LITERAL(retype) && right->isLiteral && !floatFromVal(valFromType(retype)))
1599 /* if left is literal zero return right */
1600 if (IS_LITERAL(letype) && left->isLiteral && !floatFromVal(valFromType(letype)))
1603 /* if left is an array or pointer then size */
1604 if (IS_PTR(ltype)) {
1606 isarray = left->isaddr;
1608 operandFromLit(getSize(ltype->next));
1609 right = geniCodeMultiply (right ,size);
1610 if (getSize(ltype) > 1)
1611 right = geniCodeCast(INTTYPE,right,TRUE);
1612 resType = copyLinkChain(ltype);
1614 else { /* make them the same size */
1615 resType = computeType (ltype,rtype) ;
1616 left = geniCodeCast(resType,left,TRUE);
1617 right= geniCodeCast(resType,right,TRUE);
1620 /* if they are both literals then we know */
1621 if (IS_LITERAL(letype) && IS_LITERAL(retype)
1622 && left->isLiteral && right->isLiteral)
1623 return operandFromValue (valPlus(valFromType(letype),
1624 valFromType(retype)));
1626 ic = newiCode('+',left,right);
1628 IC_RESULT(ic) = newiTempOperand(resType,1);
1629 IC_RESULT(ic)->isaddr = ( isarray ? 1 : 0);
1631 /* if left or right is a float then support
1633 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1638 return IC_RESULT(ic) ;
1642 /*-----------------------------------------------------------------*/
1643 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1644 /*-----------------------------------------------------------------*/
1645 link *aggrToPtr ( link *type, bool force)
1651 if (IS_PTR(type) && !force)
1654 etype = getSpec(type);
1658 /* if the output class is generic */
1659 if ((DCL_TYPE(ptype) = PTR_TYPE(SPEC_OCLS(etype))) == CPOINTER)
1660 DCL_PTR_CONST(ptype) = port->mem.code_ro;
1662 /* if the variable was declared a constant */
1663 /* then the pointer points to a constant */
1664 if (IS_CONSTANT(etype) )
1665 DCL_PTR_CONST(ptype) = 1;
1667 /* the variable was volatile then pointer to volatile */
1668 if (IS_VOLATILE(etype))
1669 DCL_PTR_VOLATILE(ptype) = 1;
1673 /*-----------------------------------------------------------------*/
1674 /* geniCodeArray2Ptr - array to pointer */
1675 /*-----------------------------------------------------------------*/
1676 operand *geniCodeArray2Ptr (operand *op)
1678 link *optype = operandType(op);
1679 link *opetype = getSpec(optype);
1681 /* set the pointer depending on the storage class */
1682 if ((DCL_TYPE(optype) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1683 DCL_PTR_CONST(optype) = port->mem.code_ro;
1686 /* if the variable was declared a constant */
1687 /* then the pointer points to a constant */
1688 if (IS_CONSTANT(opetype) )
1689 DCL_PTR_CONST(optype) = 1;
1691 /* the variable was volatile then pointer to volatile */
1692 if (IS_VOLATILE(opetype))
1693 DCL_PTR_VOLATILE(optype) = 1;
1698 /*-----------------------------------------------------------------*/
1699 /* geniCodeArray - array access */
1700 /*-----------------------------------------------------------------*/
1701 operand *geniCodeArray (operand *left,operand *right)
1704 link *ltype = operandType(left);
1706 if (IS_PTR(ltype)) {
1707 if (IS_PTR(ltype->next) && left->isaddr)
1708 left = geniCodeRValue(left,FALSE);
1709 return geniCodeDerefPtr(geniCodeAdd(left,right));
1713 right = geniCodeMultiply(right,
1714 operandFromLit(getSize(ltype->next)));
1716 /* we can check for limits here */
1717 if (isOperandLiteral(right) &&
1720 (operandLitValue(right)/getSize(ltype->next)) >= DCL_ELEM(ltype)) {
1721 werror(E_ARRAY_BOUND);
1722 right = operandFromLit(0);
1725 ic = newiCode('+',left,right);
1727 IC_RESULT(ic) = newiTempOperand(((IS_PTR(ltype) &&
1728 !IS_AGGREGATE(ltype->next) &&
1729 !IS_PTR(ltype->next))
1730 ? ltype : ltype->next),0);
1732 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(ltype->next));
1734 return IC_RESULT(ic) ;
1737 /*-----------------------------------------------------------------*/
1738 /* geniCodeStruct - generates intermediate code for structres */
1739 /*-----------------------------------------------------------------*/
1740 operand *geniCodeStruct (operand *left, operand *right, bool islval)
1743 link *type = operandType(left);
1744 link *etype = getSpec(type);
1746 symbol *element = getStructElement(SPEC_STRUCT(etype),
1747 right->operand.symOperand);
1749 /* add the offset */
1750 ic = newiCode('+',left,operandFromLit(element->offset));
1752 IC_RESULT(ic) = newiTempOperand(element->type,0);
1754 /* preserve the storage & output class of the struct */
1755 /* as well as the volatile attribute */
1756 retype = getSpec(operandType(IC_RESULT(ic)));
1757 SPEC_SCLS(retype) = SPEC_SCLS(etype);
1758 SPEC_OCLS(retype) = SPEC_OCLS(etype);
1759 SPEC_VOLATILE(retype) |= SPEC_VOLATILE(etype);
1761 if (IS_PTR(element->type))
1762 setOperandType(IC_RESULT(ic),aggrToPtr(operandType(IC_RESULT(ic)),TRUE));
1764 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(element->type));
1768 return (islval ? IC_RESULT(ic) : geniCodeRValue(IC_RESULT(ic),TRUE));
1771 /*-----------------------------------------------------------------*/
1772 /* geniCodePostInc - generate int code for Post increment */
1773 /*-----------------------------------------------------------------*/
1774 operand *geniCodePostInc (operand *op)
1778 link *optype = operandType(op);
1780 operand *rv = (IS_ITEMP(op) ?
1781 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1783 link *rvtype = operandType(rv);
1786 /* if this is not an address we have trouble */
1787 if ( ! op->isaddr ) {
1788 werror (E_LVALUE_REQUIRED,"++");
1792 rOp = newiTempOperand(rvtype,0);
1798 geniCodeAssign(rOp,rv,0);
1800 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1801 ic = newiCode('+',rv,operandFromLit(size));
1802 IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
1805 geniCodeAssign(op,result,0);
1811 /*-----------------------------------------------------------------*/
1812 /* geniCodePreInc - generate code for preIncrement */
1813 /*-----------------------------------------------------------------*/
1814 operand *geniCodePreInc (operand *op)
1817 link *optype = operandType(op);
1818 operand *rop = (IS_ITEMP(op) ?
1819 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1821 link *roptype = operandType(rop);
1825 if ( ! op->isaddr ) {
1826 werror(E_LVALUE_REQUIRED,"++");
1831 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1832 ic = newiCode('+',rop,operandFromLit(size));
1833 IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
1837 return geniCodeAssign(op,result,0) ;
1840 /*-----------------------------------------------------------------*/
1841 /* geniCodePostDec - generates code for Post decrement */
1842 /*-----------------------------------------------------------------*/
1843 operand *geniCodePostDec (operand *op)
1847 link *optype = operandType(op);
1849 operand *rv = (IS_ITEMP(op) ?
1850 geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1852 link *rvtype = operandType(rv);
1855 /* if this is not an address we have trouble */
1856 if ( ! op->isaddr ) {
1857 werror (E_LVALUE_REQUIRED,"++");
1861 rOp = newiTempOperand(rvtype,0);
1867 geniCodeAssign(rOp,rv,0);
1869 size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1870 ic = newiCode('-',rv,operandFromLit(size));
1871 IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
1874 geniCodeAssign(op,result,0);
1880 /*-----------------------------------------------------------------*/
1881 /* geniCodePreDec - generate code for pre decrement */
1882 /*-----------------------------------------------------------------*/
1883 operand *geniCodePreDec (operand *op)
1886 link *optype = operandType(op);
1887 operand *rop = (IS_ITEMP(op) ?
1888 geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1890 link *roptype = operandType(rop);
1894 if ( ! op->isaddr ) {
1895 werror(E_LVALUE_REQUIRED,"++");
1900 size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1901 ic = newiCode('-',rop,operandFromLit(size));
1902 IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
1906 return geniCodeAssign(op,result,0) ;
1910 /*-----------------------------------------------------------------*/
1911 /* geniCodeBitwise - gen int code for bitWise operators */
1912 /*-----------------------------------------------------------------*/
1913 operand *geniCodeBitwise (operand *left, operand *right,
1914 int oper, link *resType)
1918 left = geniCodeCast(resType,left,TRUE);
1919 right= geniCodeCast(resType,right,TRUE);
1921 ic = newiCode(oper,left,right);
1922 IC_RESULT(ic) = newiTempOperand(resType,0);
1925 return IC_RESULT(ic) ;
1928 /*-----------------------------------------------------------------*/
1929 /* geniCodeAddressOf - gens icode for '&' address of operator */
1930 /*-----------------------------------------------------------------*/
1931 operand *geniCodeAddressOf (operand *op)
1935 link *optype = operandType(op);
1936 link *opetype= getSpec(optype);
1938 /* lvalue check already done in decorateType */
1939 /* this must be a lvalue */
1940 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
1941 /* werror (E_LVALUE_REQUIRED,"&"); */
1946 p->class = DECLARATOR ;
1948 /* set the pointer depending on the storage class */
1949 if ((DCL_TYPE(p) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1950 DCL_PTR_CONST(p) = port->mem.code_ro;
1952 /* make sure we preserve the const & volatile */
1953 if (IS_CONSTANT(opetype))
1954 DCL_PTR_CONST(p) = 1;
1956 if (IS_VOLATILE(opetype))
1957 DCL_PTR_VOLATILE(p) = 1;
1959 p->next = copyLinkChain(optype);
1961 /* if already a temp */
1963 setOperandType (op,p);
1968 /* other wise make this of the type coming in */
1969 ic = newiCode(ADDRESS_OF,op,NULL);
1970 IC_RESULT(ic) = newiTempOperand(p,1);
1971 IC_RESULT(ic)->isaddr = 0;
1973 return IC_RESULT(ic);
1975 /*-----------------------------------------------------------------*/
1976 /* setOClass - sets the output class depending on the pointer type */
1977 /*-----------------------------------------------------------------*/
1978 void setOClass (link *ptr, link *spec)
1980 switch (DCL_TYPE(ptr)) {
1982 SPEC_OCLS(spec) = data ;
1986 SPEC_OCLS(spec) = generic;
1990 SPEC_OCLS(spec) = xdata ;
1994 SPEC_OCLS(spec) = code ;
1998 SPEC_OCLS(spec) = idata;
2002 SPEC_OCLS(spec) = xstack;
2006 SPEC_OCLS(spec) = eeprom;
2015 /*-----------------------------------------------------------------*/
2016 /* geniCodeDerefPtr - dereference pointer with '*' */
2017 /*-----------------------------------------------------------------*/
2018 operand *geniCodeDerefPtr (operand *op)
2020 link *rtype , *retype ;
2021 link *optype = operandType(op);
2023 /* if this is a pointer then generate the rvalue */
2024 if (IS_PTR(optype)) {
2025 if (IS_TRUE_SYMOP(op)) {
2027 op = geniCodeRValue(op,TRUE);
2030 op = geniCodeRValue(op,TRUE);
2033 /* now get rid of the pointer part */
2034 if (lvaluereq && IS_ITEMP(op) )
2036 retype = getSpec(rtype = copyLinkChain(optype)) ;
2040 retype = getSpec(rtype = copyLinkChain(optype->next)) ;
2043 /* if this is a pointer then outputclass needs 2b updated */
2045 setOClass(optype,retype);
2047 op->isGptr = IS_GENPTR(optype);
2049 /* if the pointer was declared as a constant */
2050 /* then we cannot allow assignment to the derefed */
2051 if (IS_PTR_CONST(optype))
2052 SPEC_CONST(retype) = 1;
2054 op->isaddr = (IS_PTR(rtype) ||
2061 op = geniCodeRValue(op,TRUE);
2063 setOperandType(op,rtype);
2068 /*-----------------------------------------------------------------*/
2069 /* geniCodeUnaryMinus - does a unary minus of the operand */
2070 /*-----------------------------------------------------------------*/
2071 operand *geniCodeUnaryMinus (operand *op)
2074 link *optype = operandType(op);
2076 if (IS_LITERAL(optype))
2077 return operandFromLit(- floatFromVal(op->operand.valOperand));
2079 ic = newiCode(UNARYMINUS,op,NULL);
2080 IC_RESULT(ic) = newiTempOperand(optype,0);
2082 return IC_RESULT(ic);
2085 /*-----------------------------------------------------------------*/
2086 /* geniCodeLeftShift - gen i code for left shift */
2087 /*-----------------------------------------------------------------*/
2088 operand *geniCodeLeftShift (operand *left, operand *right)
2091 link *ltype = operandType(left);
2093 ic = newiCode(LEFT_OP,left,right);
2094 IC_RESULT(ic) = newiTempOperand(ltype,0);
2096 return IC_RESULT(ic) ;
2099 /*-----------------------------------------------------------------*/
2100 /* geniCodeRightShift - gen i code for right shift */
2101 /*-----------------------------------------------------------------*/
2102 operand *geniCodeRightShift (operand *left, operand *right)
2105 link *ltype = operandType(left);
2107 ic = newiCode(RIGHT_OP,left,right);
2108 IC_RESULT(ic) = newiTempOperand(ltype,0);
2110 return IC_RESULT(ic) ;
2114 #define LONG_LONG __int64
2116 #define LONG_LONG long long
2119 /*-----------------------------------------------------------------*/
2120 /* geniCodeLogic- logic code */
2121 /*-----------------------------------------------------------------*/
2122 operand *geniCodeLogic (operand *left, operand *right, int op )
2126 link *rtype = operandType(right);
2127 link *ltype = operandType(left);
2129 /* left is integral type and right is literal then
2130 check if the literal value is within bounds */
2131 if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2132 int nbits = bitsForType(ltype);
2133 long v = operandLitValue(right);
2135 if (v > ((LONG_LONG) 1 << nbits) && v > 0)
2136 werror(W_CONST_RANGE," compare operation ");
2139 ctype = computeType(ltype,rtype);
2140 left = geniCodeCast(ctype,left,TRUE);
2141 right= geniCodeCast(ctype,right,TRUE);
2143 ic = newiCode(op,left,right);
2144 IC_RESULT(ic) = newiTempOperand (newCharLink(),1);
2146 /* if comparing anything greater than one byte
2147 and not a '==' || '!=' || '&&' || '||' (these
2149 if (getSize(ctype) > 1 &&
2157 return IC_RESULT(ic);
2160 /*-----------------------------------------------------------------*/
2161 /* geniCodeUnary - for a a generic unary operation */
2162 /*-----------------------------------------------------------------*/
2163 operand *geniCodeUnary (operand *op, int oper )
2165 iCode *ic = newiCode (oper,op,NULL);
2167 IC_RESULT(ic)= newiTempOperand(operandType(op),0);
2169 return IC_RESULT(ic) ;
2172 /*-----------------------------------------------------------------*/
2173 /* geniCodeConditional - geniCode for '?' ':' operation */
2174 /*-----------------------------------------------------------------*/
2175 operand *geniCodeConditional (ast *tree)
2178 symbol *falseLabel = newiTempLabel(NULL);
2179 symbol *exitLabel = newiTempLabel(NULL);
2180 operand *cond = ast2iCode(tree->left);
2181 operand *true, *false , *result;
2183 ic = newiCodeCondition(geniCodeRValue(cond,FALSE),
2187 true = ast2iCode(tree->right->left);
2189 /* move the value to a new Operand */
2190 result = newiTempOperand(operandType(true),0);
2191 geniCodeAssign(result,geniCodeRValue(true,FALSE),0);
2193 /* generate an unconditional goto */
2194 geniCodeGoto(exitLabel);
2196 /* now for the right side */
2197 geniCodeLabel(falseLabel);
2199 false = ast2iCode(tree->right->right);
2200 geniCodeAssign(result,geniCodeRValue(false,FALSE),0);
2202 /* create the exit label */
2203 geniCodeLabel(exitLabel);
2208 /*-----------------------------------------------------------------*/
2209 /* geniCodeAssign - generate code for assignment */
2210 /*-----------------------------------------------------------------*/
2211 operand *geniCodeAssign (operand *left, operand *right, int nosupdate)
2214 link *ltype = operandType(left);
2215 link *rtype = operandType(right);
2217 if (!left->isaddr && !IS_ITEMP(left)) {
2218 werror(E_LVALUE_REQUIRED,"assignment");
2222 /* left is integral type and right is literal then
2223 check if the literal value is within bounds */
2224 if (IS_INTEGRAL(ltype) && right->type == VALUE && IS_LITERAL(rtype)) {
2225 int nbits = bitsForType(ltype);
2226 long v = operandLitValue(right);
2228 if (v > ((LONG_LONG)1 << nbits) && v > 0)
2229 werror(W_CONST_RANGE," = operation");
2232 /* if the left & right type don't exactly match */
2233 /* if pointer set then make sure the check is
2234 done with the type & not the pointer */
2235 /* then cast rights type to left */
2237 /* first check the type for pointer assignement */
2238 if (left->isaddr && IS_PTR(ltype) && IS_ITEMP(left) &&
2239 checkType(ltype,rtype)<0) {
2240 if (checkType(ltype->next,rtype) < 0)
2241 right = geniCodeCast(ltype->next,right,TRUE);
2243 if (checkType(ltype,rtype) < 0 )
2244 right = geniCodeCast(ltype,right,TRUE);
2246 /* if left is a true symbol & ! volatile
2247 create an assignment to temporary for
2248 the right & then assign this temporary
2249 to the symbol this is SSA . isn't it simple
2250 and folks have published mountains of paper on it */
2251 if (IS_TRUE_SYMOP(left) &&
2252 !isOperandVolatile(left,FALSE) &&
2253 isOperandGlobal(left)) {
2256 if (IS_TRUE_SYMOP(right))
2257 sym = OP_SYMBOL(right);
2258 ic = newiCode('=',NULL,right);
2259 IC_RESULT(ic) = right = newiTempOperand(ltype,0);
2260 SPIL_LOC(right) = sym ;
2264 ic = newiCode('=',NULL,right);
2265 IC_RESULT(ic) = left;
2268 /* if left isgptr flag is set then support
2269 routine will be required */
2273 ic->nosupdate = nosupdate;
2277 /*-----------------------------------------------------------------*/
2278 /* geniCodeSEParms - generate code for side effecting fcalls */
2279 /*-----------------------------------------------------------------*/
2280 static void geniCodeSEParms (ast *parms)
2285 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2286 geniCodeSEParms (parms->left) ;
2287 geniCodeSEParms (parms->right);
2291 /* hack don't like this but too lazy to think of
2293 if (IS_ADDRESS_OF_OP(parms))
2294 parms->left->lvalue = 1;
2296 if (IS_CAST_OP(parms) &&
2297 IS_PTR(parms->ftype) &&
2298 IS_ADDRESS_OF_OP(parms->right))
2299 parms->right->left->lvalue = 1;
2301 parms->opval.oprnd =
2302 geniCodeRValue(ast2iCode (parms),FALSE);
2304 parms->type = EX_OPERAND ;
2307 /*-----------------------------------------------------------------*/
2308 /* geniCodeParms - generates parameters */
2309 /*-----------------------------------------------------------------*/
2310 static void geniCodeParms ( ast *parms , int *stack, link *fetype)
2318 /* if this is a param node then do the left & right */
2319 if (parms->type == EX_OP && parms->opval.op == PARAM) {
2320 geniCodeParms (parms->left, stack,fetype) ;
2321 geniCodeParms (parms->right, stack,fetype);
2325 /* get the parameter value */
2326 if (parms->type == EX_OPERAND)
2327 pval = parms->opval.oprnd ;
2329 /* maybe this else should go away ?? */
2330 /* hack don't like this but too lazy to think of
2332 if (IS_ADDRESS_OF_OP(parms))
2333 parms->left->lvalue = 1;
2335 if (IS_CAST_OP(parms) &&
2336 IS_PTR(parms->ftype) &&
2337 IS_ADDRESS_OF_OP(parms->right))
2338 parms->right->left->lvalue = 1;
2340 pval = geniCodeRValue(ast2iCode (parms),FALSE);
2343 /* if register parm then make it a send */
2344 if (((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
2345 IS_REGPARM(parms->etype)) &&
2347 ic = newiCode(SEND,pval,NULL);
2350 /* now decide whether to push or assign */
2351 if (!(options.stackAuto || IS_RENT(fetype))) {
2354 operand *top = operandFromSymbol(parms->argSym);
2355 geniCodeAssign(top,pval,1);
2358 link *p = operandType(pval);
2360 ic = newiCode(IPUSH,pval,NULL);
2362 /* update the stack adjustment */
2363 *stack += getSize(IS_AGGREGATE(p)? aggrToPtr(p,FALSE):p);
2370 /*-----------------------------------------------------------------*/
2371 /* geniCodeCall - generates temp code for calling */
2372 /*-----------------------------------------------------------------*/
2373 operand *geniCodeCall (operand *left, ast *parms)
2380 /* take care of parameters with side-effecting
2381 function calls in them, this is required to take care
2382 of overlaying function parameters */
2383 geniCodeSEParms ( parms );
2385 /* first the parameters */
2386 geniCodeParms ( parms , &stack , getSpec(operandType(left)));
2388 /* now call : if symbol then pcall */
2390 ic = newiCode(PCALL,left,NULL);
2392 ic = newiCode(CALL,left,NULL);
2394 IC_ARGS(ic) = left->operand.symOperand->args ;
2395 type = copyLinkChain(operandType(left)->next);
2396 etype = getSpec(type);
2397 SPEC_EXTR(etype) = 0;
2398 IC_RESULT(ic) = result = newiTempOperand(type,1);
2402 /* stack adjustment after call */
2403 left->parmBytes = stack;
2408 /*-----------------------------------------------------------------*/
2409 /* geniCodeReceive - generate intermediate code for "receive" */
2410 /*-----------------------------------------------------------------*/
2411 static void geniCodeReceive (value *args)
2413 /* for all arguments that are passed in registers */
2416 if (IS_REGPARM(args->etype)) {
2417 operand *opr = operandFromValue(args);
2419 symbol *sym = OP_SYMBOL(opr);
2422 /* we will use it after all optimizations
2423 and before liveRange calculation */
2424 if (!sym->addrtaken && !IS_VOLATILE(sym->etype)) {
2426 if (IN_FARSPACE(SPEC_OCLS(sym->etype)) &&
2427 options.stackAuto == 0 &&
2430 opl = newiTempOperand(args->type,0);
2432 sym->reqv->key = sym->key ;
2433 OP_SYMBOL(sym->reqv)->key = sym->key;
2434 OP_SYMBOL(sym->reqv)->isreqv = 1;
2435 OP_SYMBOL(sym->reqv)->islocal= 0;
2436 SPIL_LOC(sym->reqv) = sym;
2440 ic = newiCode(RECEIVE,NULL,NULL);
2441 currFunc->recvSize = getSize(sym->etype);
2442 IC_RESULT(ic) = opr;
2450 /*-----------------------------------------------------------------*/
2451 /* geniCodeFunctionBody - create the function body */
2452 /*-----------------------------------------------------------------*/
2453 void geniCodeFunctionBody (ast *tree)
2460 /* reset the auto generation */
2466 func = ast2iCode(tree->left);
2467 fetype = getSpec(operandType(func));
2469 savelineno = lineno;
2470 lineno = OP_SYMBOL(func)->lineDef;
2471 /* create an entry label */
2472 geniCodeLabel(entryLabel);
2473 lineno = savelineno;
2475 /* create a proc icode */
2476 ic = newiCode(FUNCTION,func,NULL);
2477 /* if the function has parmas then */
2478 /* save the parameters information */
2479 ic->argLabel.args = tree->values.args ;
2480 ic->lineno = OP_SYMBOL(func)->lineDef;
2484 /* for all parameters that are passed
2485 on registers add a "receive" */
2486 geniCodeReceive( tree->values.args );
2488 /* generate code for the body */
2489 ast2iCode(tree->right);
2491 /* create a label for return */
2492 geniCodeLabel(returnLabel);
2494 /* now generate the end proc */
2495 ic = newiCode(ENDFUNCTION,func,NULL);
2500 /*-----------------------------------------------------------------*/
2501 /* geniCodeReturn - gen icode for 'return' statement */
2502 /*-----------------------------------------------------------------*/
2503 void geniCodeReturn (operand *op)
2507 /* if the operand is present force an rvalue */
2509 op = geniCodeRValue(op,FALSE);
2511 ic = newiCode(RETURN,op,NULL);
2515 /*-----------------------------------------------------------------*/
2516 /* geniCodeIfx - generates code for extended if statement */
2517 /*-----------------------------------------------------------------*/
2518 void geniCodeIfx (ast *tree)
2521 operand *condition = ast2iCode(tree->left);
2524 /* if condition is null then exit */
2528 condition = geniCodeRValue(condition,FALSE);
2530 cetype = getSpec(operandType(condition));
2531 /* if the condition is a literal */
2532 if (IS_LITERAL(cetype)) {
2533 if (floatFromVal(condition->operand.valOperand)) {
2534 if (tree->trueLabel)
2535 geniCodeGoto(tree->trueLabel);
2540 if (tree->falseLabel)
2541 geniCodeGoto (tree->falseLabel);
2548 if ( tree->trueLabel ) {
2549 ic = newiCodeCondition(condition,
2554 if ( tree->falseLabel)
2555 geniCodeGoto(tree->falseLabel);
2558 ic = newiCodeCondition (condition,
2565 ast2iCode(tree->right);
2568 /*-----------------------------------------------------------------*/
2569 /* geniCodeJumpTable - tries to create a jump table for switch */
2570 /*-----------------------------------------------------------------*/
2571 int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
2573 int min = 0 ,max = 0, t, cnt = 0;
2578 set *labels = NULL ;
2580 if (!tree || !caseVals)
2583 /* the criteria for creating a jump table is */
2584 /* all integer numbers between the maximum & minimum must */
2585 /* be present , the maximum value should not exceed 255 */
2586 min = max = (int)floatFromVal(vch = caseVals);
2587 sprintf(buffer,"_case_%d_%d",
2588 tree->values.switchVals.swNum,
2590 addSet(&labels,newiTempLabel(buffer));
2592 /* if there is only one case value then no need */
2593 if (!(vch = vch->next ))
2597 if (((t = (int)floatFromVal(vch)) - max) != 1)
2599 sprintf(buffer,"_case_%d_%d",
2600 tree->values.switchVals.swNum,
2602 addSet(&labels,newiTempLabel(buffer));
2608 /* if the number of case statements <= 2 then */
2609 /* it is not economical to create the jump table */
2610 /* since two compares are needed for boundary conditions */
2611 if ((! optimize.noJTabBoundary && cnt <= 2) || max > (255/3))
2614 if ( tree->values.switchVals.swDefault )
2615 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2617 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2619 falseLabel = newiTempLabel (buffer);
2621 /* so we can create a jumptable */
2622 /* first we rule out the boundary conditions */
2623 /* if only optimization says so */
2624 if ( ! optimize.noJTabBoundary ) {
2625 link *cetype = getSpec(operandType(cond));
2626 /* no need to check the lower bound if
2627 the condition is unsigned & minimum value is zero */
2628 if (!( min == 0 && SPEC_USIGN(cetype))) {
2629 boundary = geniCodeLogic (cond,operandFromLit(min),'<');
2630 ic = newiCodeCondition (boundary,falseLabel,NULL);
2634 /* now for upper bounds */
2635 boundary = geniCodeLogic(cond,operandFromLit(max),'>');
2636 ic = newiCodeCondition (boundary,falseLabel,NULL);
2640 /* if the min is not zero then we no make it zero */
2642 cond = geniCodeSubtract(cond,operandFromLit(min));
2643 setOperandType(cond, UCHARTYPE);
2646 /* now create the jumptable */
2647 ic = newiCode(JUMPTABLE,NULL,NULL);
2648 IC_JTCOND(ic) = cond;
2649 IC_JTLABELS(ic) = labels;
2654 /*-----------------------------------------------------------------*/
2655 /* geniCodeSwitch - changes a switch to a if statement */
2656 /*-----------------------------------------------------------------*/
2657 void geniCodeSwitch (ast *tree)
2660 operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
2661 value *caseVals = tree->values.switchVals.swVals ;
2662 symbol *trueLabel , *falseLabel;
2664 /* if we can make this a jump table */
2665 if ( geniCodeJumpTable (cond,caseVals,tree) )
2666 goto jumpTable ; /* no need for the comparison */
2668 /* for the cases defined do */
2671 operand *compare = geniCodeLogic (cond,
2672 operandFromValue(caseVals),
2675 sprintf(buffer,"_case_%d_%d",
2676 tree->values.switchVals.swNum,
2677 (int) floatFromVal(caseVals));
2678 trueLabel = newiTempLabel(buffer);
2680 ic = newiCodeCondition(compare,trueLabel,NULL);
2682 caseVals = caseVals->next;
2687 /* if default is present then goto break else break */
2688 if ( tree->values.switchVals.swDefault )
2689 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2691 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2693 falseLabel = newiTempLabel (buffer);
2694 geniCodeGoto(falseLabel);
2697 ast2iCode(tree->right);
2700 /*-----------------------------------------------------------------*/
2701 /* geniCodeInline - intermediate code for inline assembler */
2702 /*-----------------------------------------------------------------*/
2703 static void geniCodeInline (ast *tree)
2707 ic = newiCode(INLINEASM,NULL,NULL);
2708 IC_INLINE(ic) = tree->values.inlineasm;
2712 /*-----------------------------------------------------------------*/
2713 /* ast2iCode - creates an icodeList from an ast */
2714 /*-----------------------------------------------------------------*/
2715 operand *ast2iCode (ast *tree)
2717 operand *left = NULL;
2718 operand *right= NULL;
2723 /* set the global variables for filename & line number */
2724 if ( tree->filename )
2725 filename = tree->filename ;
2727 lineno = tree->lineno ;
2729 block = tree->block ;
2731 scopeLevel = tree->level;
2733 if (tree->type == EX_VALUE )
2734 return operandFromValue(tree->opval.val);
2736 if (tree->type == EX_LINK )
2737 return operandFromLink (tree->opval.lnk);
2739 /* if we find a nullop */
2740 if (tree->type == EX_OP &&
2741 ( tree->opval.op == NULLOP ||
2742 tree->opval.op == BLOCK )) {
2743 ast2iCode (tree->left);
2744 ast2iCode (tree->right);
2748 /* special cases for not evaluating */
2749 if ( tree->opval.op != ':' &&
2750 tree->opval.op != '?' &&
2751 tree->opval.op != CALL &&
2752 tree->opval.op != IFX &&
2753 tree->opval.op != LABEL &&
2754 tree->opval.op != GOTO &&
2755 tree->opval.op != SWITCH &&
2756 tree->opval.op != FUNCTION &&
2757 tree->opval.op != INLINEASM ) {
2759 if (IS_ASSIGN_OP(tree->opval.op) ||
2760 IS_DEREF_OP(tree) ||
2761 (tree->opval.op == '&' && !tree->right) ||
2762 tree->opval.op == PTR_OP) {
2764 if ((IS_ARRAY_OP(tree->left) && IS_ARRAY_OP(tree->left->left)) ||
2765 (IS_DEREF_OP(tree) && IS_ARRAY_OP(tree->left)))
2767 int olvr = lvaluereq ;
2769 left = operandFromAst(tree->left);
2770 lvaluereq = olvr - 1;
2772 left = operandFromAst(tree->left);
2775 if (IS_DEREF_OP(tree) && IS_DEREF_OP(tree->left))
2776 left = geniCodeRValue(left,TRUE);
2778 left = operandFromAst(tree->left);
2780 if (tree->opval.op == INC_OP ||
2781 tree->opval.op == DEC_OP) {
2783 right= operandFromAst(tree->right);
2786 right= operandFromAst(tree->right);
2790 /* now depending on the type of operand */
2791 /* this will be a biggy */
2792 switch (tree->opval.op) {
2794 case '[' : /* array operation */
2796 link *ltype = operandType(left);
2797 left= geniCodeRValue (left,IS_PTR(ltype->next) ? TRUE : FALSE);
2798 right=geniCodeRValue (right,TRUE);
2801 return geniCodeArray (left,right);
2803 case '.' : /* structure dereference */
2804 if (IS_PTR(operandType(left)))
2805 left = geniCodeRValue(left,TRUE);
2807 left = geniCodeRValue(left,FALSE);
2809 return geniCodeStruct (left,right,tree->lvalue);
2811 case PTR_OP: /* structure pointer dereference */
2814 pType = operandType(left);
2815 left = geniCodeRValue(left,TRUE);
2817 setOClass (pType,getSpec(operandType(left)));
2820 return geniCodeStruct (left, right,tree->lvalue);
2822 case INC_OP: /* increment operator */
2824 return geniCodePostInc (left);
2826 return geniCodePreInc (right);
2828 case DEC_OP: /* decrement operator */
2830 return geniCodePostDec (left);
2832 return geniCodePreDec (right);
2834 case '&' : /* bitwise and or address of operator */
2835 if ( right ) { /* this is a bitwise operator */
2836 left= geniCodeRValue(left,FALSE);
2837 right= geniCodeRValue(right,FALSE);
2838 return geniCodeBitwise (left,right,BITWISEAND,tree->ftype);
2840 return geniCodeAddressOf (left);
2842 case '|': /* bitwise or & xor */
2844 return geniCodeBitwise (geniCodeRValue(left,FALSE),
2845 geniCodeRValue(right,FALSE),
2850 return geniCodeDivision (geniCodeRValue(left,FALSE),
2851 geniCodeRValue(right,FALSE));
2854 return geniCodeModulus (geniCodeRValue(left,FALSE),
2855 geniCodeRValue(right,FALSE));
2858 return geniCodeMultiply (geniCodeRValue(left,FALSE),
2859 geniCodeRValue(right,FALSE));
2861 return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
2865 return geniCodeSubtract (geniCodeRValue(left,FALSE),
2866 geniCodeRValue(right,FALSE));
2868 return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
2872 return geniCodeAdd (geniCodeRValue(left,FALSE),
2873 geniCodeRValue(right,FALSE));
2875 return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
2878 return geniCodeLeftShift (geniCodeRValue(left,FALSE),
2879 geniCodeRValue(right,FALSE));
2882 return geniCodeRightShift (geniCodeRValue(left,FALSE),
2883 geniCodeRValue(right,FALSE));
2885 return geniCodeCast (operandType(left),
2886 geniCodeRValue(right,FALSE),FALSE);
2892 return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2896 operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2897 setOperandType(op, UCHARTYPE);
2908 return geniCodeLogic (geniCodeRValue(left,FALSE),
2909 geniCodeRValue(right,FALSE),
2912 return geniCodeConditional (tree);
2915 return operandFromLit(getSize(tree->right->ftype));
2919 link *rtype = operandType(right);
2920 link *ltype = operandType(left);
2921 if (IS_PTR(rtype) && IS_ITEMP(right)
2922 && right->isaddr && checkType(rtype->next,ltype)==1)
2923 right = geniCodeRValue(right,TRUE);
2925 right = geniCodeRValue(right,FALSE);
2927 geniCodeAssign (left,right,0);
2932 geniCodeAssign(left,
2933 geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
2935 geniCodeRValue(right,FALSE)),0);
2939 geniCodeAssign(left,
2940 geniCodeDivision(geniCodeRValue(operandFromOperand(left),
2942 geniCodeRValue(right,FALSE)),0);
2945 geniCodeAssign(left,
2946 geniCodeModulus(geniCodeRValue(operandFromOperand(left),
2948 geniCodeRValue(right,FALSE)),0);
2951 link *rtype = operandType(right);
2952 link *ltype = operandType(left);
2953 if (IS_PTR(rtype) && IS_ITEMP(right)
2954 && right->isaddr && checkType(rtype->next,ltype)==1)
2955 right = geniCodeRValue(right,TRUE);
2957 right = geniCodeRValue(right,FALSE);
2960 return geniCodeAssign(left,
2961 geniCodeAdd (geniCodeRValue(operandFromOperand(left),
2967 link *rtype = operandType(right);
2968 link *ltype = operandType(left);
2969 if (IS_PTR(rtype) && IS_ITEMP(right)
2970 && right->isaddr && checkType(rtype->next,ltype)==1) {
2971 right = geniCodeRValue(right,TRUE);
2974 right = geniCodeRValue(right,FALSE);
2977 geniCodeAssign (left,
2978 geniCodeSubtract(geniCodeRValue(operandFromOperand(left),
2984 geniCodeAssign (left,
2985 geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
2987 geniCodeRValue(right,FALSE)),0);
2990 geniCodeAssign(left,
2991 geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
2993 geniCodeRValue(right,FALSE)),0);
2996 geniCodeAssign (left,
2997 geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
2999 geniCodeRValue(right,FALSE),
3001 operandType(left)),0);
3004 geniCodeAssign (left,
3005 geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
3007 geniCodeRValue(right,FALSE),
3009 operandType(left)),0);
3012 geniCodeAssign (left,
3013 geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
3015 geniCodeRValue(right,FALSE),
3017 operandType(left)),0);
3019 return geniCodeRValue(right,FALSE);
3022 return geniCodeCall (ast2iCode(tree->left),
3025 geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
3026 return ast2iCode (tree->right);
3029 geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
3030 return ast2iCode (tree->right);
3033 geniCodeFunctionBody ( tree );
3037 geniCodeReturn (right);
3045 geniCodeSwitch (tree);
3049 geniCodeInline (tree);
3056 /*-----------------------------------------------------------------*/
3057 /* reverseICChain - gets from the list and creates a linkedlist */
3058 /*-----------------------------------------------------------------*/
3059 iCode *reverseiCChain ()
3061 iCode *loop = NULL ;
3062 iCode *prev = NULL ;
3064 while ((loop = getSet(&iCodeChain))) {
3075 /*-----------------------------------------------------------------*/
3076 /* iCodeFromAst - given an ast will convert it to iCode */
3077 /*-----------------------------------------------------------------*/
3078 iCode *iCodeFromAst ( ast *tree )
3080 returnLabel = newiTempLabel("_return");
3081 entryLabel = newiTempLabel("_entry") ;
3083 return reverseiCChain ();