home *** CD-ROM | disk | FTP | other *** search
- #include "cv.h"
- static int isStdCall(Symbol f);
- #ifdef BUILTIN_ASM
- /* asmcode - emit assembly language specified by asm */
- void asmcode(char *str, Symbol argv[])
- {
- for ( ; *str; str++)
- if (*str == '%' && str[1] >= 0 && str[1] <= 9)
- print("%s", argv[*++str]->x.name);
- else
- print("%c", *str);
- print("\n");
- }
- #endif
- void ResetRegistersMasks(void)
- {
- tmask[IREG] = (1 << EDI) | (1 << ESI) | (1 << EBX) |
- (1 << EDX) | (1 << ECX) | (1 << EAX);
- vmask[IREG] = 0;
- }
-
- void SetRegistersMasks(void)
- {
- if (OptimizeFlag && FunctionInfo.hasCalls == 0 &&
- FunctionInfo.hasBlockMove == 0 &&
- FunctionInfo.hasDiv == 0) {
- tmask[IREG] = (1 << EDX) | (1 << ECX) | (1 << EAX) | (1 << ESI) | (1 << EDI) | (1 << EBX);
- vmask[IREG] = (1 << ESI) | (1 << EBX) | (1 << EDI);
- FunctionInfo.leafFunction = 1;
- }
- else if (OptimizeFlag && FunctionInfo.hasBlockMove == 0 &&
- FunctionInfo.NestedCalls == 0 && FunctionInfo.hasDiv == 0) {
- tmask[IREG] = (1 << EDX) | (1 << ECX) | (1 << EAX) |(1 << ESI) |(1 << EDI) | (1 << EBX);
- vmask[IREG] = (1 << EBX)|(1<<ESI)|(1 << EDI);
- FunctionInfo.leafFunction = 0;
-
- }
- else
- if (OptimizeFlag &&
- FunctionInfo.hasBlockMove == 0 && FunctionInfo.hasDiv == 0)
- {
- tmask[IREG] = (1 << EDX) | (1 << ECX) | (1 << EAX) |(1 << ESI) |(1 << EDI) | (1 << EBX);
- vmask[IREG] = (1 << EBX)|(1 << ESI)|(1 << EDI);
- FunctionInfo.leafFunction = 0;
-
- }
- else
- {
- tmask[IREG] = (1 << EDX) | (1 << ECX) | (1 << EAX) |(1 << ESI) |(1 << EDI) | (1 << EBX);
- vmask[IREG] = (1 << EBX);
- FunctionInfo.leafFunction = 0;
-
- }
- }
- static void progbeg(int argc,char *argv[])
- {
- int i;
-
- {
- union {
- char c;
- int i;
- } u;
- u.i = 0;
- u.c = 1;
- swap = (unsigned)(u.i == 1) != IR->little_endian;
- }
- parseflags(argc, argv);
- intreg[EAX] = mkreg("%%eax", EAX, 1, IREG);
- intreg[EDX] = mkreg("%%edx", EDX, 1, IREG);
- intreg[ECX] = mkreg("%%ecx", ECX, 1, IREG);
- intreg[EBX] = mkreg("%%ebx", EBX, 1, IREG);
- intreg[ESI] = mkreg("%%esi", ESI, 1, IREG);
- intreg[EDI] = mkreg("%%edi", EDI, 1, IREG);
- shortreg[EAX] = mkreg("%%ax", EAX, 1, IREG);
- shortreg[ECX] = mkreg("%%cx", ECX, 1, IREG);
- shortreg[EDX] = mkreg("%%dx", EDX, 1, IREG);
- shortreg[EBX] = mkreg("%%bx", EBX, 1, IREG);
- shortreg[ESI] = mkreg("%%si", ESI, 1, IREG);
- shortreg[EDI] = mkreg("%%di", EDI, 1, IREG);
-
- charreg[EAX] = mkreg("%%al", EAX, 1, IREG);
- charreg[ECX] = mkreg("%%cl", ECX, 1, IREG);
- charreg[EDX] = mkreg("%%dl", EDX, 1, IREG);
- charreg[EBX] = mkreg("%%bl", EBX, 1, IREG);
- for (i = 0; i < 8; i++)
- fltreg[i] = mkreg("%d", i, 0, FREG);
- rmap[C] = mkwildcard(charreg);
- rmap[S] = mkwildcard(shortreg);
- rmap[P] = rmap[B] = rmap[U] = rmap[I] = mkwildcard(intreg);
- rmap[F] = rmap[D] = rmap[L] = mkwildcard(fltreg);
- ResetRegistersMasks();
- tmask[FREG] = 0xff;
- vmask[FREG] = 0;
- print("\t.text\n");
- cseg = 0;
- quo = mkreg("%%eax", EAX, 1, IREG);
- quo->x.regnode->mask |= 1<<EDX;
- rem = mkreg("%%edx", EDX, 1, IREG);
- rem->x.regnode->mask |= 1<<EAX;
- InstallIntrinsics();
- }
-
- static void segment(int n)
- {
- if (n == cseg)
- return;
- cseg = n;
- if (n == CODE)
- print("\t.text\n");
- else if (cseg == BSS)
- print("\t.bss\n");
- else if (cseg == DATA || cseg == LIT)
- print("\t.data\n");
- }
-
- static void progend(void)
- {
- segment(0);
- }
- extern Symbol askreg(Symbol rs,unsigned rmask[]);
- static void target(Node p)
- {
- assert(p);
- switch (p->op) {
- case RSHI: case RSHU: case LSHI: case LSHU:
- if (generic(p->kids[1]->op) != CNST
- && !( generic(p->kids[1]->op) == INDIR
- && p->kids[1]->kids[0]->op == VREG+P
- && p->kids[1]->syms[RX]->u.t.cse
- && generic(p->kids[1]->syms[RX]->u.t.cse->op) == CNST)) {
- rtarget(p, 1, intreg[ECX]);
- setreg(p, intreg[EAX]);
- }
- break;
- case MULU:
- setreg(p, quo);
- rtarget(p, 0, intreg[EAX]);
- break;
- case DIVI: case DIVU:
- setreg(p, quo);
- rtarget(p, 0, intreg[EAX]);
- rtarget(p, 1, intreg[ECX]);
- break;
- case MODI: case MODU:
- setreg(p, rem);
- rtarget(p, 0, intreg[EAX]);
- rtarget(p, 1, intreg[ECX]);
- break;
- case ASGNB:
- rtarget(p, 0, intreg[EDI]);
- if (p->kids[0]->op == INDIRP) {
- Node pnode;
- pnode = p->kids[0];
- if (pnode->syms[RX] != intreg[EDI] &&
- !pnode->syms[RX]->x.wildcard) {
- Node q = newnode(LOADP,
- pnode, NULL, pnode->syms[0]);
- p->kids[0] = p->kids[0]->x.kids[0] = q;
- q->x.kids[0] = q->kids[0];
- setreg(q,intreg[EDI]);
- }
- }
- rtarget(p, 1, intreg[ESI]);
- #if 1
- if (p->kids[1]->op == INDIRB) {
- if (p->kids[1]->kids[0]->op == INDIRP) {
- Node pnode;
- pnode = p->kids[1]->kids[0];
- if (pnode->syms[RX] != intreg[ESI] &&
- !pnode->syms[RX]->x.wildcard) {
- Node q = newnode(LOADP,
- pnode, NULL, pnode->syms[0]);
- p->kids[1]->kids[0] = p->kids[1]->kids[0]->x.kids[0] = q;
- q->x.kids[0] = q->kids[0];
- setreg(q,intreg[ESI]);
- }
-
- }
- }
- #endif
- break;
- case ARGB:
- rtarget(p->kids[0], 0, intreg[ESI]);
- break;
- case CALLI: case CALLV:
- setreg(p, intreg[EAX]);
- break;
- case RETI:
- rtarget(p, 0, intreg[EAX]);
- break;
- }
- }
-
- static void clobber(Node p)
- {
- static int nstack = 0;
-
- assert(p);
- nstack = ckstack(p, nstack);
- switch (p->op) {
-
- case DIVI: case DIVU: case MULU:
- spill(1 << EDX, IREG, p);
- break;
- #if 0
- case MODI: case MODU:
- spill(1 << EAX, IREG, p);
- break;
- #endif
- case ASGNB: case ARGB:
- spill(1<<ECX | 1<<ESI | 1<<EDI, IREG, p);
- break;
- case EQD: case LED: case GED: case LTD: case GTD: case NED:
- case EQF: case LEF: case GEF: case LTF: case GTF: case NEF:
- spill(1<<EAX, IREG, p);
- break;
- case CALLI:
- spill(1<<EDX|1<<ECX,IREG,p);
- break;
- case ASGNL:
- case SUBL:
- case ADDL:
- case MULL:
- case DIVL:
- case MODL:
- case BCOML:
- case BORL:
- case BANDL:
- case LSHL:
- case RSHL:
- case GEL:
- case LTL:
- case EQLO:
- case NEL:
- case GTL:
- case LEL:
- case ARGL:
- spill((1<< EAX|1 << ECX|1 <<EDX),IREG,p);
- break;
-
- }
- }
-
-
- #define isfp(p) (optype((p)->op)==F || optype((p)->op)==D)
-
- static int ckstack(Node p,int n)
- {
- int i;
-
- for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
- if (isfp(p->x.kids[i]))
- n--;
- if (isfp(p) && p->count > 0)
- n++;
- if (n > 8)
- error("expression too complicated\n");
- debug(fprint(2, "(ckstack(%x)=%d)\n", p, n));
- assert(n >= 0);
- return n;
- }
-
- static int hasargs(Node p)
- {
- assert(p);
- assert(generic(p->op) == CALL);
- assert(p->syms[0]);
- if (p->x.Flags)
- return LBURG_MAX;
- if (p->syms[0]->u.c.v.i > 0)
- return 0;
- return LBURG_MAX;
- }
-
- static Node cacheMemOp=NULL;
- static int cacheMemOpResult=0;
- static int memop(Node p)
- {
- if (cacheMemOp == p)
- return cacheMemOpResult;
- cacheMemOp = p;
- assert(p);
- assert(generic(p->op) == ASGN);
- assert(p->kids[0]);
- assert(p->kids[1]);
- if (generic(p->kids[1]->kids[0]->op) == INDIR
- && sametree(p->kids[0], p->kids[1]->kids[0]->kids[0])) {
- cacheMemOpResult = 0;
- }
- else
- cacheMemOpResult = LBURG_MAX;
- return cacheMemOpResult;
- }
- static int cacheIncrmemResult=0;
- static Node cacheIncrmem=NULL;
- static int incrmem(Node p)
- {
- Node kid1;
-
- assert(p);
- if (p == cacheIncrmem)
- return cacheIncrmemResult;
- cacheIncrmem = p;
- kid1 = p->kids[1];
- if (kid1 == NULL) return LBURG_MAX;
- if (kid1->kids[0] == NULL) return LBURG_MAX;
- if (kid1->kids[0]->kids[0] == NULL) return LBURG_MAX;
- if (kid1->kids[0]->kids[0]->syms[0] == NULL) return LBURG_MAX;
- if (p->kids[0] == NULL) return LBURG_MAX;
- if (p->kids[0]->syms[0] == NULL) return LBURG_MAX;
- if (p->kids[1]->kids[0]->kids[0]->syms[0] != p->kids[0]->syms[0]) {
- if (p->kids[0]->syms[2] == NULL) return LBURG_MAX;
- if (p->kids[0]->op != VREG+P) return LBURG_MAX;
- if (p->kids[1]->kids[0]->kids[0]->syms[2] != p->kids[0]->syms[2])
- cacheIncrmemResult = LBURG_MAX;
- }
- cacheIncrmemResult = 0;
- return cacheIncrmemResult;
- }
-
- static int dequal(Node p,int v)
- {
- assert(p);
- if (p->op == CNSTD &&
- p->syms[0]->u.c.v.d == (double)v)
- return 0;
- return LBURG_MAX;
- }
- static int fequal(Node p,int v)
- {
- assert(p);
- if (p->op == CNSTF &&
- p->syms[0]->u.c.v.f == (float)v)
- return 0;
- return LBURG_MAX;
- }
-
- static Node cacheimmOpShort=NULL;
- static int cacheimmOpShortResult=0;
- static int immediateOpShort(Node p)
- {
- Node kid1;
- Symbol sym;
-
- assert(p);
- if (p == cacheimmOpShort)
- return cacheimmOpShortResult;
- cacheimmOpShort = p;
- cacheimmOpShortResult = LBURG_MAX;
- kid1 = p->kids[1];
- if (kid1 == NULL) return LBURG_MAX;
- if (kid1->kids[0] == NULL) return LBURG_MAX;
- if (kid1->kids[0]->kids[0] == NULL) return LBURG_MAX;
- if (kid1->kids[0]->kids[0]->kids[0] == NULL) return LBURG_MAX;
- if (kid1->kids[0]->kids[0]->kids[0]->kids[0] == NULL) return LBURG_MAX;
- if (p->kids[0] == NULL) return LBURG_MAX;
- sym = kid1->kids[0]->kids[0]->kids[0]->kids[0]->syms[0];
- if (sym == NULL) {
- sym = kid1->kids[0]->kids[0]->kids[0]->kids[0]->syms[2];
- if (sym == NULL) return LBURG_MAX;
- if (sym != p->kids[0]->syms[2] || sym->x.wildcard)
- return LBURG_MAX;
- cacheimmOpShortResult = 0;
- return 0;
- }
- if (sym != p->kids[0]->syms[0] && p->kids[0]->syms[0] == NULL) {
- sym = kid1->kids[0]->kids[0]->kids[0]->kids[0]->syms[2];
- if (sym == NULL) return LBURG_MAX;
- if (sym != p->kids[0]->syms[2] || sym->x.wildcard)
- return LBURG_MAX;
- cacheimmOpShortResult = 0;
- return 0;
- }
- if (sym == p->kids[0]->syms[0]) {
- cacheimmOpShortResult = 0;
- return 0;
- }
- return LBURG_MAX;
- }
- #if 0
- static int iszero(Node p)
- {
- if ((p->op == CNSTI || p->op == CNSTU)
- && p->syms[0] &&
- p->syms[0]->isconstant &&
- p->syms[0]->u.c.v.i == 0)
- return 0;
- return LBURG_MAX;
- }
- static int iscon8(Node p)
- {
- if ((p->op == CNSTI || p->op == CNSTU)
- && p->syms[0] && (p->syms[0]->u.value & ~0xff) == 0)
- return 0;
- return LBURG_MAX;
- }
- static int iscon16(Node p)
- {
- if ((p->op == CNSTI || p->op == CNSTU)
- && p->syms[0] && (p->syms[0]->u.c.v.i & ~0xffff) == 0)
- return 0;
- return LBURG_MAX;
- }
- #endif
- #ifndef ASM_LIB
- static int sametree(Node p,Node q)
- {
- return p == NULL && q == NULL
- || p && q && p->op == q->op && p->syms[0] == q->syms[0]
- && sametree(p->kids[0], q->kids[0])
- && sametree(p->kids[1], q->kids[1]);
- }
- #endif
-
- static void emit0(Node q)
- {
- #if 0/*_EMIT_DEBUG*/
- Node p = q;
- for (; p; p = p->x.next) {
- if (p->op == LABEL+V) {
- assert(p->syms[0]);
- fprint(2,"# %s:\n", p->syms[0]->x.name);
- } else {
- int i;
- fprint(2,"# node%c%d %s count=%d", p->x.listed ? '\'' : '#', p->x.inst,
- opname(p->op), p->count);
- for (i = 0; i < NELEMS(p->kids) && p->kids[i]; i++)
- fprint(2," #%d", p->kids[i]->x.inst);
- for (i = 0; i < NELEMS(p->syms) && p->syms[i]; i++) {
- if (p->syms[i]->x.name)
- fprint(2," %s", p->syms[i]->x.name);
- if (p->syms[i]->name != p->syms[i]->x.name)
- fprint(2," (%s)", p->syms[i]->name);
- }
- fprint(2,"\n");
- }
- }
- fprint(2,"\n--------\n");
- #endif
- emit(q);
- }
-
- static void emit2(Node p)
- {
- #define preg(f) ((f)[getregnum(p->x.kids[0])]->x.name)
-
- switch (p->op) {
- case CVCI:
- print("\tmovsbl\t%s,%s\n",
- preg(charreg),
- p->syms[RX]->x.name);
- break;
- case CVCU:
- print("\tmovzbl\t%s,%s\n",
- preg(charreg),
- p->syms[RX]->x.name);
- break;
- case CVSI:
- print("\tmovswl\t%s,%s\n",
- preg(shortreg),
- p->syms[RX]->x.name);
- break;
- case CVSU:
- print("\tmovzwl\t%s,%s\n",
- preg(shortreg),
- p->syms[RX]->x.name);
- break;
- case CVIC: case CVIS:
- case CVUC: case CVUS:
- { char *dst = shortreg[getregnum(p)]->x.name;
- char *src = preg(shortreg);
- if (dst != src)
- print("\tmovl\t%s,%s\n", src, dst);
- }
- break;
- }
- }
- static void doarg(Node p)
- {
- int roundedsize = p->syms[0]->u.c.v.i;
- Value v;
-
- roundedsize = (3 + roundedsize) & ~3;
- assert(p && p->syms[0]);
- mkactual(4, roundedsize);
- p->syms[1] = p->syms[0];
- if (roundedsize != p->syms[0]->u.c.v.i) {
- v.i = roundedsize;
- p->syms[0] = constant(inttype,v);
- }
- }
-
- static void blkfetch(int k,int off,int reg,int tmp)
- {
- }
-
- static void blkstore(int k,int off,int reg,int tmp)
- {
- }
-
- static void blkloop(int dreg,int doff,int sreg,int soff,int size,int tmps[])
- {
- }
-
- static void local(Symbol p)
- {
- if (isfloat(p->type) || p->type->op == LONGLONG)
- p->sclass = AUTO;
- if (askregvar(p, rmap[ttob(p->type)]) == 0)
- mkauto(p);
- }
-
- #define LABELFORMAT "_$"
- int inFunctionCode = 0;
- int FunctionHasCalls;
- int ExceptionExternsDeclared=0;
- int hasAllocA;
- extern int ediIsSaved,esiIsSaved;
- static void function(Symbol f,Symbol caller[],Symbol callee[],int n)
- {
- register int i;
- int IsStdCall,stackAdjust=0;
- int r;
- int mo,startOffset,um,prologueEnd;
- int saveOptimFlag;
-
- if (IntermediateLanguageFile) {
- int i;
- fprintf(ilFile,"\n");
- for (i=0; i<50;i++)
- fprintf(ilFile,"-");
- fprintf(ilFile,"Function %s\n",cfunc->name);
- }
- inFunctionCode = 0;
- saveOptimFlag = OptimizeFlag;
- if (hasExceptions)
- OptimizeFlag = 0;
- hasAllocA = 0;
- outflush();
- inFunctionCode = 1;
- usedmask[0] = usedmask[1] = 0;
- freemask[0] = freemask[1] = ~(unsigned) 0;
- SetupRegisterVariables();
-
- startOffset = offset = 4 + 4;
- for (i = 0; callee[i]; i++) {
- Symbol p = callee[i];
- Symbol q = caller[i];
- assert(q);
- p->x.offset = q->x.offset = offset;
- if (OptimizeFlag && p->sclass == REGISTER && p->x.regnode) {
- q->x = p->x;
- q->x.name = stringf("%d",p->x.offset);
- usedmask[0] |= p->x.regnode->mask;
- }
- else {
- if (p->sclass == REGISTER)
- p->sclass = AUTO;
- p->x.name = q->x.name = stringf("%d", p->x.offset);
- }
- offset += roundup(q->type->size, 4);
- }
- assert(caller[i] == 0);
- mo = offset - startOffset;
- offset = maxoffset = 0;
- if (1) {
- r = BuildBasicBlocks();
- if (r == 0) {
- ResetRegistersMasks();
- OptimizeFlag = 0;
- startOffset = offset = 4 + 4;
- for (i = 0; callee[i]; i++) {
- Symbol p = callee[i];
- Symbol q = caller[i];
- assert(q);
- p->x.offset = q->x.offset = offset;
- if (p->sclass == REGISTER)
- p->sclass = AUTO;
- p->x.name = q->x.name = stringf("%d", p->x.offset);
- p->x.regnode = NULL;
- offset += roundup(q->type->size, 4);
- }
- usedmask[0] = usedmask[1] = 0;
- freemask[0] = freemask[1] = ~(unsigned) 0;
- mo = offset - startOffset;
- offset = maxoffset = 0;
- }
- }
- gencode(caller, callee);
- AnalyzeSecondPass();
- IsStdCall = isStdCall(f);
- if (IsStdCall) {
- char fname[80];
-
- sprintf(fname,"_%s@%d",f->name,mo);
- f->x.name = stringf(fname);
- }
- print("\t.type\t%s,function\n", f->x.name);
- print("%s:\n", f->x.name);
- prologueEnd = 0;
- framesize = roundup(maxoffset, 4);
- if (hasExceptions) {
- OptimizeFlag = 0;
- print("\tpush\t%%ebp\n");
- print("\tmovl\t%%esp,%%ebp\n");
- print("\tpushl\t$-1\n");
- print("\tpushl\t$_$ExcepData\n");
- print("\tpushl\t$__except_handler3\n");
- print("\t.byte\t100\n");
- print("\t.byte\t161\n");
- print("\t.long\t0\n");
- print("\tpush\t%%eax\n");
- print("\t.byte\t100\n");
- print("\t.byte\t137\n");
- print("\t.byte\t37\n");
- print("\t.long\t0\n");
- print("\tsubl\t$12,%%esp\n");
- print("\tpushl\t%%ebx\n");
- print("\tpushl\t%%esi\n");
- print("\tpushl\t%%edi\n");
- print("\tmovl\t%%esp,-24(%%ebp)\n");
- f->x.PrologueEnd = 44;
- }
- else {
- if (hasAllocA || mo > 0 || framesize > 0) {
- print("\tpushl\t%%ebp\n");
- print("\tmovl\t%%esp,%%ebp\n");
- prologueEnd += 3;
- }
- if (framesize > 255) prologueEnd += 6;
- else if (framesize > 0) prologueEnd += 3;
- if (framesize > 0) {
- if (framesize < 4096) {
- print("\tsubl\t$%d,%%esp\n", framesize);
- }
- else {
- print("\t.extern\t__stackprobe\n");
- print("\tmovl\t$%d,%%eax\n",framesize);
- print("\tcall\t__stackprobe\n");
- prologueEnd += 4;
- }
- }
- um = usedmask[0];
- if (um & (1 << EBX)) {
- print("\tpushl\t%%ebx\n");
- prologueEnd++;
- stackAdjust += 4;
- }
- ediIsSaved = esiIsSaved = 0;
- if (um & (1 << ESI)) {
- print("\tpushl\t%%esi\n");
- esiIsSaved = 1;
- prologueEnd++;
- stackAdjust += 4;
- }
- if (um & (1 << EDI)) {
- print("\tpushl\t%%edi\n");
- if ((vmask[0] & (1 << EDI)) == 0)
- ediIsSaved = 1;
- prologueEnd++;
- stackAdjust += 4;
- }
- f->x.PrologueEnd = prologueEnd;
- }
- emitcode();
- if (hasAllocA) {
- char buf[40];
- sprintf(buf,"\tmovl\t%%%%ebp,%%%%esp\n\tsubl\t$%d,%%%%esp\n",stackAdjust+framesize);
- print(buf);
- }
- if (hasExceptions) {
- print("\txchg\t%%eax,%%ecx\n");
- print("\tmov\t-16(%%ebp),%%eax\n");
- /*
- The built-in assembler has problems with
- assembling the instruction
- mov %eax,%fs:0x0
- */
- print("\t.byte\t100\n");
- print("\t.byte\t163\n");
- print("\t.long\t0x0\n");
- print("\txchg\t%%eax,%%ecx\n");
- /* print("\tmov\t%%ecx,%%fs:__except_list\n"); */
- if (FunctionInfo.mmxCalls)
- print("\temms\n");
- print("\tpop\t%%edi\n");
- print("\tpop\t%%esi\n");
- print("\tpop\t%%ebx\n");
- print("\tleave\n");
- print("\tret\n");
- }
- else {
- if (um & (1 << EDI))
- print("\tpopl\t%%edi\n");
- if (um & (1 << ESI))
- print("\tpopl\t%%esi\n");
- if (um & (1 << EBX))
- print("\tpopl\t%%ebx\n");
- if (hasAllocA/*mo > 0*/ || framesize > 0) {
- print("\tleave\n");
- }
- else if (mo > 0)
- print("\tpopl\t%%ebp\n");
- if (FunctionInfo.mmxCalls)
- print("\temms\n");
- if (IsStdCall && mo) {
- print("\tret\t$%d\n",mo);
- }
- else print("\tret\n");
- }
- { int l = genlabel(1);
- print("%s%d:\n",LABELFORMAT, l);
- print("\t.size\t%s,%s%d-%s\n", f->x.name,LABELFORMAT, l, f->x.name);
- }
- if (hasExceptions) {
- if (!ExceptionExternsDeclared) {
- print("\t.extern\t__except_handler3\n");
- print("\t.extern\t__except_list\n");
- ExceptionExternsDeclared = 1;
- }
- hasExceptions = 0;
- }
- if (OptimizeFlag) {
- SendToOptimizer();
- }
- else
- outflush();
- inFunctionCode = 0;
- OptimizeFlag = saveOptimFlag;
- ResetRegistersMasks();
- }
-
- static void defsymbol(Symbol p)
- {
- if (p->scope >= LOCAL && p->sclass == STATIC)
- p->x.name = stringf("%s%d",LABELFORMAT, genlabel(1));
- else if (p->generated)
- p->x.name = stringf("%s%s",LABELFORMAT, p->name);
- else if (p->scope == GLOBAL || p->sclass == EXTERN) {
- if (p->Flags) {
- Type ty;
- int argsize = 0;
-
- ty = p->type;
- if (ty && ty->op == FUNCTION && ty->u.f.proto) {
- int i;
-
- for (i=0; ty->u.f.proto[i];i++) {
- if (ty->u.f.proto[i])
- argsize += roundup(ty->u.f.proto[i]->size,4);
- }
- }
- if (ty && ty->op == FUNCTION)
- p->x.name = stringf("_%s@%d",p->name,argsize);
- else
- p->x.name = stringf("_%s",p->name);
- }
- else p->x.name = stringf("_%s", p->name);
- }
- else
- p->x.name = p->name;
- }
-
- static void address(Symbol q,Symbol p,int n)
- {
- if (p->scope == GLOBAL
- || p->sclass == STATIC || p->sclass == EXTERN)
- q->x.name = stringf("%s%s%d",
- p->x.name, n >= 0 ? "+" : "", n);
- else {
- q->x.offset = p->x.offset + n;
- q->x.name = stringd(q->x.offset);
- }
- q->x.ArraySymbol = p;
- }
-
- static void defconst(int ty,Value v)
- {
- switch (ty) {
- case C:
- print("\t.byte\t%d\n", v.uc);
- return;
- case S:
- print("\t.word\t%d\n", v.ss);
- return;
- case I:
- print("\t.long\t%d\n", v.i);
- return;
- case U:
- print("\t.long\t0x%x\n", v.u);
- return;
- case P:
- print("\t.long\t0x%x\n", v.p);
- return;
- case F:
- print("\t.long\t0x%x\n", *(unsigned *) &v.f);
- return;
- case L:
- {
- double d = v.d;
- __int64 i64 = d;
- print("\t.long\t0x%x\n",(int)i64);
- print("\t.long\t0x%x\n",(int)(i64 >> 32));
- return;
- }
- case D:{
- unsigned *p = (unsigned *) &v.d;
- print("\t.long\t0x%x,0x%x\n", p[swap], p[1 - swap]);
- return;
- }
- }
- assert(0);
- }
-
- static void defaddress(Symbol p)
- {
- print("\t.long\t%s\n", p->x.name);
- }
-
- static int lastlinenr = -1;
- void PutLineNumber(int lineno)
- {
- if (lastlinenr == lineno) return;
- print("\t.line\t%d\n",lineno);
- lastlinenr = lineno;
- }
- static void defstring(int n,char *s)
- {
- int i;
-
- print("\t.byte\t%d%c",*s++,(n==1)?'\n':',');
- if (n == 1) return;
- n--;
- i = 1;
- while (n > 0) {
- if (n > 1 && (i!=15)) print("%d,",*s);
- else print("%d",*s);
- if (n > 1 && i==15) {
- print("\n\t.byte\t");
- i = 0;
- }
- else if (n == 1) print("\n");
- s++;
- n--;
- i++;
- }
- }
-
- static void export(Symbol p)
- {
- print("\t.globl\t%s\n", p->x.name);
- }
-
- static void
- import(Symbol p)
- {
- int oldseg = cseg;
-
- if (p->ref > 0 &&!IsIntrinsic(p->name)) {
- segment(0);
- print("\t.extern\t%s\n", p->x.name);
- segment(oldseg);
- }
- }
- static int ntypes;
-
- static void global (Symbol p)
- {
- int a;
-
- /*
- All definitions will start at an address multiple of four.
- I think that is all that the x86 requires.
- */
- if (p->type && p->type->op == DOUBLE)
- a = 3;
- else
- a = 2;
- print("\t.align\t%d\n",a);
- if (!p->generated) {
- print("\t.type\t%s,%s", p->x.name,
- isfunc(p->type) ? "function" : "object");
- print("\n");
- }
- if (p->u.seg == BSS) {
- if (p->sclass == STATIC)
- print("\t.lcomm\t%s,%d\n", p->x.name, p->type->size);
- else
- print("\t.comm\t%s,%d\n", p->x.name, p->type->size);
- } else {
- if (!p->generated)
- print("\t.size\t%s,%d\n", p->x.name, p->type->size);
- print("%s:\n", p->x.name);
- }
- }
-
- static void
- space(int n)
- {
- if (cseg != BSS)
- print("\t.space\t%d\n", n);
- }
-
- static char *currentfile; /* current file name */
- static void stabblock ARGS((int, int, Symbol*));
- static void stabinit ARGS((char *, int, char *[]));
- static void stabline ARGS((Coordinate *));
- static void stabsym ARGS((Symbol));
- static void stabtype ARGS((Symbol));
-
- static void asgncode ARGS((Type, int));
- static void dbxout ARGS((Type));
- static int emittype ARGS((Type, int, int));
-
- /* asgncode - assign type code to ty */
- static void asgncode(Type ty,int lev)
- {
- if (ty->x.marked || ty->x.typeno)
- return;
- ty->x.marked = 1;
- switch (ty->op) {
- case VOLATILE: case CONST: case VOLATILE+CONST:
- asgncode(ty->type, lev);
- ty->x.typeno = ty->type->x.typeno;
- break;
- case POINTER: case FUNCTION: case ARRAY:
- asgncode(ty->type, lev + 1);
- /* fall thru */
- case VOID: case CHAR: case SHORT: case INT: case UNSIGNED:
- case FLOAT: case DOUBLE:
- break;
- case STRUCT: case UNION: {
- Field p;
- for (p = fieldlist(ty); p; p = p->link)
- asgncode(p->type, lev + 1);
- /* fall thru */
- case ENUM:
- if (ty->x.typeno == 0)
- ty->x.typeno = ++ntypes;
- if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9'))
- dbxout(ty);
- break;
- }
- default:
- assert(0);
- }
- }
-
- /* dbxout - output .stabs entry for type ty */
- static void dbxout(Type ty)
- {
- }
-
-
- /* stabblock - output a stab entry for '{' or '}' at level lev */
- static void stabblock(int brace,int lev,Symbol *p)
- {
- if (brace == '{') {
- while (*p) {
- stabsym(*p++);
- }
- }
- }
-
- /* stabinit - initialize stab output */
- static void stabinit(char *file,int argc,char *argv[])
- {
- if (file && *file) {
- print("\t.file \"%s\"\n",file);
- currentfile = file;
- }
- }
-
- /* stabline - emit stab entry for source coordinate *cp */
- static void stabline(Coordinate *cp)
- {
- PutLineNumber(cp->y);
- }
-
- /* stabsym - output a code view entry for symbol p */
- static void stabsym(Symbol pSym)
- {
- int t,c,l;
- char SymbolRecord[90],*p;
-
- if (glevel == 0) return;
- if (pSym->name == NULL) return;
- if (isfunc(pSym->type) ) return;
- if (pSym->sclass == TYPEDEF) return;
- if (pSym->generated || pSym->computed)
- return;
- c = *pSym->name;
- if (c >= '0' && c <= '9') return;
- memset(SymbolRecord,0,90);
- p = SymbolRecord + 2;
-
- if (pSym->sclass == STATIC) {
- *(unsigned short *)p = 0x201;
- p += 2;
- }
- else if (pSym->scope == GLOBAL) {
- *(unsigned short *)p = 0x202; /* Public symbol */
- p += 2;
- }
- else return;
- p += 6; /* Skip offset and section until code generation */
- t = GetType(pSym);
- *(unsigned short *)p = t;
- p += 2;
- p = PutLengthPrefixedName(p,pSym->name);
- l = (p - SymbolRecord) - 2;
- p = SymbolRecord;
- *(unsigned short *)p = l;
- AddToCVData(SymbolRecord,l+2,pSym->x.name);
- }
-
- /* stabtype - output a stab entry for type *p */
- static void stabtype(Symbol p)
- {
- int c,n;
-
- if (p->src.file == NULL) {
- return; /* built in type */
- }
- if (p->uses == NULL || p->type == NULL) {
- return; /* not used */
- }
- if (p->type->x.marked == 0) return;
- if (p->sclass == TYPEDEF) c = 'T';
- else c = 't';
- n = GetFileNumber(p->src.file);
- fprintf(xrefFile,"%c %s %d %d",c,p->name,n,p->src.y);
- if (p->type->x.pointerEmitted) {
- Type ty;
-
- ty = p->type;
- if (ty) {
- if (ty->x.pointerEmitted) {
- fprintf(xrefFile," *");
- }
- }
- }
- fprintf(xrefFile,"\n");
- }
-
- static int isStdCall(Symbol f)
- {
- Type typePtr;
-
- if (f == NULL) return 0;
- if (f->Flags) return 1;
- typePtr = f->type;
- while (typePtr) {
- if (typePtr->op == STDCALL) {
- return 1;
- }
- typePtr = typePtr->type;
- }
- return 0;
- }
- extern void WriteLocalsDebugInfo(Symbol f,int lineno);
- Interface x86IR = {
- 1, 1, 0, /* char */
- 2, 2, 0, /* short */
- 4, 4, 0, /* int */
- 4, 4, 1, /* float */
- 8, 4, 1, /* double */
- 4, 4, 0, /* T * */
- 0, 1, 0, /* struct so that ARGB keeps stack aligned */
- 1, /* little_endian */
- 0, /* mulops_calls */
- 0, /* wants_callb */
- 1, /* wants_argb */
- 0, /* left_to_right */
- 0, /* wants_dag */
- address,
- blockbeg,
- blockend,
- defaddress,
- defconst,
- defstring,
- defsymbol,
- emit0,
- export,
- function,
- gen,
- global,
- import,
- local,
- progbeg,
- progend,
- segment,
- space,
- stabblock, 0, WriteLocalsDebugInfo, stabinit, stabline, stabsym, stabtype,
- {1, blkfetch, blkstore, blkloop,
- _label,
- _rule,
- _nts,
- _kids,
- _opname,
- _arity,
- _string,
- _templates,
- _isinstruction,
- _ntname,
- emit2,
- doarg,
- target,
- clobber,
- }
- };
-
-