home *** CD-ROM | disk | FTP | other *** search
/ Total Destruction / Total_Destruction.iso / addons / Lccwin32.exe / Lccwin32 / lccpub / src / w32incl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-11  |  25.8 KB  |  1,114 lines

  1. #include "cv.h"
  2. static int isStdCall(Symbol f);
  3. #ifdef BUILTIN_ASM
  4. /* asmcode - emit assembly language specified by asm */
  5. void asmcode(char *str, Symbol argv[]) 
  6. {
  7.         for ( ; *str; str++)
  8.                 if (*str == '%' && str[1] >= 0 && str[1] <= 9)
  9.                         print("%s", argv[*++str]->x.name);
  10.                 else
  11.                         print("%c", *str);
  12.         print("\n");
  13. }
  14. #endif
  15. void ResetRegistersMasks(void)
  16. {
  17.     tmask[IREG] =  (1 << EDI) | (1 << ESI)  | (1 << EBX)  |
  18.          (1 << EDX) | (1 << ECX) | (1 << EAX);
  19.     vmask[IREG] = 0;
  20. }
  21.  
  22. void SetRegistersMasks(void)
  23. {
  24.     if (OptimizeFlag && FunctionInfo.hasCalls == 0 &&
  25.         FunctionInfo.hasBlockMove == 0 &&
  26.         FunctionInfo.hasDiv == 0) {
  27.         tmask[IREG] = (1 << EDX) | (1 << ECX) | (1 << EAX) | (1 << ESI) | (1 << EDI) | (1 << EBX);
  28.         vmask[IREG] = (1 << ESI)  | (1 << EBX) | (1 << EDI);
  29.         FunctionInfo.leafFunction = 1;
  30.     }
  31.     else if (OptimizeFlag && FunctionInfo.hasBlockMove == 0 && 
  32.         FunctionInfo.NestedCalls == 0  && FunctionInfo.hasDiv == 0) {
  33.         tmask[IREG] = (1 << EDX) | (1 << ECX) | (1 << EAX) |(1 << ESI) |(1 << EDI) | (1 << EBX);
  34.         vmask[IREG] = (1 << EBX)|(1<<ESI)|(1 << EDI);
  35.         FunctionInfo.leafFunction = 0;
  36.         
  37.     }
  38.     else 
  39.         if (OptimizeFlag &&
  40.             FunctionInfo.hasBlockMove == 0 && FunctionInfo.hasDiv == 0) 
  41.     {
  42.         tmask[IREG] = (1 << EDX) | (1 << ECX) | (1 << EAX) |(1 << ESI) |(1 << EDI) | (1 << EBX);
  43.         vmask[IREG] = (1 << EBX)|(1 << ESI)|(1 << EDI);
  44.         FunctionInfo.leafFunction = 0;
  45.         
  46.     }
  47.     else 
  48.         {
  49.         tmask[IREG] = (1 << EDX) | (1 << ECX) | (1 << EAX) |(1 << ESI) |(1 << EDI) | (1 << EBX);
  50.         vmask[IREG] = (1 << EBX);
  51.         FunctionInfo.leafFunction = 0;
  52.         
  53.     }
  54. }
  55. static void progbeg(int argc,char *argv[])
  56. {
  57.     int i;
  58.  
  59.     {
  60.         union {
  61.             char c;
  62.             int i;
  63.         } u;
  64.         u.i = 0;
  65.         u.c = 1;
  66.         swap = (unsigned)(u.i == 1) != IR->little_endian;
  67.     }
  68.     parseflags(argc, argv);
  69.     intreg[EAX] = mkreg("%%eax", EAX, 1, IREG);
  70.     intreg[EDX] = mkreg("%%edx", EDX, 1, IREG);
  71.     intreg[ECX] = mkreg("%%ecx", ECX, 1, IREG);
  72.     intreg[EBX] = mkreg("%%ebx", EBX, 1, IREG);
  73.     intreg[ESI] = mkreg("%%esi", ESI, 1, IREG);
  74.     intreg[EDI] = mkreg("%%edi", EDI, 1, IREG);
  75.     shortreg[EAX] = mkreg("%%ax", EAX, 1, IREG);
  76.     shortreg[ECX] = mkreg("%%cx", ECX, 1, IREG);
  77.     shortreg[EDX] = mkreg("%%dx", EDX, 1, IREG);
  78.     shortreg[EBX] = mkreg("%%bx", EBX, 1, IREG);
  79.     shortreg[ESI] = mkreg("%%si", ESI, 1, IREG);
  80.     shortreg[EDI] = mkreg("%%di", EDI, 1, IREG);
  81.  
  82.     charreg[EAX] = mkreg("%%al", EAX, 1, IREG);
  83.     charreg[ECX] = mkreg("%%cl", ECX, 1, IREG);
  84.     charreg[EDX] = mkreg("%%dl", EDX, 1, IREG);
  85.     charreg[EBX] = mkreg("%%bl", EBX, 1, IREG);
  86.     for (i = 0; i < 8; i++)
  87.         fltreg[i] = mkreg("%d", i, 0, FREG);
  88.     rmap[C] = mkwildcard(charreg);
  89.     rmap[S] = mkwildcard(shortreg);
  90.     rmap[P] = rmap[B] = rmap[U] = rmap[I] = mkwildcard(intreg);
  91.     rmap[F] = rmap[D] = rmap[L] = mkwildcard(fltreg);
  92.     ResetRegistersMasks();
  93.     tmask[FREG] = 0xff;
  94.     vmask[FREG] = 0;
  95.     print("\t.text\n");
  96.     cseg = 0;
  97.     quo = mkreg("%%eax", EAX, 1, IREG);
  98.     quo->x.regnode->mask |= 1<<EDX;
  99.     rem = mkreg("%%edx", EDX, 1, IREG);
  100.     rem->x.regnode->mask |= 1<<EAX;
  101.     InstallIntrinsics();
  102. }
  103.  
  104. static void segment(int n)
  105. {
  106.     if (n == cseg)
  107.         return;
  108.     cseg = n;
  109.     if (n == CODE)
  110.         print("\t.text\n");
  111.     else if (cseg == BSS)
  112.                 print("\t.bss\n");
  113.     else if (cseg == DATA || cseg == LIT)
  114.         print("\t.data\n");
  115. }
  116.  
  117. static void progend(void)
  118. {
  119.     segment(0);
  120. }
  121. extern Symbol askreg(Symbol rs,unsigned rmask[]);
  122. static void target(Node p)
  123. {
  124.     assert(p);
  125.     switch (p->op) {
  126.     case RSHI: case RSHU: case LSHI: case LSHU:
  127.         if (generic(p->kids[1]->op) != CNST
  128.         && !(   generic(p->kids[1]->op) == INDIR
  129.              && p->kids[1]->kids[0]->op == VREG+P
  130.              && p->kids[1]->syms[RX]->u.t.cse
  131.              && generic(p->kids[1]->syms[RX]->u.t.cse->op) == CNST)) {
  132.             rtarget(p, 1, intreg[ECX]);
  133.             setreg(p, intreg[EAX]);
  134.         }
  135.         break;
  136.     case MULU:
  137.         setreg(p, quo);
  138.         rtarget(p, 0, intreg[EAX]);
  139.         break;
  140.     case DIVI: case DIVU:
  141.         setreg(p, quo);
  142.         rtarget(p, 0, intreg[EAX]);
  143.         rtarget(p, 1, intreg[ECX]);
  144.         break;
  145.     case MODI: case MODU:
  146.         setreg(p, rem);
  147.         rtarget(p, 0, intreg[EAX]);
  148.         rtarget(p, 1, intreg[ECX]);
  149.         break;
  150.     case ASGNB:
  151.         rtarget(p, 0, intreg[EDI]);
  152.         if (p->kids[0]->op == INDIRP) {
  153.                 Node pnode;
  154.                 pnode = p->kids[0];
  155.                 if (pnode->syms[RX] != intreg[EDI] &&
  156.                     !pnode->syms[RX]->x.wildcard) {
  157.                     Node q = newnode(LOADP,
  158.                         pnode, NULL, pnode->syms[0]);
  159.                     p->kids[0] = p->kids[0]->x.kids[0] = q;
  160.                     q->x.kids[0] = q->kids[0];
  161.                     setreg(q,intreg[EDI]);
  162.                 }
  163.         }
  164.         rtarget(p, 1, intreg[ESI]);
  165. #if 1
  166.         if (p->kids[1]->op == INDIRB) {
  167.             if (p->kids[1]->kids[0]->op == INDIRP) {
  168.                 Node pnode;
  169.                 pnode = p->kids[1]->kids[0];
  170.                 if (pnode->syms[RX] != intreg[ESI] &&
  171.                     !pnode->syms[RX]->x.wildcard) {
  172.                     Node q = newnode(LOADP,
  173.                         pnode, NULL, pnode->syms[0]);
  174.                     p->kids[1]->kids[0] = p->kids[1]->kids[0]->x.kids[0] = q;
  175.                     q->x.kids[0] = q->kids[0];
  176.                     setreg(q,intreg[ESI]);
  177.                 }
  178.  
  179.             }
  180.         }
  181. #endif
  182.         break;
  183.     case ARGB:
  184.         rtarget(p->kids[0], 0, intreg[ESI]);
  185.         break;
  186.     case CALLI: case CALLV:
  187.         setreg(p, intreg[EAX]);
  188.         break;
  189.     case RETI:
  190.         rtarget(p, 0, intreg[EAX]);
  191.         break;
  192.     }
  193. }
  194.  
  195. static void clobber(Node p)
  196. {
  197.     static int nstack = 0;
  198.  
  199.     assert(p);
  200.     nstack = ckstack(p, nstack);
  201.     switch (p->op) {
  202.      
  203.         case DIVI: case DIVU: case MULU:
  204.                spill(1 << EDX, IREG, p);
  205.                break;
  206. #if 0
  207.         case MODI: case MODU:
  208.                spill(1 << EAX, IREG, p);
  209.                break;
  210. #endif
  211.     case ASGNB: case ARGB:
  212.         spill(1<<ECX | 1<<ESI | 1<<EDI, IREG, p);
  213.         break;
  214.     case EQD: case LED: case GED: case LTD: case GTD: case NED:
  215.     case EQF: case LEF: case GEF: case LTF: case GTF: case NEF:
  216.         spill(1<<EAX, IREG, p);
  217.         break;
  218.     case CALLI:
  219.         spill(1<<EDX|1<<ECX,IREG,p);
  220.         break;
  221.     case ASGNL:
  222.     case SUBL:
  223.     case ADDL:
  224.     case MULL:
  225.     case DIVL:
  226.     case MODL:
  227.     case BCOML:
  228.     case BORL:
  229.     case BANDL:
  230.     case LSHL:
  231.     case RSHL:
  232.     case GEL:
  233.     case LTL:
  234.     case EQLO:
  235.     case NEL:
  236.     case GTL:
  237.     case LEL:
  238.     case ARGL:
  239.         spill((1<< EAX|1 << ECX|1 <<EDX),IREG,p);
  240.         break;
  241.  
  242.     }
  243. }
  244.  
  245.  
  246. #define isfp(p) (optype((p)->op)==F || optype((p)->op)==D)
  247.  
  248. static int ckstack(Node p,int n)
  249. {
  250.     int i;
  251.  
  252.     for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
  253.         if (isfp(p->x.kids[i]))
  254.             n--;
  255.     if (isfp(p) && p->count > 0)
  256.         n++;
  257.     if (n > 8)
  258.         error("expression too complicated\n");
  259.     debug(fprint(2, "(ckstack(%x)=%d)\n", p, n));
  260.     assert(n >= 0);
  261.     return n;
  262. }
  263.  
  264. static int hasargs(Node p)
  265. {
  266.     assert(p);
  267.     assert(generic(p->op) == CALL);
  268.     assert(p->syms[0]);
  269.     if (p->x.Flags)
  270.         return LBURG_MAX;
  271.     if (p->syms[0]->u.c.v.i > 0)
  272.         return 0;
  273.     return LBURG_MAX;
  274. }
  275.  
  276. static Node cacheMemOp=NULL;
  277. static int cacheMemOpResult=0;
  278. static int memop(Node p)
  279. {
  280.     if (cacheMemOp == p)
  281.         return cacheMemOpResult;
  282.     cacheMemOp = p;
  283.     assert(p);
  284.     assert(generic(p->op) == ASGN);
  285.     assert(p->kids[0]);
  286.     assert(p->kids[1]);
  287.     if (generic(p->kids[1]->kids[0]->op) == INDIR
  288.         && sametree(p->kids[0], p->kids[1]->kids[0]->kids[0])) {
  289.         cacheMemOpResult = 0;
  290.     }
  291.     else
  292.         cacheMemOpResult = LBURG_MAX;
  293.     return cacheMemOpResult;
  294. }
  295. static int cacheIncrmemResult=0;
  296. static Node cacheIncrmem=NULL;
  297. static int incrmem(Node p)
  298. {
  299.     Node kid1;
  300.  
  301.     assert(p);
  302.     if (p == cacheIncrmem)
  303.         return cacheIncrmemResult;
  304.     cacheIncrmem = p;
  305.     kid1 = p->kids[1];
  306.     if (kid1 == NULL) return LBURG_MAX;
  307.     if (kid1->kids[0] == NULL) return LBURG_MAX;
  308.     if (kid1->kids[0]->kids[0] == NULL) return LBURG_MAX;
  309.     if (kid1->kids[0]->kids[0]->syms[0] == NULL) return LBURG_MAX;
  310.     if (p->kids[0] == NULL) return LBURG_MAX;
  311.     if (p->kids[0]->syms[0] == NULL) return LBURG_MAX;
  312.     if (p->kids[1]->kids[0]->kids[0]->syms[0] != p->kids[0]->syms[0]) {
  313.         if (p->kids[0]->syms[2] == NULL) return LBURG_MAX;
  314.         if (p->kids[0]->op != VREG+P) return LBURG_MAX;
  315.         if (p->kids[1]->kids[0]->kids[0]->syms[2] != p->kids[0]->syms[2])
  316.             cacheIncrmemResult = LBURG_MAX;
  317.     }
  318.     cacheIncrmemResult = 0;
  319.     return cacheIncrmemResult;
  320. }
  321.  
  322. static int dequal(Node p,int v)
  323. {
  324.     assert(p);
  325.     if (p->op == CNSTD &&
  326.         p->syms[0]->u.c.v.d == (double)v)
  327.         return 0;
  328.     return LBURG_MAX;
  329. }
  330. static int fequal(Node p,int v)
  331. {
  332.     assert(p);
  333.     if (p->op == CNSTF &&
  334.         p->syms[0]->u.c.v.f == (float)v)
  335.         return 0;
  336.     return LBURG_MAX;
  337. }
  338.  
  339. static Node cacheimmOpShort=NULL;
  340. static int cacheimmOpShortResult=0;
  341. static int immediateOpShort(Node p)
  342. {
  343.     Node kid1;
  344.     Symbol sym;
  345.  
  346.     assert(p);
  347.     if (p == cacheimmOpShort)
  348.         return cacheimmOpShortResult;
  349.     cacheimmOpShort = p;
  350.     cacheimmOpShortResult = LBURG_MAX;
  351.     kid1 = p->kids[1];
  352.     if (kid1 == NULL) return LBURG_MAX;
  353.     if (kid1->kids[0] == NULL) return LBURG_MAX;
  354.     if (kid1->kids[0]->kids[0] == NULL) return LBURG_MAX;
  355.     if (kid1->kids[0]->kids[0]->kids[0] == NULL) return LBURG_MAX;
  356.     if (kid1->kids[0]->kids[0]->kids[0]->kids[0] == NULL) return LBURG_MAX;
  357.     if (p->kids[0] == NULL) return LBURG_MAX;
  358.     sym = kid1->kids[0]->kids[0]->kids[0]->kids[0]->syms[0];
  359.     if (sym == NULL) {
  360.         sym = kid1->kids[0]->kids[0]->kids[0]->kids[0]->syms[2];
  361.         if (sym == NULL) return LBURG_MAX;
  362.         if (sym != p->kids[0]->syms[2] || sym->x.wildcard)
  363.             return LBURG_MAX;
  364.         cacheimmOpShortResult = 0;
  365.         return 0;
  366.     }
  367.     if (sym != p->kids[0]->syms[0] && p->kids[0]->syms[0] == NULL) {
  368.         sym = kid1->kids[0]->kids[0]->kids[0]->kids[0]->syms[2];
  369.         if (sym == NULL) return LBURG_MAX;
  370.         if (sym != p->kids[0]->syms[2] || sym->x.wildcard)
  371.             return LBURG_MAX;
  372.         cacheimmOpShortResult = 0;
  373.         return 0;
  374.     }
  375.     if (sym == p->kids[0]->syms[0]) {
  376.         cacheimmOpShortResult = 0;
  377.         return 0;
  378.     }
  379.     return LBURG_MAX;
  380. }
  381. #if 0
  382. static int iszero(Node p)
  383. {
  384.     if ((p->op == CNSTI || p->op == CNSTU)
  385.         && p->syms[0] && 
  386.         p->syms[0]->isconstant &&
  387.         p->syms[0]->u.c.v.i == 0)
  388.         return 0;
  389.     return LBURG_MAX;
  390. }
  391. static int iscon8(Node p)
  392. {
  393.     if ((p->op == CNSTI || p->op == CNSTU)
  394.         && p->syms[0] && (p->syms[0]->u.value & ~0xff) == 0)
  395.         return 0;
  396.     return LBURG_MAX;
  397. }
  398. static int iscon16(Node p)
  399. {
  400.     if ((p->op == CNSTI || p->op == CNSTU)
  401.         && p->syms[0] && (p->syms[0]->u.c.v.i & ~0xffff) == 0)
  402.         return 0;
  403.     return LBURG_MAX;
  404. }
  405. #endif
  406. #ifndef ASM_LIB
  407. static int sametree(Node p,Node q)
  408. {
  409.     return p == NULL && q == NULL
  410.         || p && q && p->op == q->op && p->syms[0] == q->syms[0]
  411.         && sametree(p->kids[0], q->kids[0])
  412.         && sametree(p->kids[1], q->kids[1]);
  413. }
  414. #endif
  415.  
  416. static void emit0(Node q)
  417. {
  418. #if 0/*_EMIT_DEBUG*/
  419.     Node p = q;
  420.     for (; p; p = p->x.next) {
  421.         if (p->op == LABEL+V) {
  422.             assert(p->syms[0]);
  423.             fprint(2,"# %s:\n", p->syms[0]->x.name);
  424.         } else {
  425.             int i;
  426.             fprint(2,"# node%c%d %s count=%d", p->x.listed ? '\'' : '#', p->x.inst,
  427.                 opname(p->op), p->count);
  428.             for (i = 0; i < NELEMS(p->kids) && p->kids[i]; i++)
  429.                 fprint(2," #%d", p->kids[i]->x.inst);
  430.             for (i = 0; i < NELEMS(p->syms) && p->syms[i]; i++) {
  431.                 if (p->syms[i]->x.name)
  432.                     fprint(2," %s", p->syms[i]->x.name);
  433.                 if (p->syms[i]->name != p->syms[i]->x.name)
  434.                     fprint(2," (%s)", p->syms[i]->name);
  435.             }
  436.             fprint(2,"\n");
  437.         }
  438.     }
  439.     fprint(2,"\n--------\n");
  440. #endif
  441.     emit(q);
  442. }
  443.  
  444. static void emit2(Node p)
  445. {
  446. #define preg(f) ((f)[getregnum(p->x.kids[0])]->x.name)
  447.  
  448.     switch (p->op) {
  449.     case CVCI:
  450.         print("\tmovsbl\t%s,%s\n",
  451.               preg(charreg),
  452.               p->syms[RX]->x.name);
  453.         break;
  454.     case CVCU:
  455.         print("\tmovzbl\t%s,%s\n",
  456.               preg(charreg),
  457.               p->syms[RX]->x.name);
  458.         break;
  459.     case CVSI:
  460.         print("\tmovswl\t%s,%s\n",
  461.               preg(shortreg),
  462.               p->syms[RX]->x.name);
  463.         break;
  464.     case CVSU:
  465.         print("\tmovzwl\t%s,%s\n",
  466.               preg(shortreg),
  467.               p->syms[RX]->x.name);
  468.         break;
  469.     case CVIC: case CVIS:
  470.     case CVUC: case CVUS:
  471.         { char *dst = shortreg[getregnum(p)]->x.name;
  472.           char *src = preg(shortreg);
  473.           if (dst != src)
  474.             print("\tmovl\t%s,%s\n", src, dst);
  475.         }
  476.         break;
  477.     }
  478. }
  479. static void doarg(Node p)
  480. {
  481.         int roundedsize = p->syms[0]->u.c.v.i;
  482.         Value v;
  483.  
  484.         roundedsize = (3 + roundedsize) & ~3;
  485.         assert(p && p->syms[0]);
  486.         mkactual(4, roundedsize);
  487.         p->syms[1] = p->syms[0];
  488.         if (roundedsize != p->syms[0]->u.c.v.i) {
  489.                 v.i = roundedsize;
  490.                 p->syms[0] = constant(inttype,v);
  491.         }
  492. }
  493.  
  494. static void blkfetch(int k,int off,int reg,int tmp)
  495. {
  496. }
  497.  
  498. static void blkstore(int k,int off,int reg,int tmp)
  499. {
  500. }
  501.  
  502. static void blkloop(int dreg,int doff,int sreg,int soff,int size,int tmps[])
  503. {
  504. }
  505.  
  506. static void local(Symbol p)
  507. {
  508.     if (isfloat(p->type) || p->type->op == LONGLONG)
  509.         p->sclass = AUTO;
  510.     if (askregvar(p, rmap[ttob(p->type)]) == 0)
  511.         mkauto(p);
  512. }
  513.  
  514. #define LABELFORMAT "_$"
  515. int inFunctionCode = 0;
  516. int FunctionHasCalls;
  517. int ExceptionExternsDeclared=0;
  518. int hasAllocA;
  519. extern int ediIsSaved,esiIsSaved;
  520. static void function(Symbol f,Symbol caller[],Symbol callee[],int n)
  521. {
  522.     register int i;
  523.     int IsStdCall,stackAdjust=0;
  524.     int r;
  525.     int mo,startOffset,um,prologueEnd;
  526.     int saveOptimFlag;
  527.  
  528.     if (IntermediateLanguageFile) {
  529.         int i;
  530.         fprintf(ilFile,"\n");
  531.         for (i=0; i<50;i++)
  532.             fprintf(ilFile,"-");
  533.         fprintf(ilFile,"Function %s\n",cfunc->name);
  534.     }
  535.     inFunctionCode = 0;
  536.     saveOptimFlag = OptimizeFlag;
  537.     if (hasExceptions)
  538.         OptimizeFlag = 0;
  539.     hasAllocA = 0;
  540.     outflush();
  541.     inFunctionCode = 1;
  542.     usedmask[0] = usedmask[1] = 0;
  543.     freemask[0] = freemask[1] = ~(unsigned) 0;
  544.     SetupRegisterVariables();
  545.  
  546.     startOffset = offset = 4 + 4;
  547.     for (i = 0; callee[i]; i++) {
  548.         Symbol p = callee[i];
  549.         Symbol q = caller[i];
  550.         assert(q);
  551.         p->x.offset = q->x.offset = offset;
  552.         if (OptimizeFlag && p->sclass == REGISTER && p->x.regnode) {
  553.             q->x = p->x;
  554.             q->x.name = stringf("%d",p->x.offset);
  555.             usedmask[0] |= p->x.regnode->mask;
  556.         }
  557.         else {
  558.             if (p->sclass == REGISTER)
  559.                 p->sclass = AUTO;
  560.             p->x.name = q->x.name = stringf("%d", p->x.offset);
  561.         }
  562.         offset += roundup(q->type->size, 4);
  563.     }
  564.     assert(caller[i] == 0);
  565.     mo =  offset - startOffset;
  566.     offset = maxoffset = 0;
  567.     if (1) {
  568.         r = BuildBasicBlocks();
  569.         if (r == 0) {
  570.             ResetRegistersMasks();
  571.             OptimizeFlag = 0;
  572.             startOffset = offset = 4 + 4;
  573.             for (i = 0; callee[i]; i++) {
  574.                 Symbol p = callee[i];
  575.                 Symbol q = caller[i];
  576.                 assert(q);
  577.                 p->x.offset = q->x.offset = offset;
  578.                 if (p->sclass == REGISTER)
  579.                     p->sclass = AUTO;
  580.                 p->x.name = q->x.name = stringf("%d", p->x.offset);
  581.                 p->x.regnode = NULL;
  582.                 offset += roundup(q->type->size, 4);
  583.             }
  584.             usedmask[0] = usedmask[1] = 0;
  585.             freemask[0] = freemask[1] = ~(unsigned) 0;
  586.             mo =  offset - startOffset;
  587.             offset = maxoffset = 0;
  588.         }
  589.     }
  590.     gencode(caller, callee);
  591.     AnalyzeSecondPass();
  592.     IsStdCall = isStdCall(f);
  593.      if (IsStdCall) {
  594.          char fname[80];
  595.  
  596.         sprintf(fname,"_%s@%d",f->name,mo);
  597.         f->x.name = stringf(fname);
  598.      }
  599.      print("\t.type\t%s,function\n", f->x.name);
  600.      print("%s:\n", f->x.name);
  601.     prologueEnd = 0;
  602.     framesize = roundup(maxoffset, 4);
  603.     if (hasExceptions) {
  604.         OptimizeFlag = 0;
  605.         print("\tpush\t%%ebp\n");
  606.         print("\tmovl\t%%esp,%%ebp\n");
  607.         print("\tpushl\t$-1\n");
  608.         print("\tpushl\t$_$ExcepData\n");
  609.         print("\tpushl\t$__except_handler3\n");
  610.         print("\t.byte\t100\n");
  611.         print("\t.byte\t161\n");
  612.         print("\t.long\t0\n");
  613.         print("\tpush\t%%eax\n");
  614.         print("\t.byte\t100\n");
  615.         print("\t.byte\t137\n");
  616.         print("\t.byte\t37\n");
  617.         print("\t.long\t0\n");
  618.         print("\tsubl\t$12,%%esp\n");
  619.         print("\tpushl\t%%ebx\n");
  620.         print("\tpushl\t%%esi\n");
  621.         print("\tpushl\t%%edi\n");
  622.         print("\tmovl\t%%esp,-24(%%ebp)\n");
  623.         f->x.PrologueEnd = 44;
  624.     }
  625.     else {
  626.         if (hasAllocA || mo > 0 || framesize > 0) {
  627.             print("\tpushl\t%%ebp\n");
  628.              print("\tmovl\t%%esp,%%ebp\n");
  629.             prologueEnd += 3;
  630.         }
  631.         if (framesize > 255) prologueEnd += 6;
  632.         else if (framesize > 0) prologueEnd += 3;
  633.         if (framesize > 0) {
  634.             if (framesize < 4096) {
  635.                 print("\tsubl\t$%d,%%esp\n", framesize);
  636.             }
  637.             else {
  638.                 print("\t.extern\t__stackprobe\n");
  639.                 print("\tmovl\t$%d,%%eax\n",framesize);
  640.                 print("\tcall\t__stackprobe\n");
  641.                 prologueEnd += 4;
  642.             }
  643.         }
  644.         um = usedmask[0];
  645.         if (um & (1 << EBX)) {
  646.              print("\tpushl\t%%ebx\n");
  647.             prologueEnd++;
  648.             stackAdjust += 4;
  649.         }
  650.         ediIsSaved = esiIsSaved = 0;
  651.         if (um & (1 << ESI)) {
  652.              print("\tpushl\t%%esi\n");
  653.             esiIsSaved = 1;
  654.             prologueEnd++;
  655.             stackAdjust += 4;
  656.         }
  657.         if (um & (1 << EDI)) {
  658.              print("\tpushl\t%%edi\n");
  659.             if ((vmask[0] & (1 << EDI)) == 0)
  660.                 ediIsSaved = 1;
  661.             prologueEnd++;
  662.             stackAdjust += 4;
  663.         }
  664.         f->x.PrologueEnd = prologueEnd;
  665.     }
  666.     emitcode();
  667.     if (hasAllocA) {
  668.         char buf[40];
  669.         sprintf(buf,"\tmovl\t%%%%ebp,%%%%esp\n\tsubl\t$%d,%%%%esp\n",stackAdjust+framesize);
  670.         print(buf);
  671.     }
  672.     if (hasExceptions) {
  673.         print("\txchg\t%%eax,%%ecx\n");
  674.         print("\tmov\t-16(%%ebp),%%eax\n");
  675.         /*
  676.         The built-in assembler has problems with
  677.         assembling the instruction
  678.         mov %eax,%fs:0x0
  679.         */
  680.         print("\t.byte\t100\n");
  681.         print("\t.byte\t163\n");
  682.         print("\t.long\t0x0\n");
  683.           print("\txchg\t%%eax,%%ecx\n");
  684. /*        print("\tmov\t%%ecx,%%fs:__except_list\n"); */
  685.         if (FunctionInfo.mmxCalls)
  686.             print("\temms\n");
  687.         print("\tpop\t%%edi\n");
  688.         print("\tpop\t%%esi\n");
  689.         print("\tpop\t%%ebx\n");
  690.         print("\tleave\n");
  691.         print("\tret\n");
  692.     }
  693.     else {
  694.         if (um & (1 << EDI))
  695.             print("\tpopl\t%%edi\n");
  696.         if (um & (1 << ESI))
  697.             print("\tpopl\t%%esi\n");
  698.         if (um & (1 << EBX))
  699.             print("\tpopl\t%%ebx\n");
  700.         if (hasAllocA/*mo > 0*/ || framesize > 0) {
  701.             print("\tleave\n");
  702.         }
  703.         else    if (mo > 0)
  704.             print("\tpopl\t%%ebp\n");
  705.         if (FunctionInfo.mmxCalls)
  706.             print("\temms\n");
  707.         if (IsStdCall && mo) {
  708.             print("\tret\t$%d\n",mo);
  709.         }
  710.         else print("\tret\n");
  711.     }
  712.     { int l = genlabel(1);
  713.       print("%s%d:\n",LABELFORMAT, l);
  714.       print("\t.size\t%s,%s%d-%s\n", f->x.name,LABELFORMAT, l, f->x.name);
  715.     }
  716.     if (hasExceptions) {
  717.         if (!ExceptionExternsDeclared) {
  718.             print("\t.extern\t__except_handler3\n");
  719.             print("\t.extern\t__except_list\n");
  720.             ExceptionExternsDeclared = 1;
  721.         }
  722.         hasExceptions = 0;
  723.     }
  724.     if (OptimizeFlag) {
  725.         SendToOptimizer();
  726.     }
  727.     else 
  728.         outflush();
  729.     inFunctionCode = 0;
  730.     OptimizeFlag = saveOptimFlag;
  731.     ResetRegistersMasks();
  732. }
  733.  
  734. static void defsymbol(Symbol p)
  735. {
  736.     if (p->scope >= LOCAL && p->sclass == STATIC)
  737.         p->x.name = stringf("%s%d",LABELFORMAT, genlabel(1));
  738.     else if (p->generated)
  739.         p->x.name = stringf("%s%s",LABELFORMAT, p->name);
  740.     else if (p->scope == GLOBAL || p->sclass == EXTERN) {
  741.         if (p->Flags) {
  742.             Type ty;
  743.             int argsize = 0;
  744.  
  745.             ty = p->type;
  746.             if (ty && ty->op == FUNCTION && ty->u.f.proto) {
  747.                 int i;
  748.  
  749.                 for (i=0; ty->u.f.proto[i];i++) {
  750.                     if (ty->u.f.proto[i])
  751.                         argsize += roundup(ty->u.f.proto[i]->size,4);
  752.                 }
  753.             }
  754.             if (ty && ty->op == FUNCTION)
  755.                 p->x.name = stringf("_%s@%d",p->name,argsize);
  756.             else
  757.                 p->x.name = stringf("_%s",p->name);
  758.         }
  759.         else p->x.name = stringf("_%s", p->name);
  760.     }
  761.     else
  762.         p->x.name = p->name;
  763. }
  764.  
  765. static void address(Symbol q,Symbol p,int n)
  766. {
  767.     if (p->scope == GLOBAL
  768.         || p->sclass == STATIC || p->sclass == EXTERN)
  769.         q->x.name = stringf("%s%s%d",
  770.                     p->x.name, n >= 0 ? "+" : "", n);
  771.     else {
  772.         q->x.offset = p->x.offset + n;
  773.         q->x.name = stringd(q->x.offset);
  774.     }
  775.     q->x.ArraySymbol = p;
  776. }
  777.  
  778. static void defconst(int ty,Value v)
  779. {
  780.     switch (ty) {
  781.     case C:
  782.         print("\t.byte\t%d\n", v.uc);
  783.         return;
  784.     case S:
  785.         print("\t.word\t%d\n", v.ss);
  786.         return;
  787.     case I:
  788.         print("\t.long\t%d\n", v.i);
  789.         return;
  790.     case U:
  791.         print("\t.long\t0x%x\n", v.u);
  792.         return;
  793.     case P:
  794.         print("\t.long\t0x%x\n", v.p);
  795.         return;
  796.     case F:
  797.         print("\t.long\t0x%x\n", *(unsigned *) &v.f);
  798.         return;
  799.     case L:
  800.         {
  801.             double d = v.d;
  802.             __int64 i64 = d;
  803.             print("\t.long\t0x%x\n",(int)i64);
  804.             print("\t.long\t0x%x\n",(int)(i64 >> 32));
  805.             return;
  806.         }
  807.     case D:{
  808.             unsigned *p = (unsigned *) &v.d;
  809.             print("\t.long\t0x%x,0x%x\n", p[swap], p[1 - swap]);
  810.             return;
  811.         }
  812.     }
  813.     assert(0);
  814. }
  815.  
  816. static void defaddress(Symbol p)
  817. {
  818.     print("\t.long\t%s\n", p->x.name);
  819. }
  820.  
  821. static int lastlinenr = -1;
  822. void PutLineNumber(int lineno)
  823. {
  824.     if (lastlinenr == lineno) return;
  825.     print("\t.line\t%d\n",lineno);
  826.     lastlinenr = lineno;
  827. }
  828. static void defstring(int n,char *s)
  829. {
  830.     int i;
  831.  
  832.     print("\t.byte\t%d%c",*s++,(n==1)?'\n':',');
  833.     if (n == 1) return;
  834.     n--;
  835.     i = 1;
  836.     while (n > 0) {
  837.         if (n > 1 && (i!=15)) print("%d,",*s);
  838.         else print("%d",*s);
  839.         if (n > 1 && i==15) {
  840.             print("\n\t.byte\t");
  841.             i = 0;
  842.         }
  843.         else if (n == 1) print("\n");
  844.         s++;
  845.         n--;
  846.         i++;
  847.     }
  848. }
  849.  
  850. static void export(Symbol p)
  851. {
  852.     print("\t.globl\t%s\n", p->x.name);
  853. }
  854.  
  855. static void 
  856. import(Symbol p)
  857. {
  858.     int oldseg = cseg;
  859.  
  860.     if (p->ref > 0 &&!IsIntrinsic(p->name)) {
  861.         segment(0);
  862.         print("\t.extern\t%s\n", p->x.name);
  863.         segment(oldseg);
  864.     }
  865. }
  866. static int ntypes;
  867.  
  868. static void global (Symbol p)
  869. {
  870.     int a;
  871.  
  872.     /*
  873.     All definitions will start at an address multiple of four.
  874.     I think that is all that the x86 requires.
  875.     */
  876.     if (p->type && p->type->op == DOUBLE)
  877.         a = 3;
  878.     else 
  879.         a = 2;
  880.     print("\t.align\t%d\n",a);
  881.     if (!p->generated) {
  882.         print("\t.type\t%s,%s", p->x.name,
  883.             isfunc(p->type) ? "function" : "object");
  884.         print("\n");
  885.     }
  886.     if (p->u.seg == BSS) {
  887.         if (p->sclass == STATIC)
  888.             print("\t.lcomm\t%s,%d\n", p->x.name, p->type->size);
  889.         else
  890.             print("\t.comm\t%s,%d\n", p->x.name, p->type->size);
  891.     } else {
  892.         if (!p->generated)
  893.             print("\t.size\t%s,%d\n", p->x.name, p->type->size);
  894.         print("%s:\n", p->x.name);
  895.     }
  896. }
  897.  
  898. static void 
  899. space(int n)
  900. {
  901.     if (cseg != BSS)
  902.         print("\t.space\t%d\n", n);
  903. }
  904.  
  905. static char *currentfile;       /* current file name */
  906. static void stabblock ARGS((int, int, Symbol*));
  907. static void stabinit ARGS((char *, int, char *[]));
  908. static void stabline ARGS((Coordinate *));
  909. static void stabsym ARGS((Symbol));
  910. static void stabtype ARGS((Symbol));
  911.  
  912. static void asgncode ARGS((Type, int));
  913. static void dbxout ARGS((Type));
  914. static int emittype ARGS((Type, int, int));
  915.  
  916. /* asgncode - assign type code to ty */
  917. static void asgncode(Type ty,int lev)
  918. {
  919.     if (ty->x.marked || ty->x.typeno)
  920.         return;
  921.     ty->x.marked = 1;
  922.     switch (ty->op) {
  923.     case VOLATILE: case CONST: case VOLATILE+CONST:
  924.         asgncode(ty->type, lev);
  925.         ty->x.typeno = ty->type->x.typeno;
  926.         break;
  927.     case POINTER: case FUNCTION: case ARRAY:
  928.         asgncode(ty->type, lev + 1);
  929.         /* fall thru */
  930.     case VOID: case CHAR: case SHORT: case INT: case UNSIGNED:
  931.     case FLOAT: case DOUBLE:
  932.         break;
  933.     case STRUCT: case UNION: {
  934.         Field p;
  935.         for (p = fieldlist(ty); p; p = p->link)
  936.             asgncode(p->type, lev + 1);
  937.         /* fall thru */
  938.     case ENUM:
  939.         if (ty->x.typeno == 0)
  940.             ty->x.typeno = ++ntypes;
  941.         if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9'))
  942.             dbxout(ty);
  943.         break;
  944.         }
  945.     default:
  946.         assert(0);
  947.     }
  948. }
  949.  
  950. /* dbxout - output .stabs entry for type ty */
  951. static void dbxout(Type ty)
  952. {
  953. }
  954.  
  955.  
  956. /* stabblock - output a stab entry for '{' or '}' at level lev */
  957. static void stabblock(int brace,int lev,Symbol *p)
  958. {
  959.     if (brace == '{') {
  960.         while (*p) {
  961.             stabsym(*p++);
  962.         }
  963.     }
  964. }
  965.  
  966. /* stabinit - initialize stab output */
  967. static void stabinit(char *file,int argc,char *argv[])
  968. {
  969.     if (file && *file) {
  970.         print("\t.file \"%s\"\n",file);
  971.         currentfile = file;
  972.     }
  973. }
  974.  
  975. /* stabline - emit stab entry for source coordinate *cp */
  976. static void stabline(Coordinate *cp) 
  977. {
  978.     PutLineNumber(cp->y);
  979. }
  980.  
  981. /* stabsym - output a code view entry for symbol p */
  982. static void stabsym(Symbol pSym)
  983. {
  984.     int t,c,l;
  985.     char SymbolRecord[90],*p;
  986.  
  987.     if (glevel == 0) return;    
  988.     if (pSym->name == NULL) return;
  989.     if (isfunc(pSym->type) ) return;
  990.     if (pSym->sclass == TYPEDEF) return;
  991.     if (pSym->generated || pSym->computed)
  992.         return;
  993.     c = *pSym->name;
  994.     if (c >= '0' && c <= '9') return;
  995.     memset(SymbolRecord,0,90);
  996.     p = SymbolRecord + 2;
  997.  
  998.     if (pSym->sclass == STATIC) {
  999.         *(unsigned short *)p = 0x201;
  1000.         p += 2;
  1001.     }
  1002.     else if (pSym->scope == GLOBAL) {
  1003.         *(unsigned short *)p = 0x202; /* Public symbol */
  1004.         p += 2;
  1005.     }
  1006.     else return;
  1007.     p += 6; /* Skip offset and section until code generation */
  1008.     t = GetType(pSym);
  1009.     *(unsigned short *)p = t;
  1010.     p += 2;
  1011.     p = PutLengthPrefixedName(p,pSym->name);
  1012.     l = (p - SymbolRecord) - 2;
  1013.     p = SymbolRecord;
  1014.     *(unsigned short *)p = l;
  1015.     AddToCVData(SymbolRecord,l+2,pSym->x.name);
  1016. }
  1017.  
  1018. /* stabtype - output a stab entry for type *p */
  1019. static void stabtype(Symbol p)
  1020. {
  1021.     int c,n;
  1022.  
  1023.     if (p->src.file == NULL) {
  1024.         return; /* built in type */
  1025.     }
  1026.     if (p->uses == NULL || p->type == NULL) {
  1027.         return; /* not used */
  1028.     }
  1029.     if (p->type->x.marked == 0) return;
  1030.     if (p->sclass == TYPEDEF) c = 'T';
  1031.     else c = 't';
  1032.     n = GetFileNumber(p->src.file);
  1033.     fprintf(xrefFile,"%c %s %d %d",c,p->name,n,p->src.y);
  1034.     if (p->type->x.pointerEmitted) {
  1035.         Type ty;
  1036.  
  1037.         ty = p->type;
  1038.         if (ty) {
  1039.             if (ty->x.pointerEmitted) {
  1040.                 fprintf(xrefFile," *");
  1041.             }
  1042.         }
  1043.     }
  1044.     fprintf(xrefFile,"\n");
  1045. }
  1046.  
  1047. static int isStdCall(Symbol f)
  1048. {
  1049.     Type typePtr;
  1050.  
  1051.     if (f == NULL) return 0;
  1052.     if (f->Flags) return 1;
  1053.     typePtr = f->type;
  1054.     while (typePtr) {
  1055.         if (typePtr->op == STDCALL) {
  1056.             return 1;
  1057.         }
  1058.         typePtr = typePtr->type;
  1059.     }
  1060.     return 0;
  1061. }
  1062. extern void WriteLocalsDebugInfo(Symbol f,int lineno);
  1063. Interface x86IR = {
  1064.     1, 1, 0,        /* char */
  1065.     2, 2, 0,        /* short */
  1066.     4, 4, 0,        /* int */
  1067.     4, 4, 1,        /* float */
  1068.     8, 4, 1,        /* double */
  1069.     4, 4, 0,        /* T * */
  1070.     0, 1, 0,        /* struct so that ARGB keeps stack aligned */
  1071.     1,            /* little_endian */
  1072.     0,            /* mulops_calls */
  1073.     0,            /* wants_callb */
  1074.     1,            /* wants_argb */
  1075.     0,            /* left_to_right */
  1076.     0,            /* wants_dag */
  1077.     address,
  1078.     blockbeg,
  1079.     blockend,
  1080.     defaddress,
  1081.     defconst,
  1082.     defstring,
  1083.     defsymbol,
  1084.     emit0,
  1085.     export,
  1086.     function,
  1087.     gen,
  1088.     global,
  1089.     import,
  1090.     local,
  1091.     progbeg,
  1092.     progend,
  1093.     segment,
  1094.     space,
  1095.     stabblock, 0, WriteLocalsDebugInfo, stabinit, stabline, stabsym, stabtype,
  1096.     {1, blkfetch, blkstore, blkloop,
  1097.         _label,
  1098.         _rule,
  1099.         _nts,
  1100.         _kids,
  1101.         _opname,
  1102.         _arity,
  1103.         _string,
  1104.         _templates,
  1105.         _isinstruction,
  1106.         _ntname,
  1107.         emit2,
  1108.         doarg,
  1109.         target,
  1110.         clobber,
  1111.     }
  1112. };
  1113.  
  1114.