mirror of
https://github.com/UberGames/lilium-voyager.git
synced 2025-01-05 16:30:51 +00:00
72dea0a184
* Fix many many strict aliasing warnings, now that it's re-enabled
367 lines
8 KiB
C
367 lines
8 KiB
C
#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) {
|
|
floatint_t fi;
|
|
fi.f = v.d;
|
|
print("byte 4 %u\n", fi.ui);
|
|
} 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
|
|
floatint_t temp;
|
|
|
|
temp.f = p->u.c.v.d;
|
|
p->x.name = stringf("%U", temp.ui );
|
|
}
|
|
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 ) {
|
|
size_t size;
|
|
size = 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) */
|
|
};
|