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 ;
43 symbol *returnLabel ; /* function return label */
44 symbol *entryLabel ; /* function entry label */
45 /*-----------------------------------------------------------------*/
46 /* forward definition of some functions */
47 operand *geniCodeDivision (operand *,operand *);
48 operand *geniCodeAssign (operand *,operand *,int);
49 operand *geniCodeArray (operand *,operand *);
50 operand *geniCodeArray2Ptr (operand *);
51 operand *geniCodeRValue (operand *, bool );
52 operand *geniCodeDerefPtr (operand *);
54 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
55 /* forward definition of print functions */
56 PRINTFUNC(picGetValueAtAddr);
57 PRINTFUNC(picSetValueAtAddr);
59 PRINTFUNC(picGeneric);
60 PRINTFUNC(picGenericOne);
66 PRINTFUNC(picJumpTable);
68 PRINTFUNC(picReceive);
70 iCodeTable codeTable[] = {
71 { '!' , "not", picGenericOne , NULL },
72 { '~' , "~" , picGenericOne , NULL },
73 { RRC , "rrc", picGenericOne , NULL },
74 { RLC , "rlc", picGenericOne , NULL },
75 { GETHBIT ,"ghbit", picGenericOne , NULL },
76 { UNARYMINUS , "-" , picGenericOne , NULL },
77 { IPUSH , "push",picGenericOne , NULL },
78 { IPOP , "pop", picGenericOne , NULL },
79 { CALL , "call",picGenericOne , NULL },
80 { PCALL , "pcall",picGenericOne , NULL },
81 { FUNCTION , "proc", picGenericOne , NULL },
82 { ENDFUNCTION ,"eproc", picGenericOne , NULL },
83 { RETURN , "ret", picGenericOne , NULL },
84 { '+' , "+" , picGeneric , NULL },
85 { '-' , "-" , picGeneric , NULL },
86 { '*' , "*" , picGeneric , NULL },
87 { '/' , "/" , picGeneric , NULL },
88 { '%' , "%" , picGeneric , NULL },
89 { '>' , ">" , picGeneric , NULL },
90 { '<' , "<" , picGeneric , NULL },
91 { LE_OP , "<=" , picGeneric , NULL },
92 { GE_OP , ">=" , picGeneric , NULL },
93 { EQ_OP , "==" , picGeneric , NULL },
94 { NE_OP , "!=" , picGeneric , NULL },
95 { AND_OP , "&&" , picGeneric , NULL },
96 { OR_OP , "||" , picGeneric , NULL },
97 { '^' , "^" , picGeneric , NULL },
98 { '|' , "|" , picGeneric , NULL },
99 { BITWISEAND , "&" , picGeneric , NULL },
100 { LEFT_OP , "<<" , picGeneric , NULL },
101 { RIGHT_OP , ">>" , picGeneric , NULL },
102 { GET_VALUE_AT_ADDRESS, "@" , picGetValueAtAddr, NULL },
103 { ADDRESS_OF , "&" , picAddrOf , NULL },
104 { CAST , "<>" , picCast , NULL },
105 { '=' , ":=" , picAssign , NULL },
106 { LABEL , "" , picLabel , NULL },
107 { GOTO , "" , picGoto , NULL },
108 { JUMPTABLE ,"jtab" , picJumpTable , NULL },
109 { IFX , "if" , picIfx , NULL },
110 { INLINEASM , "" , picInline , NULL },
111 { RECEIVE , "recv", picReceive , NULL },
112 { SEND , "send", picGenericOne , NULL }
116 /*-----------------------------------------------------------------*/
117 /* operandName - returns the name of the operand */
118 /*-----------------------------------------------------------------*/
119 int printOperand (operand *op, FILE *file)
134 opetype = getSpec (operandType(op));
135 if (SPEC_NOUN(opetype) == V_FLOAT)
136 fprintf (file,"%g {", SPEC_CVAL(opetype).v_float);
138 fprintf (file,"0x%x {",(int) floatFromVal(op->operand.valOperand));
139 printTypeChain(operandType(op),file);
146 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}" ,*/
147 (OP_SYMBOL(op)->rname[0] ? OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name),
149 OP_LIVEFROM(op),OP_LIVETO(op),
150 OP_SYMBOL(op)->stack,
151 op->isaddr, OP_SYMBOL(op)->isreqv,OP_SYMBOL(op)->remat
154 fprintf(file,"{"); printTypeChain(operandType(op),file);
155 if (SPIL_LOC(op) && IS_ITEMP(op))
156 fprintf(file,"}{ sir@ %s",SPIL_LOC(op)->rname);
161 /* if assigned to registers */
162 if (OP_SYMBOL(op)->nRegs) {
163 if (OP_SYMBOL(op)->isspilt) {
164 if (!OP_SYMBOL(op)->remat)
165 if (OP_SYMBOL(op)->usl.spillLoc)
166 fprintf(file,"[%s]",(OP_SYMBOL(op)->usl.spillLoc->rname[0] ?
167 OP_SYMBOL(op)->usl.spillLoc->rname :
168 OP_SYMBOL(op)->usl.spillLoc->name));
170 fprintf(file,"[err]");
172 fprintf(file,"[remat]");
177 for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
178 fprintf(file,"%s ", port->getRegName(OP_SYMBOL(op)->regs[i]));
183 fprintf(file,"%s",(OP_SYMBOL(op)->rname[0] ?
184 OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name));
185 /* if assigned to registers */
186 if (OP_SYMBOL(op)->nRegs && !OP_SYMBOL(op)->isspilt) {
189 for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
190 fprintf(file,"%s ",(OP_SYMBOL(op)->regs[i] ?
191 OP_SYMBOL(op)->regs[i]->name :
200 printTypeChain(op->operand.typeOperand,file);
211 /*-----------------------------------------------------------------*/
212 /* print functions */
213 /*-----------------------------------------------------------------*/
214 PRINTFUNC(picGetValueAtAddr)
217 printOperand (IC_RESULT(ic),of);
220 printOperand (IC_LEFT(ic), of);
226 PRINTFUNC(picSetValueAtAddr)
230 printOperand(IC_LEFT(ic),of);
232 printOperand(IC_RIGHT(ic),of);
239 printOperand(IC_RESULT(ic),of);
240 if (IS_ITEMP(IC_LEFT(ic)))
244 printOperand(IC_LEFT(ic),of);
246 if (IS_ITEMP(IC_LEFT(ic)))
247 fprintf(of," offsetAdd ");
250 printOperand(IC_RIGHT(ic),of);
252 if (IS_ITEMP(IC_LEFT(ic)))
258 PRINTFUNC(picJumpTable)
263 fprintf(of,"%s\t",s);
264 printOperand(IC_JTCOND(ic),of);
266 for ( sym = setFirstItem(IC_JTLABELS(ic)); sym;
267 sym = setNextItem(IC_JTLABELS(ic)))
268 fprintf(of,"\t\t\t%s\n",sym->name);
271 PRINTFUNC(picGeneric)
274 printOperand(IC_RESULT(ic),of);
276 printOperand(IC_LEFT(ic),of);
277 fprintf(of," %s ",s);
278 printOperand(IC_RIGHT(ic),of);
282 PRINTFUNC(picGenericOne)
285 if ( IC_RESULT(ic) ) {
286 printOperand(IC_RESULT(ic),of);
291 fprintf (of,"%s ",s);
292 printOperand(IC_LEFT(ic),of);
295 if (! IC_RESULT(ic) && !IC_LEFT(ic))
304 printOperand(IC_RESULT(ic),of);
306 printOperand(IC_LEFT(ic),of);
307 printOperand(IC_RIGHT(ic),of);
316 if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
319 printOperand(IC_RESULT(ic),of);
321 if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
324 fprintf(of," %s ", s);
325 printOperand (IC_RIGHT(ic),of);
332 fprintf(of," %s($%d) :\n",IC_LABEL(ic)->name,IC_LABEL(ic)->key);
338 fprintf (of," goto %s($%d)\n", IC_LABEL(ic)->name,IC_LABEL(ic)->key);
345 printOperand(IC_COND(ic),of);
348 fprintf (of," == 0 goto %s($%d)\n",IC_FALSE(ic)->name,IC_FALSE(ic)->key);
350 fprintf (of," != 0 goto %s($%d)\n",IC_TRUE(ic)->name,IC_TRUE(ic)->key);
352 fprintf (of,"\tzzgoto %s\n",IC_FALSE(ic)->name);
358 fprintf(of,"%s",IC_INLINE(ic));
361 PRINTFUNC(picReceive)
363 printOperand(IC_RESULT(ic),of);
364 fprintf(of," = %s ",s);
365 printOperand(IC_LEFT(ic),of);
369 /*-----------------------------------------------------------------*/
370 /* piCode - prints one iCode */
371 /*-----------------------------------------------------------------*/
372 int piCode (void *item, FILE *of)
380 icTab = getTableEntry(ic->op) ;
381 fprintf(stdout,"%s(%d:%d:%d:%d:%d)\t",
382 ic->filename,ic->lineno,
383 ic->seq,ic->key,ic->depth,ic->supportRtn);
384 icTab->iCodePrint(of,ic,icTab->printName);
388 /*-----------------------------------------------------------------*/
389 /* printiCChain - prints intermediate code for humans */
390 /*-----------------------------------------------------------------*/
391 void printiCChain (iCode *icChain, FILE *of)
398 for ( loop = icChain ; loop ; loop = loop->next ) {
399 if ((icTab = getTableEntry (loop->op ))) {
400 fprintf(of,"%s(%d:%d:%d:%d:%d)\t",
401 loop->filename,loop->lineno,
402 loop->seq,loop->key,loop->depth,loop->supportRtn);
404 icTab->iCodePrint (of,loop,icTab->printName);
410 /*-----------------------------------------------------------------*/
411 /* newOperand - allocate, init & return a new iCode */
412 /*-----------------------------------------------------------------*/
413 operand *newOperand ()
417 ALLOC(op,sizeof(operand));
423 /*-----------------------------------------------------------------*/
424 /* newiCode - create and return a new iCode entry initialised */
425 /*-----------------------------------------------------------------*/
426 iCode *newiCode (int op, operand *left, operand *right)
430 ALLOC(ic,sizeof(iCode));
432 ic->lineno = lineno ;
433 ic->filename= filename ;
435 ic->level = scopeLevel;
437 ic->key= iCodeKey++ ;
444 /*-----------------------------------------------------------------*/
445 /* newiCode for conditional statements */
446 /*-----------------------------------------------------------------*/
447 iCode *newiCodeCondition (operand *condition,
453 ic = newiCode(IFX,NULL,NULL);
454 IC_COND(ic) = condition ;
455 IC_TRUE(ic) = trueLabel ;
456 IC_FALSE(ic) = falseLabel;
460 /*-----------------------------------------------------------------*/
461 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
462 /*-----------------------------------------------------------------*/
463 iCode *newiCodeLabelGoto (int op, symbol *label)
467 ic = newiCode(op,NULL,NULL);
469 ic->argLabel.label = label ;
471 IC_RIGHT(ic) = NULL ;
472 IC_RESULT(ic) = NULL ;
476 /*-----------------------------------------------------------------*/
477 /* newiTemp - allocate & return a newItemp Variable */
478 /*-----------------------------------------------------------------*/
479 symbol *newiTemp (char *s)
484 sprintf(buffer,"%s",s);
486 sprintf (buffer,"iTemp%d",iTempNum++);
487 itmp = newSymbol (buffer,1);
488 strcpy(itmp->rname,itmp->name);
494 /*-----------------------------------------------------------------*/
495 /* newiTempLabel - creates a temp variable label */
496 /*-----------------------------------------------------------------*/
497 symbol *newiTempLabel (char *s)
501 /* check if this alredy exists */
502 if (s && (itmplbl = findSym(LabelTab, NULL, s)))
506 itmplbl = newSymbol(s,1);
508 sprintf(buffer,"iTempLbl%d",iTempLblNum++);
509 itmplbl = newSymbol(buffer,1);
514 itmplbl->key = labelKey++ ;
515 addSym (LabelTab, itmplbl, itmplbl->name,0,0);
519 /*-----------------------------------------------------------------*/
520 /* newiTempPreheaderLabel - creates a new preheader label */
521 /*-----------------------------------------------------------------*/
522 symbol *newiTempPreheaderLabel()
526 sprintf(buffer,"preHeaderLbl%d",iTempLblNum++);
527 itmplbl = newSymbol(buffer,1);
531 itmplbl->key = labelKey++ ;
532 addSym (LabelTab, itmplbl, itmplbl->name,0,0);
537 /*-----------------------------------------------------------------*/
538 /* initiCode - initialises some iCode related stuff */
539 /*-----------------------------------------------------------------*/
545 /*-----------------------------------------------------------------*/
546 /* copyiCode - make a copy of the iCode given */
547 /*-----------------------------------------------------------------*/
548 iCode *copyiCode (iCode *ic)
550 iCode *nic = newiCode(ic->op,NULL,NULL);
552 nic->lineno = ic->lineno ;
553 nic->filename= ic->filename ;
554 nic->block = ic->block;
555 nic->level = ic->level;
557 /* deal with the special cases first */
560 IC_COND(nic) = operandFromOperand(IC_COND(ic));
561 IC_TRUE(nic) = IC_TRUE(ic);
562 IC_FALSE(nic)= IC_FALSE(ic);
566 IC_JTCOND(nic) = operandFromOperand(IC_JTCOND(ic));
567 IC_JTLABELS(nic) = IC_JTLABELS(ic);
572 IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
573 IC_LEFT(nic) = operandFromOperand(IC_LEFT(ic));
574 IC_ARGS(nic) = IC_ARGS(ic);
578 IC_INLINE(nic) = IC_INLINE(ic);
582 IC_RESULT(nic) = operandFromOperand(IC_RESULT(ic));
583 IC_LEFT(nic) = operandFromOperand(IC_LEFT(ic));
584 IC_RIGHT(nic)= operandFromOperand(IC_RIGHT(ic));
590 /*-----------------------------------------------------------------*/
591 /* getTableEntry - gets the table entry for the given operator */
592 /*-----------------------------------------------------------------*/
593 iCodeTable *getTableEntry (int oper )
597 for ( i = 0 ; i < (sizeof(codeTable)/sizeof(iCodeTable)); i++ )
598 if (oper == codeTable[i].icode)
599 return &codeTable[i] ;
604 /*-----------------------------------------------------------------*/
605 /* newiTempOperand - new intermediate temp operand */
606 /*-----------------------------------------------------------------*/
607 operand *newiTempOperand (link *type, char throwType)
610 operand *op = newOperand();
614 itmp = newiTemp(NULL);
616 etype = getSpec(type);
618 if (IS_LITERAL(etype) )
621 /* copy the type information */
623 itmp->etype = getSpec (itmp->type = (throwType ? type :
624 copyLinkChain(type)));
625 if (IS_LITERAL(itmp->etype)) {
626 SPEC_SCLS(itmp->etype) = S_REGISTER ;
627 SPEC_OCLS(itmp->etype) = reg;
630 op->operand.symOperand = itmp;
631 op->key = itmp->key = ++operandKey ;
635 /*-----------------------------------------------------------------*/
636 /* operandType - returns the type chain for an operand */
637 /*-----------------------------------------------------------------*/
638 link *operandType (operand *op)
640 /* depending on type of operand */
644 return op->operand.valOperand->type ;
647 return op->operand.symOperand->type ;
650 return op->operand.typeOperand ;
652 werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
653 " operand type not known ");
654 assert (0) ; /* should never come here */
655 /* Just to keep the compiler happy */
660 /*-----------------------------------------------------------------*/
661 /* isParamterToCall - will return 1 if op is a parameter to args */
662 /*-----------------------------------------------------------------*/
663 int isParameterToCall (value *args, operand *op)
669 isSymbolEqual(op->operand.symOperand,tval->sym))
676 /*-----------------------------------------------------------------*/
677 /* isOperandGlobal - return 1 if operand is a global variable */
678 /*-----------------------------------------------------------------*/
679 int isOperandGlobal ( operand *op )
687 if (op->type == SYMBOL &&
688 (op->operand.symOperand->level == 0 ||
689 IS_STATIC(op->operand.symOperand->etype) ||
690 IS_EXTERN(op->operand.symOperand->etype))
697 /*-----------------------------------------------------------------*/
698 /* isOperandVolatile - return 1 if the operand is volatile */
699 /*-----------------------------------------------------------------*/
700 int isOperandVolatile ( operand *op , bool chkTemp)
705 if (IS_ITEMP(op) && !chkTemp)
708 opetype = getSpec(optype = operandType(op));
710 if (IS_PTR(optype) && DCL_PTR_VOLATILE(optype))
713 if (IS_VOLATILE(opetype))
718 /*-----------------------------------------------------------------*/
719 /* isOperandLiteral - returns 1 if an operand contains a literal */
720 /*-----------------------------------------------------------------*/
721 int isOperandLiteral ( operand *op )
728 opetype = getSpec (operandType(op));
730 if (IS_LITERAL(opetype))
735 /*-----------------------------------------------------------------*/
736 /* isOperandInFarSpace - will return true if operand is in farSpace*/
737 /*-----------------------------------------------------------------*/
738 bool isOperandInFarSpace (operand *op)
748 if (!IS_TRUE_SYMOP(op)) {
750 etype = SPIL_LOC(op)->etype;
756 etype = getSpec(operandType(op));
758 return (IN_FARSPACE(SPEC_OCLS(etype)) ? TRUE : FALSE);
761 /*-----------------------------------------------------------------*/
762 /* operandLitValue - literal value of an operand */
763 /*-----------------------------------------------------------------*/
764 double operandLitValue ( operand *op )
766 assert(isOperandLiteral(op));
768 return floatFromVal(op->operand.valOperand);
771 /*-----------------------------------------------------------------*/
772 /* operandOperation - perforoms operations on operands */
773 /*-----------------------------------------------------------------*/
774 operand *operandOperation (operand *left,operand *right,
777 operand *retval = (operand *)0;
779 assert(isOperandLiteral(left));
781 assert(isOperandLiteral(right));
785 retval = operandFromValue (valCastLiteral(type,
786 operandLitValue(left) +
787 operandLitValue(right)));
790 retval = operandFromValue(valCastLiteral(type,
791 operandLitValue(left) -
792 operandLitValue(right)));
795 retval = operandFromValue(valCastLiteral(type,
796 operandLitValue(left) *
797 operandLitValue(right)));
800 if ((unsigned long) operandLitValue(right) == 0){
801 werror(E_DIVIDE_BY_ZERO);
806 retval = operandFromValue (valCastLiteral(type,
807 operandLitValue(left) /
808 operandLitValue(right)));
811 if ((unsigned long) operandLitValue(right) == 0){
812 werror(E_DIVIDE_BY_ZERO);
816 retval = operandFromLit ((unsigned long) operandLitValue(left) %
817 (unsigned long) operandLitValue(right));
820 retval = operandFromLit ((unsigned long) operandLitValue(left) <<
821 (unsigned long) operandLitValue(right));
824 retval = operandFromLit ((unsigned long) operandLitValue(left) >>
825 (unsigned long) operandLitValue(right));
828 retval = operandFromLit (operandLitValue(left) ==
829 operandLitValue(right));
832 retval = operandFromLit (operandLitValue(left) <
833 operandLitValue(right));
836 retval = operandFromLit (operandLitValue(left) <=
837 operandLitValue(right));
840 retval = operandFromLit (operandLitValue(left) !=
841 operandLitValue(right));
844 retval = operandFromLit (operandLitValue(left) >
845 operandLitValue(right));
848 retval = operandFromLit (operandLitValue(left) >=
849 operandLitValue(right));
852 retval = operandFromLit ((unsigned long) operandLitValue(left) &
853 (unsigned long) operandLitValue(right));
856 retval = operandFromLit ((unsigned long) operandLitValue(left) |
857 (unsigned long) operandLitValue(right));
860 retval = operandFromLit ((unsigned long) operandLitValue(left) ^
861 (unsigned long) operandLitValue(right));
864 retval = operandFromLit (operandLitValue(left) &&
865 operandLitValue(right));
868 retval = operandFromLit (operandLitValue(left) ||
869 operandLitValue(right));
873 long i = operandLitValue(left);
875 retval = operandFromLit ((i >> (getSize(operandType(left))*8 - 1)) |
881 long i = operandLitValue(left);
883 retval = operandFromLit ((i << (getSize(operandType(left))*8 - 1)) |
889 retval = operandFromLit(-1 * operandLitValue(left));
893 retval = operandFromLit(~ ((long) operandLitValue(left)));
897 retval = operandFromLit(! operandLitValue(left));
901 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
902 " operandOperation invalid operator ");
910 /*-----------------------------------------------------------------*/
911 /* isOperandEqual - compares two operand & return 1 if they r = */
912 /*-----------------------------------------------------------------*/
913 int isOperandEqual (operand *left, operand *right)
915 /* if the pointers are equal then they are equal */
919 /* if either of them null then false */
920 if ( !left || !right)
923 if (left->type != right->type)
926 if (IS_SYMOP(left) && IS_SYMOP(right))
927 return left->key == right->key ;
929 /* if types are the same */
930 switch (left->type) {
932 return isSymbolEqual(left->operand.symOperand,
933 right->operand.symOperand);
935 return (floatFromVal(left->operand.valOperand) ==
936 floatFromVal(right->operand.valOperand));
938 if (checkType(left->operand.typeOperand,
939 right->operand.typeOperand) == 1)
946 /*-----------------------------------------------------------------*/
947 /* isiCodeEqual - comapres two iCodes are returns true if yes */
948 /*-----------------------------------------------------------------*/
949 int isiCodeEqual (iCode *left, iCode *right)
951 /* if the same pointer */
955 /* if either of them null */
959 /* if operand are the same */
960 if ( left->op == right->op ) {
962 /* compare all the elements depending on type */
963 if (left->op != IFX ) {
964 if (!isOperandEqual(IC_LEFT(left),IC_LEFT(right)))
966 if (!isOperandEqual(IC_RIGHT(left),IC_RIGHT(right)))
970 if (!isOperandEqual(IC_COND(left),IC_COND(right)))
972 if (!isSymbolEqual (IC_TRUE(left),IC_TRUE(right)))
974 if (!isSymbolEqual(IC_FALSE(left),IC_FALSE(right)))
982 /*-----------------------------------------------------------------*/
983 /* newiTempFromOp - create a temp Operand with same attributes */
984 /*-----------------------------------------------------------------*/
985 operand *newiTempFromOp (operand *op)
995 nop = newiTempOperand(operandType(op),TRUE);
996 nop->isaddr = op->isaddr ;
997 nop->isvolatile = op->isvolatile ;
998 nop->isGlobal = op->isGlobal ;
999 nop->isLiteral= op->isLiteral ;
1000 nop->noSpilLoc= op->noSpilLoc;
1001 nop->usesDefs = op->usesDefs;
1002 nop->isParm = op->isParm;
1003 nop->parmBytes = op->parmBytes;
1007 /*-----------------------------------------------------------------*/
1008 /* operand from operand - creates an operand holder for the type */
1009 /*-----------------------------------------------------------------*/
1010 operand *operandFromOperand (operand *op)
1017 nop->type = op->type;
1018 nop->isaddr = op->isaddr ;
1019 nop->key = op->key ;
1020 nop->isvolatile = op->isvolatile ;
1021 nop->isGlobal = op->isGlobal ;
1022 nop->isLiteral= op->isLiteral ;
1023 nop->noSpilLoc= op->noSpilLoc;
1024 nop->usesDefs = op->usesDefs;
1025 nop->isParm = op->isParm;
1026 nop->parmBytes = op->parmBytes;
1028 switch (nop->type) {
1030 nop->operand.symOperand = op->operand.symOperand ;
1033 nop->operand.valOperand = op->operand.valOperand;
1036 nop->operand.typeOperand = op->operand.typeOperand ;
1043 /*-----------------------------------------------------------------*/
1044 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1045 /*-----------------------------------------------------------------*/
1046 operand *opFromOpWithDU (operand *op, bitVect *defs, bitVect *uses)
1048 operand *nop = operandFromOperand(op);
1050 if (nop->type == SYMBOL) {
1051 OP_SYMBOL(nop)->defs = bitVectCopy(defs);
1052 OP_SYMBOL(nop)->uses = bitVectCopy(uses);
1058 /*-----------------------------------------------------------------*/
1059 /* operandFromSymbol - creates an operand from a symbol */
1060 /*-----------------------------------------------------------------*/
1061 operand *operandFromSymbol (symbol *sym)
1066 /* if the symbol's type is a literal */
1067 /* then it is an enumerator type */
1068 if (IS_LITERAL(sym->etype) && SPEC_ENUM(sym->etype))
1069 return operandFromValue (valFromType(sym->etype));
1072 sym->key = ++operandKey ;
1074 /* if this an implicit variable, means struct/union */
1075 /* member so just return it */
1076 if (sym->implicit || IS_FUNC(sym->type)) {
1079 op->operand.symOperand = sym;
1080 op->key = sym->key ;
1081 op->isvolatile = isOperandVolatile(op,TRUE);
1082 op->isGlobal = isOperandGlobal(op);
1083 op->parmBytes = sym->argStack;
1087 /* under the following conditions create a
1088 register equivalent for a local symbol */
1089 if (sym->level && sym->etype && SPEC_OCLS(sym->etype) &&
1090 IN_FARSPACE(SPEC_OCLS(sym->etype)) &&
1091 options.stackAuto == 0)
1094 if (!IS_AGGREGATE(sym->type) && /* not an aggregate */
1095 !IS_FUNC(sym->type) && /* not a function */
1096 !sym->_isparm && /* not a parameter */
1097 sym->level && /* is a local variable */
1098 !sym->addrtaken && /* whose address has not been taken */
1099 !sym->reqv && /* does not already have a register euivalence */
1100 !IS_VOLATILE(sym->etype) && /* not declared as volatile */
1101 !IS_STATIC(sym->etype) && /* and not declared static */
1102 !sym->islbl && /* not a label */
1103 ok && /* farspace check */
1104 !IS_BITVAR(sym->etype) /* not a bit variable */
1107 /* we will use it after all optimizations
1108 and before liveRange calculation */
1109 sym->reqv = newiTempOperand(sym->type,0);
1110 sym->reqv->key = sym->key ;
1111 OP_SYMBOL(sym->reqv)->key = sym->key;
1112 OP_SYMBOL(sym->reqv)->isreqv = 1;
1113 OP_SYMBOL(sym->reqv)->islocal = 1;
1114 SPIL_LOC(sym->reqv) = sym;
1117 if (!IS_AGGREGATE(sym->type)) {
1120 op->operand.symOperand = sym;
1123 op->isvolatile = isOperandVolatile(op,TRUE);
1124 op->isGlobal = isOperandGlobal(op);
1125 op->isPtr = IS_PTR(operandType(op));
1126 op->isParm = sym->_isparm ;
1131 /* itemp = &[_symbol] */
1133 ic = newiCode(ADDRESS_OF,newOperand(),NULL);
1134 IC_LEFT(ic)->type = SYMBOL ;
1135 IC_LEFT(ic)->operand.symOperand = sym ;
1136 IC_LEFT(ic)->key = sym->key;
1137 (IC_LEFT(ic))->isvolatile = isOperandVolatile(IC_LEFT(ic),TRUE);
1138 (IC_LEFT(ic))->isGlobal = isOperandGlobal(IC_LEFT(ic));
1139 IC_LEFT(ic)->isPtr = IS_PTR(operandType(IC_LEFT(ic)));
1142 IC_RESULT(ic) = newiTempOperand(sym->type,0);
1143 if (IS_ARRAY(sym->type)) {
1144 IC_RESULT(ic) = geniCodeArray2Ptr (IC_RESULT(ic));
1145 IC_RESULT(ic)->isaddr = 0;
1147 IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(sym->type));
1149 IC_RESULT(ic)->operand.symOperand->args = sym->args;
1153 return IC_RESULT(ic) ;
1156 /*-----------------------------------------------------------------*/
1157 /* operandFromValue - creates an operand from value */
1158 /*-----------------------------------------------------------------*/
1159 operand *operandFromValue (value *val)
1163 /* if this is a symbol then do the symbol thing */
1165 return operandFromSymbol (val->sym);
1167 /* this is not a symbol */
1170 op->operand.valOperand = val ;
1171 op->isLiteral = isOperandLiteral(op);
1175 /*-----------------------------------------------------------------*/
1176 /* operandFromLink - operand from typeChain */
1177 /*-----------------------------------------------------------------*/
1178 operand *operandFromLink (link *type)
1182 /* operand from link */
1188 op->operand.typeOperand = copyLinkChain(type);
1192 /*-----------------------------------------------------------------*/
1193 /* operandFromLit - makes an operand from a literal value */
1194 /*-----------------------------------------------------------------*/
1195 operand *operandFromLit ( float i)
1197 return operandFromValue (valueFromLit (i));
1200 /*-----------------------------------------------------------------*/
1201 /* operandFromAst - creates an operand from an ast */
1202 /*-----------------------------------------------------------------*/
1203 operand *operandFromAst ( ast *tree )
1209 /* depending on type do */
1210 switch (tree->type ) {
1212 return ast2iCode (tree) ;
1216 return operandFromValue(tree->opval.val) ;
1220 return operandFromLink (tree->opval.lnk) ;
1224 /* Just to keep the comiler happy */
1225 return (operand *)0;
1228 /*-----------------------------------------------------------------*/
1229 /* setOperandType - sets the operand's type to the given type */
1230 /*-----------------------------------------------------------------*/
1231 void setOperandType (operand *op, link *type)
1233 /* depending on the type of operand */
1237 op->operand.valOperand->etype =
1238 getSpec( op->operand.valOperand->type =
1239 copyLinkChain (type )) ;
1243 if (op->operand.symOperand->isitmp )
1244 op->operand.symOperand->etype =
1245 getSpec( op->operand.symOperand->type =
1246 copyLinkChain (type )) ;
1248 werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
1249 "attempt to modify type of source");
1253 op->operand.typeOperand = copyLinkChain (type);
1259 /*-----------------------------------------------------------------*/
1260 /* geniCodeValueAtAddress - generate intermeditate code for value */
1262 /*-----------------------------------------------------------------*/
1263 operand *geniCodeRValue (operand *op, bool force)
1266 link *type = operandType(op);
1267 link *etype= getSpec(type);
1269 /* if this is an array & already */
1270 /* an address then return this */
1271 if (IS_AGGREGATE(type) ||
1272 (IS_PTR(type) && !force && !op->isaddr))
1273 return operandFromOperand(op);
1275 /* if this is not an address then must be */
1276 /* rvalue already so return this one */
1280 /* if this is not a temp symbol then */
1281 if (!IS_ITEMP(op) &&
1283 !IN_FARSPACE(SPEC_OCLS(etype))) {
1284 op = operandFromOperand(op);
1289 if (IS_SPEC(type) &&
1290 IS_TRUE_SYMOP(op) &&
1291 !IN_FARSPACE(SPEC_OCLS(etype))) {
1292 op = operandFromOperand(op);
1297 ic = newiCode(GET_VALUE_AT_ADDRESS,op,NULL);
1298 if (IS_PTR(type) && op->isaddr && force)
1301 type = copyLinkChain(type);
1303 IC_RESULT(ic) = newiTempOperand (type,1);
1304 IC_RESULT(ic)->isaddr = 0;
1306 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1308 /* if the right is a symbol */
1309 if (op->type == SYMBOL)
1310 IC_RESULT(ic)->operand.symOperand->args =
1311 op->operand.symOperand->args ;
1314 return IC_RESULT(ic) ;
1317 /*-----------------------------------------------------------------*/
1318 /* geniCodeCast - changes the value from one type to another */
1319 /*-----------------------------------------------------------------*/
1320 operand *geniCodeCast (link *type, operand *op, bool implicit)
1324 link *opetype = getSpec(optype = operandType(op));
1327 /* one of them has size zero then error */
1328 if (IS_VOID(optype)) {
1329 werror(E_CAST_ZERO);
1333 /* if the operand is already the desired type then do nothing */
1334 if ( checkType (type,optype) == 1)
1337 /* if this is a literal then just change the type & return */
1338 if (IS_LITERAL(opetype) && op->type == VALUE && !IS_PTR(type) && !IS_PTR(optype))
1339 return operandFromValue(valCastLiteral(type,
1340 operandLitValue(op)));
1342 /* if casting to some pointer type &&
1343 the destination is not a generic pointer
1344 then give a warning : (only for implicit casts)*/
1345 if (IS_PTR(optype) && implicit &&
1346 (DCL_TYPE(optype) != DCL_TYPE(type)) &&
1348 werror(E_INCOMPAT_CAST);
1349 werror(E_CONTINUE,"from type '");
1350 printTypeChain(optype,stderr);fprintf(stderr,"' to type '");
1351 printTypeChain(type,stderr);fprintf(stderr,"'\n");
1354 /* if they are the same size create an assignment */
1355 if (getSize(type) == getSize(optype) &&
1356 !IS_BITFIELD(type) &&
1358 !IS_FLOAT(optype) &&
1359 ((IS_SPEC(type) && IS_SPEC(optype)) ||
1360 (!IS_SPEC(type) && !IS_SPEC(optype)))) {
1362 ic = newiCode('=',NULL,op);
1363 IC_RESULT(ic) = newiTempOperand(type,0);
1364 SPIL_LOC(IC_RESULT(ic)) =
1365 (IS_TRUE_SYMOP(op) ? OP_SYMBOL(op) : NULL);
1366 IC_RESULT(ic)->isaddr = 0;
1368 ic = newiCode(CAST,operandFromLink(type),
1369 geniCodeRValue(op,FALSE));
1371 IC_RESULT(ic)= newiTempOperand(type,0);
1374 /* preserve the storage class & output class */
1375 /* of the original variable */
1376 restype = getSpec(operandType(IC_RESULT(ic)));
1377 SPEC_SCLS(restype) = SPEC_SCLS(opetype);
1378 SPEC_OCLS(restype) = SPEC_OCLS(opetype);
1381 return IC_RESULT(ic) ;
1384 /*-----------------------------------------------------------------*/
1385 /* geniCodeLabel - will create a Label */
1386 /*-----------------------------------------------------------------*/
1387 void geniCodeLabel (symbol *label)
1391 ic = newiCodeLabelGoto(LABEL,label);
1395 /*-----------------------------------------------------------------*/
1396 /* geniCodeGoto - will create a Goto */
1397 /*-----------------------------------------------------------------*/
1398 void geniCodeGoto (symbol *label)
1402 ic = newiCodeLabelGoto(GOTO,label);
1406 /*-----------------------------------------------------------------*/
1407 /* geniCodeMultiply - gen intermediate code for multiplication */
1408 /*-----------------------------------------------------------------*/
1409 operand *geniCodeMultiply (operand *left, operand *right)
1416 /* if they are both literal then we know the result */
1417 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1418 return operandFromValue (valMult(left->operand.valOperand,
1419 right->operand.valOperand));
1421 resType = computeType (ltype,rtype) ;
1422 left = geniCodeCast(resType,left,TRUE);
1423 right= geniCodeCast(resType,right,TRUE);
1425 /* if the right is a literal & power of 2 */
1426 /* then make it a left shift */
1427 if (IS_LITERAL(retype) && !IS_FLOAT(letype) &&
1428 (p2 = powof2 ((unsigned long)floatFromVal(right->operand.valOperand))))
1429 ic = newiCode(LEFT_OP, left,operandFromLit(p2)); /* left shift */
1431 ic = newiCode('*',left,right); /* normal multiplication */
1432 /* if the size left or right > 1 then support routine */
1433 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1437 IC_RESULT(ic) = newiTempOperand(resType,1);
1440 return IC_RESULT(ic) ;
1443 /*-----------------------------------------------------------------*/
1444 /* geniCodeDivision - gen intermediate code for division */
1445 /*-----------------------------------------------------------------*/
1446 operand *geniCodeDivision (operand *left, operand *right)
1451 link *rtype = operandType(right);
1452 link *retype= getSpec(rtype);
1453 link *ltype = operandType(left);
1454 link *letype= getSpec(ltype);
1456 resType = computeType (ltype,rtype) ;
1457 left = geniCodeCast(resType,left,TRUE);
1458 right= geniCodeCast(resType,right,TRUE);
1460 /* if the right is a literal & power of 2 */
1461 /* then make it a right shift */
1462 if (IS_LITERAL(retype) &&
1463 !IS_FLOAT(letype) &&
1464 (p2 = powof2 ((unsigned long)
1465 floatFromVal(right->operand.valOperand))))
1466 ic = newiCode(RIGHT_OP, left,operandFromLit(p2)); /* right shift */
1468 ic = newiCode('/',left,right); /* normal division */
1469 /* if the size left or right > 1 then support routine */
1470 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1473 IC_RESULT(ic) = newiTempOperand(resType,0);
1476 return IC_RESULT(ic) ;
1478 /*-----------------------------------------------------------------*/
1479 /* geniCodeModulus - gen intermediate code for modulus */
1480 /*-----------------------------------------------------------------*/
1481 operand *geniCodeModulus (operand *left, operand *right)
1487 /* if they are both literal then we know the result */
1488 if (IS_LITERAL(letype) && IS_LITERAL(retype))
1489 return operandFromValue (valMod(left->operand.valOperand,
1490 right->operand.valOperand));
1492 resType = computeType (ltype,rtype) ;
1493 left = geniCodeCast(resType,left,TRUE);
1494 right= geniCodeCast(resType,right,TRUE);
1496 /* now they are the same size */
1497 ic = newiCode('%',left,right);
1499 /* if the size left or right > 1 then support routine */
1500 if (getSize(ltype) > 1 || getSize(rtype) > 1)
1502 IC_RESULT(ic) = newiTempOperand(resType,0);
1505 return IC_RESULT(ic) ;
1508 /*-----------------------------------------------------------------*/
1509 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1510 /*-----------------------------------------------------------------*/
1511 operand *geniCodePtrPtrSubtract (operand *left, operand *right)
1517 /* if they are both literals then */
1518 if (IS_LITERAL(letype) && IS_LITERAL(retype)) {
1519 result = operandFromValue (valMinus(left->operand.valOperand,
1520 right->operand.valOperand));
1524 ic = newiCode('-',left,right);
1526 IC_RESULT(ic) = result = newiTempOperand(newIntLink(),1);
1530 return geniCodeDivision (result,
1531 operandFromLit(getSize(ltype->next)));
1534 /*-----------------------------------------------------------------*/
1535 /* geniCodeSubtract - generates code for subtraction */
1536 /*-----------------------------------------------------------------*/
1537 operand *geniCodeSubtract (operand *left, operand *right)
1544 /* if they both pointers then */
1545 if ((IS_PTR(ltype) || IS_ARRAY(ltype)) &&
1546 (IS_PTR(rtype) || IS_ARRAY(rtype)))
1547 return geniCodePtrPtrSubtract (left,right);
1549 /* if they are both literal then we know the result */
1550 if (IS_LITERAL(letype) && IS_LITERAL(retype)
1551 && left->isLiteral && right->isLiteral)
1552 return operandFromValue (valMinus(left->operand.valOperand,
1553 right->operand.valOperand));
1555 /* if left is an array or pointer */
1556 if ( IS_PTR(ltype) || IS_ARRAY(ltype) ) {
1557 isarray = left->isaddr ;
1558 right = geniCodeMultiply (right,
1559 operandFromLit(getSize(ltype->next)));
1560 resType = copyLinkChain(IS_ARRAY(ltype) ? ltype->next : ltype);
1562 else { /* make them the same size */
1563 resType = computeType (ltype,rtype) ;
1564 left = geniCodeCast(resType,left,TRUE);
1565 right= geniCodeCast(resType,right,TRUE);
1568 ic = newiCode('-',left,right);
1570 IC_RESULT(ic)= newiTempOperand(resType,1);
1571 IC_RESULT(ic)->isaddr = (isarray ? 1 : 0);
1573 /* if left or right is a float */
1574 if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1578 return IC_RESULT(ic) ;
1581 /*-----------------------------------------------------------------*/
1582 /* geniCodeAdd - generates iCode for addition */
1583 /*-----------------------------------------------------------------*/
1584 operand *geniCodeAdd (operand *left, operand *right )
1592 /* if left is an array then array access */
1593 if (IS_ARRAY(ltype))
1594 return geniCodeArray (left,right);
1596 /* if the right side is LITERAL zero */
1597 /* return the left side */
1598 if (IS_LITERAL(retype) && right->isLiteral && !floatFromVal(valFromType(retype)))
1601 /* if left is literal zero return right */
1602 if (IS_LITERAL(letype) && left->isLiteral && !floatFromVal(valFromType(letype)))
1605 /* if left is an array or pointer then size */
1606 if (IS_PTR(ltype)) {
1608 isarray = left->isaddr;
1610 operandFromLit(getSize(ltype->next));
1611 right = geniCodeMultiply (right ,size);
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) {
2429 opl = newiTempOperand(args->type,0);
2431 sym->reqv->key = sym->key ;
2432 OP_SYMBOL(sym->reqv)->key = sym->key;
2433 OP_SYMBOL(sym->reqv)->isreqv = 1;
2434 OP_SYMBOL(sym->reqv)->islocal= 0;
2435 SPIL_LOC(sym->reqv) = sym;
2439 ic = newiCode(RECEIVE,NULL,NULL);
2440 currFunc->recvSize = getSize(sym->etype);
2441 IC_RESULT(ic) = opr;
2449 /*-----------------------------------------------------------------*/
2450 /* geniCodeFunctionBody - create the function body */
2451 /*-----------------------------------------------------------------*/
2452 void geniCodeFunctionBody (ast *tree)
2459 /* reset the auto generation */
2465 func = ast2iCode(tree->left);
2466 fetype = getSpec(operandType(func));
2468 savelineno = lineno;
2469 lineno = OP_SYMBOL(func)->lineDef;
2470 /* create an entry label */
2471 geniCodeLabel(entryLabel);
2472 lineno = savelineno;
2474 /* create a proc icode */
2475 ic = newiCode(FUNCTION,func,NULL);
2476 /* if the function has parmas then */
2477 /* save the parameters information */
2478 ic->argLabel.args = tree->values.args ;
2479 ic->lineno = OP_SYMBOL(func)->lineDef;
2483 /* for all parameters that are passed
2484 on registers add a "receive" */
2485 geniCodeReceive( tree->values.args );
2487 /* generate code for the body */
2488 ast2iCode(tree->right);
2490 /* create a label for return */
2491 geniCodeLabel(returnLabel);
2493 /* now generate the end proc */
2494 ic = newiCode(ENDFUNCTION,func,NULL);
2499 /*-----------------------------------------------------------------*/
2500 /* geniCodeReturn - gen icode for 'return' statement */
2501 /*-----------------------------------------------------------------*/
2502 void geniCodeReturn (operand *op)
2506 /* if the operand is present force an rvalue */
2508 op = geniCodeRValue(op,FALSE);
2510 ic = newiCode(RETURN,op,NULL);
2514 /*-----------------------------------------------------------------*/
2515 /* geniCodeIfx - generates code for extended if statement */
2516 /*-----------------------------------------------------------------*/
2517 void geniCodeIfx (ast *tree)
2520 operand *condition = ast2iCode(tree->left);
2523 /* if condition is null then exit */
2527 condition = geniCodeRValue(condition,FALSE);
2529 cetype = getSpec(operandType(condition));
2530 /* if the condition is a literal */
2531 if (IS_LITERAL(cetype)) {
2532 if (floatFromVal(condition->operand.valOperand)) {
2533 if (tree->trueLabel)
2534 geniCodeGoto(tree->trueLabel);
2539 if (tree->falseLabel)
2540 geniCodeGoto (tree->falseLabel);
2547 if ( tree->trueLabel ) {
2548 ic = newiCodeCondition(condition,
2553 if ( tree->falseLabel)
2554 geniCodeGoto(tree->falseLabel);
2557 ic = newiCodeCondition (condition,
2564 ast2iCode(tree->right);
2567 /*-----------------------------------------------------------------*/
2568 /* geniCodeJumpTable - tries to create a jump table for switch */
2569 /*-----------------------------------------------------------------*/
2570 int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
2572 int min = 0 ,max = 0, t, cnt = 0;
2577 set *labels = NULL ;
2579 if (!tree || !caseVals)
2582 /* the criteria for creating a jump table is */
2583 /* all integer numbers between the maximum & minimum must */
2584 /* be present , the maximum value should not exceed 255 */
2585 min = max = (int)floatFromVal(vch = caseVals);
2586 sprintf(buffer,"_case_%d_%d",
2587 tree->values.switchVals.swNum,
2589 addSet(&labels,newiTempLabel(buffer));
2591 /* if there is only one case value then no need */
2592 if (!(vch = vch->next ))
2596 if (((t = (int)floatFromVal(vch)) - max) != 1)
2598 sprintf(buffer,"_case_%d_%d",
2599 tree->values.switchVals.swNum,
2601 addSet(&labels,newiTempLabel(buffer));
2607 /* if the number of case statements <= 2 then */
2608 /* it is not economical to create the jump table */
2609 /* since two compares are needed for boundary conditions */
2610 if ((! optimize.noJTabBoundary && cnt <= 2) || max > (255/3))
2613 if ( tree->values.switchVals.swDefault )
2614 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2616 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2618 falseLabel = newiTempLabel (buffer);
2620 /* so we can create a jumptable */
2621 /* first we rule out the boundary conditions */
2622 /* if only optimization says so */
2623 if ( ! optimize.noJTabBoundary ) {
2624 link *cetype = getSpec(operandType(cond));
2625 /* no need to check the lower bound if
2626 the condition is unsigned & minimum value is zero */
2627 if (!( min == 0 && SPEC_USIGN(cetype))) {
2628 boundary = geniCodeLogic (cond,operandFromLit(min),'<');
2629 ic = newiCodeCondition (boundary,falseLabel,NULL);
2633 /* now for upper bounds */
2634 boundary = geniCodeLogic(cond,operandFromLit(max),'>');
2635 ic = newiCodeCondition (boundary,falseLabel,NULL);
2639 /* if the min is not zero then we no make it zero */
2641 cond = geniCodeSubtract(cond,operandFromLit(min));
2642 setOperandType(cond, UCHARTYPE);
2645 /* now create the jumptable */
2646 ic = newiCode(JUMPTABLE,NULL,NULL);
2647 IC_JTCOND(ic) = cond;
2648 IC_JTLABELS(ic) = labels;
2653 /*-----------------------------------------------------------------*/
2654 /* geniCodeSwitch - changes a switch to a if statement */
2655 /*-----------------------------------------------------------------*/
2656 void geniCodeSwitch (ast *tree)
2659 operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
2660 value *caseVals = tree->values.switchVals.swVals ;
2661 symbol *trueLabel , *falseLabel;
2663 /* if we can make this a jump table */
2664 if ( geniCodeJumpTable (cond,caseVals,tree) )
2665 goto jumpTable ; /* no need for the comparison */
2667 /* for the cases defined do */
2670 operand *compare = geniCodeLogic (cond,
2671 operandFromValue(caseVals),
2674 sprintf(buffer,"_case_%d_%d",
2675 tree->values.switchVals.swNum,
2676 (int) floatFromVal(caseVals));
2677 trueLabel = newiTempLabel(buffer);
2679 ic = newiCodeCondition(compare,trueLabel,NULL);
2681 caseVals = caseVals->next;
2686 /* if default is present then goto break else break */
2687 if ( tree->values.switchVals.swDefault )
2688 sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2690 sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum );
2692 falseLabel = newiTempLabel (buffer);
2693 geniCodeGoto(falseLabel);
2696 ast2iCode(tree->right);
2699 /*-----------------------------------------------------------------*/
2700 /* geniCodeInline - intermediate code for inline assembler */
2701 /*-----------------------------------------------------------------*/
2702 static void geniCodeInline (ast *tree)
2706 ic = newiCode(INLINEASM,NULL,NULL);
2707 IC_INLINE(ic) = tree->values.inlineasm;
2711 /*-----------------------------------------------------------------*/
2712 /* ast2iCode - creates an icodeList from an ast */
2713 /*-----------------------------------------------------------------*/
2714 operand *ast2iCode (ast *tree)
2716 operand *left = NULL;
2717 operand *right= NULL;
2722 /* set the global variables for filename & line number */
2723 if ( tree->filename )
2724 filename = tree->filename ;
2726 lineno = tree->lineno ;
2728 block = tree->block ;
2730 scopeLevel = tree->level;
2732 if (tree->type == EX_VALUE )
2733 return operandFromValue(tree->opval.val);
2735 if (tree->type == EX_LINK )
2736 return operandFromLink (tree->opval.lnk);
2738 /* if we find a nullop */
2739 if (tree->type == EX_OP &&
2740 ( tree->opval.op == NULLOP ||
2741 tree->opval.op == BLOCK )) {
2742 ast2iCode (tree->left);
2743 ast2iCode (tree->right);
2747 /* special cases for not evaluating */
2748 if ( tree->opval.op != ':' &&
2749 tree->opval.op != '?' &&
2750 tree->opval.op != CALL &&
2751 tree->opval.op != IFX &&
2752 tree->opval.op != LABEL &&
2753 tree->opval.op != GOTO &&
2754 tree->opval.op != SWITCH &&
2755 tree->opval.op != FUNCTION &&
2756 tree->opval.op != INLINEASM ) {
2757 if (IS_ASSIGN_OP(tree->opval.op) ||
2758 IS_DEREF_OP(tree) ||
2759 (tree->opval.op == '&' && !tree->right) ||
2760 tree->opval.op == PTR_OP) {
2762 if (IS_ARRAY_OP(tree->left) && IS_ARRAY_OP(tree->left->left))
2765 left = operandFromAst(tree->left);
2767 left = operandFromAst(tree->left);
2770 if (IS_DEREF_OP(tree) && IS_DEREF_OP(tree->left))
2771 left = geniCodeRValue(left,TRUE);
2773 left = operandFromAst(tree->left);
2775 if (tree->opval.op == INC_OP ||
2776 tree->opval.op == DEC_OP) {
2778 right= operandFromAst(tree->right);
2781 right= operandFromAst(tree->right);
2785 /* now depending on the type of operand */
2786 /* this will be a biggy */
2787 switch (tree->opval.op) {
2789 case '[' : /* array operation */
2791 link *ltype = operandType(left);
2792 left= geniCodeRValue (left,IS_PTR(ltype->next) ? TRUE : FALSE);
2793 right=geniCodeRValue (right,TRUE);
2796 return geniCodeArray (left,right);
2798 case '.' : /* structure dereference */
2799 if (IS_PTR(operandType(left)))
2800 left = geniCodeRValue(left,TRUE);
2802 left = geniCodeRValue(left,FALSE);
2804 return geniCodeStruct (left,right,tree->lvalue);
2806 case PTR_OP: /* structure pointer dereference */
2809 pType = operandType(left);
2810 left = geniCodeRValue(left,TRUE);
2812 setOClass (pType,getSpec(operandType(left)));
2815 return geniCodeStruct (left, right,tree->lvalue);
2817 case INC_OP: /* increment operator */
2819 return geniCodePostInc (left);
2821 return geniCodePreInc (right);
2823 case DEC_OP: /* decrement operator */
2825 return geniCodePostDec (left);
2827 return geniCodePreDec (right);
2829 case '&' : /* bitwise and or address of operator */
2830 if ( right ) { /* this is a bitwise operator */
2831 left= geniCodeRValue(left,FALSE);
2832 right= geniCodeRValue(right,FALSE);
2833 return geniCodeBitwise (left,right,BITWISEAND,tree->ftype);
2835 return geniCodeAddressOf (left);
2837 case '|': /* bitwise or & xor */
2839 return geniCodeBitwise (geniCodeRValue(left,FALSE),
2840 geniCodeRValue(right,FALSE),
2845 return geniCodeDivision (geniCodeRValue(left,FALSE),
2846 geniCodeRValue(right,FALSE));
2849 return geniCodeModulus (geniCodeRValue(left,FALSE),
2850 geniCodeRValue(right,FALSE));
2853 return geniCodeMultiply (geniCodeRValue(left,FALSE),
2854 geniCodeRValue(right,FALSE));
2856 return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
2860 return geniCodeSubtract (geniCodeRValue(left,FALSE),
2861 geniCodeRValue(right,FALSE));
2863 return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
2867 return geniCodeAdd (geniCodeRValue(left,FALSE),
2868 geniCodeRValue(right,FALSE));
2870 return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
2873 return geniCodeLeftShift (geniCodeRValue(left,FALSE),
2874 geniCodeRValue(right,FALSE));
2877 return geniCodeRightShift (geniCodeRValue(left,FALSE),
2878 geniCodeRValue(right,FALSE));
2880 return geniCodeCast (operandType(left),
2881 geniCodeRValue(right,FALSE),FALSE);
2887 return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2891 operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2892 setOperandType(op, UCHARTYPE);
2903 return geniCodeLogic (geniCodeRValue(left,FALSE),
2904 geniCodeRValue(right,FALSE),
2907 return geniCodeConditional (tree);
2910 return operandFromLit(getSize(tree->right->ftype));
2914 link *rtype = operandType(right);
2915 link *ltype = operandType(left);
2916 if (IS_PTR(rtype) && IS_ITEMP(right)
2917 && right->isaddr && checkType(rtype->next,ltype)==1)
2918 right = geniCodeRValue(right,TRUE);
2920 right = geniCodeRValue(right,FALSE);
2922 geniCodeAssign (left,right,0);
2927 geniCodeAssign(left,
2928 geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
2930 geniCodeRValue(right,FALSE)),0);
2934 geniCodeAssign(left,
2935 geniCodeDivision(geniCodeRValue(operandFromOperand(left),
2937 geniCodeRValue(right,FALSE)),0);
2940 geniCodeAssign(left,
2941 geniCodeModulus(geniCodeRValue(operandFromOperand(left),
2943 geniCodeRValue(right,FALSE)),0);
2946 link *rtype = operandType(right);
2947 link *ltype = operandType(left);
2948 if (IS_PTR(rtype) && IS_ITEMP(right)
2949 && right->isaddr && checkType(rtype->next,ltype)==1)
2950 right = geniCodeRValue(right,TRUE);
2952 right = geniCodeRValue(right,FALSE);
2955 return geniCodeAssign(left,
2956 geniCodeAdd (geniCodeRValue(operandFromOperand(left),
2962 link *rtype = operandType(right);
2963 link *ltype = operandType(left);
2964 if (IS_PTR(rtype) && IS_ITEMP(right)
2965 && right->isaddr && checkType(rtype->next,ltype)==1) {
2966 right = geniCodeRValue(right,TRUE);
2969 right = geniCodeRValue(right,FALSE);
2972 geniCodeAssign (left,
2973 geniCodeSubtract(geniCodeRValue(operandFromOperand(left),
2979 geniCodeAssign (left,
2980 geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
2982 geniCodeRValue(right,FALSE)),0);
2985 geniCodeAssign(left,
2986 geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
2988 geniCodeRValue(right,FALSE)),0);
2991 geniCodeAssign (left,
2992 geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
2994 geniCodeRValue(right,FALSE),
2996 operandType(left)),0);
2999 geniCodeAssign (left,
3000 geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
3002 geniCodeRValue(right,FALSE),
3004 operandType(left)),0);
3007 geniCodeAssign (left,
3008 geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
3010 geniCodeRValue(right,FALSE),
3012 operandType(left)),0);
3014 return geniCodeRValue(right,FALSE);
3017 return geniCodeCall (ast2iCode(tree->left),
3020 geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
3021 return ast2iCode (tree->right);
3024 geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
3025 return ast2iCode (tree->right);
3028 geniCodeFunctionBody ( tree );
3032 geniCodeReturn (right);
3040 geniCodeSwitch (tree);
3044 geniCodeInline (tree);
3051 /*-----------------------------------------------------------------*/
3052 /* reverseICChain - gets from the list and creates a linkedlist */
3053 /*-----------------------------------------------------------------*/
3054 iCode *reverseiCChain ()
3056 iCode *loop = NULL ;
3057 iCode *prev = NULL ;
3059 while ((loop = getSet(&iCodeChain))) {
3070 /*-----------------------------------------------------------------*/
3071 /* iCodeFromAst - given an ast will convert it to iCode */
3072 /*-----------------------------------------------------------------*/
3073 iCode *iCodeFromAst ( ast *tree )
3075 returnLabel = newiTempLabel("_return");
3076 entryLabel = newiTempLabel("_entry") ;
3078 return reverseiCChain ();