#include "c.h" #define I(f) b_##f static void I(segment)(int n) { static int cseg; if (cseg != n) switch (cseg = n) { case CODE: print("code\n"); return; case DATA: print("data\n"); return; case BSS: print("bss\n"); return; case LIT: print("lit\n"); return; default: assert(0); } } static void I(address)(Symbol q, Symbol p, long n) { q->x.name = stringf("%s%s%D", p->x.name, n > 0 ? "+" : "", n); } static void I(defaddress)(Symbol p) { print("address %s\n", p->x.name); } static void I(defconst)(int suffix, int size, Value v) { switch (suffix) { case I: if (size > sizeof (int)) print("byte %d %D\n", size, v.i); else print("byte %d %d\n", size, v.i); return; case U: if (size > sizeof (unsigned)) print("byte %d %U\n", size, v.u); else print("byte %d %u\n", size, v.u); return; case P: print("byte %d %U\n", size, (unsigned long)v.p); return; case F: if (size == 4) { float f = v.d; print("byte 4 %u\n", *(unsigned *)&f); } else { unsigned *p = (unsigned *)&v.d; print("byte 4 %u\n", p[swap]); print("byte 4 %u\n", p[1 - swap]); } return; } assert(0); } static void I(defstring)(int len, char *str) { char *s; for (s = str; s < str + len; s++) print("byte 1 %d\n", (*s)&0377); } static void I(defsymbol)(Symbol p) { if (p->scope == CONSTANTS) switch (optype(ttob(p->type))) { case I: p->x.name = stringf("%D", p->u.c.v.i); break; case U: p->x.name = stringf("%U", p->u.c.v.u); break; case P: p->x.name = stringf("%U", p->u.c.v.p); break; case F: { // JDC: added this to get inline floats unsigned temp; *(float *)&temp = p->u.c.v.d; p->x.name = stringf("%U", temp ); } break;// JDC: added this default: assert(0); } else if (p->scope >= LOCAL && p->sclass == STATIC) p->x.name = stringf("$%d", genlabel(1)); else if (p->scope == LABELS || p->generated) p->x.name = stringf("$%s", p->name); else p->x.name = p->name; } static void dumptree(Node p) { switch (specific(p->op)) { case ASGN+B: assert(p->kids[0]); assert(p->kids[1]); assert(p->syms[0]); dumptree(p->kids[0]); dumptree(p->kids[1]); print("%s %d\n", opname(p->op), p->syms[0]->u.c.v.u); return; case RET+V: assert(!p->kids[0]); assert(!p->kids[1]); print("%s\n", opname(p->op)); return; } switch (generic(p->op)) { case CNST: case ADDRG: case ADDRF: case ADDRL: case LABEL: assert(!p->kids[0]); assert(!p->kids[1]); assert(p->syms[0] && p->syms[0]->x.name); print("%s %s\n", opname(p->op), p->syms[0]->x.name); return; case CVF: case CVI: case CVP: case CVU: assert(p->kids[0]); assert(!p->kids[1]); assert(p->syms[0]); dumptree(p->kids[0]); print("%s %d\n", opname(p->op), p->syms[0]->u.c.v.i); return; case ARG: case BCOM: case NEG: case INDIR: case JUMP: case RET: assert(p->kids[0]); assert(!p->kids[1]); dumptree(p->kids[0]); print("%s\n", opname(p->op)); return; case CALL: assert(p->kids[0]); assert(!p->kids[1]); assert(optype(p->op) != B); dumptree(p->kids[0]); print("%s\n", opname(p->op)); if ( !p->count ) { printf("pop\n"); }; // JDC return; case ASGN: case BOR: case BAND: case BXOR: case RSH: case LSH: case ADD: case SUB: case DIV: case MUL: case MOD: assert(p->kids[0]); assert(p->kids[1]); dumptree(p->kids[0]); dumptree(p->kids[1]); print("%s\n", opname(p->op)); return; case EQ: case NE: case GT: case GE: case LE: case LT: assert(p->kids[0]); assert(p->kids[1]); assert(p->syms[0]); assert(p->syms[0]->x.name); dumptree(p->kids[0]); dumptree(p->kids[1]); print("%s %s\n", opname(p->op), p->syms[0]->x.name); return; } assert(0); } static void I(emit)(Node p) { for (; p; p = p->link) dumptree(p); } static void I(export)(Symbol p) { print("export %s\n", p->x.name); } static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { int i; (*IR->segment)(CODE); offset = 0; for (i = 0; caller[i] && callee[i]; i++) { offset = roundup(offset, caller[i]->type->align); caller[i]->x.name = callee[i]->x.name = stringf("%d", offset); caller[i]->x.offset = callee[i]->x.offset = offset; offset += caller[i]->type->size; } maxargoffset = maxoffset = argoffset = offset = 0; gencode(caller, callee); print("proc %s %d %d\n", f->x.name, maxoffset, maxargoffset); emitcode(); print("endproc %s %d %d\n", f->x.name, maxoffset, maxargoffset); } static void gen02(Node p) { assert(p); if (generic(p->op) == ARG) { assert(p->syms[0]); argoffset += (p->syms[0]->u.c.v.i < 4 ? 4 : p->syms[0]->u.c.v.i); } else if (generic(p->op) == CALL) { maxargoffset = (argoffset > maxargoffset ? argoffset : maxargoffset); argoffset = 0; } } static void gen01(Node p) { if (p) { gen01(p->kids[0]); gen01(p->kids[1]); gen02(p); } } static Node I(gen)(Node p) { Node q; assert(p); for (q = p; q; q = q->link) gen01(q); return p; } static void I(global)(Symbol p) { print("align %d\n", p->type->align > 4 ? 4 : p->type->align); print("LABELV %s\n", p->x.name); } static void I(import)(Symbol p) { print("import %s\n", p->x.name); } static void I(local)(Symbol p) { offset = roundup(offset, p->type->align); p->x.name = stringf("%d", offset); p->x.offset = offset; offset += p->type->size; } static void I(progbeg)(int argc, char *argv[]) {} static void I(progend)(void) {} static void I(space)(int n) { print("skip %d\n", n); } //======================================================== // JDC: hacked up to get interleaved source lines in asm code static char *sourceFile; static char *sourcePtr; static int sourceLine; static int filelength( FILE *f ) { int pos; int end; pos = ftell (f); fseek (f, 0, SEEK_END); end = ftell (f); fseek (f, pos, SEEK_SET); return end; } static void LoadSourceFile( const char *filename ) { FILE *f; int length; f = fopen( filename, "r" ); if ( !f ) { print( ";couldn't open %s\n", filename ); sourceFile = NULL; return; } length = filelength( f ); sourceFile = malloc( length + 1 ); if ( sourceFile ) { fread( sourceFile, length, 1, f ); sourceFile[length] = 0; } fclose( f ); sourceLine = 1; sourcePtr = sourceFile; } static void PrintToSourceLine( int line ) { int c; if ( !sourceFile ) { return; } while ( sourceLine <= line ) { int i; for ( i = 0 ; sourcePtr[i] && sourcePtr[i] != '\n' ; i++ ) { } c = sourcePtr[i]; if ( c == '\n' ) { sourcePtr[i] = 0; } print( ";%d:%s\n", sourceLine, sourcePtr ); if ( c == 0 ) { sourcePtr += i; // end of file } else { sourcePtr += i+1; } sourceLine++; } } static void I(stabline)(Coordinate *cp) { static char *prevfile; static int prevline; if (cp->file && (prevfile == NULL || strcmp(prevfile, cp->file) != 0)) { print("file \"%s\"\n", prevfile = cp->file); prevline = 0; if ( sourceFile ) { free( sourceFile ); sourceFile = NULL; } // load the new source file LoadSourceFile( cp->file ); } if (cp->y != prevline) { print("line %d\n", prevline = cp->y); PrintToSourceLine( cp->y ); } } //======================================================== #define b_blockbeg blockbeg #define b_blockend blockend Interface bytecodeIR = { 1, 1, 0, /* char */ 2, 2, 0, /* short */ 4, 4, 0, /* int */ 4, 4, 0, /* long */ 4, 4, 0, /* long long */ 4, 4, 0, /* float */ // JDC: use inline floats 4, 4, 0, /* double */ // JDC: don't ever emit 8 byte double code 4, 4, 0, /* long double */ // JDC: don't ever emit 8 byte double code 4, 4, 0, /* T* */ 0, 4, 0, /* struct */ 0, /* little_endian */ 0, /* mulops_calls */ 0, /* wants_callb */ 0, /* wants_argb */ 1, /* left_to_right */ 0, /* wants_dag */ 0, /* unsigned_char */ I(address), I(blockbeg), I(blockend), I(defaddress), I(defconst), I(defstring), I(defsymbol), I(emit), I(export), I(function), I(gen), I(global), I(import), I(local), I(progbeg), I(progend), I(segment), I(space), 0, /* I(stabblock) */ 0, /* I(stabend) */ 0, /* I(stabfend) */ 0, /* I(stabinit) */ I(stabline), 0, /* I(stabsym) */ 0, /* I(stabtype) */ };