blob: e628a5a99dac40e65e6f1d4199c619ff6eb58782 [file] [log] [blame]
#include "c.h"
#define I(f) b_##f
static char rcsid[] = "$Id: bytecode.c 355 2007-02-18 22:08:49Z drh $";
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 {
double d = v.d;
unsigned *p = (unsigned *)&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;
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));
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);
}
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 (cp->y != prevline)
print("line %d\n", prevline = 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, 1, /* float */
8, 8, 1, /* double */
8, 8, 1, /* long double */
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) */
};