Itsa me, quake3io!
This commit is contained in:
parent
dbe4ddb103
commit
5b755058f5
1409 changed files with 798983 additions and 798983 deletions
1110
lcc/src/2html.c
Normal file → Executable file
1110
lcc/src/2html.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
188
lcc/src/alloc.c
Normal file → Executable file
188
lcc/src/alloc.c
Normal file → Executable file
|
@ -1,94 +1,94 @@
|
|||
#include "c.h"
|
||||
struct block {
|
||||
struct block *next;
|
||||
char *limit;
|
||||
char *avail;
|
||||
};
|
||||
union align {
|
||||
long l;
|
||||
char *p;
|
||||
double d;
|
||||
int (*f)(void);
|
||||
};
|
||||
union header {
|
||||
struct block b;
|
||||
union align a;
|
||||
};
|
||||
#ifdef PURIFY
|
||||
union header *arena[3];
|
||||
|
||||
void *allocate(unsigned long n, unsigned a) {
|
||||
union header *new = malloc(sizeof *new + n);
|
||||
|
||||
assert(a < NELEMS(arena));
|
||||
if (new == NULL) {
|
||||
error("insufficient memory\n");
|
||||
exit(1);
|
||||
}
|
||||
new->b.next = (void *)arena[a];
|
||||
arena[a] = new;
|
||||
return new + 1;
|
||||
}
|
||||
|
||||
void deallocate(unsigned a) {
|
||||
union header *p, *q;
|
||||
|
||||
assert(a < NELEMS(arena));
|
||||
for (p = arena[a]; p; p = q) {
|
||||
q = (void *)p->b.next;
|
||||
free(p);
|
||||
}
|
||||
arena[a] = NULL;
|
||||
}
|
||||
|
||||
void *newarray(unsigned long m, unsigned long n, unsigned a) {
|
||||
return allocate(m*n, a);
|
||||
}
|
||||
#else
|
||||
static struct block
|
||||
first[] = { { NULL }, { NULL }, { NULL } },
|
||||
*arena[] = { &first[0], &first[1], &first[2] };
|
||||
static struct block *freeblocks;
|
||||
|
||||
void *allocate(unsigned long n, unsigned a) {
|
||||
struct block *ap;
|
||||
|
||||
assert(a < NELEMS(arena));
|
||||
assert(n > 0);
|
||||
ap = arena[a];
|
||||
n = roundup(n, sizeof (union align));
|
||||
while (n > ap->limit - ap->avail) {
|
||||
if ((ap->next = freeblocks) != NULL) {
|
||||
freeblocks = freeblocks->next;
|
||||
ap = ap->next;
|
||||
} else
|
||||
{
|
||||
unsigned m = sizeof (union header) + n + roundup(10*1024, sizeof (union align));
|
||||
ap->next = malloc(m);
|
||||
ap = ap->next;
|
||||
if (ap == NULL) {
|
||||
error("insufficient memory\n");
|
||||
exit(1);
|
||||
}
|
||||
ap->limit = (char *)ap + m;
|
||||
}
|
||||
ap->avail = (char *)((union header *)ap + 1);
|
||||
ap->next = NULL;
|
||||
arena[a] = ap;
|
||||
|
||||
}
|
||||
ap->avail += n;
|
||||
return ap->avail - n;
|
||||
}
|
||||
|
||||
void *newarray(unsigned long m, unsigned long n, unsigned a) {
|
||||
return allocate(m*n, a);
|
||||
}
|
||||
void deallocate(unsigned a) {
|
||||
assert(a < NELEMS(arena));
|
||||
arena[a]->next = freeblocks;
|
||||
freeblocks = first[a].next;
|
||||
first[a].next = NULL;
|
||||
arena[a] = &first[a];
|
||||
}
|
||||
#endif
|
||||
#include "c.h"
|
||||
struct block {
|
||||
struct block *next;
|
||||
char *limit;
|
||||
char *avail;
|
||||
};
|
||||
union align {
|
||||
long l;
|
||||
char *p;
|
||||
double d;
|
||||
int (*f)(void);
|
||||
};
|
||||
union header {
|
||||
struct block b;
|
||||
union align a;
|
||||
};
|
||||
#ifdef PURIFY
|
||||
union header *arena[3];
|
||||
|
||||
void *allocate(unsigned long n, unsigned a) {
|
||||
union header *new = malloc(sizeof *new + n);
|
||||
|
||||
assert(a < NELEMS(arena));
|
||||
if (new == NULL) {
|
||||
error("insufficient memory\n");
|
||||
exit(1);
|
||||
}
|
||||
new->b.next = (void *)arena[a];
|
||||
arena[a] = new;
|
||||
return new + 1;
|
||||
}
|
||||
|
||||
void deallocate(unsigned a) {
|
||||
union header *p, *q;
|
||||
|
||||
assert(a < NELEMS(arena));
|
||||
for (p = arena[a]; p; p = q) {
|
||||
q = (void *)p->b.next;
|
||||
free(p);
|
||||
}
|
||||
arena[a] = NULL;
|
||||
}
|
||||
|
||||
void *newarray(unsigned long m, unsigned long n, unsigned a) {
|
||||
return allocate(m*n, a);
|
||||
}
|
||||
#else
|
||||
static struct block
|
||||
first[] = { { NULL }, { NULL }, { NULL } },
|
||||
*arena[] = { &first[0], &first[1], &first[2] };
|
||||
static struct block *freeblocks;
|
||||
|
||||
void *allocate(unsigned long n, unsigned a) {
|
||||
struct block *ap;
|
||||
|
||||
assert(a < NELEMS(arena));
|
||||
assert(n > 0);
|
||||
ap = arena[a];
|
||||
n = roundup(n, sizeof (union align));
|
||||
while (n > ap->limit - ap->avail) {
|
||||
if ((ap->next = freeblocks) != NULL) {
|
||||
freeblocks = freeblocks->next;
|
||||
ap = ap->next;
|
||||
} else
|
||||
{
|
||||
unsigned m = sizeof (union header) + n + roundup(10*1024, sizeof (union align));
|
||||
ap->next = malloc(m);
|
||||
ap = ap->next;
|
||||
if (ap == NULL) {
|
||||
error("insufficient memory\n");
|
||||
exit(1);
|
||||
}
|
||||
ap->limit = (char *)ap + m;
|
||||
}
|
||||
ap->avail = (char *)((union header *)ap + 1);
|
||||
ap->next = NULL;
|
||||
arena[a] = ap;
|
||||
|
||||
}
|
||||
ap->avail += n;
|
||||
return ap->avail - n;
|
||||
}
|
||||
|
||||
void *newarray(unsigned long m, unsigned long n, unsigned a) {
|
||||
return allocate(m*n, a);
|
||||
}
|
||||
void deallocate(unsigned a) {
|
||||
assert(a < NELEMS(arena));
|
||||
arena[a]->next = freeblocks;
|
||||
freeblocks = first[a].next;
|
||||
first[a].next = NULL;
|
||||
arena[a] = &first[a];
|
||||
}
|
||||
#endif
|
||||
|
|
2384
lcc/src/alpha.md
Normal file → Executable file
2384
lcc/src/alpha.md
Normal file → Executable file
File diff suppressed because it is too large
Load diff
798
lcc/src/asdl.c
Normal file → Executable file
798
lcc/src/asdl.c
Normal file → Executable file
|
@ -1,399 +1,399 @@
|
|||
#include "c.h"
|
||||
#include "rcc.h"
|
||||
#if WIN32
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
|
||||
static list_ty interfaces;
|
||||
static rcc_program_ty pickle;
|
||||
|
||||
char *string(const char *str) {
|
||||
return (char *)Atom_string(str);
|
||||
}
|
||||
|
||||
char *stringd(long n) {
|
||||
return (char *)Atom_int(n);
|
||||
}
|
||||
|
||||
char *stringn(const char *str, int len) {
|
||||
return (char *)Atom_new(str, len);
|
||||
}
|
||||
|
||||
static void put(rcc_interface_ty node) {
|
||||
Seq_addhi(interfaces, node);
|
||||
}
|
||||
|
||||
static int typeuid(Type ty) {
|
||||
rcc_type_ty type;
|
||||
|
||||
assert(ty);
|
||||
if (ty->x.typeno != 0)
|
||||
return ty->x.typeno;
|
||||
ty->x.typeno = pickle->nuids++;
|
||||
switch (ty->op) {
|
||||
#define xx(op) case op: type = rcc_##op(ty->size, ty->align); break
|
||||
xx(INT);
|
||||
xx(UNSIGNED);
|
||||
xx(FLOAT);
|
||||
xx(VOID);
|
||||
#undef xx
|
||||
#define xx(op) case op: type = rcc_##op(ty->size, ty->align, typeuid(ty->type)); break
|
||||
xx(POINTER);
|
||||
xx(ARRAY);
|
||||
xx(CONST);
|
||||
xx(VOLATILE);
|
||||
#undef xx
|
||||
case CONST+VOLATILE:
|
||||
type = rcc_CONST(ty->size, ty->align, typeuid(ty->type));
|
||||
break;
|
||||
case ENUM: {
|
||||
list_ty ids = Seq_new(0);
|
||||
int i;
|
||||
for (i = 0; ty->u.sym->u.idlist[i] != NULL; i++)
|
||||
Seq_addhi(ids, rcc_enum_(ty->u.sym->u.idlist[i]->name,
|
||||
ty->u.sym->u.idlist[i]->u.value));
|
||||
assert(i > 0);
|
||||
type = rcc_ENUM(ty->size, ty->align, ty->u.sym->name, ids);
|
||||
break;
|
||||
}
|
||||
case STRUCT: case UNION: {
|
||||
list_ty fields = Seq_new(0);
|
||||
Field p = fieldlist(ty);
|
||||
for ( ; p != NULL; p = p->link)
|
||||
Seq_addhi(fields, rcc_field(p->name, typeuid(p->type), p->offset, p->bitsize, p->lsb));
|
||||
if (ty->op == STRUCT)
|
||||
type = rcc_STRUCT(ty->size, ty->align, ty->u.sym->name, fields);
|
||||
else
|
||||
type = rcc_UNION (ty->size, ty->align, ty->u.sym->name, fields);
|
||||
break;
|
||||
}
|
||||
case FUNCTION: {
|
||||
list_ty formals = Seq_new(0);
|
||||
if (ty->u.f.proto != NULL && ty->u.f.proto[0] != NULL) {
|
||||
int i;
|
||||
for (i = 0; ty->u.f.proto[i] != NULL; i++)
|
||||
Seq_addhi(formals, to_generic_int(typeuid(ty->u.f.proto[i])));
|
||||
} else if (ty->u.f.proto != NULL && ty->u.f.proto[0] == NULL)
|
||||
Seq_addhi(formals, to_generic_int(typeuid(voidtype)));
|
||||
type = rcc_FUNCTION(ty->size, ty->align, typeuid(ty->type), formals);
|
||||
break;
|
||||
}
|
||||
default: assert(0);
|
||||
}
|
||||
Seq_addhi(pickle->items, rcc_Type(ty->x.typeno, type));
|
||||
return ty->x.typeno;
|
||||
}
|
||||
|
||||
static int symboluid(Symbol p) {
|
||||
assert(p);
|
||||
assert(p->scope != CONSTANTS && p->scope != LABELS);
|
||||
if (p->x.offset == 0)
|
||||
p->x.offset = pickle->nuids++;
|
||||
return p->x.offset;
|
||||
}
|
||||
|
||||
static rcc_symbol_ty mk_symbol(Symbol p) {
|
||||
int flags = 0, ref = 10000*p->ref;
|
||||
|
||||
if (p->ref > 0 && ref == 0)
|
||||
ref++;
|
||||
#define xx(f,n) flags |= p->f<<n;
|
||||
xx(structarg,0)
|
||||
xx(addressed,1)
|
||||
xx(computed,2)
|
||||
xx(temporary,3)
|
||||
xx(generated,4)
|
||||
#undef xx
|
||||
return rcc_symbol(p->name, typeuid(p->type), p->scope, p->sclass, ref, flags);
|
||||
}
|
||||
|
||||
static rcc_real_ty mk_real(int size, Value v) {
|
||||
unsigned *p = (unsigned *)&v.d;
|
||||
return rcc_real(p[swap], p[1-swap]);
|
||||
}
|
||||
|
||||
static void asdl_segment(int n) {
|
||||
static int cseg;
|
||||
|
||||
if (cseg != n)
|
||||
put(rcc_Segment(cseg = n));
|
||||
}
|
||||
|
||||
static void asdl_address(Symbol q, Symbol p, long n) {
|
||||
assert(q->x.offset == 0);
|
||||
put(rcc_Address(symboluid(q), mk_symbol(q), symboluid(p), n));
|
||||
}
|
||||
|
||||
static void asdl_blockbeg(Env *e) {
|
||||
put(rcc_Blockbeg());
|
||||
}
|
||||
|
||||
static void asdl_blockend(Env *e) {
|
||||
put(rcc_Blockend());
|
||||
}
|
||||
|
||||
static void asdl_defaddress(Symbol p) {
|
||||
if (p->scope == LABELS)
|
||||
put(rcc_Deflabel(p->u.l.label));
|
||||
else
|
||||
put(rcc_Defaddress(symboluid(p)));
|
||||
}
|
||||
|
||||
static void asdl_defconst(int suffix, int size, Value v) {
|
||||
switch (suffix) {
|
||||
case I: put(rcc_Defconst(suffix, size, v.i)); return;
|
||||
case U: put(rcc_Defconst(suffix, size, v.u)); return;
|
||||
case P: put(rcc_Defconst(suffix, size, (unsigned long)v.p)); return; /* FIXME */
|
||||
case F: put(rcc_Defconstf(size, mk_real(size, v))); return;
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void asdl_defstring(int len, char *str) {
|
||||
put(rcc_Defstring(Text_box(stringn(str, len), len)));
|
||||
}
|
||||
|
||||
static void asdl_defsymbol(Symbol p) {
|
||||
if (p->scope >= GLOBAL)
|
||||
symboluid(p);
|
||||
}
|
||||
|
||||
static Symbol temps;
|
||||
|
||||
static rcc_node_ty visit(Node p) {
|
||||
Symbol q;
|
||||
rcc_node_ty left = NULL, right = NULL;
|
||||
int suffix = optype(p->op), size = opsize(p->op);
|
||||
|
||||
assert(p);
|
||||
for (q = temps; q; q = q->u.t.next)
|
||||
if (q->u.t.cse == p) {
|
||||
q->u.t.cse = NULL;
|
||||
return rcc_CSE(0, 0, symboluid(q), visit(p));
|
||||
}
|
||||
if (p->kids[0] != NULL)
|
||||
left = visit(p->kids[0]);
|
||||
if (p->kids[1] != NULL)
|
||||
right = visit(p->kids[1]);
|
||||
switch (specific(p->op)) {
|
||||
case CNST+F:
|
||||
assert(p->syms[0]);
|
||||
return rcc_CNSTF(suffix, size, mk_real(size, p->syms[0]->u.c.v));
|
||||
case CALL+B:
|
||||
assert(p->syms[0]);
|
||||
assert(p->syms[0]->type);
|
||||
return rcc_CALLB(suffix, size, left, right, typeuid(p->syms[0]->type));
|
||||
case RET+V:
|
||||
return rcc_RET(suffix, size);
|
||||
case LABEL+V:
|
||||
assert(p->syms[0]);
|
||||
return rcc_LABEL(suffix, size, p->syms[0]->u.l.label);
|
||||
}
|
||||
switch (generic(p->op)) {
|
||||
case CNST:
|
||||
assert(p->syms[0]);
|
||||
return rcc_CNST(suffix, size, p->syms[0]->u.c.v.i); /* FIXME */
|
||||
case ARG:
|
||||
assert(p->syms[0]);
|
||||
return rcc_ARG(suffix, size, left, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i);
|
||||
case ASGN:
|
||||
assert(p->syms[0]);
|
||||
assert(p->syms[1]);
|
||||
return rcc_ASGN(suffix, size, left, right, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i);
|
||||
case CVF: case CVI: case CVP: case CVU:
|
||||
assert(p->syms[0]);
|
||||
return rcc_CVT(suffix, size, generic(p->op), left, p->syms[0]->u.c.v.i);
|
||||
case CALL:
|
||||
assert(p->syms[0]);
|
||||
assert(p->syms[0]->type);
|
||||
return rcc_CALL(suffix, size, left, typeuid(p->syms[0]->type));
|
||||
#define xx(op) case op: return rcc_##op(suffix, size, symboluid(p->syms[0]))
|
||||
xx(ADDRG);
|
||||
xx(ADDRF);
|
||||
#undef xx
|
||||
case ADDRL:
|
||||
if (!p->syms[0]->defined)
|
||||
(*IR->local)(p->syms[0]);
|
||||
p->syms[0]->defined = 1;
|
||||
return rcc_ADDRL(suffix, size, symboluid(p->syms[0]));
|
||||
case JUMP:
|
||||
if (p->syms[0] != NULL)
|
||||
return rcc_BRANCH(suffix, size, p->syms[0]->u.l.label);
|
||||
return rcc_Unary(suffix, size, generic(p->op), left);
|
||||
case INDIR: case RET: case NEG: case BCOM:
|
||||
return rcc_Unary(suffix, size, generic(p->op), left);
|
||||
case BOR: case BAND: case BXOR: case RSH: case LSH:
|
||||
case ADD: case SUB: case DIV: case MUL: case MOD:
|
||||
return rcc_Binary(suffix, size, generic(p->op), left, right);
|
||||
case EQ: case NE: case GT: case GE: case LE: case LT:
|
||||
assert(p->syms[0]);
|
||||
return rcc_Compare(suffix, size, generic(p->op), left, right, p->syms[0]->u.l.label);
|
||||
}
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void asdl_emit(Node p) {}
|
||||
|
||||
static void asdl_local(Symbol p) {
|
||||
assert(p->x.offset == 0);
|
||||
put(rcc_Local(symboluid(p), mk_symbol(p)));
|
||||
if (p->temporary && p->u.t.cse) {
|
||||
p->u.t.next = temps;
|
||||
temps = p;
|
||||
}
|
||||
}
|
||||
|
||||
static Symbol pending = NULL;
|
||||
|
||||
static void dopending(Symbol p) {
|
||||
if (pending != NULL) {
|
||||
int uid = symboluid(pending);
|
||||
rcc_symbol_ty symbol = mk_symbol(pending);
|
||||
Seq_addhi(pickle->items, rcc_Symbol(uid, symbol));
|
||||
}
|
||||
pending = p;
|
||||
}
|
||||
|
||||
|
||||
static void asdl_export(Symbol p) {
|
||||
put(rcc_Export(symboluid(p)));
|
||||
}
|
||||
|
||||
static void asdl_function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
|
||||
list_ty codelist = Seq_new(0), save, calleelist = Seq_new(0), callerlist = Seq_new(0);
|
||||
int i;
|
||||
|
||||
dopending(f);
|
||||
for (i = 0; caller[i] != NULL; i++) {
|
||||
asdl_local(caller[i]);
|
||||
Seq_addhi(callerlist, to_generic_int(symboluid(caller[i])));
|
||||
}
|
||||
for (i = 0; callee[i] != NULL; i++) {
|
||||
asdl_local(callee[i]);
|
||||
Seq_addhi(calleelist, to_generic_int(symboluid(callee[i])));
|
||||
}
|
||||
save = interfaces;
|
||||
interfaces = codelist;
|
||||
gencode(caller, callee);
|
||||
asdl_segment(CODE);
|
||||
emitcode();
|
||||
interfaces = save;
|
||||
put(rcc_Function(symboluid(f), callerlist, calleelist, ncalls, codelist));
|
||||
}
|
||||
|
||||
static Node asdl_gen(Node p) {
|
||||
Node q;
|
||||
list_ty forest = Seq_new(0);
|
||||
|
||||
for (q = p; p != NULL; p = p->link)
|
||||
if (specific(p->op) == JUMP+V && specific(p->kids[0]->op) == ADDRG+P
|
||||
&& p->kids[0]->syms[0]->scope == LABELS) {
|
||||
p->syms[0] = p->kids[0]->syms[0];
|
||||
p->kids[0] = NULL;
|
||||
}
|
||||
for (p = q; p != NULL; p = p->link)
|
||||
Seq_addhi(forest, visit(p));
|
||||
put(rcc_Forest(forest));
|
||||
temps = NULL;
|
||||
return q;
|
||||
}
|
||||
|
||||
static void asdl_global(Symbol p) {
|
||||
dopending(p);
|
||||
put(rcc_Global(symboluid(p), p->u.seg));
|
||||
}
|
||||
|
||||
static void asdl_import(Symbol p) {
|
||||
dopending(p);
|
||||
put(rcc_Import(symboluid(p)));
|
||||
}
|
||||
|
||||
static void asdl_progbeg(int argc, char *argv[]) {
|
||||
int i;
|
||||
|
||||
#if WIN32
|
||||
_setmode(_fileno(stdout), _O_BINARY);
|
||||
#endif
|
||||
pickle = rcc_program(1, 0, Seq_new(0), Seq_new(0), argc, Seq_new(0));
|
||||
for (i = 0; i < argc; i++)
|
||||
Seq_addhi(pickle->argv, to_generic_string(Text_box(argv[i], strlen(argv[i]) + 1)));
|
||||
interfaces = pickle->interfaces;
|
||||
}
|
||||
|
||||
static int checkuid(list_ty list) {
|
||||
int i, n = 0, count = Seq_length(list);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
rcc_interface_ty in = Seq_get(list, i);
|
||||
if (in->kind == rcc_Local_enum
|
||||
|| in->kind == rcc_Address_enum)
|
||||
n++;
|
||||
else if (in->kind == rcc_Function_enum)
|
||||
n += checkuid(in->v.rcc_Function.codelist);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static void asdl_progend(void) {
|
||||
dopending(NULL);
|
||||
{
|
||||
int n = checkuid(pickle->interfaces) + Seq_length(pickle->items);
|
||||
if (n != pickle->nuids - 1)
|
||||
fprintf(stderr, "?bogus uid count: have %d should have %d\n",
|
||||
n, pickle->nuids-1);
|
||||
}
|
||||
pickle->nlabels = genlabel(0);
|
||||
write_int((int)(100*(assert(strstr(rcsid, ",v")), strtod(strstr(rcsid, ",v")+2, NULL))
|
||||
), stdout);
|
||||
rcc_write_program(pickle, stdout);
|
||||
}
|
||||
static void asdl_space(int n) {
|
||||
put(rcc_Space(n));
|
||||
}
|
||||
|
||||
void asdl_init(int argc, char *argv[]) {
|
||||
int i;
|
||||
static int inited;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
inited = 1;
|
||||
for (i = 1; i < argc; i++)
|
||||
if (strcmp(argv[i], "-asdl") == 0) {
|
||||
#define xx(f) IR->f = asdl_##f
|
||||
xx(address);
|
||||
xx(blockbeg);
|
||||
xx(blockend);
|
||||
xx(defaddress);
|
||||
xx(defconst);
|
||||
xx(defstring);
|
||||
xx(defsymbol);
|
||||
xx(emit);
|
||||
xx(export);
|
||||
xx(function);
|
||||
xx(gen);
|
||||
xx(global);
|
||||
xx(import);
|
||||
xx(local);
|
||||
xx(progbeg);
|
||||
xx(progend);
|
||||
xx(segment);
|
||||
xx(space);
|
||||
#undef xx
|
||||
#define xx(f) IR->f = 0
|
||||
xx(stabblock);
|
||||
xx(stabend);
|
||||
xx(stabfend);
|
||||
xx(stabinit);
|
||||
xx(stabline);
|
||||
xx(stabsym);
|
||||
xx(stabtype);
|
||||
#undef xx
|
||||
IR->wants_dag = 0;
|
||||
prunetemps = 0; /* pass2 prunes useless temps */
|
||||
assignargs = 0; /* pass2 generates caller to callee assignments */
|
||||
}
|
||||
}
|
||||
#include "c.h"
|
||||
#include "rcc.h"
|
||||
#if WIN32
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
|
||||
static list_ty interfaces;
|
||||
static rcc_program_ty pickle;
|
||||
|
||||
char *string(const char *str) {
|
||||
return (char *)Atom_string(str);
|
||||
}
|
||||
|
||||
char *stringd(long n) {
|
||||
return (char *)Atom_int(n);
|
||||
}
|
||||
|
||||
char *stringn(const char *str, int len) {
|
||||
return (char *)Atom_new(str, len);
|
||||
}
|
||||
|
||||
static void put(rcc_interface_ty node) {
|
||||
Seq_addhi(interfaces, node);
|
||||
}
|
||||
|
||||
static int typeuid(Type ty) {
|
||||
rcc_type_ty type;
|
||||
|
||||
assert(ty);
|
||||
if (ty->x.typeno != 0)
|
||||
return ty->x.typeno;
|
||||
ty->x.typeno = pickle->nuids++;
|
||||
switch (ty->op) {
|
||||
#define xx(op) case op: type = rcc_##op(ty->size, ty->align); break
|
||||
xx(INT);
|
||||
xx(UNSIGNED);
|
||||
xx(FLOAT);
|
||||
xx(VOID);
|
||||
#undef xx
|
||||
#define xx(op) case op: type = rcc_##op(ty->size, ty->align, typeuid(ty->type)); break
|
||||
xx(POINTER);
|
||||
xx(ARRAY);
|
||||
xx(CONST);
|
||||
xx(VOLATILE);
|
||||
#undef xx
|
||||
case CONST+VOLATILE:
|
||||
type = rcc_CONST(ty->size, ty->align, typeuid(ty->type));
|
||||
break;
|
||||
case ENUM: {
|
||||
list_ty ids = Seq_new(0);
|
||||
int i;
|
||||
for (i = 0; ty->u.sym->u.idlist[i] != NULL; i++)
|
||||
Seq_addhi(ids, rcc_enum_(ty->u.sym->u.idlist[i]->name,
|
||||
ty->u.sym->u.idlist[i]->u.value));
|
||||
assert(i > 0);
|
||||
type = rcc_ENUM(ty->size, ty->align, ty->u.sym->name, ids);
|
||||
break;
|
||||
}
|
||||
case STRUCT: case UNION: {
|
||||
list_ty fields = Seq_new(0);
|
||||
Field p = fieldlist(ty);
|
||||
for ( ; p != NULL; p = p->link)
|
||||
Seq_addhi(fields, rcc_field(p->name, typeuid(p->type), p->offset, p->bitsize, p->lsb));
|
||||
if (ty->op == STRUCT)
|
||||
type = rcc_STRUCT(ty->size, ty->align, ty->u.sym->name, fields);
|
||||
else
|
||||
type = rcc_UNION (ty->size, ty->align, ty->u.sym->name, fields);
|
||||
break;
|
||||
}
|
||||
case FUNCTION: {
|
||||
list_ty formals = Seq_new(0);
|
||||
if (ty->u.f.proto != NULL && ty->u.f.proto[0] != NULL) {
|
||||
int i;
|
||||
for (i = 0; ty->u.f.proto[i] != NULL; i++)
|
||||
Seq_addhi(formals, to_generic_int(typeuid(ty->u.f.proto[i])));
|
||||
} else if (ty->u.f.proto != NULL && ty->u.f.proto[0] == NULL)
|
||||
Seq_addhi(formals, to_generic_int(typeuid(voidtype)));
|
||||
type = rcc_FUNCTION(ty->size, ty->align, typeuid(ty->type), formals);
|
||||
break;
|
||||
}
|
||||
default: assert(0);
|
||||
}
|
||||
Seq_addhi(pickle->items, rcc_Type(ty->x.typeno, type));
|
||||
return ty->x.typeno;
|
||||
}
|
||||
|
||||
static int symboluid(Symbol p) {
|
||||
assert(p);
|
||||
assert(p->scope != CONSTANTS && p->scope != LABELS);
|
||||
if (p->x.offset == 0)
|
||||
p->x.offset = pickle->nuids++;
|
||||
return p->x.offset;
|
||||
}
|
||||
|
||||
static rcc_symbol_ty mk_symbol(Symbol p) {
|
||||
int flags = 0, ref = 10000*p->ref;
|
||||
|
||||
if (p->ref > 0 && ref == 0)
|
||||
ref++;
|
||||
#define xx(f,n) flags |= p->f<<n;
|
||||
xx(structarg,0)
|
||||
xx(addressed,1)
|
||||
xx(computed,2)
|
||||
xx(temporary,3)
|
||||
xx(generated,4)
|
||||
#undef xx
|
||||
return rcc_symbol(p->name, typeuid(p->type), p->scope, p->sclass, ref, flags);
|
||||
}
|
||||
|
||||
static rcc_real_ty mk_real(int size, Value v) {
|
||||
unsigned *p = (unsigned *)&v.d;
|
||||
return rcc_real(p[swap], p[1-swap]);
|
||||
}
|
||||
|
||||
static void asdl_segment(int n) {
|
||||
static int cseg;
|
||||
|
||||
if (cseg != n)
|
||||
put(rcc_Segment(cseg = n));
|
||||
}
|
||||
|
||||
static void asdl_address(Symbol q, Symbol p, long n) {
|
||||
assert(q->x.offset == 0);
|
||||
put(rcc_Address(symboluid(q), mk_symbol(q), symboluid(p), n));
|
||||
}
|
||||
|
||||
static void asdl_blockbeg(Env *e) {
|
||||
put(rcc_Blockbeg());
|
||||
}
|
||||
|
||||
static void asdl_blockend(Env *e) {
|
||||
put(rcc_Blockend());
|
||||
}
|
||||
|
||||
static void asdl_defaddress(Symbol p) {
|
||||
if (p->scope == LABELS)
|
||||
put(rcc_Deflabel(p->u.l.label));
|
||||
else
|
||||
put(rcc_Defaddress(symboluid(p)));
|
||||
}
|
||||
|
||||
static void asdl_defconst(int suffix, int size, Value v) {
|
||||
switch (suffix) {
|
||||
case I: put(rcc_Defconst(suffix, size, v.i)); return;
|
||||
case U: put(rcc_Defconst(suffix, size, v.u)); return;
|
||||
case P: put(rcc_Defconst(suffix, size, (unsigned long)v.p)); return; /* FIXME */
|
||||
case F: put(rcc_Defconstf(size, mk_real(size, v))); return;
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void asdl_defstring(int len, char *str) {
|
||||
put(rcc_Defstring(Text_box(stringn(str, len), len)));
|
||||
}
|
||||
|
||||
static void asdl_defsymbol(Symbol p) {
|
||||
if (p->scope >= GLOBAL)
|
||||
symboluid(p);
|
||||
}
|
||||
|
||||
static Symbol temps;
|
||||
|
||||
static rcc_node_ty visit(Node p) {
|
||||
Symbol q;
|
||||
rcc_node_ty left = NULL, right = NULL;
|
||||
int suffix = optype(p->op), size = opsize(p->op);
|
||||
|
||||
assert(p);
|
||||
for (q = temps; q; q = q->u.t.next)
|
||||
if (q->u.t.cse == p) {
|
||||
q->u.t.cse = NULL;
|
||||
return rcc_CSE(0, 0, symboluid(q), visit(p));
|
||||
}
|
||||
if (p->kids[0] != NULL)
|
||||
left = visit(p->kids[0]);
|
||||
if (p->kids[1] != NULL)
|
||||
right = visit(p->kids[1]);
|
||||
switch (specific(p->op)) {
|
||||
case CNST+F:
|
||||
assert(p->syms[0]);
|
||||
return rcc_CNSTF(suffix, size, mk_real(size, p->syms[0]->u.c.v));
|
||||
case CALL+B:
|
||||
assert(p->syms[0]);
|
||||
assert(p->syms[0]->type);
|
||||
return rcc_CALLB(suffix, size, left, right, typeuid(p->syms[0]->type));
|
||||
case RET+V:
|
||||
return rcc_RET(suffix, size);
|
||||
case LABEL+V:
|
||||
assert(p->syms[0]);
|
||||
return rcc_LABEL(suffix, size, p->syms[0]->u.l.label);
|
||||
}
|
||||
switch (generic(p->op)) {
|
||||
case CNST:
|
||||
assert(p->syms[0]);
|
||||
return rcc_CNST(suffix, size, p->syms[0]->u.c.v.i); /* FIXME */
|
||||
case ARG:
|
||||
assert(p->syms[0]);
|
||||
return rcc_ARG(suffix, size, left, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i);
|
||||
case ASGN:
|
||||
assert(p->syms[0]);
|
||||
assert(p->syms[1]);
|
||||
return rcc_ASGN(suffix, size, left, right, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i);
|
||||
case CVF: case CVI: case CVP: case CVU:
|
||||
assert(p->syms[0]);
|
||||
return rcc_CVT(suffix, size, generic(p->op), left, p->syms[0]->u.c.v.i);
|
||||
case CALL:
|
||||
assert(p->syms[0]);
|
||||
assert(p->syms[0]->type);
|
||||
return rcc_CALL(suffix, size, left, typeuid(p->syms[0]->type));
|
||||
#define xx(op) case op: return rcc_##op(suffix, size, symboluid(p->syms[0]))
|
||||
xx(ADDRG);
|
||||
xx(ADDRF);
|
||||
#undef xx
|
||||
case ADDRL:
|
||||
if (!p->syms[0]->defined)
|
||||
(*IR->local)(p->syms[0]);
|
||||
p->syms[0]->defined = 1;
|
||||
return rcc_ADDRL(suffix, size, symboluid(p->syms[0]));
|
||||
case JUMP:
|
||||
if (p->syms[0] != NULL)
|
||||
return rcc_BRANCH(suffix, size, p->syms[0]->u.l.label);
|
||||
return rcc_Unary(suffix, size, generic(p->op), left);
|
||||
case INDIR: case RET: case NEG: case BCOM:
|
||||
return rcc_Unary(suffix, size, generic(p->op), left);
|
||||
case BOR: case BAND: case BXOR: case RSH: case LSH:
|
||||
case ADD: case SUB: case DIV: case MUL: case MOD:
|
||||
return rcc_Binary(suffix, size, generic(p->op), left, right);
|
||||
case EQ: case NE: case GT: case GE: case LE: case LT:
|
||||
assert(p->syms[0]);
|
||||
return rcc_Compare(suffix, size, generic(p->op), left, right, p->syms[0]->u.l.label);
|
||||
}
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void asdl_emit(Node p) {}
|
||||
|
||||
static void asdl_local(Symbol p) {
|
||||
assert(p->x.offset == 0);
|
||||
put(rcc_Local(symboluid(p), mk_symbol(p)));
|
||||
if (p->temporary && p->u.t.cse) {
|
||||
p->u.t.next = temps;
|
||||
temps = p;
|
||||
}
|
||||
}
|
||||
|
||||
static Symbol pending = NULL;
|
||||
|
||||
static void dopending(Symbol p) {
|
||||
if (pending != NULL) {
|
||||
int uid = symboluid(pending);
|
||||
rcc_symbol_ty symbol = mk_symbol(pending);
|
||||
Seq_addhi(pickle->items, rcc_Symbol(uid, symbol));
|
||||
}
|
||||
pending = p;
|
||||
}
|
||||
|
||||
|
||||
static void asdl_export(Symbol p) {
|
||||
put(rcc_Export(symboluid(p)));
|
||||
}
|
||||
|
||||
static void asdl_function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
|
||||
list_ty codelist = Seq_new(0), save, calleelist = Seq_new(0), callerlist = Seq_new(0);
|
||||
int i;
|
||||
|
||||
dopending(f);
|
||||
for (i = 0; caller[i] != NULL; i++) {
|
||||
asdl_local(caller[i]);
|
||||
Seq_addhi(callerlist, to_generic_int(symboluid(caller[i])));
|
||||
}
|
||||
for (i = 0; callee[i] != NULL; i++) {
|
||||
asdl_local(callee[i]);
|
||||
Seq_addhi(calleelist, to_generic_int(symboluid(callee[i])));
|
||||
}
|
||||
save = interfaces;
|
||||
interfaces = codelist;
|
||||
gencode(caller, callee);
|
||||
asdl_segment(CODE);
|
||||
emitcode();
|
||||
interfaces = save;
|
||||
put(rcc_Function(symboluid(f), callerlist, calleelist, ncalls, codelist));
|
||||
}
|
||||
|
||||
static Node asdl_gen(Node p) {
|
||||
Node q;
|
||||
list_ty forest = Seq_new(0);
|
||||
|
||||
for (q = p; p != NULL; p = p->link)
|
||||
if (specific(p->op) == JUMP+V && specific(p->kids[0]->op) == ADDRG+P
|
||||
&& p->kids[0]->syms[0]->scope == LABELS) {
|
||||
p->syms[0] = p->kids[0]->syms[0];
|
||||
p->kids[0] = NULL;
|
||||
}
|
||||
for (p = q; p != NULL; p = p->link)
|
||||
Seq_addhi(forest, visit(p));
|
||||
put(rcc_Forest(forest));
|
||||
temps = NULL;
|
||||
return q;
|
||||
}
|
||||
|
||||
static void asdl_global(Symbol p) {
|
||||
dopending(p);
|
||||
put(rcc_Global(symboluid(p), p->u.seg));
|
||||
}
|
||||
|
||||
static void asdl_import(Symbol p) {
|
||||
dopending(p);
|
||||
put(rcc_Import(symboluid(p)));
|
||||
}
|
||||
|
||||
static void asdl_progbeg(int argc, char *argv[]) {
|
||||
int i;
|
||||
|
||||
#if WIN32
|
||||
_setmode(_fileno(stdout), _O_BINARY);
|
||||
#endif
|
||||
pickle = rcc_program(1, 0, Seq_new(0), Seq_new(0), argc, Seq_new(0));
|
||||
for (i = 0; i < argc; i++)
|
||||
Seq_addhi(pickle->argv, to_generic_string(Text_box(argv[i], strlen(argv[i]) + 1)));
|
||||
interfaces = pickle->interfaces;
|
||||
}
|
||||
|
||||
static int checkuid(list_ty list) {
|
||||
int i, n = 0, count = Seq_length(list);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
rcc_interface_ty in = Seq_get(list, i);
|
||||
if (in->kind == rcc_Local_enum
|
||||
|| in->kind == rcc_Address_enum)
|
||||
n++;
|
||||
else if (in->kind == rcc_Function_enum)
|
||||
n += checkuid(in->v.rcc_Function.codelist);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static void asdl_progend(void) {
|
||||
dopending(NULL);
|
||||
{
|
||||
int n = checkuid(pickle->interfaces) + Seq_length(pickle->items);
|
||||
if (n != pickle->nuids - 1)
|
||||
fprintf(stderr, "?bogus uid count: have %d should have %d\n",
|
||||
n, pickle->nuids-1);
|
||||
}
|
||||
pickle->nlabels = genlabel(0);
|
||||
write_int((int)(100*(assert(strstr(rcsid, ",v")), strtod(strstr(rcsid, ",v")+2, NULL))
|
||||
), stdout);
|
||||
rcc_write_program(pickle, stdout);
|
||||
}
|
||||
static void asdl_space(int n) {
|
||||
put(rcc_Space(n));
|
||||
}
|
||||
|
||||
void asdl_init(int argc, char *argv[]) {
|
||||
int i;
|
||||
static int inited;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
inited = 1;
|
||||
for (i = 1; i < argc; i++)
|
||||
if (strcmp(argv[i], "-asdl") == 0) {
|
||||
#define xx(f) IR->f = asdl_##f
|
||||
xx(address);
|
||||
xx(blockbeg);
|
||||
xx(blockend);
|
||||
xx(defaddress);
|
||||
xx(defconst);
|
||||
xx(defstring);
|
||||
xx(defsymbol);
|
||||
xx(emit);
|
||||
xx(export);
|
||||
xx(function);
|
||||
xx(gen);
|
||||
xx(global);
|
||||
xx(import);
|
||||
xx(local);
|
||||
xx(progbeg);
|
||||
xx(progend);
|
||||
xx(segment);
|
||||
xx(space);
|
||||
#undef xx
|
||||
#define xx(f) IR->f = 0
|
||||
xx(stabblock);
|
||||
xx(stabend);
|
||||
xx(stabfend);
|
||||
xx(stabinit);
|
||||
xx(stabline);
|
||||
xx(stabsym);
|
||||
xx(stabtype);
|
||||
#undef xx
|
||||
IR->wants_dag = 0;
|
||||
prunetemps = 0; /* pass2 prunes useless temps */
|
||||
assignargs = 0; /* pass2 generates caller to callee assignments */
|
||||
}
|
||||
}
|
||||
|
|
46
lcc/src/bind.c
Normal file → Executable file
46
lcc/src/bind.c
Normal file → Executable file
|
@ -1,23 +1,23 @@
|
|||
#include "c.h"
|
||||
extern Interface alphaIR;
|
||||
extern Interface mipsebIR, mipselIR;
|
||||
extern Interface sparcIR, solarisIR;
|
||||
extern Interface x86IR, x86linuxIR;
|
||||
extern Interface symbolicIR, symbolic64IR;
|
||||
extern Interface nullIR;
|
||||
extern Interface bytecodeIR;
|
||||
Binding bindings[] = {
|
||||
"alpha/osf", &alphaIR,
|
||||
"mips/irix", &mipsebIR,
|
||||
"mips/ultrix", &mipselIR,
|
||||
"sparc/sun", &sparcIR,
|
||||
"sparc/solaris", &solarisIR,
|
||||
"x86/win32", &x86IR,
|
||||
"x86/linux", &x86linuxIR,
|
||||
"symbolic/osf", &symbolic64IR,
|
||||
"symbolic/irix", &symbolicIR,
|
||||
"symbolic", &symbolicIR,
|
||||
"null", &nullIR,
|
||||
"bytecode", &bytecodeIR,
|
||||
NULL, NULL
|
||||
};
|
||||
#include "c.h"
|
||||
extern Interface alphaIR;
|
||||
extern Interface mipsebIR, mipselIR;
|
||||
extern Interface sparcIR, solarisIR;
|
||||
extern Interface x86IR, x86linuxIR;
|
||||
extern Interface symbolicIR, symbolic64IR;
|
||||
extern Interface nullIR;
|
||||
extern Interface bytecodeIR;
|
||||
Binding bindings[] = {
|
||||
"alpha/osf", &alphaIR,
|
||||
"mips/irix", &mipsebIR,
|
||||
"mips/ultrix", &mipselIR,
|
||||
"sparc/sun", &sparcIR,
|
||||
"sparc/solaris", &solarisIR,
|
||||
"x86/win32", &x86IR,
|
||||
"x86/linux", &x86linuxIR,
|
||||
"symbolic/osf", &symbolic64IR,
|
||||
"symbolic/irix", &symbolicIR,
|
||||
"symbolic", &symbolicIR,
|
||||
"null", &nullIR,
|
||||
"bytecode", &bytecodeIR,
|
||||
NULL, NULL
|
||||
};
|
||||
|
|
730
lcc/src/bytecode.c
Normal file → Executable file
730
lcc/src/bytecode.c
Normal file → Executable file
|
@ -1,365 +1,365 @@
|
|||
#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) */
|
||||
};
|
||||
#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) */
|
||||
};
|
||||
|
|
1446
lcc/src/c.h
Normal file → Executable file
1446
lcc/src/c.h
Normal file → Executable file
File diff suppressed because it is too large
Load diff
204
lcc/src/config.h
Normal file → Executable file
204
lcc/src/config.h
Normal file → Executable file
|
@ -1,102 +1,102 @@
|
|||
typedef struct {
|
||||
unsigned char max_unaligned_load;
|
||||
Symbol (*rmap)(int);
|
||||
|
||||
void (*blkfetch)(int size, int off, int reg, int tmp);
|
||||
void (*blkstore)(int size, int off, int reg, int tmp);
|
||||
void (*blkloop)(int dreg, int doff,
|
||||
int sreg, int soff,
|
||||
int size, int tmps[]);
|
||||
void (*_label)(Node);
|
||||
int (*_rule)(void*, int);
|
||||
short **_nts;
|
||||
void (*_kids)(Node, int, Node*);
|
||||
char **_string;
|
||||
char **_templates;
|
||||
char *_isinstruction;
|
||||
char **_ntname;
|
||||
void (*emit2)(Node);
|
||||
void (*doarg)(Node);
|
||||
void (*target)(Node);
|
||||
void (*clobber)(Node);
|
||||
} Xinterface;
|
||||
extern int askregvar(Symbol, Symbol);
|
||||
extern void blkcopy(int, int, int, int, int, int[]);
|
||||
extern int getregnum(Node);
|
||||
extern int mayrecalc(Node);
|
||||
extern int mkactual(int, int);
|
||||
extern void mkauto(Symbol);
|
||||
extern Symbol mkreg(char *, int, int, int);
|
||||
extern Symbol mkwildcard(Symbol *);
|
||||
extern int move(Node);
|
||||
extern int notarget(Node);
|
||||
extern void parseflags(int, char **);
|
||||
extern int range(Node, int, int);
|
||||
extern unsigned regloc(Symbol); /* omit */
|
||||
extern void rtarget(Node, int, Symbol);
|
||||
extern void setreg(Node, Symbol);
|
||||
extern void spill(unsigned, int, Node);
|
||||
extern int widens(Node);
|
||||
|
||||
extern int argoffset, maxargoffset;
|
||||
extern int bflag, dflag;
|
||||
extern int dalign, salign;
|
||||
extern int framesize;
|
||||
extern unsigned freemask[], usedmask[];
|
||||
extern int offset, maxoffset;
|
||||
extern int swap;
|
||||
extern unsigned tmask[], vmask[];
|
||||
typedef struct {
|
||||
unsigned listed:1;
|
||||
unsigned registered:1;
|
||||
unsigned emitted:1;
|
||||
unsigned copy:1;
|
||||
unsigned equatable:1;
|
||||
unsigned spills:1;
|
||||
unsigned mayrecalc:1;
|
||||
void *state;
|
||||
short inst;
|
||||
Node kids[3];
|
||||
Node prev, next;
|
||||
Node prevuse;
|
||||
short argno;
|
||||
} Xnode;
|
||||
typedef struct {
|
||||
Symbol vbl;
|
||||
short set;
|
||||
short number;
|
||||
unsigned mask;
|
||||
} *Regnode;
|
||||
enum { IREG=0, FREG=1 };
|
||||
typedef struct {
|
||||
char *name;
|
||||
unsigned int eaddr; /* omit */
|
||||
int offset;
|
||||
Node lastuse;
|
||||
int usecount;
|
||||
Regnode regnode;
|
||||
Symbol *wildcard;
|
||||
} Xsymbol;
|
||||
enum { RX=2 };
|
||||
typedef struct {
|
||||
int offset;
|
||||
unsigned freemask[2];
|
||||
} Env;
|
||||
|
||||
#define LBURG_MAX SHRT_MAX
|
||||
|
||||
enum { VREG=(44<<4) };
|
||||
|
||||
/* Exported for the front end */
|
||||
extern void blockbeg(Env *);
|
||||
extern void blockend(Env *);
|
||||
extern void emit(Node);
|
||||
extern Node gen(Node);
|
||||
|
||||
extern unsigned emitbin(Node, int);
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define debug(x) (void)0
|
||||
#else
|
||||
#define debug(x) (void)(dflag&&((x),0))
|
||||
#endif
|
||||
typedef struct {
|
||||
unsigned char max_unaligned_load;
|
||||
Symbol (*rmap)(int);
|
||||
|
||||
void (*blkfetch)(int size, int off, int reg, int tmp);
|
||||
void (*blkstore)(int size, int off, int reg, int tmp);
|
||||
void (*blkloop)(int dreg, int doff,
|
||||
int sreg, int soff,
|
||||
int size, int tmps[]);
|
||||
void (*_label)(Node);
|
||||
int (*_rule)(void*, int);
|
||||
short **_nts;
|
||||
void (*_kids)(Node, int, Node*);
|
||||
char **_string;
|
||||
char **_templates;
|
||||
char *_isinstruction;
|
||||
char **_ntname;
|
||||
void (*emit2)(Node);
|
||||
void (*doarg)(Node);
|
||||
void (*target)(Node);
|
||||
void (*clobber)(Node);
|
||||
} Xinterface;
|
||||
extern int askregvar(Symbol, Symbol);
|
||||
extern void blkcopy(int, int, int, int, int, int[]);
|
||||
extern int getregnum(Node);
|
||||
extern int mayrecalc(Node);
|
||||
extern int mkactual(int, int);
|
||||
extern void mkauto(Symbol);
|
||||
extern Symbol mkreg(char *, int, int, int);
|
||||
extern Symbol mkwildcard(Symbol *);
|
||||
extern int move(Node);
|
||||
extern int notarget(Node);
|
||||
extern void parseflags(int, char **);
|
||||
extern int range(Node, int, int);
|
||||
extern unsigned regloc(Symbol); /* omit */
|
||||
extern void rtarget(Node, int, Symbol);
|
||||
extern void setreg(Node, Symbol);
|
||||
extern void spill(unsigned, int, Node);
|
||||
extern int widens(Node);
|
||||
|
||||
extern int argoffset, maxargoffset;
|
||||
extern int bflag, dflag;
|
||||
extern int dalign, salign;
|
||||
extern int framesize;
|
||||
extern unsigned freemask[], usedmask[];
|
||||
extern int offset, maxoffset;
|
||||
extern int swap;
|
||||
extern unsigned tmask[], vmask[];
|
||||
typedef struct {
|
||||
unsigned listed:1;
|
||||
unsigned registered:1;
|
||||
unsigned emitted:1;
|
||||
unsigned copy:1;
|
||||
unsigned equatable:1;
|
||||
unsigned spills:1;
|
||||
unsigned mayrecalc:1;
|
||||
void *state;
|
||||
short inst;
|
||||
Node kids[3];
|
||||
Node prev, next;
|
||||
Node prevuse;
|
||||
short argno;
|
||||
} Xnode;
|
||||
typedef struct {
|
||||
Symbol vbl;
|
||||
short set;
|
||||
short number;
|
||||
unsigned mask;
|
||||
} *Regnode;
|
||||
enum { IREG=0, FREG=1 };
|
||||
typedef struct {
|
||||
char *name;
|
||||
unsigned int eaddr; /* omit */
|
||||
int offset;
|
||||
Node lastuse;
|
||||
int usecount;
|
||||
Regnode regnode;
|
||||
Symbol *wildcard;
|
||||
} Xsymbol;
|
||||
enum { RX=2 };
|
||||
typedef struct {
|
||||
int offset;
|
||||
unsigned freemask[2];
|
||||
} Env;
|
||||
|
||||
#define LBURG_MAX SHRT_MAX
|
||||
|
||||
enum { VREG=(44<<4) };
|
||||
|
||||
/* Exported for the front end */
|
||||
extern void blockbeg(Env *);
|
||||
extern void blockend(Env *);
|
||||
extern void emit(Node);
|
||||
extern Node gen(Node);
|
||||
|
||||
extern unsigned emitbin(Node, int);
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define debug(x) (void)0
|
||||
#else
|
||||
#define debug(x) (void)(dflag&&((x),0))
|
||||
#endif
|
||||
|
|
1470
lcc/src/dag.c
Normal file → Executable file
1470
lcc/src/dag.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
420
lcc/src/dagcheck.md
Normal file → Executable file
420
lcc/src/dagcheck.md
Normal file → Executable file
|
@ -1,210 +1,210 @@
|
|||
%{
|
||||
#include "c.h"
|
||||
typedef Node NODEPTR_TYPE;
|
||||
#define OP_LABEL(p) (specific((p)->op))
|
||||
#define LEFT_CHILD(p) ((p)->kids[0])
|
||||
#define RIGHT_CHILD(p) ((p)->kids[1])
|
||||
#define STATE_LABEL(p) ((p)->x.state)
|
||||
#define PANIC error
|
||||
%}
|
||||
%term CNSTF=17 CNSTI=21 CNSTP=23 CNSTU=22
|
||||
%term ARGB=41 ARGF=33 ARGI=37 ARGP=39 ARGU=38
|
||||
%term ASGNB=57 ASGNF=49 ASGNI=53 ASGNP=55 ASGNU=54
|
||||
%term INDIRB=73 INDIRF=65 INDIRI=69 INDIRP=71 INDIRU=70
|
||||
%term CVFF=113 CVFI=117
|
||||
%term CVIF=129 CVII=133 CVIU=134
|
||||
%term CVPP=151 CVPU=150
|
||||
%term CVUI=181 CVUP=183 CVUU=182
|
||||
%term NEGF=193 NEGI=197
|
||||
%term CALLB=217 CALLF=209 CALLI=213 CALLP=215 CALLU=214 CALLV=216
|
||||
%term RETF=241 RETI=245 RETP=247 RETU=246 RETV=248
|
||||
%term ADDRGP=263
|
||||
%term ADDRFP=279
|
||||
%term ADDRLP=295
|
||||
%term ADDF=305 ADDI=309 ADDP=311 ADDU=310
|
||||
%term SUBF=321 SUBI=325 SUBP=327 SUBU=326
|
||||
%term LSHI=341 LSHU=342
|
||||
%term MODI=357 MODU=358
|
||||
%term RSHI=373 RSHU=374
|
||||
%term BANDI=389 BANDU=390
|
||||
%term BCOMI=405 BCOMU=406
|
||||
%term BORI=421 BORU=422
|
||||
%term BXORI=437 BXORU=438
|
||||
%term DIVF=449 DIVI=453 DIVU=454
|
||||
%term MULF=465 MULI=469 MULU=470
|
||||
%term EQF=481 EQI=485 EQU=486
|
||||
%term GEF=497 GEI=501 GEU=502
|
||||
%term GTF=513 GTI=517 GTU=518
|
||||
%term LEF=529 LEI=533 LEU=534
|
||||
%term LTF=545 LTI=549 LTU=550
|
||||
%term NEF=561 NEI=565 NEU=566
|
||||
%term JUMPV=584
|
||||
%term LABELV=600
|
||||
%%
|
||||
stmt: INDIRB(P) ""
|
||||
stmt: INDIRF(P) ""
|
||||
stmt: INDIRI(P) ""
|
||||
stmt: INDIRU(P) ""
|
||||
stmt: INDIRP(P) ""
|
||||
stmt: CALLF(P) ""
|
||||
stmt: CALLI(P) ""
|
||||
stmt: CALLU(P) ""
|
||||
stmt: CALLP(P) ""
|
||||
stmt: V ""
|
||||
bogus: I "" 1
|
||||
bogus: U "" 1
|
||||
bogus: P "" 1
|
||||
bogus: F "" 1
|
||||
bogus: B "" 1
|
||||
bogus: V "" 1
|
||||
I: bogus "" 1
|
||||
U: bogus "" 1
|
||||
P: bogus "" 1
|
||||
F: bogus "" 1
|
||||
B: bogus "" 1
|
||||
V: bogus "" 1
|
||||
F: CNSTF ""
|
||||
I: CNSTI ""
|
||||
P: CNSTP ""
|
||||
U: CNSTU ""
|
||||
V: ARGB(B) ""
|
||||
V: ARGF(F) ""
|
||||
V: ARGI(I) ""
|
||||
V: ARGU(U) ""
|
||||
V: ARGP(P) ""
|
||||
V: ASGNB(P,B) ""
|
||||
V: ASGNF(P,F) ""
|
||||
V: ASGNI(P,I) ""
|
||||
V: ASGNU(P,U) ""
|
||||
V: ASGNP(P,P) ""
|
||||
B: INDIRB(P) ""
|
||||
F: INDIRF(P) ""
|
||||
I: INDIRI(P) ""
|
||||
U: INDIRU(P) ""
|
||||
P: INDIRP(P) ""
|
||||
I: CVII(I) ""
|
||||
I: CVUI(U) ""
|
||||
I: CVFI(F) ""
|
||||
U: CVIU(I) ""
|
||||
U: CVUU(U) ""
|
||||
U: CVPU(P) ""
|
||||
F: CVIF(I) ""
|
||||
F: CVFF(F) ""
|
||||
P: CVUP(U) ""
|
||||
P: CVPP(P) ""
|
||||
F: NEGF(F) ""
|
||||
I: NEGI(I) ""
|
||||
V: CALLB(P,P) ""
|
||||
F: CALLF(P) ""
|
||||
I: CALLI(P) ""
|
||||
U: CALLU(P) ""
|
||||
P: CALLP(P) ""
|
||||
V: CALLV(P) ""
|
||||
V: RETF(F) ""
|
||||
V: RETI(I) ""
|
||||
V: RETU(U) ""
|
||||
V: RETP(P) ""
|
||||
V: RETV ""
|
||||
P: ADDRGP ""
|
||||
P: ADDRFP ""
|
||||
P: ADDRLP ""
|
||||
F: ADDF(F,F) ""
|
||||
I: ADDI(I,I) ""
|
||||
P: ADDP(P,I) ""
|
||||
P: ADDP(I,P) ""
|
||||
P: ADDP(U,P) ""
|
||||
P: ADDP(P,U) ""
|
||||
U: ADDU(U,U) ""
|
||||
F: SUBF(F,F) ""
|
||||
I: SUBI(I,I) ""
|
||||
P: SUBP(P,I) ""
|
||||
P: SUBP(P,U) ""
|
||||
U: SUBU(U,U) ""
|
||||
I: LSHI(I,I) ""
|
||||
U: LSHU(U,I) ""
|
||||
I: MODI(I,I) ""
|
||||
U: MODU(U,U) ""
|
||||
I: RSHI(I,I) ""
|
||||
U: RSHU(U,I) ""
|
||||
U: BANDU(U,U) ""
|
||||
I: BANDI(I,I) ""
|
||||
U: BCOMU(U) ""
|
||||
I: BCOMI(I) ""
|
||||
I: BORI(I,I) ""
|
||||
U: BORU(U,U) ""
|
||||
U: BXORU(U,U) ""
|
||||
I: BXORI(I,I) ""
|
||||
F: DIVF(F,F) ""
|
||||
I: DIVI(I,I) ""
|
||||
U: DIVU(U,U) ""
|
||||
F: MULF(F,F) ""
|
||||
I: MULI(I,I) ""
|
||||
U: MULU(U,U) ""
|
||||
V: EQF(F,F) ""
|
||||
V: EQI(I,I) ""
|
||||
V: EQU(U,U) ""
|
||||
V: GEF(F,F) ""
|
||||
V: GEI(I,I) ""
|
||||
V: GEU(U,U) ""
|
||||
V: GTF(F,F) ""
|
||||
V: GTI(I,I) ""
|
||||
V: GTU(U,U) ""
|
||||
V: LEF(F,F) ""
|
||||
V: LEI(I,I) ""
|
||||
V: LEU(U,U) ""
|
||||
V: LTF(F,F) ""
|
||||
V: LTI(I,I) ""
|
||||
V: LTU(U,U) ""
|
||||
V: NEF(F,F) ""
|
||||
V: NEI(I,I) ""
|
||||
V: NEU(U,U) ""
|
||||
V: JUMPV(P) ""
|
||||
V: LABELV ""
|
||||
%%
|
||||
|
||||
static void reduce(NODEPTR_TYPE p, int goalnt) {
|
||||
int i, sz = opsize(p->op), rulenumber = _rule(p->x.state, goalnt);
|
||||
short *nts = _nts[rulenumber];
|
||||
NODEPTR_TYPE kids[10];
|
||||
|
||||
assert(rulenumber);
|
||||
_kids(p, rulenumber, kids);
|
||||
for (i = 0; nts[i]; i++)
|
||||
reduce(kids[i], nts[i]);
|
||||
switch (optype(p->op)) {
|
||||
#define xx(ty) if (sz == ty->size) return
|
||||
case I:
|
||||
case U:
|
||||
xx(chartype);
|
||||
xx(shorttype);
|
||||
xx(inttype);
|
||||
xx(longtype);
|
||||
xx(longlong);
|
||||
break;
|
||||
case F:
|
||||
xx(floattype);
|
||||
xx(doubletype);
|
||||
xx(longdouble);
|
||||
break;
|
||||
case P:
|
||||
xx(voidptype);
|
||||
xx(funcptype);
|
||||
break;
|
||||
case V:
|
||||
case B: if (sz == 0) return;
|
||||
#undef xx
|
||||
}
|
||||
printdag(p, 2);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void check(Node p) {
|
||||
struct _state { short cost[1]; };
|
||||
|
||||
_label(p);
|
||||
if (((struct _state *)p->x.state)->cost[1] > 0) {
|
||||
printdag(p, 2);
|
||||
assert(0);
|
||||
}
|
||||
reduce(p, 1);
|
||||
}
|
||||
%{
|
||||
#include "c.h"
|
||||
typedef Node NODEPTR_TYPE;
|
||||
#define OP_LABEL(p) (specific((p)->op))
|
||||
#define LEFT_CHILD(p) ((p)->kids[0])
|
||||
#define RIGHT_CHILD(p) ((p)->kids[1])
|
||||
#define STATE_LABEL(p) ((p)->x.state)
|
||||
#define PANIC error
|
||||
%}
|
||||
%term CNSTF=17 CNSTI=21 CNSTP=23 CNSTU=22
|
||||
%term ARGB=41 ARGF=33 ARGI=37 ARGP=39 ARGU=38
|
||||
%term ASGNB=57 ASGNF=49 ASGNI=53 ASGNP=55 ASGNU=54
|
||||
%term INDIRB=73 INDIRF=65 INDIRI=69 INDIRP=71 INDIRU=70
|
||||
%term CVFF=113 CVFI=117
|
||||
%term CVIF=129 CVII=133 CVIU=134
|
||||
%term CVPP=151 CVPU=150
|
||||
%term CVUI=181 CVUP=183 CVUU=182
|
||||
%term NEGF=193 NEGI=197
|
||||
%term CALLB=217 CALLF=209 CALLI=213 CALLP=215 CALLU=214 CALLV=216
|
||||
%term RETF=241 RETI=245 RETP=247 RETU=246 RETV=248
|
||||
%term ADDRGP=263
|
||||
%term ADDRFP=279
|
||||
%term ADDRLP=295
|
||||
%term ADDF=305 ADDI=309 ADDP=311 ADDU=310
|
||||
%term SUBF=321 SUBI=325 SUBP=327 SUBU=326
|
||||
%term LSHI=341 LSHU=342
|
||||
%term MODI=357 MODU=358
|
||||
%term RSHI=373 RSHU=374
|
||||
%term BANDI=389 BANDU=390
|
||||
%term BCOMI=405 BCOMU=406
|
||||
%term BORI=421 BORU=422
|
||||
%term BXORI=437 BXORU=438
|
||||
%term DIVF=449 DIVI=453 DIVU=454
|
||||
%term MULF=465 MULI=469 MULU=470
|
||||
%term EQF=481 EQI=485 EQU=486
|
||||
%term GEF=497 GEI=501 GEU=502
|
||||
%term GTF=513 GTI=517 GTU=518
|
||||
%term LEF=529 LEI=533 LEU=534
|
||||
%term LTF=545 LTI=549 LTU=550
|
||||
%term NEF=561 NEI=565 NEU=566
|
||||
%term JUMPV=584
|
||||
%term LABELV=600
|
||||
%%
|
||||
stmt: INDIRB(P) ""
|
||||
stmt: INDIRF(P) ""
|
||||
stmt: INDIRI(P) ""
|
||||
stmt: INDIRU(P) ""
|
||||
stmt: INDIRP(P) ""
|
||||
stmt: CALLF(P) ""
|
||||
stmt: CALLI(P) ""
|
||||
stmt: CALLU(P) ""
|
||||
stmt: CALLP(P) ""
|
||||
stmt: V ""
|
||||
bogus: I "" 1
|
||||
bogus: U "" 1
|
||||
bogus: P "" 1
|
||||
bogus: F "" 1
|
||||
bogus: B "" 1
|
||||
bogus: V "" 1
|
||||
I: bogus "" 1
|
||||
U: bogus "" 1
|
||||
P: bogus "" 1
|
||||
F: bogus "" 1
|
||||
B: bogus "" 1
|
||||
V: bogus "" 1
|
||||
F: CNSTF ""
|
||||
I: CNSTI ""
|
||||
P: CNSTP ""
|
||||
U: CNSTU ""
|
||||
V: ARGB(B) ""
|
||||
V: ARGF(F) ""
|
||||
V: ARGI(I) ""
|
||||
V: ARGU(U) ""
|
||||
V: ARGP(P) ""
|
||||
V: ASGNB(P,B) ""
|
||||
V: ASGNF(P,F) ""
|
||||
V: ASGNI(P,I) ""
|
||||
V: ASGNU(P,U) ""
|
||||
V: ASGNP(P,P) ""
|
||||
B: INDIRB(P) ""
|
||||
F: INDIRF(P) ""
|
||||
I: INDIRI(P) ""
|
||||
U: INDIRU(P) ""
|
||||
P: INDIRP(P) ""
|
||||
I: CVII(I) ""
|
||||
I: CVUI(U) ""
|
||||
I: CVFI(F) ""
|
||||
U: CVIU(I) ""
|
||||
U: CVUU(U) ""
|
||||
U: CVPU(P) ""
|
||||
F: CVIF(I) ""
|
||||
F: CVFF(F) ""
|
||||
P: CVUP(U) ""
|
||||
P: CVPP(P) ""
|
||||
F: NEGF(F) ""
|
||||
I: NEGI(I) ""
|
||||
V: CALLB(P,P) ""
|
||||
F: CALLF(P) ""
|
||||
I: CALLI(P) ""
|
||||
U: CALLU(P) ""
|
||||
P: CALLP(P) ""
|
||||
V: CALLV(P) ""
|
||||
V: RETF(F) ""
|
||||
V: RETI(I) ""
|
||||
V: RETU(U) ""
|
||||
V: RETP(P) ""
|
||||
V: RETV ""
|
||||
P: ADDRGP ""
|
||||
P: ADDRFP ""
|
||||
P: ADDRLP ""
|
||||
F: ADDF(F,F) ""
|
||||
I: ADDI(I,I) ""
|
||||
P: ADDP(P,I) ""
|
||||
P: ADDP(I,P) ""
|
||||
P: ADDP(U,P) ""
|
||||
P: ADDP(P,U) ""
|
||||
U: ADDU(U,U) ""
|
||||
F: SUBF(F,F) ""
|
||||
I: SUBI(I,I) ""
|
||||
P: SUBP(P,I) ""
|
||||
P: SUBP(P,U) ""
|
||||
U: SUBU(U,U) ""
|
||||
I: LSHI(I,I) ""
|
||||
U: LSHU(U,I) ""
|
||||
I: MODI(I,I) ""
|
||||
U: MODU(U,U) ""
|
||||
I: RSHI(I,I) ""
|
||||
U: RSHU(U,I) ""
|
||||
U: BANDU(U,U) ""
|
||||
I: BANDI(I,I) ""
|
||||
U: BCOMU(U) ""
|
||||
I: BCOMI(I) ""
|
||||
I: BORI(I,I) ""
|
||||
U: BORU(U,U) ""
|
||||
U: BXORU(U,U) ""
|
||||
I: BXORI(I,I) ""
|
||||
F: DIVF(F,F) ""
|
||||
I: DIVI(I,I) ""
|
||||
U: DIVU(U,U) ""
|
||||
F: MULF(F,F) ""
|
||||
I: MULI(I,I) ""
|
||||
U: MULU(U,U) ""
|
||||
V: EQF(F,F) ""
|
||||
V: EQI(I,I) ""
|
||||
V: EQU(U,U) ""
|
||||
V: GEF(F,F) ""
|
||||
V: GEI(I,I) ""
|
||||
V: GEU(U,U) ""
|
||||
V: GTF(F,F) ""
|
||||
V: GTI(I,I) ""
|
||||
V: GTU(U,U) ""
|
||||
V: LEF(F,F) ""
|
||||
V: LEI(I,I) ""
|
||||
V: LEU(U,U) ""
|
||||
V: LTF(F,F) ""
|
||||
V: LTI(I,I) ""
|
||||
V: LTU(U,U) ""
|
||||
V: NEF(F,F) ""
|
||||
V: NEI(I,I) ""
|
||||
V: NEU(U,U) ""
|
||||
V: JUMPV(P) ""
|
||||
V: LABELV ""
|
||||
%%
|
||||
|
||||
static void reduce(NODEPTR_TYPE p, int goalnt) {
|
||||
int i, sz = opsize(p->op), rulenumber = _rule(p->x.state, goalnt);
|
||||
short *nts = _nts[rulenumber];
|
||||
NODEPTR_TYPE kids[10];
|
||||
|
||||
assert(rulenumber);
|
||||
_kids(p, rulenumber, kids);
|
||||
for (i = 0; nts[i]; i++)
|
||||
reduce(kids[i], nts[i]);
|
||||
switch (optype(p->op)) {
|
||||
#define xx(ty) if (sz == ty->size) return
|
||||
case I:
|
||||
case U:
|
||||
xx(chartype);
|
||||
xx(shorttype);
|
||||
xx(inttype);
|
||||
xx(longtype);
|
||||
xx(longlong);
|
||||
break;
|
||||
case F:
|
||||
xx(floattype);
|
||||
xx(doubletype);
|
||||
xx(longdouble);
|
||||
break;
|
||||
case P:
|
||||
xx(voidptype);
|
||||
xx(funcptype);
|
||||
break;
|
||||
case V:
|
||||
case B: if (sz == 0) return;
|
||||
#undef xx
|
||||
}
|
||||
printdag(p, 2);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void check(Node p) {
|
||||
struct _state { short cost[1]; };
|
||||
|
||||
_label(p);
|
||||
if (((struct _state *)p->x.state)->cost[1] > 0) {
|
||||
printdag(p, 2);
|
||||
assert(0);
|
||||
}
|
||||
reduce(p, 1);
|
||||
}
|
||||
|
|
2320
lcc/src/decl.c
Normal file → Executable file
2320
lcc/src/decl.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1086
lcc/src/enode.c
Normal file → Executable file
1086
lcc/src/enode.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
274
lcc/src/error.c
Normal file → Executable file
274
lcc/src/error.c
Normal file → Executable file
|
@ -1,137 +1,137 @@
|
|||
#include "c.h"
|
||||
|
||||
|
||||
static void printtoken(void);
|
||||
int errcnt = 0;
|
||||
int errlimit = 20;
|
||||
char kind[] = {
|
||||
#define xx(a,b,c,d,e,f,g) f,
|
||||
#define yy(a,b,c,d,e,f,g) f,
|
||||
#include "token.h"
|
||||
};
|
||||
int wflag; /* != 0 to suppress warning messages */
|
||||
|
||||
void test(int tok, char set[]) {
|
||||
if (t == tok)
|
||||
t = gettok();
|
||||
else {
|
||||
expect(tok);
|
||||
skipto(tok, set);
|
||||
if (t == tok)
|
||||
t = gettok();
|
||||
}
|
||||
}
|
||||
void expect(int tok) {
|
||||
if (t == tok)
|
||||
t = gettok();
|
||||
else {
|
||||
error("syntax error; found");
|
||||
printtoken();
|
||||
fprint(stderr, " expecting `%k'\n", tok);
|
||||
}
|
||||
}
|
||||
void error(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
if (errcnt++ >= errlimit) {
|
||||
errcnt = -1;
|
||||
error("too many errors\n");
|
||||
exit(1);
|
||||
}
|
||||
va_start(ap, fmt);
|
||||
if (firstfile != file && firstfile && *firstfile)
|
||||
fprint(stderr, "%s: ", firstfile);
|
||||
fprint(stderr, "%w: ", &src);
|
||||
vfprint(stderr, NULL, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void skipto(int tok, char set[]) {
|
||||
int n;
|
||||
char *s;
|
||||
|
||||
assert(set);
|
||||
for (n = 0; t != EOI && t != tok; t = gettok()) {
|
||||
for (s = set; *s && kind[t] != *s; s++)
|
||||
;
|
||||
if (kind[t] == *s)
|
||||
break;
|
||||
if (n++ == 0)
|
||||
error("skipping");
|
||||
if (n <= 8)
|
||||
printtoken();
|
||||
else if (n == 9)
|
||||
fprint(stderr, " ...");
|
||||
}
|
||||
if (n > 8) {
|
||||
fprint(stderr, " up to");
|
||||
printtoken();
|
||||
}
|
||||
if (n > 0)
|
||||
fprint(stderr, "\n");
|
||||
}
|
||||
/* fatal - issue fatal error message and exit */
|
||||
int fatal(const char *name, const char *fmt, int n) {
|
||||
print("\n");
|
||||
errcnt = -1;
|
||||
error("compiler error in %s--", name);
|
||||
fprint(stderr, fmt, n);
|
||||
exit(EXIT_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* printtoken - print current token preceeded by a space */
|
||||
static void printtoken(void) {
|
||||
switch (t) {
|
||||
case ID: fprint(stderr, " `%s'", token); break;
|
||||
case ICON:
|
||||
fprint(stderr, " `%s'", vtoa(tsym->type, tsym->u.c.v));
|
||||
break;
|
||||
case SCON: {
|
||||
int i, n;
|
||||
if (ischar(tsym->type->type)) {
|
||||
char *s = tsym->u.c.v.p;
|
||||
n = tsym->type->size;
|
||||
fprint(stderr, " \"");
|
||||
for (i = 0; i < 20 && i < n && *s; s++, i++)
|
||||
if (*s < ' ' || *s >= 0177)
|
||||
fprint(stderr, "\\%o", *s);
|
||||
else
|
||||
fprint(stderr, "%c", *s);
|
||||
} else { /* wchar_t string */
|
||||
unsigned int *s = tsym->u.c.v.p;
|
||||
assert(tsym->type->type->size == widechar->size);
|
||||
n = tsym->type->size/widechar->size;
|
||||
fprint(stderr, " L\"");
|
||||
for (i = 0; i < 20 && i < n && *s; s++, i++)
|
||||
if (*s < ' ' || *s >= 0177)
|
||||
fprint(stderr, "\\x%x", *s);
|
||||
else
|
||||
fprint(stderr, "%c", *s);
|
||||
}
|
||||
if (i < n)
|
||||
fprint(stderr, " ...");
|
||||
else
|
||||
fprint(stderr, "\"");
|
||||
break;
|
||||
}
|
||||
case FCON:
|
||||
fprint(stderr, " `%S'", token, (char*)cp - token);
|
||||
break;
|
||||
case '`': case '\'': fprint(stderr, " \"%k\"", t); break;
|
||||
default: fprint(stderr, " `%k'", t);
|
||||
}
|
||||
}
|
||||
|
||||
/* warning - issue warning error message */
|
||||
void warning(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
if (wflag == 0) {
|
||||
errcnt--;
|
||||
error("warning: ");
|
||||
vfprint(stderr, NULL, fmt, ap);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
#include "c.h"
|
||||
|
||||
|
||||
static void printtoken(void);
|
||||
int errcnt = 0;
|
||||
int errlimit = 20;
|
||||
char kind[] = {
|
||||
#define xx(a,b,c,d,e,f,g) f,
|
||||
#define yy(a,b,c,d,e,f,g) f,
|
||||
#include "token.h"
|
||||
};
|
||||
int wflag; /* != 0 to suppress warning messages */
|
||||
|
||||
void test(int tok, char set[]) {
|
||||
if (t == tok)
|
||||
t = gettok();
|
||||
else {
|
||||
expect(tok);
|
||||
skipto(tok, set);
|
||||
if (t == tok)
|
||||
t = gettok();
|
||||
}
|
||||
}
|
||||
void expect(int tok) {
|
||||
if (t == tok)
|
||||
t = gettok();
|
||||
else {
|
||||
error("syntax error; found");
|
||||
printtoken();
|
||||
fprint(stderr, " expecting `%k'\n", tok);
|
||||
}
|
||||
}
|
||||
void error(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
if (errcnt++ >= errlimit) {
|
||||
errcnt = -1;
|
||||
error("too many errors\n");
|
||||
exit(1);
|
||||
}
|
||||
va_start(ap, fmt);
|
||||
if (firstfile != file && firstfile && *firstfile)
|
||||
fprint(stderr, "%s: ", firstfile);
|
||||
fprint(stderr, "%w: ", &src);
|
||||
vfprint(stderr, NULL, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void skipto(int tok, char set[]) {
|
||||
int n;
|
||||
char *s;
|
||||
|
||||
assert(set);
|
||||
for (n = 0; t != EOI && t != tok; t = gettok()) {
|
||||
for (s = set; *s && kind[t] != *s; s++)
|
||||
;
|
||||
if (kind[t] == *s)
|
||||
break;
|
||||
if (n++ == 0)
|
||||
error("skipping");
|
||||
if (n <= 8)
|
||||
printtoken();
|
||||
else if (n == 9)
|
||||
fprint(stderr, " ...");
|
||||
}
|
||||
if (n > 8) {
|
||||
fprint(stderr, " up to");
|
||||
printtoken();
|
||||
}
|
||||
if (n > 0)
|
||||
fprint(stderr, "\n");
|
||||
}
|
||||
/* fatal - issue fatal error message and exit */
|
||||
int fatal(const char *name, const char *fmt, int n) {
|
||||
print("\n");
|
||||
errcnt = -1;
|
||||
error("compiler error in %s--", name);
|
||||
fprint(stderr, fmt, n);
|
||||
exit(EXIT_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* printtoken - print current token preceeded by a space */
|
||||
static void printtoken(void) {
|
||||
switch (t) {
|
||||
case ID: fprint(stderr, " `%s'", token); break;
|
||||
case ICON:
|
||||
fprint(stderr, " `%s'", vtoa(tsym->type, tsym->u.c.v));
|
||||
break;
|
||||
case SCON: {
|
||||
int i, n;
|
||||
if (ischar(tsym->type->type)) {
|
||||
char *s = tsym->u.c.v.p;
|
||||
n = tsym->type->size;
|
||||
fprint(stderr, " \"");
|
||||
for (i = 0; i < 20 && i < n && *s; s++, i++)
|
||||
if (*s < ' ' || *s >= 0177)
|
||||
fprint(stderr, "\\%o", *s);
|
||||
else
|
||||
fprint(stderr, "%c", *s);
|
||||
} else { /* wchar_t string */
|
||||
unsigned int *s = tsym->u.c.v.p;
|
||||
assert(tsym->type->type->size == widechar->size);
|
||||
n = tsym->type->size/widechar->size;
|
||||
fprint(stderr, " L\"");
|
||||
for (i = 0; i < 20 && i < n && *s; s++, i++)
|
||||
if (*s < ' ' || *s >= 0177)
|
||||
fprint(stderr, "\\x%x", *s);
|
||||
else
|
||||
fprint(stderr, "%c", *s);
|
||||
}
|
||||
if (i < n)
|
||||
fprint(stderr, " ...");
|
||||
else
|
||||
fprint(stderr, "\"");
|
||||
break;
|
||||
}
|
||||
case FCON:
|
||||
fprint(stderr, " `%S'", token, (char*)cp - token);
|
||||
break;
|
||||
case '`': case '\'': fprint(stderr, " \"%k\"", t); break;
|
||||
default: fprint(stderr, " `%k'", t);
|
||||
}
|
||||
}
|
||||
|
||||
/* warning - issue warning error message */
|
||||
void warning(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
if (wflag == 0) {
|
||||
errcnt--;
|
||||
error("warning: ");
|
||||
vfprint(stderr, NULL, fmt, ap);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
|
56
lcc/src/event.c
Normal file → Executable file
56
lcc/src/event.c
Normal file → Executable file
|
@ -1,28 +1,28 @@
|
|||
#include "c.h"
|
||||
|
||||
|
||||
struct entry {
|
||||
Apply func;
|
||||
void *cl;
|
||||
};
|
||||
|
||||
Events events;
|
||||
void attach(Apply func, void *cl, List *list) {
|
||||
struct entry *p;
|
||||
|
||||
NEW(p, PERM);
|
||||
p->func = func;
|
||||
p->cl = cl;
|
||||
*list = append(p, *list);
|
||||
}
|
||||
void apply(List event, void *arg1, void *arg2) {
|
||||
if (event) {
|
||||
List lp = event;
|
||||
do {
|
||||
struct entry *p = lp->x;
|
||||
(*p->func)(p->cl, arg1, arg2);
|
||||
lp = lp->link;
|
||||
} while (lp != event);
|
||||
}
|
||||
}
|
||||
|
||||
#include "c.h"
|
||||
|
||||
|
||||
struct entry {
|
||||
Apply func;
|
||||
void *cl;
|
||||
};
|
||||
|
||||
Events events;
|
||||
void attach(Apply func, void *cl, List *list) {
|
||||
struct entry *p;
|
||||
|
||||
NEW(p, PERM);
|
||||
p->func = func;
|
||||
p->cl = cl;
|
||||
*list = append(p, *list);
|
||||
}
|
||||
void apply(List event, void *arg1, void *arg2) {
|
||||
if (event) {
|
||||
List lp = event;
|
||||
do {
|
||||
struct entry *p = lp->x;
|
||||
(*p->func)(p->cl, arg1, arg2);
|
||||
lp = lp->link;
|
||||
} while (lp != event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
1418
lcc/src/expr.c
Normal file → Executable file
1418
lcc/src/expr.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1660
lcc/src/gen.c
Normal file → Executable file
1660
lcc/src/gen.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
636
lcc/src/init.c
Normal file → Executable file
636
lcc/src/init.c
Normal file → Executable file
|
@ -1,318 +1,318 @@
|
|||
#include "c.h"
|
||||
|
||||
|
||||
static int curseg; /* current segment */
|
||||
|
||||
/* defpointer - initialize a pointer to p or to 0 if p==0 */
|
||||
void defpointer(Symbol p) {
|
||||
if (p) {
|
||||
(*IR->defaddress)(p);
|
||||
p->ref++;
|
||||
} else {
|
||||
static Value v;
|
||||
(*IR->defconst)(P, voidptype->size, v);
|
||||
}
|
||||
}
|
||||
|
||||
/* genconst - generate/check constant expression e; return size */
|
||||
static int genconst(Tree e, int def) {
|
||||
for (;;)
|
||||
switch (generic(e->op)) {
|
||||
case ADDRG:
|
||||
if (def)
|
||||
(*IR->defaddress)(e->u.sym);
|
||||
return e->type->size;
|
||||
case CNST:
|
||||
if (e->op == CNST+P && isarray(e->type)) {
|
||||
e = cvtconst(e);
|
||||
continue;
|
||||
}
|
||||
if (def)
|
||||
(*IR->defconst)(e->type->op, e->type->size, e->u.v);
|
||||
return e->type->size;
|
||||
case RIGHT:
|
||||
assert(e->kids[0] || e->kids[1]);
|
||||
if (e->kids[1] && e->kids[0])
|
||||
error("initializer must be constant\n");
|
||||
e = e->kids[1] ? e->kids[1] : e->kids[0];
|
||||
continue;
|
||||
case CVP:
|
||||
if (isarith(e->type))
|
||||
error("cast from `%t' to `%t' is illegal in constant expressions\n",
|
||||
e->kids[0]->type, e->type);
|
||||
/* fall thru */
|
||||
case CVI: case CVU: case CVF:
|
||||
e = e->kids[0];
|
||||
continue;
|
||||
default:
|
||||
error("initializer must be constant\n");
|
||||
if (def)
|
||||
genconst(consttree(0, inttype), def);
|
||||
return inttype->size;
|
||||
}
|
||||
}
|
||||
|
||||
/* initvalue - evaluate a constant expression for a value of integer type ty */
|
||||
static Tree initvalue(Type ty) {
|
||||
Type aty;
|
||||
Tree e;
|
||||
|
||||
needconst++;
|
||||
e = expr1(0);
|
||||
if ((aty = assign(ty, e)) != NULL)
|
||||
e = cast(e, aty);
|
||||
else {
|
||||
error("invalid initialization type; found `%t' expected `%t'\n",
|
||||
e->type, ty);
|
||||
e = retype(consttree(0, inttype), ty);
|
||||
}
|
||||
needconst--;
|
||||
if (generic(e->op) != CNST) {
|
||||
error("initializer must be constant\n");
|
||||
e = retype(consttree(0, inttype), ty);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
/* initarray - initialize array of ty of <= len bytes; if len == 0, go to } */
|
||||
static int initarray(int len, Type ty, int lev) {
|
||||
int n = 0;
|
||||
|
||||
do {
|
||||
initializer(ty, lev);
|
||||
n += ty->size;
|
||||
if (len > 0 && n >= len || t != ',')
|
||||
break;
|
||||
t = gettok();
|
||||
} while (t != '}');
|
||||
return n;
|
||||
}
|
||||
|
||||
/* initchar - initialize array of <= len ty characters; if len == 0, go to } */
|
||||
static int initchar(int len, Type ty) {
|
||||
int n = 0;
|
||||
char buf[16], *s = buf;
|
||||
|
||||
do {
|
||||
*s++ = initvalue(ty)->u.v.i;
|
||||
if (++n%inttype->size == 0) {
|
||||
(*IR->defstring)(inttype->size, buf);
|
||||
s = buf;
|
||||
}
|
||||
if (len > 0 && n >= len || t != ',')
|
||||
break;
|
||||
t = gettok();
|
||||
} while (t != '}');
|
||||
if (s > buf)
|
||||
(*IR->defstring)(s - buf, buf);
|
||||
return n;
|
||||
}
|
||||
|
||||
/* initend - finish off an initialization at level lev; accepts trailing comma */
|
||||
static void initend(int lev, char follow[]) {
|
||||
if (lev == 0 && t == ',')
|
||||
t = gettok();
|
||||
test('}', follow);
|
||||
}
|
||||
|
||||
/* initfields - initialize <= an unsigned's worth of bit fields in fields p to q */
|
||||
static int initfields(Field p, Field q) {
|
||||
unsigned int bits = 0;
|
||||
int i, n = 0;
|
||||
|
||||
do {
|
||||
i = initvalue(inttype)->u.v.i;
|
||||
if (fieldsize(p) < 8*p->type->size) {
|
||||
if (p->type == inttype &&
|
||||
(i < -(int)(fieldmask(p)>>1)-1 || i > (int)(fieldmask(p)>>1))
|
||||
|| p->type == unsignedtype && (i&~fieldmask(p)) != 0)
|
||||
warning("initializer exceeds bit-field width\n");
|
||||
i &= fieldmask(p);
|
||||
}
|
||||
bits |= i<<fieldright(p);
|
||||
if (IR->little_endian) {
|
||||
if (fieldsize(p) + fieldright(p) > n)
|
||||
n = fieldsize(p) + fieldright(p);
|
||||
} else {
|
||||
if (fieldsize(p) + fieldleft(p) > n)
|
||||
n = fieldsize(p) + fieldleft(p);
|
||||
}
|
||||
if (p->link == q)
|
||||
break;
|
||||
p = p->link;
|
||||
} while (t == ',' && (t = gettok()) != 0);
|
||||
n = (n + 7)/8;
|
||||
for (i = 0; i < n; i++) {
|
||||
Value v;
|
||||
if (IR->little_endian) {
|
||||
v.u = (unsigned char)bits;
|
||||
bits >>= 8;
|
||||
} else { /* a big endian */
|
||||
v.u = (unsigned char)(bits>>(8*(unsignedtype->size - 1)));
|
||||
bits <<= 8;
|
||||
}
|
||||
(*IR->defconst)(U, unsignedchar->size, v);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* initstruct - initialize a struct ty of <= len bytes; if len == 0, go to } */
|
||||
static int initstruct(int len, Type ty, int lev) {
|
||||
int a, n = 0;
|
||||
Field p = ty->u.sym->u.s.flist;
|
||||
|
||||
do {
|
||||
if (p->offset > n) {
|
||||
(*IR->space)(p->offset - n);
|
||||
n += p->offset - n;
|
||||
}
|
||||
if (p->lsb) {
|
||||
Field q = p;
|
||||
while (q->link && q->link->offset == p->offset)
|
||||
q = q->link;
|
||||
n += initfields(p, q->link);
|
||||
p = q;
|
||||
} else {
|
||||
initializer(p->type, lev);
|
||||
n += p->type->size;
|
||||
}
|
||||
if (p->link) {
|
||||
p = p->link;
|
||||
a = p->type->align;
|
||||
} else
|
||||
a = ty->align;
|
||||
if (a && n%a) {
|
||||
(*IR->space)(a - n%a);
|
||||
n = roundup(n, a);
|
||||
}
|
||||
if (len > 0 && n >= len || t != ',')
|
||||
break;
|
||||
t = gettok();
|
||||
} while (t != '}');
|
||||
return n;
|
||||
}
|
||||
|
||||
/* initializer - constexpr | { constexpr ( , constexpr )* [ , ] } */
|
||||
Type initializer(Type ty, int lev) {
|
||||
int n = 0;
|
||||
Tree e;
|
||||
Type aty = NULL;
|
||||
static char follow[] = { IF, CHAR, STATIC, 0 };
|
||||
|
||||
ty = unqual(ty);
|
||||
if (isscalar(ty)) {
|
||||
needconst++;
|
||||
if (t == '{') {
|
||||
t = gettok();
|
||||
e = expr1(0);
|
||||
initend(lev, follow);
|
||||
} else
|
||||
e = expr1(0);
|
||||
e = pointer(e);
|
||||
if ((aty = assign(ty, e)) != NULL)
|
||||
e = cast(e, aty);
|
||||
else
|
||||
error("invalid initialization type; found `%t' expected `%t'\n",
|
||||
e->type, ty);
|
||||
n = genconst(e, 1);
|
||||
deallocate(STMT);
|
||||
needconst--;
|
||||
}
|
||||
if ((isunion(ty) || isstruct(ty)) && ty->size == 0) {
|
||||
static char follow[] = { CHAR, STATIC, 0 };
|
||||
error("cannot initialize undefined `%t'\n", ty);
|
||||
skipto(';', follow);
|
||||
return ty;
|
||||
} else if (isunion(ty)) {
|
||||
if (t == '{') {
|
||||
t = gettok();
|
||||
n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
|
||||
initend(lev, follow);
|
||||
} else {
|
||||
if (lev == 0)
|
||||
error("missing { in initialization of `%t'\n", ty);
|
||||
n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
|
||||
}
|
||||
} else if (isstruct(ty)) {
|
||||
if (t == '{') {
|
||||
t = gettok();
|
||||
n = initstruct(0, ty, lev + 1);
|
||||
test('}', follow);
|
||||
} else if (lev > 0)
|
||||
n = initstruct(ty->size, ty, lev + 1);
|
||||
else {
|
||||
error("missing { in initialization of `%t'\n", ty);
|
||||
n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
|
||||
}
|
||||
}
|
||||
if (isarray(ty))
|
||||
aty = unqual(ty->type);
|
||||
if (isarray(ty) && ischar(aty)) {
|
||||
if (t == SCON) {
|
||||
if (ty->size > 0 && ty->size == tsym->type->size - 1)
|
||||
tsym->type = array(chartype, ty->size, 0);
|
||||
n = tsym->type->size;
|
||||
(*IR->defstring)(tsym->type->size, tsym->u.c.v.p);
|
||||
t = gettok();
|
||||
} else if (t == '{') {
|
||||
t = gettok();
|
||||
if (t == SCON) {
|
||||
ty = initializer(ty, lev + 1);
|
||||
initend(lev, follow);
|
||||
return ty;
|
||||
}
|
||||
n = initchar(0, aty);
|
||||
test('}', follow);
|
||||
} else if (lev > 0 && ty->size > 0)
|
||||
n = initchar(ty->size, aty);
|
||||
else { /* eg, char c[] = 0; */
|
||||
error("missing { in initialization of `%t'\n", ty);
|
||||
n = initchar(1, aty);
|
||||
}
|
||||
} else if (isarray(ty)) {
|
||||
if (t == SCON && aty == widechar) {
|
||||
int i;
|
||||
unsigned int *s = tsym->u.c.v.p;
|
||||
if (ty->size > 0 && ty->size == tsym->type->size - widechar->size)
|
||||
tsym->type = array(widechar, ty->size/widechar->size, 0);
|
||||
n = tsym->type->size;
|
||||
for (i = 0; i < n; i += widechar->size) {
|
||||
Value v;
|
||||
v.u = *s++;
|
||||
(*IR->defconst)(widechar->op, widechar->size, v);
|
||||
}
|
||||
t = gettok();
|
||||
} else if (t == '{') {
|
||||
t = gettok();
|
||||
if (t == SCON && aty == widechar) {
|
||||
ty = initializer(ty, lev + 1);
|
||||
initend(lev, follow);
|
||||
return ty;
|
||||
}
|
||||
n = initarray(0, aty, lev + 1);
|
||||
test('}', follow);
|
||||
} else if (lev > 0 && ty->size > 0)
|
||||
n = initarray(ty->size, aty, lev + 1);
|
||||
else {
|
||||
error("missing { in initialization of `%t'\n", ty);
|
||||
n = initarray(aty->size, aty, lev + 1);
|
||||
}
|
||||
}
|
||||
if (ty->size) {
|
||||
if (n > ty->size)
|
||||
error("too many initializers\n");
|
||||
else if (n < ty->size)
|
||||
(*IR->space)(ty->size - n);
|
||||
} else if (isarray(ty) && ty->type->size > 0)
|
||||
ty = array(ty->type, n/ty->type->size, 0);
|
||||
else
|
||||
ty->size = n;
|
||||
return ty;
|
||||
}
|
||||
|
||||
/* swtoseg - switch to segment seg, if necessary */
|
||||
void swtoseg(int seg) {
|
||||
if (curseg != seg)
|
||||
(*IR->segment)(seg);
|
||||
curseg = seg;
|
||||
}
|
||||
#include "c.h"
|
||||
|
||||
|
||||
static int curseg; /* current segment */
|
||||
|
||||
/* defpointer - initialize a pointer to p or to 0 if p==0 */
|
||||
void defpointer(Symbol p) {
|
||||
if (p) {
|
||||
(*IR->defaddress)(p);
|
||||
p->ref++;
|
||||
} else {
|
||||
static Value v;
|
||||
(*IR->defconst)(P, voidptype->size, v);
|
||||
}
|
||||
}
|
||||
|
||||
/* genconst - generate/check constant expression e; return size */
|
||||
static int genconst(Tree e, int def) {
|
||||
for (;;)
|
||||
switch (generic(e->op)) {
|
||||
case ADDRG:
|
||||
if (def)
|
||||
(*IR->defaddress)(e->u.sym);
|
||||
return e->type->size;
|
||||
case CNST:
|
||||
if (e->op == CNST+P && isarray(e->type)) {
|
||||
e = cvtconst(e);
|
||||
continue;
|
||||
}
|
||||
if (def)
|
||||
(*IR->defconst)(e->type->op, e->type->size, e->u.v);
|
||||
return e->type->size;
|
||||
case RIGHT:
|
||||
assert(e->kids[0] || e->kids[1]);
|
||||
if (e->kids[1] && e->kids[0])
|
||||
error("initializer must be constant\n");
|
||||
e = e->kids[1] ? e->kids[1] : e->kids[0];
|
||||
continue;
|
||||
case CVP:
|
||||
if (isarith(e->type))
|
||||
error("cast from `%t' to `%t' is illegal in constant expressions\n",
|
||||
e->kids[0]->type, e->type);
|
||||
/* fall thru */
|
||||
case CVI: case CVU: case CVF:
|
||||
e = e->kids[0];
|
||||
continue;
|
||||
default:
|
||||
error("initializer must be constant\n");
|
||||
if (def)
|
||||
genconst(consttree(0, inttype), def);
|
||||
return inttype->size;
|
||||
}
|
||||
}
|
||||
|
||||
/* initvalue - evaluate a constant expression for a value of integer type ty */
|
||||
static Tree initvalue(Type ty) {
|
||||
Type aty;
|
||||
Tree e;
|
||||
|
||||
needconst++;
|
||||
e = expr1(0);
|
||||
if ((aty = assign(ty, e)) != NULL)
|
||||
e = cast(e, aty);
|
||||
else {
|
||||
error("invalid initialization type; found `%t' expected `%t'\n",
|
||||
e->type, ty);
|
||||
e = retype(consttree(0, inttype), ty);
|
||||
}
|
||||
needconst--;
|
||||
if (generic(e->op) != CNST) {
|
||||
error("initializer must be constant\n");
|
||||
e = retype(consttree(0, inttype), ty);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
/* initarray - initialize array of ty of <= len bytes; if len == 0, go to } */
|
||||
static int initarray(int len, Type ty, int lev) {
|
||||
int n = 0;
|
||||
|
||||
do {
|
||||
initializer(ty, lev);
|
||||
n += ty->size;
|
||||
if (len > 0 && n >= len || t != ',')
|
||||
break;
|
||||
t = gettok();
|
||||
} while (t != '}');
|
||||
return n;
|
||||
}
|
||||
|
||||
/* initchar - initialize array of <= len ty characters; if len == 0, go to } */
|
||||
static int initchar(int len, Type ty) {
|
||||
int n = 0;
|
||||
char buf[16], *s = buf;
|
||||
|
||||
do {
|
||||
*s++ = initvalue(ty)->u.v.i;
|
||||
if (++n%inttype->size == 0) {
|
||||
(*IR->defstring)(inttype->size, buf);
|
||||
s = buf;
|
||||
}
|
||||
if (len > 0 && n >= len || t != ',')
|
||||
break;
|
||||
t = gettok();
|
||||
} while (t != '}');
|
||||
if (s > buf)
|
||||
(*IR->defstring)(s - buf, buf);
|
||||
return n;
|
||||
}
|
||||
|
||||
/* initend - finish off an initialization at level lev; accepts trailing comma */
|
||||
static void initend(int lev, char follow[]) {
|
||||
if (lev == 0 && t == ',')
|
||||
t = gettok();
|
||||
test('}', follow);
|
||||
}
|
||||
|
||||
/* initfields - initialize <= an unsigned's worth of bit fields in fields p to q */
|
||||
static int initfields(Field p, Field q) {
|
||||
unsigned int bits = 0;
|
||||
int i, n = 0;
|
||||
|
||||
do {
|
||||
i = initvalue(inttype)->u.v.i;
|
||||
if (fieldsize(p) < 8*p->type->size) {
|
||||
if (p->type == inttype &&
|
||||
(i < -(int)(fieldmask(p)>>1)-1 || i > (int)(fieldmask(p)>>1))
|
||||
|| p->type == unsignedtype && (i&~fieldmask(p)) != 0)
|
||||
warning("initializer exceeds bit-field width\n");
|
||||
i &= fieldmask(p);
|
||||
}
|
||||
bits |= i<<fieldright(p);
|
||||
if (IR->little_endian) {
|
||||
if (fieldsize(p) + fieldright(p) > n)
|
||||
n = fieldsize(p) + fieldright(p);
|
||||
} else {
|
||||
if (fieldsize(p) + fieldleft(p) > n)
|
||||
n = fieldsize(p) + fieldleft(p);
|
||||
}
|
||||
if (p->link == q)
|
||||
break;
|
||||
p = p->link;
|
||||
} while (t == ',' && (t = gettok()) != 0);
|
||||
n = (n + 7)/8;
|
||||
for (i = 0; i < n; i++) {
|
||||
Value v;
|
||||
if (IR->little_endian) {
|
||||
v.u = (unsigned char)bits;
|
||||
bits >>= 8;
|
||||
} else { /* a big endian */
|
||||
v.u = (unsigned char)(bits>>(8*(unsignedtype->size - 1)));
|
||||
bits <<= 8;
|
||||
}
|
||||
(*IR->defconst)(U, unsignedchar->size, v);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* initstruct - initialize a struct ty of <= len bytes; if len == 0, go to } */
|
||||
static int initstruct(int len, Type ty, int lev) {
|
||||
int a, n = 0;
|
||||
Field p = ty->u.sym->u.s.flist;
|
||||
|
||||
do {
|
||||
if (p->offset > n) {
|
||||
(*IR->space)(p->offset - n);
|
||||
n += p->offset - n;
|
||||
}
|
||||
if (p->lsb) {
|
||||
Field q = p;
|
||||
while (q->link && q->link->offset == p->offset)
|
||||
q = q->link;
|
||||
n += initfields(p, q->link);
|
||||
p = q;
|
||||
} else {
|
||||
initializer(p->type, lev);
|
||||
n += p->type->size;
|
||||
}
|
||||
if (p->link) {
|
||||
p = p->link;
|
||||
a = p->type->align;
|
||||
} else
|
||||
a = ty->align;
|
||||
if (a && n%a) {
|
||||
(*IR->space)(a - n%a);
|
||||
n = roundup(n, a);
|
||||
}
|
||||
if (len > 0 && n >= len || t != ',')
|
||||
break;
|
||||
t = gettok();
|
||||
} while (t != '}');
|
||||
return n;
|
||||
}
|
||||
|
||||
/* initializer - constexpr | { constexpr ( , constexpr )* [ , ] } */
|
||||
Type initializer(Type ty, int lev) {
|
||||
int n = 0;
|
||||
Tree e;
|
||||
Type aty = NULL;
|
||||
static char follow[] = { IF, CHAR, STATIC, 0 };
|
||||
|
||||
ty = unqual(ty);
|
||||
if (isscalar(ty)) {
|
||||
needconst++;
|
||||
if (t == '{') {
|
||||
t = gettok();
|
||||
e = expr1(0);
|
||||
initend(lev, follow);
|
||||
} else
|
||||
e = expr1(0);
|
||||
e = pointer(e);
|
||||
if ((aty = assign(ty, e)) != NULL)
|
||||
e = cast(e, aty);
|
||||
else
|
||||
error("invalid initialization type; found `%t' expected `%t'\n",
|
||||
e->type, ty);
|
||||
n = genconst(e, 1);
|
||||
deallocate(STMT);
|
||||
needconst--;
|
||||
}
|
||||
if ((isunion(ty) || isstruct(ty)) && ty->size == 0) {
|
||||
static char follow[] = { CHAR, STATIC, 0 };
|
||||
error("cannot initialize undefined `%t'\n", ty);
|
||||
skipto(';', follow);
|
||||
return ty;
|
||||
} else if (isunion(ty)) {
|
||||
if (t == '{') {
|
||||
t = gettok();
|
||||
n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
|
||||
initend(lev, follow);
|
||||
} else {
|
||||
if (lev == 0)
|
||||
error("missing { in initialization of `%t'\n", ty);
|
||||
n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
|
||||
}
|
||||
} else if (isstruct(ty)) {
|
||||
if (t == '{') {
|
||||
t = gettok();
|
||||
n = initstruct(0, ty, lev + 1);
|
||||
test('}', follow);
|
||||
} else if (lev > 0)
|
||||
n = initstruct(ty->size, ty, lev + 1);
|
||||
else {
|
||||
error("missing { in initialization of `%t'\n", ty);
|
||||
n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
|
||||
}
|
||||
}
|
||||
if (isarray(ty))
|
||||
aty = unqual(ty->type);
|
||||
if (isarray(ty) && ischar(aty)) {
|
||||
if (t == SCON) {
|
||||
if (ty->size > 0 && ty->size == tsym->type->size - 1)
|
||||
tsym->type = array(chartype, ty->size, 0);
|
||||
n = tsym->type->size;
|
||||
(*IR->defstring)(tsym->type->size, tsym->u.c.v.p);
|
||||
t = gettok();
|
||||
} else if (t == '{') {
|
||||
t = gettok();
|
||||
if (t == SCON) {
|
||||
ty = initializer(ty, lev + 1);
|
||||
initend(lev, follow);
|
||||
return ty;
|
||||
}
|
||||
n = initchar(0, aty);
|
||||
test('}', follow);
|
||||
} else if (lev > 0 && ty->size > 0)
|
||||
n = initchar(ty->size, aty);
|
||||
else { /* eg, char c[] = 0; */
|
||||
error("missing { in initialization of `%t'\n", ty);
|
||||
n = initchar(1, aty);
|
||||
}
|
||||
} else if (isarray(ty)) {
|
||||
if (t == SCON && aty == widechar) {
|
||||
int i;
|
||||
unsigned int *s = tsym->u.c.v.p;
|
||||
if (ty->size > 0 && ty->size == tsym->type->size - widechar->size)
|
||||
tsym->type = array(widechar, ty->size/widechar->size, 0);
|
||||
n = tsym->type->size;
|
||||
for (i = 0; i < n; i += widechar->size) {
|
||||
Value v;
|
||||
v.u = *s++;
|
||||
(*IR->defconst)(widechar->op, widechar->size, v);
|
||||
}
|
||||
t = gettok();
|
||||
} else if (t == '{') {
|
||||
t = gettok();
|
||||
if (t == SCON && aty == widechar) {
|
||||
ty = initializer(ty, lev + 1);
|
||||
initend(lev, follow);
|
||||
return ty;
|
||||
}
|
||||
n = initarray(0, aty, lev + 1);
|
||||
test('}', follow);
|
||||
} else if (lev > 0 && ty->size > 0)
|
||||
n = initarray(ty->size, aty, lev + 1);
|
||||
else {
|
||||
error("missing { in initialization of `%t'\n", ty);
|
||||
n = initarray(aty->size, aty, lev + 1);
|
||||
}
|
||||
}
|
||||
if (ty->size) {
|
||||
if (n > ty->size)
|
||||
error("too many initializers\n");
|
||||
else if (n < ty->size)
|
||||
(*IR->space)(ty->size - n);
|
||||
} else if (isarray(ty) && ty->type->size > 0)
|
||||
ty = array(ty->type, n/ty->type->size, 0);
|
||||
else
|
||||
ty->size = n;
|
||||
return ty;
|
||||
}
|
||||
|
||||
/* swtoseg - switch to segment seg, if necessary */
|
||||
void swtoseg(int seg) {
|
||||
if (curseg != seg)
|
||||
(*IR->segment)(seg);
|
||||
curseg = seg;
|
||||
}
|
||||
|
|
16
lcc/src/inits.c
Normal file → Executable file
16
lcc/src/inits.c
Normal file → Executable file
|
@ -1,8 +1,8 @@
|
|||
void init(int argc, char *argv[]) {
|
||||
{extern void input_init(int, char *[]); input_init(argc, argv);}
|
||||
{extern void main_init(int, char *[]); main_init(argc, argv);}
|
||||
{extern void prof_init(int, char *[]); prof_init(argc, argv);}
|
||||
{extern void trace_init(int, char *[]); trace_init(argc, argv);}
|
||||
{extern void type_init(int, char *[]); type_init(argc, argv);}
|
||||
{extern void x86linux_init(int, char *[]); x86linux_init(argc, argv);}
|
||||
}
|
||||
void init(int argc, char *argv[]) {
|
||||
{extern void input_init(int, char *[]); input_init(argc, argv);}
|
||||
{extern void main_init(int, char *[]); main_init(argc, argv);}
|
||||
{extern void prof_init(int, char *[]); prof_init(argc, argv);}
|
||||
{extern void trace_init(int, char *[]); trace_init(argc, argv);}
|
||||
{extern void type_init(int, char *[]); type_init(argc, argv);}
|
||||
{extern void x86linux_init(int, char *[]); x86linux_init(argc, argv);}
|
||||
}
|
||||
|
|
268
lcc/src/input.c
Normal file → Executable file
268
lcc/src/input.c
Normal file → Executable file
|
@ -1,134 +1,134 @@
|
|||
#include "c.h"
|
||||
|
||||
|
||||
static void pragma(void);
|
||||
static void resynch(void);
|
||||
|
||||
static int bsize;
|
||||
static unsigned char buffer[MAXLINE+1 + BUFSIZE+1];
|
||||
unsigned char *cp; /* current input character */
|
||||
char *file; /* current input file name */
|
||||
char *firstfile; /* first input file */
|
||||
unsigned char *limit; /* points to last character + 1 */
|
||||
char *line; /* current line */
|
||||
int lineno; /* line number of current line */
|
||||
|
||||
void nextline(void) {
|
||||
do {
|
||||
if (cp >= limit) {
|
||||
fillbuf();
|
||||
if (cp >= limit)
|
||||
cp = limit;
|
||||
if (cp == limit)
|
||||
return;
|
||||
} else {
|
||||
lineno++;
|
||||
for (line = (char *)cp; *cp==' ' || *cp=='\t'; cp++)
|
||||
;
|
||||
if (*cp == '#') {
|
||||
resynch();
|
||||
nextline();
|
||||
}
|
||||
}
|
||||
} while (*cp == '\n' && cp == limit);
|
||||
}
|
||||
void fillbuf(void) {
|
||||
if (bsize == 0)
|
||||
return;
|
||||
if (cp >= limit)
|
||||
cp = &buffer[MAXLINE+1];
|
||||
else
|
||||
{
|
||||
int n = limit - cp;
|
||||
unsigned char *s = &buffer[MAXLINE+1] - n;
|
||||
assert(s >= buffer);
|
||||
line = (char *)s - ((char *)cp - line);
|
||||
while (cp < limit)
|
||||
*s++ = *cp++;
|
||||
cp = &buffer[MAXLINE+1] - n;
|
||||
}
|
||||
if (feof(stdin))
|
||||
bsize = 0;
|
||||
else
|
||||
bsize = fread(&buffer[MAXLINE+1], 1, BUFSIZE, stdin);
|
||||
if (bsize < 0) {
|
||||
error("read error\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
limit = &buffer[MAXLINE+1+bsize];
|
||||
*limit = '\n';
|
||||
}
|
||||
void input_init(int argc, char *argv[]) {
|
||||
static int inited;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
inited = 1;
|
||||
main_init(argc, argv);
|
||||
limit = cp = &buffer[MAXLINE+1];
|
||||
bsize = -1;
|
||||
lineno = 0;
|
||||
file = NULL;
|
||||
fillbuf();
|
||||
if (cp >= limit)
|
||||
cp = limit;
|
||||
nextline();
|
||||
}
|
||||
|
||||
/* pragma - handle #pragma ref id... */
|
||||
static void pragma(void) {
|
||||
if ((t = gettok()) == ID && strcmp(token, "ref") == 0)
|
||||
for (;;) {
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if (*cp == '\n' || *cp == 0)
|
||||
break;
|
||||
if ((t = gettok()) == ID && tsym) {
|
||||
tsym->ref++;
|
||||
use(tsym, src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* resynch - set line number/file name in # n [ "file" ] and #pragma ... */
|
||||
static void resynch(void) {
|
||||
for (cp++; *cp == ' ' || *cp == '\t'; )
|
||||
cp++;
|
||||
if (limit - cp < MAXLINE)
|
||||
fillbuf();
|
||||
if (strncmp((char *)cp, "pragma", 6) == 0) {
|
||||
cp += 6;
|
||||
pragma();
|
||||
} else if (*cp >= '0' && *cp <= '9') {
|
||||
line: for (lineno = 0; *cp >= '0' && *cp <= '9'; )
|
||||
lineno = 10*lineno + *cp++ - '0';
|
||||
lineno--;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if (*cp == '"') {
|
||||
file = (char *)++cp;
|
||||
while (*cp && *cp != '"' && *cp != '\n')
|
||||
cp++;
|
||||
file = stringn(file, (char *)cp - file);
|
||||
if (*cp == '\n')
|
||||
warning("missing \" in preprocessor line\n");
|
||||
if (firstfile == 0)
|
||||
firstfile = file;
|
||||
}
|
||||
} else if (strncmp((char *)cp, "line", 4) == 0) {
|
||||
for (cp += 4; *cp == ' ' || *cp == '\t'; )
|
||||
cp++;
|
||||
if (*cp >= '0' && *cp <= '9')
|
||||
goto line;
|
||||
if (Aflag >= 2)
|
||||
warning("unrecognized control line\n");
|
||||
} else if (Aflag >= 2 && *cp != '\n')
|
||||
warning("unrecognized control line\n");
|
||||
while (*cp)
|
||||
if (*cp++ == '\n')
|
||||
if (cp == limit + 1)
|
||||
nextline();
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
#include "c.h"
|
||||
|
||||
|
||||
static void pragma(void);
|
||||
static void resynch(void);
|
||||
|
||||
static int bsize;
|
||||
static unsigned char buffer[MAXLINE+1 + BUFSIZE+1];
|
||||
unsigned char *cp; /* current input character */
|
||||
char *file; /* current input file name */
|
||||
char *firstfile; /* first input file */
|
||||
unsigned char *limit; /* points to last character + 1 */
|
||||
char *line; /* current line */
|
||||
int lineno; /* line number of current line */
|
||||
|
||||
void nextline(void) {
|
||||
do {
|
||||
if (cp >= limit) {
|
||||
fillbuf();
|
||||
if (cp >= limit)
|
||||
cp = limit;
|
||||
if (cp == limit)
|
||||
return;
|
||||
} else {
|
||||
lineno++;
|
||||
for (line = (char *)cp; *cp==' ' || *cp=='\t'; cp++)
|
||||
;
|
||||
if (*cp == '#') {
|
||||
resynch();
|
||||
nextline();
|
||||
}
|
||||
}
|
||||
} while (*cp == '\n' && cp == limit);
|
||||
}
|
||||
void fillbuf(void) {
|
||||
if (bsize == 0)
|
||||
return;
|
||||
if (cp >= limit)
|
||||
cp = &buffer[MAXLINE+1];
|
||||
else
|
||||
{
|
||||
int n = limit - cp;
|
||||
unsigned char *s = &buffer[MAXLINE+1] - n;
|
||||
assert(s >= buffer);
|
||||
line = (char *)s - ((char *)cp - line);
|
||||
while (cp < limit)
|
||||
*s++ = *cp++;
|
||||
cp = &buffer[MAXLINE+1] - n;
|
||||
}
|
||||
if (feof(stdin))
|
||||
bsize = 0;
|
||||
else
|
||||
bsize = fread(&buffer[MAXLINE+1], 1, BUFSIZE, stdin);
|
||||
if (bsize < 0) {
|
||||
error("read error\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
limit = &buffer[MAXLINE+1+bsize];
|
||||
*limit = '\n';
|
||||
}
|
||||
void input_init(int argc, char *argv[]) {
|
||||
static int inited;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
inited = 1;
|
||||
main_init(argc, argv);
|
||||
limit = cp = &buffer[MAXLINE+1];
|
||||
bsize = -1;
|
||||
lineno = 0;
|
||||
file = NULL;
|
||||
fillbuf();
|
||||
if (cp >= limit)
|
||||
cp = limit;
|
||||
nextline();
|
||||
}
|
||||
|
||||
/* pragma - handle #pragma ref id... */
|
||||
static void pragma(void) {
|
||||
if ((t = gettok()) == ID && strcmp(token, "ref") == 0)
|
||||
for (;;) {
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if (*cp == '\n' || *cp == 0)
|
||||
break;
|
||||
if ((t = gettok()) == ID && tsym) {
|
||||
tsym->ref++;
|
||||
use(tsym, src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* resynch - set line number/file name in # n [ "file" ] and #pragma ... */
|
||||
static void resynch(void) {
|
||||
for (cp++; *cp == ' ' || *cp == '\t'; )
|
||||
cp++;
|
||||
if (limit - cp < MAXLINE)
|
||||
fillbuf();
|
||||
if (strncmp((char *)cp, "pragma", 6) == 0) {
|
||||
cp += 6;
|
||||
pragma();
|
||||
} else if (*cp >= '0' && *cp <= '9') {
|
||||
line: for (lineno = 0; *cp >= '0' && *cp <= '9'; )
|
||||
lineno = 10*lineno + *cp++ - '0';
|
||||
lineno--;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if (*cp == '"') {
|
||||
file = (char *)++cp;
|
||||
while (*cp && *cp != '"' && *cp != '\n')
|
||||
cp++;
|
||||
file = stringn(file, (char *)cp - file);
|
||||
if (*cp == '\n')
|
||||
warning("missing \" in preprocessor line\n");
|
||||
if (firstfile == 0)
|
||||
firstfile = file;
|
||||
}
|
||||
} else if (strncmp((char *)cp, "line", 4) == 0) {
|
||||
for (cp += 4; *cp == ' ' || *cp == '\t'; )
|
||||
cp++;
|
||||
if (*cp >= '0' && *cp <= '9')
|
||||
goto line;
|
||||
if (Aflag >= 2)
|
||||
warning("unrecognized control line\n");
|
||||
} else if (Aflag >= 2 && *cp != '\n')
|
||||
warning("unrecognized control line\n");
|
||||
while (*cp)
|
||||
if (*cp++ == '\n')
|
||||
if (cp == limit + 1)
|
||||
nextline();
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
1844
lcc/src/lex.c
Normal file → Executable file
1844
lcc/src/lex.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
112
lcc/src/list.c
Normal file → Executable file
112
lcc/src/list.c
Normal file → Executable file
|
@ -1,56 +1,56 @@
|
|||
#include "c.h"
|
||||
|
||||
|
||||
static List freenodes; /* free list nodes */
|
||||
|
||||
/* append - append x to list, return new list */
|
||||
List append(void *x, List list) {
|
||||
List new;
|
||||
|
||||
if ((new = freenodes) != NULL)
|
||||
freenodes = freenodes->link;
|
||||
else
|
||||
NEW(new, PERM);
|
||||
if (list) {
|
||||
new->link = list->link;
|
||||
list->link = new;
|
||||
} else
|
||||
new->link = new;
|
||||
new->x = x;
|
||||
return new;
|
||||
}
|
||||
|
||||
/* length - # elements in list */
|
||||
int length(List list) {
|
||||
int n = 0;
|
||||
|
||||
if (list) {
|
||||
List lp = list;
|
||||
do
|
||||
n++;
|
||||
while ((lp = lp->link) != list);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* ltov - convert list to an NULL-terminated vector allocated in arena */
|
||||
void *ltov(List *list, unsigned arena) {
|
||||
int i = 0;
|
||||
void **array = newarray(length(*list) + 1, sizeof array[0], arena);
|
||||
|
||||
if (*list) {
|
||||
List lp = *list;
|
||||
do {
|
||||
lp = lp->link;
|
||||
array[i++] = lp->x;
|
||||
} while (lp != *list);
|
||||
#ifndef PURIFY
|
||||
lp = (*list)->link;
|
||||
(*list)->link = freenodes;
|
||||
freenodes = lp;
|
||||
#endif
|
||||
}
|
||||
*list = NULL;
|
||||
array[i] = NULL;
|
||||
return array;
|
||||
}
|
||||
#include "c.h"
|
||||
|
||||
|
||||
static List freenodes; /* free list nodes */
|
||||
|
||||
/* append - append x to list, return new list */
|
||||
List append(void *x, List list) {
|
||||
List new;
|
||||
|
||||
if ((new = freenodes) != NULL)
|
||||
freenodes = freenodes->link;
|
||||
else
|
||||
NEW(new, PERM);
|
||||
if (list) {
|
||||
new->link = list->link;
|
||||
list->link = new;
|
||||
} else
|
||||
new->link = new;
|
||||
new->x = x;
|
||||
return new;
|
||||
}
|
||||
|
||||
/* length - # elements in list */
|
||||
int length(List list) {
|
||||
int n = 0;
|
||||
|
||||
if (list) {
|
||||
List lp = list;
|
||||
do
|
||||
n++;
|
||||
while ((lp = lp->link) != list);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* ltov - convert list to an NULL-terminated vector allocated in arena */
|
||||
void *ltov(List *list, unsigned arena) {
|
||||
int i = 0;
|
||||
void **array = newarray(length(*list) + 1, sizeof array[0], arena);
|
||||
|
||||
if (*list) {
|
||||
List lp = *list;
|
||||
do {
|
||||
lp = lp->link;
|
||||
array[i++] = lp->x;
|
||||
} while (lp != *list);
|
||||
#ifndef PURIFY
|
||||
lp = (*list)->link;
|
||||
(*list)->link = freenodes;
|
||||
freenodes = lp;
|
||||
#endif
|
||||
}
|
||||
*list = NULL;
|
||||
array[i] = NULL;
|
||||
return array;
|
||||
}
|
||||
|
|
450
lcc/src/main.c
Normal file → Executable file
450
lcc/src/main.c
Normal file → Executable file
|
@ -1,225 +1,225 @@
|
|||
#include "c.h"
|
||||
|
||||
static char rcsid[] = "main.c - faked rcsid";
|
||||
|
||||
static void typestab(Symbol, void *);
|
||||
|
||||
static void stabline(Coordinate *);
|
||||
static void stabend(Coordinate *, Symbol, Coordinate **, Symbol *, Symbol *);
|
||||
Interface *IR = NULL;
|
||||
|
||||
int Aflag; /* >= 0 if -A specified */
|
||||
int Pflag; /* != 0 if -P specified */
|
||||
int glevel; /* == [0-9] if -g[0-9] specified */
|
||||
int xref; /* != 0 for cross-reference data */
|
||||
Symbol YYnull; /* _YYnull symbol if -n or -nvalidate specified */
|
||||
Symbol YYcheck; /* _YYcheck symbol if -nvalidate,check specified */
|
||||
|
||||
static char *comment;
|
||||
static Interface stabIR;
|
||||
static char *currentfile; /* current file name */
|
||||
static int currentline; /* current line number */
|
||||
static FILE *srcfp; /* stream for current file, if non-NULL */
|
||||
static int srcpos; /* position of srcfp, if srcfp is non-NULL */
|
||||
int main(int argc, char *argv[]) {
|
||||
int i, j;
|
||||
for (i = argc - 1; i > 0; i--)
|
||||
if (strncmp(argv[i], "-target=", 8) == 0)
|
||||
break;
|
||||
if (i > 0) {
|
||||
char *s = strchr(argv[i], '\\');
|
||||
if (s != NULL)
|
||||
*s = '/';
|
||||
for (j = 0; bindings[j].name && bindings[j].ir; j++)
|
||||
if (strcmp(&argv[i][8], bindings[j].name) == 0) {
|
||||
IR = bindings[j].ir;
|
||||
break;
|
||||
}
|
||||
if (s != NULL)
|
||||
*s = '\\';
|
||||
}
|
||||
if (!IR) {
|
||||
fprint(stderr, "%s: unknown target", argv[0]);
|
||||
if (i > 0)
|
||||
fprint(stderr, " `%s'", &argv[i][8]);
|
||||
fprint(stderr, "; must specify one of\n");
|
||||
for (i = 0; bindings[i].name; i++)
|
||||
fprint(stderr, "\t-target=%s\n", bindings[i].name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
init(argc, argv);
|
||||
t = gettok();
|
||||
(*IR->progbeg)(argc, argv);
|
||||
if (glevel && IR->stabinit)
|
||||
(*IR->stabinit)(firstfile, argc, argv);
|
||||
program();
|
||||
if (events.end)
|
||||
apply(events.end, NULL, NULL);
|
||||
memset(&events, 0, sizeof events);
|
||||
if (glevel || xref) {
|
||||
Symbol symroot = NULL;
|
||||
Coordinate src;
|
||||
foreach(types, GLOBAL, typestab, &symroot);
|
||||
foreach(identifiers, GLOBAL, typestab, &symroot);
|
||||
src.file = firstfile;
|
||||
src.x = 0;
|
||||
src.y = lineno;
|
||||
if ((glevel > 2 || xref) && IR->stabend)
|
||||
(*IR->stabend)(&src, symroot,
|
||||
ltov(&loci, PERM),
|
||||
ltov(&symbols, PERM), NULL);
|
||||
else if (IR->stabend)
|
||||
(*IR->stabend)(&src, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
finalize();
|
||||
(*IR->progend)();
|
||||
deallocate(PERM);
|
||||
return errcnt > 0;
|
||||
}
|
||||
/* main_init - process program arguments */
|
||||
void main_init(int argc, char *argv[]) {
|
||||
char *infile = NULL, *outfile = NULL;
|
||||
int i;
|
||||
static int inited;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
inited = 1;
|
||||
type_init(argc, argv);
|
||||
for (i = 1; i < argc; i++)
|
||||
if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "-g2") == 0)
|
||||
glevel = 2;
|
||||
else if (strncmp(argv[i], "-g", 2) == 0) { /* -gn[,x] */
|
||||
char *p = strchr(argv[i], ',');
|
||||
glevel = atoi(argv[i]+2);
|
||||
if (p) {
|
||||
comment = p + 1;
|
||||
if (glevel == 0)
|
||||
glevel = 1;
|
||||
if (stabIR.stabline == NULL) {
|
||||
stabIR.stabline = IR->stabline;
|
||||
stabIR.stabend = IR->stabend;
|
||||
IR->stabline = stabline;
|
||||
IR->stabend = stabend;
|
||||
}
|
||||
}
|
||||
} else if (strcmp(argv[i], "-x") == 0)
|
||||
xref++;
|
||||
else if (strcmp(argv[i], "-A") == 0) {
|
||||
++Aflag;
|
||||
} else if (strcmp(argv[i], "-P") == 0)
|
||||
Pflag++;
|
||||
else if (strcmp(argv[i], "-w") == 0)
|
||||
wflag++;
|
||||
else if (strcmp(argv[i], "-n") == 0) {
|
||||
if (!YYnull) {
|
||||
YYnull = install(string("_YYnull"), &globals, GLOBAL, PERM);
|
||||
YYnull->type = func(voidptype, NULL, 1);
|
||||
YYnull->sclass = EXTERN;
|
||||
(*IR->defsymbol)(YYnull);
|
||||
}
|
||||
} else if (strncmp(argv[i], "-n", 2) == 0) { /* -nvalid[,check] */
|
||||
char *p = strchr(argv[i], ',');
|
||||
if (p) {
|
||||
YYcheck = install(string(p+1), &globals, GLOBAL, PERM);
|
||||
YYcheck->type = func(voidptype, NULL, 1);
|
||||
YYcheck->sclass = EXTERN;
|
||||
(*IR->defsymbol)(YYcheck);
|
||||
p = stringn(argv[i]+2, p - (argv[i]+2));
|
||||
} else
|
||||
p = string(argv[i]+2);
|
||||
YYnull = install(p, &globals, GLOBAL, PERM);
|
||||
YYnull->type = func(voidptype, NULL, 1);
|
||||
YYnull->sclass = EXTERN;
|
||||
(*IR->defsymbol)(YYnull);
|
||||
} else if (strcmp(argv[i], "-v") == 0)
|
||||
fprint(stderr, "%s %s\n", argv[0], rcsid);
|
||||
else if (strncmp(argv[i], "-s", 2) == 0)
|
||||
density = strtod(&argv[i][2], NULL);
|
||||
else if (strncmp(argv[i], "-errout=", 8) == 0) {
|
||||
FILE *f = fopen(argv[i]+8, "w");
|
||||
if (f == NULL) {
|
||||
fprint(stderr, "%s: can't write errors to `%s'\n", argv[0], argv[i]+8);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fclose(f);
|
||||
f = freopen(argv[i]+8, "w", stderr);
|
||||
assert(f);
|
||||
} else if (strncmp(argv[i], "-e", 2) == 0) {
|
||||
int x;
|
||||
if ((x = strtol(&argv[i][2], NULL, 0)) > 0)
|
||||
errlimit = x;
|
||||
} else if (strncmp(argv[i], "-little_endian=", 15) == 0)
|
||||
IR->little_endian = argv[i][15] - '0';
|
||||
else if (strncmp(argv[i], "-mulops_calls=", 18) == 0)
|
||||
IR->mulops_calls = argv[i][18] - '0';
|
||||
else if (strncmp(argv[i], "-wants_callb=", 13) == 0)
|
||||
IR->wants_callb = argv[i][13] - '0';
|
||||
else if (strncmp(argv[i], "-wants_argb=", 12) == 0)
|
||||
IR->wants_argb = argv[i][12] - '0';
|
||||
else if (strncmp(argv[i], "-left_to_right=", 15) == 0)
|
||||
IR->left_to_right = argv[i][15] - '0';
|
||||
else if (strncmp(argv[i], "-wants_dag=", 11) == 0)
|
||||
IR->wants_dag = argv[i][11] - '0';
|
||||
else if (*argv[i] != '-' || strcmp(argv[i], "-") == 0) {
|
||||
if (infile == NULL)
|
||||
infile = argv[i];
|
||||
else if (outfile == NULL)
|
||||
outfile = argv[i];
|
||||
}
|
||||
|
||||
if (infile != NULL && strcmp(infile, "-") != 0
|
||||
&& freopen(infile, "r", stdin) == NULL) {
|
||||
fprint(stderr, "%s: can't read `%s'\n", argv[0], infile);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (outfile != NULL && strcmp(outfile, "-") != 0
|
||||
&& freopen(outfile, "w", stdout) == NULL) {
|
||||
fprint(stderr, "%s: can't write `%s'\n", argv[0], outfile);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
/* typestab - emit stab entries for p */
|
||||
static void typestab(Symbol p, void *cl) {
|
||||
if (*(Symbol *)cl == 0 && p->sclass && p->sclass != TYPEDEF)
|
||||
*(Symbol *)cl = p;
|
||||
if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype)
|
||||
(*IR->stabtype)(p);
|
||||
}
|
||||
|
||||
/* stabline - emit source code for source coordinate *cp */
|
||||
static void stabline(Coordinate *cp) {
|
||||
if (cp->file && cp->file != currentfile) {
|
||||
if (srcfp)
|
||||
fclose(srcfp);
|
||||
currentfile = cp->file;
|
||||
srcfp = fopen(currentfile, "r");
|
||||
srcpos = 0;
|
||||
currentline = 0;
|
||||
}
|
||||
if (currentline != cp->y && srcfp) {
|
||||
char buf[512];
|
||||
if (srcpos > cp->y) {
|
||||
rewind(srcfp);
|
||||
srcpos = 0;
|
||||
}
|
||||
for ( ; srcpos < cp->y; srcpos++)
|
||||
if (fgets(buf, sizeof buf, srcfp) == NULL) {
|
||||
fclose(srcfp);
|
||||
srcfp = NULL;
|
||||
break;
|
||||
}
|
||||
if (srcfp && srcpos == cp->y)
|
||||
print("%s%s", comment, buf);
|
||||
}
|
||||
currentline = cp->y;
|
||||
if (stabIR.stabline)
|
||||
(*stabIR.stabline)(cp);
|
||||
}
|
||||
|
||||
static void stabend(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {
|
||||
if (stabIR.stabend)
|
||||
(*stabIR.stabend)(cp, p, cpp, sp, stab);
|
||||
if (srcfp)
|
||||
fclose(srcfp);
|
||||
}
|
||||
#include "c.h"
|
||||
|
||||
static char rcsid[] = "main.c - faked rcsid";
|
||||
|
||||
static void typestab(Symbol, void *);
|
||||
|
||||
static void stabline(Coordinate *);
|
||||
static void stabend(Coordinate *, Symbol, Coordinate **, Symbol *, Symbol *);
|
||||
Interface *IR = NULL;
|
||||
|
||||
int Aflag; /* >= 0 if -A specified */
|
||||
int Pflag; /* != 0 if -P specified */
|
||||
int glevel; /* == [0-9] if -g[0-9] specified */
|
||||
int xref; /* != 0 for cross-reference data */
|
||||
Symbol YYnull; /* _YYnull symbol if -n or -nvalidate specified */
|
||||
Symbol YYcheck; /* _YYcheck symbol if -nvalidate,check specified */
|
||||
|
||||
static char *comment;
|
||||
static Interface stabIR;
|
||||
static char *currentfile; /* current file name */
|
||||
static int currentline; /* current line number */
|
||||
static FILE *srcfp; /* stream for current file, if non-NULL */
|
||||
static int srcpos; /* position of srcfp, if srcfp is non-NULL */
|
||||
int main(int argc, char *argv[]) {
|
||||
int i, j;
|
||||
for (i = argc - 1; i > 0; i--)
|
||||
if (strncmp(argv[i], "-target=", 8) == 0)
|
||||
break;
|
||||
if (i > 0) {
|
||||
char *s = strchr(argv[i], '\\');
|
||||
if (s != NULL)
|
||||
*s = '/';
|
||||
for (j = 0; bindings[j].name && bindings[j].ir; j++)
|
||||
if (strcmp(&argv[i][8], bindings[j].name) == 0) {
|
||||
IR = bindings[j].ir;
|
||||
break;
|
||||
}
|
||||
if (s != NULL)
|
||||
*s = '\\';
|
||||
}
|
||||
if (!IR) {
|
||||
fprint(stderr, "%s: unknown target", argv[0]);
|
||||
if (i > 0)
|
||||
fprint(stderr, " `%s'", &argv[i][8]);
|
||||
fprint(stderr, "; must specify one of\n");
|
||||
for (i = 0; bindings[i].name; i++)
|
||||
fprint(stderr, "\t-target=%s\n", bindings[i].name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
init(argc, argv);
|
||||
t = gettok();
|
||||
(*IR->progbeg)(argc, argv);
|
||||
if (glevel && IR->stabinit)
|
||||
(*IR->stabinit)(firstfile, argc, argv);
|
||||
program();
|
||||
if (events.end)
|
||||
apply(events.end, NULL, NULL);
|
||||
memset(&events, 0, sizeof events);
|
||||
if (glevel || xref) {
|
||||
Symbol symroot = NULL;
|
||||
Coordinate src;
|
||||
foreach(types, GLOBAL, typestab, &symroot);
|
||||
foreach(identifiers, GLOBAL, typestab, &symroot);
|
||||
src.file = firstfile;
|
||||
src.x = 0;
|
||||
src.y = lineno;
|
||||
if ((glevel > 2 || xref) && IR->stabend)
|
||||
(*IR->stabend)(&src, symroot,
|
||||
ltov(&loci, PERM),
|
||||
ltov(&symbols, PERM), NULL);
|
||||
else if (IR->stabend)
|
||||
(*IR->stabend)(&src, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
finalize();
|
||||
(*IR->progend)();
|
||||
deallocate(PERM);
|
||||
return errcnt > 0;
|
||||
}
|
||||
/* main_init - process program arguments */
|
||||
void main_init(int argc, char *argv[]) {
|
||||
char *infile = NULL, *outfile = NULL;
|
||||
int i;
|
||||
static int inited;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
inited = 1;
|
||||
type_init(argc, argv);
|
||||
for (i = 1; i < argc; i++)
|
||||
if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "-g2") == 0)
|
||||
glevel = 2;
|
||||
else if (strncmp(argv[i], "-g", 2) == 0) { /* -gn[,x] */
|
||||
char *p = strchr(argv[i], ',');
|
||||
glevel = atoi(argv[i]+2);
|
||||
if (p) {
|
||||
comment = p + 1;
|
||||
if (glevel == 0)
|
||||
glevel = 1;
|
||||
if (stabIR.stabline == NULL) {
|
||||
stabIR.stabline = IR->stabline;
|
||||
stabIR.stabend = IR->stabend;
|
||||
IR->stabline = stabline;
|
||||
IR->stabend = stabend;
|
||||
}
|
||||
}
|
||||
} else if (strcmp(argv[i], "-x") == 0)
|
||||
xref++;
|
||||
else if (strcmp(argv[i], "-A") == 0) {
|
||||
++Aflag;
|
||||
} else if (strcmp(argv[i], "-P") == 0)
|
||||
Pflag++;
|
||||
else if (strcmp(argv[i], "-w") == 0)
|
||||
wflag++;
|
||||
else if (strcmp(argv[i], "-n") == 0) {
|
||||
if (!YYnull) {
|
||||
YYnull = install(string("_YYnull"), &globals, GLOBAL, PERM);
|
||||
YYnull->type = func(voidptype, NULL, 1);
|
||||
YYnull->sclass = EXTERN;
|
||||
(*IR->defsymbol)(YYnull);
|
||||
}
|
||||
} else if (strncmp(argv[i], "-n", 2) == 0) { /* -nvalid[,check] */
|
||||
char *p = strchr(argv[i], ',');
|
||||
if (p) {
|
||||
YYcheck = install(string(p+1), &globals, GLOBAL, PERM);
|
||||
YYcheck->type = func(voidptype, NULL, 1);
|
||||
YYcheck->sclass = EXTERN;
|
||||
(*IR->defsymbol)(YYcheck);
|
||||
p = stringn(argv[i]+2, p - (argv[i]+2));
|
||||
} else
|
||||
p = string(argv[i]+2);
|
||||
YYnull = install(p, &globals, GLOBAL, PERM);
|
||||
YYnull->type = func(voidptype, NULL, 1);
|
||||
YYnull->sclass = EXTERN;
|
||||
(*IR->defsymbol)(YYnull);
|
||||
} else if (strcmp(argv[i], "-v") == 0)
|
||||
fprint(stderr, "%s %s\n", argv[0], rcsid);
|
||||
else if (strncmp(argv[i], "-s", 2) == 0)
|
||||
density = strtod(&argv[i][2], NULL);
|
||||
else if (strncmp(argv[i], "-errout=", 8) == 0) {
|
||||
FILE *f = fopen(argv[i]+8, "w");
|
||||
if (f == NULL) {
|
||||
fprint(stderr, "%s: can't write errors to `%s'\n", argv[0], argv[i]+8);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fclose(f);
|
||||
f = freopen(argv[i]+8, "w", stderr);
|
||||
assert(f);
|
||||
} else if (strncmp(argv[i], "-e", 2) == 0) {
|
||||
int x;
|
||||
if ((x = strtol(&argv[i][2], NULL, 0)) > 0)
|
||||
errlimit = x;
|
||||
} else if (strncmp(argv[i], "-little_endian=", 15) == 0)
|
||||
IR->little_endian = argv[i][15] - '0';
|
||||
else if (strncmp(argv[i], "-mulops_calls=", 18) == 0)
|
||||
IR->mulops_calls = argv[i][18] - '0';
|
||||
else if (strncmp(argv[i], "-wants_callb=", 13) == 0)
|
||||
IR->wants_callb = argv[i][13] - '0';
|
||||
else if (strncmp(argv[i], "-wants_argb=", 12) == 0)
|
||||
IR->wants_argb = argv[i][12] - '0';
|
||||
else if (strncmp(argv[i], "-left_to_right=", 15) == 0)
|
||||
IR->left_to_right = argv[i][15] - '0';
|
||||
else if (strncmp(argv[i], "-wants_dag=", 11) == 0)
|
||||
IR->wants_dag = argv[i][11] - '0';
|
||||
else if (*argv[i] != '-' || strcmp(argv[i], "-") == 0) {
|
||||
if (infile == NULL)
|
||||
infile = argv[i];
|
||||
else if (outfile == NULL)
|
||||
outfile = argv[i];
|
||||
}
|
||||
|
||||
if (infile != NULL && strcmp(infile, "-") != 0
|
||||
&& freopen(infile, "r", stdin) == NULL) {
|
||||
fprint(stderr, "%s: can't read `%s'\n", argv[0], infile);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (outfile != NULL && strcmp(outfile, "-") != 0
|
||||
&& freopen(outfile, "w", stdout) == NULL) {
|
||||
fprint(stderr, "%s: can't write `%s'\n", argv[0], outfile);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
/* typestab - emit stab entries for p */
|
||||
static void typestab(Symbol p, void *cl) {
|
||||
if (*(Symbol *)cl == 0 && p->sclass && p->sclass != TYPEDEF)
|
||||
*(Symbol *)cl = p;
|
||||
if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype)
|
||||
(*IR->stabtype)(p);
|
||||
}
|
||||
|
||||
/* stabline - emit source code for source coordinate *cp */
|
||||
static void stabline(Coordinate *cp) {
|
||||
if (cp->file && cp->file != currentfile) {
|
||||
if (srcfp)
|
||||
fclose(srcfp);
|
||||
currentfile = cp->file;
|
||||
srcfp = fopen(currentfile, "r");
|
||||
srcpos = 0;
|
||||
currentline = 0;
|
||||
}
|
||||
if (currentline != cp->y && srcfp) {
|
||||
char buf[512];
|
||||
if (srcpos > cp->y) {
|
||||
rewind(srcfp);
|
||||
srcpos = 0;
|
||||
}
|
||||
for ( ; srcpos < cp->y; srcpos++)
|
||||
if (fgets(buf, sizeof buf, srcfp) == NULL) {
|
||||
fclose(srcfp);
|
||||
srcfp = NULL;
|
||||
break;
|
||||
}
|
||||
if (srcfp && srcpos == cp->y)
|
||||
print("%s%s", comment, buf);
|
||||
}
|
||||
currentline = cp->y;
|
||||
if (stabIR.stabline)
|
||||
(*stabIR.stabline)(cp);
|
||||
}
|
||||
|
||||
static void stabend(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {
|
||||
if (stabIR.stabend)
|
||||
(*stabIR.stabend)(cp, p, cpp, sp, stab);
|
||||
if (srcfp)
|
||||
fclose(srcfp);
|
||||
}
|
||||
|
|
2240
lcc/src/mips.md
Normal file → Executable file
2240
lcc/src/mips.md
Normal file → Executable file
File diff suppressed because it is too large
Load diff
148
lcc/src/null.c
Normal file → Executable file
148
lcc/src/null.c
Normal file → Executable file
|
@ -1,74 +1,74 @@
|
|||
#include "c.h"
|
||||
#define I(f) null_##f
|
||||
|
||||
static Node I(gen)(Node p) { return p; }
|
||||
static void I(address)(Symbol q, Symbol p, long n) {}
|
||||
static void I(blockbeg)(Env *e) {}
|
||||
static void I(blockend)(Env *e) {}
|
||||
static void I(defaddress)(Symbol p) {}
|
||||
static void I(defconst)(int suffix, int size, Value v) {}
|
||||
static void I(defstring)(int len, char *s) {}
|
||||
static void I(defsymbol)(Symbol p) {}
|
||||
static void I(emit)(Node p) {}
|
||||
static void I(export)(Symbol p) {}
|
||||
static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {}
|
||||
static void I(global)(Symbol p) {}
|
||||
static void I(import)(Symbol p) {}
|
||||
static void I(local)(Symbol p) {}
|
||||
static void I(progbeg)(int argc, char *argv[]) {}
|
||||
static void I(progend)(void) {}
|
||||
static void I(segment)(int s) {}
|
||||
static void I(space)(int n) {}
|
||||
static void I(stabblock)(int brace, int lev, Symbol *p) {}
|
||||
static void I(stabend)(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {}
|
||||
static void I(stabfend)(Symbol p, int lineno) {}
|
||||
static void I(stabinit)(char *file, int argc, char *argv[]) {}
|
||||
static void I(stabline)(Coordinate *cp) {}
|
||||
static void I(stabsym)(Symbol p) {}
|
||||
static void I(stabtype)(Symbol p) {}
|
||||
|
||||
|
||||
Interface nullIR = {
|
||||
1, 1, 0, /* char */
|
||||
2, 2, 0, /* short */
|
||||
4, 4, 0, /* int */
|
||||
8, 8, 1, /* long */
|
||||
8 ,8, 1, /* long long */
|
||||
4, 4, 1, /* float */
|
||||
8, 8, 1, /* double */
|
||||
16,16,1, /* long double */
|
||||
4, 4, 0, /* T* */
|
||||
0, 4, 0, /* struct */
|
||||
1, /* 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),
|
||||
I(stabblock),
|
||||
I(stabend),
|
||||
I(stabfend),
|
||||
I(stabinit),
|
||||
I(stabline),
|
||||
I(stabsym),
|
||||
I(stabtype)
|
||||
};
|
||||
#include "c.h"
|
||||
#define I(f) null_##f
|
||||
|
||||
static Node I(gen)(Node p) { return p; }
|
||||
static void I(address)(Symbol q, Symbol p, long n) {}
|
||||
static void I(blockbeg)(Env *e) {}
|
||||
static void I(blockend)(Env *e) {}
|
||||
static void I(defaddress)(Symbol p) {}
|
||||
static void I(defconst)(int suffix, int size, Value v) {}
|
||||
static void I(defstring)(int len, char *s) {}
|
||||
static void I(defsymbol)(Symbol p) {}
|
||||
static void I(emit)(Node p) {}
|
||||
static void I(export)(Symbol p) {}
|
||||
static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {}
|
||||
static void I(global)(Symbol p) {}
|
||||
static void I(import)(Symbol p) {}
|
||||
static void I(local)(Symbol p) {}
|
||||
static void I(progbeg)(int argc, char *argv[]) {}
|
||||
static void I(progend)(void) {}
|
||||
static void I(segment)(int s) {}
|
||||
static void I(space)(int n) {}
|
||||
static void I(stabblock)(int brace, int lev, Symbol *p) {}
|
||||
static void I(stabend)(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {}
|
||||
static void I(stabfend)(Symbol p, int lineno) {}
|
||||
static void I(stabinit)(char *file, int argc, char *argv[]) {}
|
||||
static void I(stabline)(Coordinate *cp) {}
|
||||
static void I(stabsym)(Symbol p) {}
|
||||
static void I(stabtype)(Symbol p) {}
|
||||
|
||||
|
||||
Interface nullIR = {
|
||||
1, 1, 0, /* char */
|
||||
2, 2, 0, /* short */
|
||||
4, 4, 0, /* int */
|
||||
8, 8, 1, /* long */
|
||||
8 ,8, 1, /* long long */
|
||||
4, 4, 1, /* float */
|
||||
8, 8, 1, /* double */
|
||||
16,16,1, /* long double */
|
||||
4, 4, 0, /* T* */
|
||||
0, 4, 0, /* struct */
|
||||
1, /* 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),
|
||||
I(stabblock),
|
||||
I(stabend),
|
||||
I(stabfend),
|
||||
I(stabinit),
|
||||
I(stabline),
|
||||
I(stabsym),
|
||||
I(stabtype)
|
||||
};
|
||||
|
|
268
lcc/src/output.c
Normal file → Executable file
268
lcc/src/output.c
Normal file → Executable file
|
@ -1,134 +1,134 @@
|
|||
#include "c.h"
|
||||
|
||||
|
||||
static char *outs(const char *str, FILE *f, char *bp) {
|
||||
if (f)
|
||||
fputs(str, f);
|
||||
else
|
||||
while (*bp = *str++)
|
||||
bp++;
|
||||
return bp;
|
||||
}
|
||||
|
||||
static char *outd(long n, FILE *f, char *bp) {
|
||||
unsigned long m;
|
||||
char buf[25], *s = buf + sizeof buf;
|
||||
|
||||
*--s = '\0';
|
||||
if (n < 0)
|
||||
m = -n;
|
||||
else
|
||||
m = n;
|
||||
do
|
||||
*--s = m%10 + '0';
|
||||
while ((m /= 10) != 0);
|
||||
if (n < 0)
|
||||
*--s = '-';
|
||||
return outs(s, f, bp);
|
||||
}
|
||||
|
||||
static char *outu(unsigned long n, int base, FILE *f, char *bp) {
|
||||
char buf[25], *s = buf + sizeof buf;
|
||||
|
||||
*--s = '\0';
|
||||
do
|
||||
*--s = "0123456789abcdef"[n%base];
|
||||
while ((n /= base) != 0);
|
||||
return outs(s, f, bp);
|
||||
}
|
||||
void print(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprint(stdout, NULL, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
/* fprint - formatted output to f */
|
||||
void fprint(FILE *f, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprint(f, NULL, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* stringf - formatted output to a saved string */
|
||||
char *stringf(const char *fmt, ...) {
|
||||
char buf[1024];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprint(NULL, buf, fmt, ap);
|
||||
va_end(ap);
|
||||
return string(buf);
|
||||
}
|
||||
|
||||
/* vfprint - formatted output to f or string bp */
|
||||
void vfprint(FILE *f, char *bp, const char *fmt, va_list ap) {
|
||||
for (; *fmt; fmt++)
|
||||
if (*fmt == '%')
|
||||
switch (*++fmt) {
|
||||
case 'd': bp = outd(va_arg(ap, int), f, bp); break;
|
||||
case 'D': bp = outd(va_arg(ap, long), f, bp); break;
|
||||
case 'U': bp = outu(va_arg(ap, unsigned long), 10, f, bp); break;
|
||||
case 'u': bp = outu(va_arg(ap, unsigned), 10, f, bp); break;
|
||||
case 'o': bp = outu(va_arg(ap, unsigned), 8, f, bp); break;
|
||||
case 'X': bp = outu(va_arg(ap, unsigned long), 16, f, bp); break;
|
||||
case 'x': bp = outu(va_arg(ap, unsigned), 16, f, bp); break;
|
||||
case 'f': case 'e':
|
||||
case 'g': {
|
||||
static char format[] = "%f";
|
||||
char buf[128];
|
||||
format[1] = *fmt;
|
||||
sprintf(buf, format, va_arg(ap, double));
|
||||
bp = outs(buf, f, bp);
|
||||
}
|
||||
; break;
|
||||
case 's': bp = outs(va_arg(ap, char *), f, bp); break;
|
||||
case 'p': {
|
||||
void *p = va_arg(ap, void *);
|
||||
if (p)
|
||||
bp = outs("0x", f, bp);
|
||||
bp = outu((unsigned long)p, 16, f, bp);
|
||||
break;
|
||||
}
|
||||
case 'c': if (f) fputc(va_arg(ap, int), f); else *bp++ = va_arg(ap, int); break;
|
||||
case 'S': { char *s = va_arg(ap, char *);
|
||||
int n = va_arg(ap, int);
|
||||
if (s)
|
||||
for ( ; n-- > 0; s++)
|
||||
if (f) (void)putc(*s, f); else *bp++ = *s;
|
||||
} break;
|
||||
case 'k': { int t = va_arg(ap, int);
|
||||
static char *tokens[] = {
|
||||
#define xx(a,b,c,d,e,f,g) g,
|
||||
#define yy(a,b,c,d,e,f,g) g,
|
||||
#include "token.h"
|
||||
};
|
||||
assert(tokens[t&0177]);
|
||||
bp = outs(tokens[t&0177], f, bp);
|
||||
} break;
|
||||
case 't': { Type ty = va_arg(ap, Type);
|
||||
assert(f);
|
||||
outtype(ty ? ty : voidtype, f);
|
||||
} break;
|
||||
case 'w': { Coordinate *p = va_arg(ap, Coordinate *);
|
||||
if (p->file && *p->file) {
|
||||
bp = outs(p->file, f, bp);
|
||||
bp = outs(":", f, bp);
|
||||
}
|
||||
bp = outd(p->y, f, bp);
|
||||
} break;
|
||||
case 'I': { int n = va_arg(ap, int);
|
||||
while (--n >= 0)
|
||||
if (f) (void)putc(' ', f); else *bp++ = ' ';
|
||||
} break;
|
||||
default: if (f) (void)putc(*fmt, f); else *bp++ = *fmt; break;
|
||||
}
|
||||
else if (f)
|
||||
(void)putc(*fmt, f);
|
||||
else
|
||||
*bp++ = *fmt;
|
||||
if (!f)
|
||||
*bp = '\0';
|
||||
}
|
||||
#include "c.h"
|
||||
|
||||
|
||||
static char *outs(const char *str, FILE *f, char *bp) {
|
||||
if (f)
|
||||
fputs(str, f);
|
||||
else
|
||||
while (*bp = *str++)
|
||||
bp++;
|
||||
return bp;
|
||||
}
|
||||
|
||||
static char *outd(long n, FILE *f, char *bp) {
|
||||
unsigned long m;
|
||||
char buf[25], *s = buf + sizeof buf;
|
||||
|
||||
*--s = '\0';
|
||||
if (n < 0)
|
||||
m = -n;
|
||||
else
|
||||
m = n;
|
||||
do
|
||||
*--s = m%10 + '0';
|
||||
while ((m /= 10) != 0);
|
||||
if (n < 0)
|
||||
*--s = '-';
|
||||
return outs(s, f, bp);
|
||||
}
|
||||
|
||||
static char *outu(unsigned long n, int base, FILE *f, char *bp) {
|
||||
char buf[25], *s = buf + sizeof buf;
|
||||
|
||||
*--s = '\0';
|
||||
do
|
||||
*--s = "0123456789abcdef"[n%base];
|
||||
while ((n /= base) != 0);
|
||||
return outs(s, f, bp);
|
||||
}
|
||||
void print(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprint(stdout, NULL, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
/* fprint - formatted output to f */
|
||||
void fprint(FILE *f, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprint(f, NULL, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* stringf - formatted output to a saved string */
|
||||
char *stringf(const char *fmt, ...) {
|
||||
char buf[1024];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprint(NULL, buf, fmt, ap);
|
||||
va_end(ap);
|
||||
return string(buf);
|
||||
}
|
||||
|
||||
/* vfprint - formatted output to f or string bp */
|
||||
void vfprint(FILE *f, char *bp, const char *fmt, va_list ap) {
|
||||
for (; *fmt; fmt++)
|
||||
if (*fmt == '%')
|
||||
switch (*++fmt) {
|
||||
case 'd': bp = outd(va_arg(ap, int), f, bp); break;
|
||||
case 'D': bp = outd(va_arg(ap, long), f, bp); break;
|
||||
case 'U': bp = outu(va_arg(ap, unsigned long), 10, f, bp); break;
|
||||
case 'u': bp = outu(va_arg(ap, unsigned), 10, f, bp); break;
|
||||
case 'o': bp = outu(va_arg(ap, unsigned), 8, f, bp); break;
|
||||
case 'X': bp = outu(va_arg(ap, unsigned long), 16, f, bp); break;
|
||||
case 'x': bp = outu(va_arg(ap, unsigned), 16, f, bp); break;
|
||||
case 'f': case 'e':
|
||||
case 'g': {
|
||||
static char format[] = "%f";
|
||||
char buf[128];
|
||||
format[1] = *fmt;
|
||||
sprintf(buf, format, va_arg(ap, double));
|
||||
bp = outs(buf, f, bp);
|
||||
}
|
||||
; break;
|
||||
case 's': bp = outs(va_arg(ap, char *), f, bp); break;
|
||||
case 'p': {
|
||||
void *p = va_arg(ap, void *);
|
||||
if (p)
|
||||
bp = outs("0x", f, bp);
|
||||
bp = outu((unsigned long)p, 16, f, bp);
|
||||
break;
|
||||
}
|
||||
case 'c': if (f) fputc(va_arg(ap, int), f); else *bp++ = va_arg(ap, int); break;
|
||||
case 'S': { char *s = va_arg(ap, char *);
|
||||
int n = va_arg(ap, int);
|
||||
if (s)
|
||||
for ( ; n-- > 0; s++)
|
||||
if (f) (void)putc(*s, f); else *bp++ = *s;
|
||||
} break;
|
||||
case 'k': { int t = va_arg(ap, int);
|
||||
static char *tokens[] = {
|
||||
#define xx(a,b,c,d,e,f,g) g,
|
||||
#define yy(a,b,c,d,e,f,g) g,
|
||||
#include "token.h"
|
||||
};
|
||||
assert(tokens[t&0177]);
|
||||
bp = outs(tokens[t&0177], f, bp);
|
||||
} break;
|
||||
case 't': { Type ty = va_arg(ap, Type);
|
||||
assert(f);
|
||||
outtype(ty ? ty : voidtype, f);
|
||||
} break;
|
||||
case 'w': { Coordinate *p = va_arg(ap, Coordinate *);
|
||||
if (p->file && *p->file) {
|
||||
bp = outs(p->file, f, bp);
|
||||
bp = outs(":", f, bp);
|
||||
}
|
||||
bp = outd(p->y, f, bp);
|
||||
} break;
|
||||
case 'I': { int n = va_arg(ap, int);
|
||||
while (--n >= 0)
|
||||
if (f) (void)putc(' ', f); else *bp++ = ' ';
|
||||
} break;
|
||||
default: if (f) (void)putc(*fmt, f); else *bp++ = *fmt; break;
|
||||
}
|
||||
else if (f)
|
||||
(void)putc(*fmt, f);
|
||||
else
|
||||
*bp++ = *fmt;
|
||||
if (!f)
|
||||
*bp = '\0';
|
||||
}
|
||||
|
|
1330
lcc/src/pass2.c
Normal file → Executable file
1330
lcc/src/pass2.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
454
lcc/src/prof.c
Normal file → Executable file
454
lcc/src/prof.c
Normal file → Executable file
|
@ -1,227 +1,227 @@
|
|||
#include "c.h"
|
||||
|
||||
|
||||
struct callsite {
|
||||
char *file, *name;
|
||||
union coordinate {
|
||||
unsigned int coord;
|
||||
struct { unsigned int y:16,x:10,index:6; } le;
|
||||
struct { unsigned int index:6,x:10,y:16; } be;
|
||||
} u;
|
||||
};
|
||||
struct func {
|
||||
struct func *link;
|
||||
struct caller *callers;
|
||||
char *name;
|
||||
union coordinate src;
|
||||
};
|
||||
struct map { /* source code map; 200 coordinates/map */
|
||||
int size;
|
||||
union coordinate u[200];
|
||||
};
|
||||
|
||||
int npoints; /* # of execution points if -b specified */
|
||||
int ncalled = -1; /* #times prof.out says current function was called */
|
||||
static Symbol YYlink; /* symbol for file's struct _bbdata */
|
||||
static Symbol YYcounts; /* symbol for _YYcounts if -b specified */
|
||||
static List maplist; /* list of struct map *'s */
|
||||
static List filelist; /* list of file names */
|
||||
static Symbol funclist; /* list of struct func *'s */
|
||||
static Symbol afunc; /* current function's struct func */
|
||||
|
||||
/* bbcall - build tree to set _callsite at call site *cp, emit call site data */
|
||||
static void bbcall(Symbol yycounts, Coordinate *cp, Tree *e) {
|
||||
static Symbol caller;
|
||||
Value v;
|
||||
union coordinate u;
|
||||
Symbol p = genident(STATIC, array(voidptype, 0, 0), GLOBAL);
|
||||
Tree t = *e;
|
||||
|
||||
defglobal(p, LIT);
|
||||
defpointer(cp->file ? mkstr(cp->file)->u.c.loc : (Symbol)0);
|
||||
defpointer(mkstr(cfunc->name)->u.c.loc);
|
||||
if (IR->little_endian) {
|
||||
u.le.x = cp->x;
|
||||
u.le.y = cp->y;
|
||||
} else {
|
||||
u.be.x = cp->x;
|
||||
u.be.y = cp->y;
|
||||
}
|
||||
(*IR->defconst)(U, unsignedtype->size, (v.u = u.coord, v));
|
||||
if (caller == 0) {
|
||||
caller = mksymbol(EXTERN, "_caller", ptr(voidptype));
|
||||
caller->defined = 0;
|
||||
}
|
||||
if (generic((*e)->op) != CALL)
|
||||
t = (*e)->kids[0];
|
||||
assert(generic(t->op) == CALL);
|
||||
t = tree(t->op, t->type,
|
||||
tree(RIGHT, t->kids[0]->type,
|
||||
t->kids[0],
|
||||
tree(RIGHT, t->kids[0]->type, asgn(caller, idtree(p)), t->kids[0])),
|
||||
t->kids[1]);
|
||||
if (generic((*e)->op) != CALL)
|
||||
t = tree((*e)->op, (*e)->type, t, (*e)->kids[1]);
|
||||
*e = t;
|
||||
}
|
||||
|
||||
/* bbentry - return tree for _prologue(&afunc, &YYlink)' */
|
||||
static void bbentry(Symbol yylink, Symbol f) {
|
||||
static Symbol prologue;
|
||||
|
||||
afunc = genident(STATIC, array(voidptype, 4, 0), GLOBAL);
|
||||
if (prologue == 0) {
|
||||
prologue = mksymbol(EXTERN, "_prologue", ftype(inttype, voidptype));
|
||||
prologue->defined = 0;
|
||||
}
|
||||
walk(vcall(prologue, voidtype, pointer(idtree(afunc)), pointer(idtree(yylink)), NULL), 0, 0);
|
||||
|
||||
}
|
||||
|
||||
/* bbexit - return tree for _epilogue(&afunc)' */
|
||||
static void bbexit(Symbol yylink, Symbol f, Tree e) {
|
||||
static Symbol epilogue;
|
||||
|
||||
if (epilogue == 0) {
|
||||
epilogue = mksymbol(EXTERN, "_epilogue", ftype(inttype, voidptype));
|
||||
epilogue->defined = 0;
|
||||
}
|
||||
walk(vcall(epilogue, voidtype, pointer(idtree(afunc)), NULL), 0, 0);
|
||||
}
|
||||
|
||||
/* bbfile - add file to list of file names, return its index */
|
||||
static int bbfile(char *file) {
|
||||
if (file) {
|
||||
List lp;
|
||||
int i = 1;
|
||||
if ((lp = filelist) != NULL)
|
||||
do {
|
||||
lp = lp->link;
|
||||
if (((Symbol)lp->x)->u.c.v.p == file)
|
||||
return i;
|
||||
i++;
|
||||
} while (lp != filelist);
|
||||
filelist = append(mkstr(file), filelist);
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* bbfunc - emit function name and src coordinates */
|
||||
static void bbfunc(Symbol yylink, Symbol f) {
|
||||
Value v;
|
||||
union coordinate u;
|
||||
|
||||
defglobal(afunc, DATA);
|
||||
defpointer(funclist);
|
||||
defpointer(NULL);
|
||||
defpointer(mkstr(f->name)->u.c.loc);
|
||||
if (IR->little_endian) {
|
||||
u.le.x = f->u.f.pt.x;
|
||||
u.le.y = f->u.f.pt.y;
|
||||
u.le.index = bbfile(f->u.f.pt.file);
|
||||
} else {
|
||||
u.be.x = f->u.f.pt.x;
|
||||
u.be.y = f->u.f.pt.y;
|
||||
u.be.index = bbfile(f->u.f.pt.file);
|
||||
}
|
||||
(*IR->defconst)(U, unsignedtype->size, (v.u = u.coord, v));
|
||||
funclist = afunc;
|
||||
}
|
||||
|
||||
/* bbincr - build tree to increment execution point at *cp */
|
||||
static void bbincr(Symbol yycounts, Coordinate *cp, Tree *e) {
|
||||
struct map *mp = maplist->x;
|
||||
Tree t;
|
||||
|
||||
/* append *cp to source map */
|
||||
if (mp->size >= NELEMS(mp->u)) {
|
||||
NEW(mp, PERM);
|
||||
mp->size = 0;
|
||||
maplist = append(mp, maplist);
|
||||
}
|
||||
if (IR->little_endian) {
|
||||
mp->u[mp->size].le.x = cp->x;
|
||||
mp->u[mp->size].le.y = cp->y;
|
||||
mp->u[mp->size++].le.index = bbfile(cp->file);
|
||||
} else {
|
||||
mp->u[mp->size].be.x = cp->x;
|
||||
mp->u[mp->size].be.y = cp->y;
|
||||
mp->u[mp->size++].be.index = bbfile(cp->file);
|
||||
}
|
||||
t = incr('+', rvalue((*optree['+'])(ADD, pointer(idtree(yycounts)),
|
||||
consttree(npoints++, inttype))), consttree(1, inttype));
|
||||
if (*e)
|
||||
*e = tree(RIGHT, (*e)->type, t, *e);
|
||||
else
|
||||
*e = t;
|
||||
}
|
||||
|
||||
/* bbvars - emit definition for basic block counting data */
|
||||
static void bbvars(Symbol yylink) {
|
||||
int i, j, n = npoints;
|
||||
Value v;
|
||||
struct map **mp;
|
||||
Symbol coords, files, *p;
|
||||
|
||||
if (!YYcounts && !yylink)
|
||||
return;
|
||||
if (YYcounts) {
|
||||
if (n <= 0)
|
||||
n = 1;
|
||||
YYcounts->type = array(unsignedtype, n, 0);
|
||||
defglobal(YYcounts, BSS);
|
||||
}
|
||||
files = genident(STATIC, array(charptype, 1, 0), GLOBAL);
|
||||
defglobal(files, LIT);
|
||||
for (p = ltov(&filelist, PERM); *p; p++)
|
||||
defpointer((*p)->u.c.loc);
|
||||
defpointer(NULL);
|
||||
coords = genident(STATIC, array(unsignedtype, n, 0), GLOBAL);
|
||||
defglobal(coords, LIT);
|
||||
for (i = n, mp = ltov(&maplist, PERM); *mp; i -= (*mp)->size, mp++)
|
||||
for (j = 0; j < (*mp)->size; j++)
|
||||
(*IR->defconst)(U, unsignedtype->size, (v.u = (*mp)->u[j].coord, v));
|
||||
if (i > 0)
|
||||
(*IR->space)(i*coords->type->type->size);
|
||||
defpointer(NULL);
|
||||
defglobal(yylink, DATA);
|
||||
defpointer(NULL);
|
||||
(*IR->defconst)(U, unsignedtype->size, (v.u = n, v));
|
||||
defpointer(YYcounts);
|
||||
defpointer(coords);
|
||||
defpointer(files);
|
||||
defpointer(funclist);
|
||||
}
|
||||
|
||||
/* profInit - initialize basic block profiling options */
|
||||
void prof_init(int argc, char *argv[]) {
|
||||
int i;
|
||||
static int inited;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
inited = 1;
|
||||
type_init(argc, argv);
|
||||
if (IR)
|
||||
for (i = 1; i < argc; i++)
|
||||
if (strncmp(argv[i], "-a", 2) == 0) {
|
||||
if (ncalled == -1
|
||||
&& process(argv[i][2] ? &argv[i][2] : "prof.out") > 0)
|
||||
ncalled = 0;
|
||||
} else if ((strcmp(argv[i], "-b") == 0
|
||||
|| strcmp(argv[i], "-C") == 0) && YYlink == 0) {
|
||||
YYlink = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL);
|
||||
attach((Apply)bbentry, YYlink, &events.entry);
|
||||
attach((Apply)bbexit, YYlink, &events.returns);
|
||||
attach((Apply)bbfunc, YYlink, &events.exit);
|
||||
attach((Apply)bbvars, YYlink, &events.end);
|
||||
if (strcmp(argv[i], "-b") == 0) {
|
||||
YYcounts = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL);
|
||||
maplist = append(allocate(sizeof (struct map), PERM), maplist);
|
||||
((struct map *)maplist->x)->size = 0;
|
||||
attach((Apply)bbcall, YYcounts, &events.calls);
|
||||
attach((Apply)bbincr, YYcounts, &events.points);
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "c.h"
|
||||
|
||||
|
||||
struct callsite {
|
||||
char *file, *name;
|
||||
union coordinate {
|
||||
unsigned int coord;
|
||||
struct { unsigned int y:16,x:10,index:6; } le;
|
||||
struct { unsigned int index:6,x:10,y:16; } be;
|
||||
} u;
|
||||
};
|
||||
struct func {
|
||||
struct func *link;
|
||||
struct caller *callers;
|
||||
char *name;
|
||||
union coordinate src;
|
||||
};
|
||||
struct map { /* source code map; 200 coordinates/map */
|
||||
int size;
|
||||
union coordinate u[200];
|
||||
};
|
||||
|
||||
int npoints; /* # of execution points if -b specified */
|
||||
int ncalled = -1; /* #times prof.out says current function was called */
|
||||
static Symbol YYlink; /* symbol for file's struct _bbdata */
|
||||
static Symbol YYcounts; /* symbol for _YYcounts if -b specified */
|
||||
static List maplist; /* list of struct map *'s */
|
||||
static List filelist; /* list of file names */
|
||||
static Symbol funclist; /* list of struct func *'s */
|
||||
static Symbol afunc; /* current function's struct func */
|
||||
|
||||
/* bbcall - build tree to set _callsite at call site *cp, emit call site data */
|
||||
static void bbcall(Symbol yycounts, Coordinate *cp, Tree *e) {
|
||||
static Symbol caller;
|
||||
Value v;
|
||||
union coordinate u;
|
||||
Symbol p = genident(STATIC, array(voidptype, 0, 0), GLOBAL);
|
||||
Tree t = *e;
|
||||
|
||||
defglobal(p, LIT);
|
||||
defpointer(cp->file ? mkstr(cp->file)->u.c.loc : (Symbol)0);
|
||||
defpointer(mkstr(cfunc->name)->u.c.loc);
|
||||
if (IR->little_endian) {
|
||||
u.le.x = cp->x;
|
||||
u.le.y = cp->y;
|
||||
} else {
|
||||
u.be.x = cp->x;
|
||||
u.be.y = cp->y;
|
||||
}
|
||||
(*IR->defconst)(U, unsignedtype->size, (v.u = u.coord, v));
|
||||
if (caller == 0) {
|
||||
caller = mksymbol(EXTERN, "_caller", ptr(voidptype));
|
||||
caller->defined = 0;
|
||||
}
|
||||
if (generic((*e)->op) != CALL)
|
||||
t = (*e)->kids[0];
|
||||
assert(generic(t->op) == CALL);
|
||||
t = tree(t->op, t->type,
|
||||
tree(RIGHT, t->kids[0]->type,
|
||||
t->kids[0],
|
||||
tree(RIGHT, t->kids[0]->type, asgn(caller, idtree(p)), t->kids[0])),
|
||||
t->kids[1]);
|
||||
if (generic((*e)->op) != CALL)
|
||||
t = tree((*e)->op, (*e)->type, t, (*e)->kids[1]);
|
||||
*e = t;
|
||||
}
|
||||
|
||||
/* bbentry - return tree for _prologue(&afunc, &YYlink)' */
|
||||
static void bbentry(Symbol yylink, Symbol f) {
|
||||
static Symbol prologue;
|
||||
|
||||
afunc = genident(STATIC, array(voidptype, 4, 0), GLOBAL);
|
||||
if (prologue == 0) {
|
||||
prologue = mksymbol(EXTERN, "_prologue", ftype(inttype, voidptype));
|
||||
prologue->defined = 0;
|
||||
}
|
||||
walk(vcall(prologue, voidtype, pointer(idtree(afunc)), pointer(idtree(yylink)), NULL), 0, 0);
|
||||
|
||||
}
|
||||
|
||||
/* bbexit - return tree for _epilogue(&afunc)' */
|
||||
static void bbexit(Symbol yylink, Symbol f, Tree e) {
|
||||
static Symbol epilogue;
|
||||
|
||||
if (epilogue == 0) {
|
||||
epilogue = mksymbol(EXTERN, "_epilogue", ftype(inttype, voidptype));
|
||||
epilogue->defined = 0;
|
||||
}
|
||||
walk(vcall(epilogue, voidtype, pointer(idtree(afunc)), NULL), 0, 0);
|
||||
}
|
||||
|
||||
/* bbfile - add file to list of file names, return its index */
|
||||
static int bbfile(char *file) {
|
||||
if (file) {
|
||||
List lp;
|
||||
int i = 1;
|
||||
if ((lp = filelist) != NULL)
|
||||
do {
|
||||
lp = lp->link;
|
||||
if (((Symbol)lp->x)->u.c.v.p == file)
|
||||
return i;
|
||||
i++;
|
||||
} while (lp != filelist);
|
||||
filelist = append(mkstr(file), filelist);
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* bbfunc - emit function name and src coordinates */
|
||||
static void bbfunc(Symbol yylink, Symbol f) {
|
||||
Value v;
|
||||
union coordinate u;
|
||||
|
||||
defglobal(afunc, DATA);
|
||||
defpointer(funclist);
|
||||
defpointer(NULL);
|
||||
defpointer(mkstr(f->name)->u.c.loc);
|
||||
if (IR->little_endian) {
|
||||
u.le.x = f->u.f.pt.x;
|
||||
u.le.y = f->u.f.pt.y;
|
||||
u.le.index = bbfile(f->u.f.pt.file);
|
||||
} else {
|
||||
u.be.x = f->u.f.pt.x;
|
||||
u.be.y = f->u.f.pt.y;
|
||||
u.be.index = bbfile(f->u.f.pt.file);
|
||||
}
|
||||
(*IR->defconst)(U, unsignedtype->size, (v.u = u.coord, v));
|
||||
funclist = afunc;
|
||||
}
|
||||
|
||||
/* bbincr - build tree to increment execution point at *cp */
|
||||
static void bbincr(Symbol yycounts, Coordinate *cp, Tree *e) {
|
||||
struct map *mp = maplist->x;
|
||||
Tree t;
|
||||
|
||||
/* append *cp to source map */
|
||||
if (mp->size >= NELEMS(mp->u)) {
|
||||
NEW(mp, PERM);
|
||||
mp->size = 0;
|
||||
maplist = append(mp, maplist);
|
||||
}
|
||||
if (IR->little_endian) {
|
||||
mp->u[mp->size].le.x = cp->x;
|
||||
mp->u[mp->size].le.y = cp->y;
|
||||
mp->u[mp->size++].le.index = bbfile(cp->file);
|
||||
} else {
|
||||
mp->u[mp->size].be.x = cp->x;
|
||||
mp->u[mp->size].be.y = cp->y;
|
||||
mp->u[mp->size++].be.index = bbfile(cp->file);
|
||||
}
|
||||
t = incr('+', rvalue((*optree['+'])(ADD, pointer(idtree(yycounts)),
|
||||
consttree(npoints++, inttype))), consttree(1, inttype));
|
||||
if (*e)
|
||||
*e = tree(RIGHT, (*e)->type, t, *e);
|
||||
else
|
||||
*e = t;
|
||||
}
|
||||
|
||||
/* bbvars - emit definition for basic block counting data */
|
||||
static void bbvars(Symbol yylink) {
|
||||
int i, j, n = npoints;
|
||||
Value v;
|
||||
struct map **mp;
|
||||
Symbol coords, files, *p;
|
||||
|
||||
if (!YYcounts && !yylink)
|
||||
return;
|
||||
if (YYcounts) {
|
||||
if (n <= 0)
|
||||
n = 1;
|
||||
YYcounts->type = array(unsignedtype, n, 0);
|
||||
defglobal(YYcounts, BSS);
|
||||
}
|
||||
files = genident(STATIC, array(charptype, 1, 0), GLOBAL);
|
||||
defglobal(files, LIT);
|
||||
for (p = ltov(&filelist, PERM); *p; p++)
|
||||
defpointer((*p)->u.c.loc);
|
||||
defpointer(NULL);
|
||||
coords = genident(STATIC, array(unsignedtype, n, 0), GLOBAL);
|
||||
defglobal(coords, LIT);
|
||||
for (i = n, mp = ltov(&maplist, PERM); *mp; i -= (*mp)->size, mp++)
|
||||
for (j = 0; j < (*mp)->size; j++)
|
||||
(*IR->defconst)(U, unsignedtype->size, (v.u = (*mp)->u[j].coord, v));
|
||||
if (i > 0)
|
||||
(*IR->space)(i*coords->type->type->size);
|
||||
defpointer(NULL);
|
||||
defglobal(yylink, DATA);
|
||||
defpointer(NULL);
|
||||
(*IR->defconst)(U, unsignedtype->size, (v.u = n, v));
|
||||
defpointer(YYcounts);
|
||||
defpointer(coords);
|
||||
defpointer(files);
|
||||
defpointer(funclist);
|
||||
}
|
||||
|
||||
/* profInit - initialize basic block profiling options */
|
||||
void prof_init(int argc, char *argv[]) {
|
||||
int i;
|
||||
static int inited;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
inited = 1;
|
||||
type_init(argc, argv);
|
||||
if (IR)
|
||||
for (i = 1; i < argc; i++)
|
||||
if (strncmp(argv[i], "-a", 2) == 0) {
|
||||
if (ncalled == -1
|
||||
&& process(argv[i][2] ? &argv[i][2] : "prof.out") > 0)
|
||||
ncalled = 0;
|
||||
} else if ((strcmp(argv[i], "-b") == 0
|
||||
|| strcmp(argv[i], "-C") == 0) && YYlink == 0) {
|
||||
YYlink = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL);
|
||||
attach((Apply)bbentry, YYlink, &events.entry);
|
||||
attach((Apply)bbexit, YYlink, &events.returns);
|
||||
attach((Apply)bbfunc, YYlink, &events.exit);
|
||||
attach((Apply)bbvars, YYlink, &events.end);
|
||||
if (strcmp(argv[i], "-b") == 0) {
|
||||
YYcounts = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL);
|
||||
maplist = append(allocate(sizeof (struct map), PERM), maplist);
|
||||
((struct map *)maplist->x)->size = 0;
|
||||
attach((Apply)bbcall, YYcounts, &events.calls);
|
||||
attach((Apply)bbincr, YYcounts, &events.points);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
552
lcc/src/profio.c
Normal file → Executable file
552
lcc/src/profio.c
Normal file → Executable file
|
@ -1,276 +1,276 @@
|
|||
/* C compiler: prof.out input
|
||||
|
||||
prof.out format:
|
||||
#files
|
||||
name
|
||||
... (#files-1 times)
|
||||
#functions
|
||||
name file# x y count caller file x y
|
||||
... (#functions-1 times)
|
||||
#points
|
||||
file# x y count
|
||||
... (#points-1 times)
|
||||
*/
|
||||
#include "c.h"
|
||||
|
||||
|
||||
struct count { /* count data: */
|
||||
int x, y; /* source coordinate */
|
||||
int count; /* associated execution count */
|
||||
};
|
||||
|
||||
#define MAXTOKEN 64
|
||||
|
||||
struct file { /* per-file prof.out data: */
|
||||
struct file *link; /* link to next file */
|
||||
char *name; /* file name */
|
||||
int size; /* size of counts[] */
|
||||
int count; /* counts[0..count-1] hold valid data */
|
||||
struct count *counts; /* count data */
|
||||
struct func { /* function data: */
|
||||
struct func *link; /* link to next function */
|
||||
char *name; /* function name */
|
||||
struct count count; /* total number of calls */
|
||||
struct caller { /* caller data: */
|
||||
struct caller *link; /* link to next caller */
|
||||
char *name; /* caller's name */
|
||||
char *file; /* call site: file, x, y */
|
||||
int x, y;
|
||||
int count; /* number of calls from this site */
|
||||
} *callers;
|
||||
} *funcs; /* list of functions */
|
||||
} *filelist;
|
||||
FILE *fp;
|
||||
|
||||
/* acaller - add caller and site (file,x,y) to callee's callers list */
|
||||
static void acaller(char *caller, char *file, int x, int y, int count, struct func *callee) {
|
||||
struct caller *q;
|
||||
|
||||
assert(callee);
|
||||
for (q = callee->callers; q && (caller != q->name
|
||||
|| file != q->file || x != q->x || y != q->y); q = q->link)
|
||||
;
|
||||
if (!q) {
|
||||
struct caller **r;
|
||||
NEW(q, PERM);
|
||||
q->name = caller;
|
||||
q->file = file;
|
||||
q->x = x;
|
||||
q->y = y;
|
||||
q->count = 0;
|
||||
for (r = &callee->callers; *r && (strcmp(q->name, (*r)->name) > 0
|
||||
|| strcmp(q->file, (*r)->file) > 0 || q->y > (*r)->y || q->y > (*r)->y); r = &(*r)->link)
|
||||
;
|
||||
q->link = *r;
|
||||
*r = q;
|
||||
}
|
||||
q->count += count;
|
||||
}
|
||||
|
||||
/* compare - return <0, 0, >0 if a<b, a==b, a>b, resp. */
|
||||
static int compare(struct count *a, struct count *b) {
|
||||
if (a->y == b->y)
|
||||
return a->x - b->x;
|
||||
return a->y - b->y;
|
||||
}
|
||||
|
||||
/* findfile - return file name's file list entry, or 0 */
|
||||
static struct file *findfile(char *name) {
|
||||
struct file *p;
|
||||
|
||||
for (p = filelist; p; p = p->link)
|
||||
if (p->name == name)
|
||||
return p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* afunction - add function name and its data to file's function list */
|
||||
static struct func *afunction(char *name, char *file, int x, int y, int count) {
|
||||
struct file *p = findfile(file);
|
||||
struct func *q;
|
||||
|
||||
assert(p);
|
||||
for (q = p->funcs; q && name != q->name; q = q->link)
|
||||
;
|
||||
if (!q) {
|
||||
struct func **r;
|
||||
NEW(q, PERM);
|
||||
q->name = name;
|
||||
q->count.x = x;
|
||||
q->count.y = y;
|
||||
q->count.count = 0;
|
||||
q->callers = 0;
|
||||
for (r = &p->funcs; *r && compare(&q->count, &(*r)->count) > 0; r = &(*r)->link)
|
||||
;
|
||||
q->link = *r;
|
||||
*r = q;
|
||||
}
|
||||
q->count.count += count;
|
||||
return q;
|
||||
}
|
||||
|
||||
/* apoint - append execution point i to file's data */
|
||||
static void apoint(int i, char *file, int x, int y, int count) {
|
||||
struct file *p = findfile(file);
|
||||
|
||||
assert(p);
|
||||
if (i >= p->size) {
|
||||
int j;
|
||||
if (p->size == 0) {
|
||||
p->size = i >= 200 ? 2*i : 200;
|
||||
p->counts = newarray(p->size, sizeof *p->counts, PERM);
|
||||
} else {
|
||||
struct count *new;
|
||||
p->size = 2*i;
|
||||
new = newarray(p->size, sizeof *new, PERM);
|
||||
for (j = 0; j < p->count; j++)
|
||||
new[j] = p->counts[j];
|
||||
p->counts = new;
|
||||
}
|
||||
for (j = p->count; j < p->size; j++) {
|
||||
static struct count z;
|
||||
p->counts[j] = z;
|
||||
}
|
||||
}
|
||||
p->counts[i].x = x;
|
||||
p->counts[i].y = y;
|
||||
p->counts[i].count += count;
|
||||
if (i >= p->count)
|
||||
p->count = i + 1;
|
||||
}
|
||||
|
||||
/* findcount - return count associated with (file,x,y) or -1 */
|
||||
int findcount(char *file, int x, int y) {
|
||||
static struct file *cursor;
|
||||
|
||||
if (cursor == 0 || cursor->name != file)
|
||||
cursor = findfile(file);
|
||||
if (cursor) {
|
||||
int l, u;
|
||||
struct count *c = cursor->counts;
|
||||
for (l = 0, u = cursor->count - 1; l <= u; ) {
|
||||
int k = (l + u)/2;
|
||||
if (c[k].y > y || c[k].y == y && c[k].x > x)
|
||||
u = k - 1;
|
||||
else if (c[k].y < y || c[k].y == y && c[k].x < x)
|
||||
l = k + 1;
|
||||
else
|
||||
return c[k].count;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* findfunc - return count associated with function name in file or -1 */
|
||||
int findfunc(char *name, char *file) {
|
||||
static struct file *cursor;
|
||||
|
||||
if (cursor == 0 || cursor->name != file)
|
||||
cursor = findfile(file);
|
||||
if (cursor) {
|
||||
struct func *p;
|
||||
for (p = cursor->funcs; p; p = p->link)
|
||||
if (p->name == name)
|
||||
return p->count.count;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* getd - read a nonnegative number */
|
||||
static int getd(void) {
|
||||
int c, n = 0;
|
||||
|
||||
while ((c = getc(fp)) != EOF && (c == ' ' || c == '\n' || c == '\t'))
|
||||
;
|
||||
if (c >= '0' && c <= '9') {
|
||||
do
|
||||
n = 10*n + (c - '0');
|
||||
while ((c = getc(fp)) >= '0' && c <= '9');
|
||||
return n;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* getstr - read a string */
|
||||
static char *getstr(void) {
|
||||
int c;
|
||||
char buf[MAXTOKEN], *s = buf;
|
||||
|
||||
while ((c = getc(fp)) != EOF && c != ' ' && c != '\n' && c != '\t')
|
||||
if (s - buf < (int)sizeof buf - 2)
|
||||
*s++ = c;
|
||||
*s = 0;
|
||||
return s == buf ? (char *)0 : string(buf);
|
||||
}
|
||||
|
||||
/* gather - read prof.out data from fd */
|
||||
static int gather(void) {
|
||||
int i, nfiles, nfuncs, npoints;
|
||||
char *files[64];
|
||||
|
||||
if ((nfiles = getd()) < 0)
|
||||
return 0;
|
||||
assert(nfiles < NELEMS(files));
|
||||
for (i = 0; i < nfiles; i++) {
|
||||
if ((files[i] = getstr()) == 0)
|
||||
return -1;
|
||||
if (!findfile(files[i])) {
|
||||
struct file *new;
|
||||
NEW(new, PERM);
|
||||
new->name = files[i];
|
||||
new->size = new->count = 0;
|
||||
new->counts = 0;
|
||||
new->funcs = 0;
|
||||
new->link = filelist;
|
||||
filelist = new;
|
||||
}
|
||||
}
|
||||
if ((nfuncs = getd()) < 0)
|
||||
return -1;
|
||||
for (i = 0; i < nfuncs; i++) {
|
||||
struct func *q;
|
||||
char *name, *file;
|
||||
int f, x, y, count;
|
||||
if ((name = getstr()) == 0 || (f = getd()) <= 0
|
||||
|| (x = getd()) < 0 || (y = getd()) < 0 || (count = getd()) < 0)
|
||||
return -1;
|
||||
q = afunction(name, files[f-1], x, y, count);
|
||||
if ((name = getstr()) == 0 || (file = getstr()) == 0
|
||||
|| (x = getd()) < 0 || (y = getd()) < 0)
|
||||
return -1;
|
||||
if (*name != '?')
|
||||
acaller(name, file, x, y, count, q);
|
||||
}
|
||||
if ((npoints = getd()) < 0)
|
||||
return -1;
|
||||
for (i = 0; i < npoints; i++) {
|
||||
int f, x, y, count;
|
||||
if ((f = getd()) < 0 || (x = getd()) < 0 || (y = getd()) < 0
|
||||
|| (count = getd()) < 0)
|
||||
return -1;
|
||||
if (f)
|
||||
apoint(i, files[f-1], x, y, count);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* process - read prof.out data from file */
|
||||
int process(char *file) {
|
||||
int more;
|
||||
|
||||
if ((fp = fopen(file, "r")) != NULL) {
|
||||
struct file *p;
|
||||
while ((more = gather()) > 0)
|
||||
;
|
||||
fclose(fp);
|
||||
if (more < 0)
|
||||
return more;
|
||||
for (p = filelist; p; p = p->link)
|
||||
qsort(p->counts, p->count, sizeof *p->counts,
|
||||
(int (*)(const void *, const void *))
|
||||
compare);
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* C compiler: prof.out input
|
||||
|
||||
prof.out format:
|
||||
#files
|
||||
name
|
||||
... (#files-1 times)
|
||||
#functions
|
||||
name file# x y count caller file x y
|
||||
... (#functions-1 times)
|
||||
#points
|
||||
file# x y count
|
||||
... (#points-1 times)
|
||||
*/
|
||||
#include "c.h"
|
||||
|
||||
|
||||
struct count { /* count data: */
|
||||
int x, y; /* source coordinate */
|
||||
int count; /* associated execution count */
|
||||
};
|
||||
|
||||
#define MAXTOKEN 64
|
||||
|
||||
struct file { /* per-file prof.out data: */
|
||||
struct file *link; /* link to next file */
|
||||
char *name; /* file name */
|
||||
int size; /* size of counts[] */
|
||||
int count; /* counts[0..count-1] hold valid data */
|
||||
struct count *counts; /* count data */
|
||||
struct func { /* function data: */
|
||||
struct func *link; /* link to next function */
|
||||
char *name; /* function name */
|
||||
struct count count; /* total number of calls */
|
||||
struct caller { /* caller data: */
|
||||
struct caller *link; /* link to next caller */
|
||||
char *name; /* caller's name */
|
||||
char *file; /* call site: file, x, y */
|
||||
int x, y;
|
||||
int count; /* number of calls from this site */
|
||||
} *callers;
|
||||
} *funcs; /* list of functions */
|
||||
} *filelist;
|
||||
FILE *fp;
|
||||
|
||||
/* acaller - add caller and site (file,x,y) to callee's callers list */
|
||||
static void acaller(char *caller, char *file, int x, int y, int count, struct func *callee) {
|
||||
struct caller *q;
|
||||
|
||||
assert(callee);
|
||||
for (q = callee->callers; q && (caller != q->name
|
||||
|| file != q->file || x != q->x || y != q->y); q = q->link)
|
||||
;
|
||||
if (!q) {
|
||||
struct caller **r;
|
||||
NEW(q, PERM);
|
||||
q->name = caller;
|
||||
q->file = file;
|
||||
q->x = x;
|
||||
q->y = y;
|
||||
q->count = 0;
|
||||
for (r = &callee->callers; *r && (strcmp(q->name, (*r)->name) > 0
|
||||
|| strcmp(q->file, (*r)->file) > 0 || q->y > (*r)->y || q->y > (*r)->y); r = &(*r)->link)
|
||||
;
|
||||
q->link = *r;
|
||||
*r = q;
|
||||
}
|
||||
q->count += count;
|
||||
}
|
||||
|
||||
/* compare - return <0, 0, >0 if a<b, a==b, a>b, resp. */
|
||||
static int compare(struct count *a, struct count *b) {
|
||||
if (a->y == b->y)
|
||||
return a->x - b->x;
|
||||
return a->y - b->y;
|
||||
}
|
||||
|
||||
/* findfile - return file name's file list entry, or 0 */
|
||||
static struct file *findfile(char *name) {
|
||||
struct file *p;
|
||||
|
||||
for (p = filelist; p; p = p->link)
|
||||
if (p->name == name)
|
||||
return p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* afunction - add function name and its data to file's function list */
|
||||
static struct func *afunction(char *name, char *file, int x, int y, int count) {
|
||||
struct file *p = findfile(file);
|
||||
struct func *q;
|
||||
|
||||
assert(p);
|
||||
for (q = p->funcs; q && name != q->name; q = q->link)
|
||||
;
|
||||
if (!q) {
|
||||
struct func **r;
|
||||
NEW(q, PERM);
|
||||
q->name = name;
|
||||
q->count.x = x;
|
||||
q->count.y = y;
|
||||
q->count.count = 0;
|
||||
q->callers = 0;
|
||||
for (r = &p->funcs; *r && compare(&q->count, &(*r)->count) > 0; r = &(*r)->link)
|
||||
;
|
||||
q->link = *r;
|
||||
*r = q;
|
||||
}
|
||||
q->count.count += count;
|
||||
return q;
|
||||
}
|
||||
|
||||
/* apoint - append execution point i to file's data */
|
||||
static void apoint(int i, char *file, int x, int y, int count) {
|
||||
struct file *p = findfile(file);
|
||||
|
||||
assert(p);
|
||||
if (i >= p->size) {
|
||||
int j;
|
||||
if (p->size == 0) {
|
||||
p->size = i >= 200 ? 2*i : 200;
|
||||
p->counts = newarray(p->size, sizeof *p->counts, PERM);
|
||||
} else {
|
||||
struct count *new;
|
||||
p->size = 2*i;
|
||||
new = newarray(p->size, sizeof *new, PERM);
|
||||
for (j = 0; j < p->count; j++)
|
||||
new[j] = p->counts[j];
|
||||
p->counts = new;
|
||||
}
|
||||
for (j = p->count; j < p->size; j++) {
|
||||
static struct count z;
|
||||
p->counts[j] = z;
|
||||
}
|
||||
}
|
||||
p->counts[i].x = x;
|
||||
p->counts[i].y = y;
|
||||
p->counts[i].count += count;
|
||||
if (i >= p->count)
|
||||
p->count = i + 1;
|
||||
}
|
||||
|
||||
/* findcount - return count associated with (file,x,y) or -1 */
|
||||
int findcount(char *file, int x, int y) {
|
||||
static struct file *cursor;
|
||||
|
||||
if (cursor == 0 || cursor->name != file)
|
||||
cursor = findfile(file);
|
||||
if (cursor) {
|
||||
int l, u;
|
||||
struct count *c = cursor->counts;
|
||||
for (l = 0, u = cursor->count - 1; l <= u; ) {
|
||||
int k = (l + u)/2;
|
||||
if (c[k].y > y || c[k].y == y && c[k].x > x)
|
||||
u = k - 1;
|
||||
else if (c[k].y < y || c[k].y == y && c[k].x < x)
|
||||
l = k + 1;
|
||||
else
|
||||
return c[k].count;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* findfunc - return count associated with function name in file or -1 */
|
||||
int findfunc(char *name, char *file) {
|
||||
static struct file *cursor;
|
||||
|
||||
if (cursor == 0 || cursor->name != file)
|
||||
cursor = findfile(file);
|
||||
if (cursor) {
|
||||
struct func *p;
|
||||
for (p = cursor->funcs; p; p = p->link)
|
||||
if (p->name == name)
|
||||
return p->count.count;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* getd - read a nonnegative number */
|
||||
static int getd(void) {
|
||||
int c, n = 0;
|
||||
|
||||
while ((c = getc(fp)) != EOF && (c == ' ' || c == '\n' || c == '\t'))
|
||||
;
|
||||
if (c >= '0' && c <= '9') {
|
||||
do
|
||||
n = 10*n + (c - '0');
|
||||
while ((c = getc(fp)) >= '0' && c <= '9');
|
||||
return n;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* getstr - read a string */
|
||||
static char *getstr(void) {
|
||||
int c;
|
||||
char buf[MAXTOKEN], *s = buf;
|
||||
|
||||
while ((c = getc(fp)) != EOF && c != ' ' && c != '\n' && c != '\t')
|
||||
if (s - buf < (int)sizeof buf - 2)
|
||||
*s++ = c;
|
||||
*s = 0;
|
||||
return s == buf ? (char *)0 : string(buf);
|
||||
}
|
||||
|
||||
/* gather - read prof.out data from fd */
|
||||
static int gather(void) {
|
||||
int i, nfiles, nfuncs, npoints;
|
||||
char *files[64];
|
||||
|
||||
if ((nfiles = getd()) < 0)
|
||||
return 0;
|
||||
assert(nfiles < NELEMS(files));
|
||||
for (i = 0; i < nfiles; i++) {
|
||||
if ((files[i] = getstr()) == 0)
|
||||
return -1;
|
||||
if (!findfile(files[i])) {
|
||||
struct file *new;
|
||||
NEW(new, PERM);
|
||||
new->name = files[i];
|
||||
new->size = new->count = 0;
|
||||
new->counts = 0;
|
||||
new->funcs = 0;
|
||||
new->link = filelist;
|
||||
filelist = new;
|
||||
}
|
||||
}
|
||||
if ((nfuncs = getd()) < 0)
|
||||
return -1;
|
||||
for (i = 0; i < nfuncs; i++) {
|
||||
struct func *q;
|
||||
char *name, *file;
|
||||
int f, x, y, count;
|
||||
if ((name = getstr()) == 0 || (f = getd()) <= 0
|
||||
|| (x = getd()) < 0 || (y = getd()) < 0 || (count = getd()) < 0)
|
||||
return -1;
|
||||
q = afunction(name, files[f-1], x, y, count);
|
||||
if ((name = getstr()) == 0 || (file = getstr()) == 0
|
||||
|| (x = getd()) < 0 || (y = getd()) < 0)
|
||||
return -1;
|
||||
if (*name != '?')
|
||||
acaller(name, file, x, y, count, q);
|
||||
}
|
||||
if ((npoints = getd()) < 0)
|
||||
return -1;
|
||||
for (i = 0; i < npoints; i++) {
|
||||
int f, x, y, count;
|
||||
if ((f = getd()) < 0 || (x = getd()) < 0 || (y = getd()) < 0
|
||||
|| (count = getd()) < 0)
|
||||
return -1;
|
||||
if (f)
|
||||
apoint(i, files[f-1], x, y, count);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* process - read prof.out data from file */
|
||||
int process(char *file) {
|
||||
int more;
|
||||
|
||||
if ((fp = fopen(file, "r")) != NULL) {
|
||||
struct file *p;
|
||||
while ((more = gather()) > 0)
|
||||
;
|
||||
fclose(fp);
|
||||
if (more < 0)
|
||||
return more;
|
||||
for (p = filelist; p; p = p->link)
|
||||
qsort(p->counts, p->count, sizeof *p->counts,
|
||||
(int (*)(const void *, const void *))
|
||||
compare);
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
140
lcc/src/rcc.asdl
Normal file → Executable file
140
lcc/src/rcc.asdl
Normal file → Executable file
|
@ -1,70 +1,70 @@
|
|||
-- lcc IR
|
||||
-- $Id: rcc.asdl 145 2001-10-17 21:53:10Z timo $
|
||||
module rcc {
|
||||
|
||||
-- Pickles start with an int version number, followed by rcc.program
|
||||
|
||||
program = (int nuids,int nlabels,item* items,interface* interfaces,int argc,string *argv)
|
||||
|
||||
real = (int msb,int lsb)
|
||||
|
||||
item = Symbol(symbol symbol)
|
||||
| Type(type type)
|
||||
attributes(int uid)
|
||||
|
||||
symbol = (identifier id,int type,int scope,int sclass,int ref,int flags)
|
||||
|
||||
field = (identifier id,int type,int offset,int bitsize,int lsb)
|
||||
|
||||
enum = (identifier id,int value)
|
||||
|
||||
type = INT
|
||||
| UNSIGNED
|
||||
| FLOAT
|
||||
| VOID
|
||||
| POINTER(int type)
|
||||
| ENUM(identifier tag,enum* ids)
|
||||
| STRUCT(identifier tag,field* fields)
|
||||
| UNION(identifier tag,field* fields)
|
||||
| ARRAY(int type)
|
||||
| FUNCTION(int type,int* formals)
|
||||
| CONST(int type)
|
||||
| VOLATILE(int type)
|
||||
attributes(int size,int align)
|
||||
|
||||
interface = Export(int p)
|
||||
| Import(int p)
|
||||
| Global(int p,int seg)
|
||||
| Local(int uid,symbol p) -- includes formals
|
||||
| Address(int uid,symbol q,int p,int n)
|
||||
| Segment(int seg)
|
||||
| Defaddress(int p)
|
||||
| Deflabel(int label)
|
||||
| Defconst(int suffix,int size,int value)
|
||||
| Defconstf(int size,real value)
|
||||
| Defstring(string s)
|
||||
| Space(int n)
|
||||
| Function(int f,int* caller,int* callee,int ncalls,interface* codelist)
|
||||
| Blockbeg
|
||||
| Blockend
|
||||
| Forest(node* nodes)
|
||||
|
||||
node = CNST(int value)
|
||||
| CNSTF(real value)
|
||||
| ARG(node left,int len,int align)
|
||||
| ASGN(node left,node right,int len,int align)
|
||||
| CVT(int op,node left,int fromsize)
|
||||
| CALL(node left,int type)
|
||||
| CALLB(node left,node right,int type)
|
||||
| RET
|
||||
| ADDRG(int uid)
|
||||
| ADDRL(int uid)
|
||||
| ADDRF(int uid)
|
||||
| Unary(int op,node left) -- INDIR RET JUMP NEG BCOM
|
||||
| Binary(int op,node left,node right) -- ADD SUB DIV MUL MOD BOR BAND BXOR RSH LSH
|
||||
| Compare(int op,node left,node right,int label) -- EQ NE GT GE LE LT
|
||||
| LABEL(int label)
|
||||
| BRANCH(int label)
|
||||
| CSE(int uid,node node)
|
||||
attributes(int suffix,int size)
|
||||
}
|
||||
-- lcc IR
|
||||
-- $Id: rcc.asdl 145 2001-10-17 21:53:10Z timo $
|
||||
module rcc {
|
||||
|
||||
-- Pickles start with an int version number, followed by rcc.program
|
||||
|
||||
program = (int nuids,int nlabels,item* items,interface* interfaces,int argc,string *argv)
|
||||
|
||||
real = (int msb,int lsb)
|
||||
|
||||
item = Symbol(symbol symbol)
|
||||
| Type(type type)
|
||||
attributes(int uid)
|
||||
|
||||
symbol = (identifier id,int type,int scope,int sclass,int ref,int flags)
|
||||
|
||||
field = (identifier id,int type,int offset,int bitsize,int lsb)
|
||||
|
||||
enum = (identifier id,int value)
|
||||
|
||||
type = INT
|
||||
| UNSIGNED
|
||||
| FLOAT
|
||||
| VOID
|
||||
| POINTER(int type)
|
||||
| ENUM(identifier tag,enum* ids)
|
||||
| STRUCT(identifier tag,field* fields)
|
||||
| UNION(identifier tag,field* fields)
|
||||
| ARRAY(int type)
|
||||
| FUNCTION(int type,int* formals)
|
||||
| CONST(int type)
|
||||
| VOLATILE(int type)
|
||||
attributes(int size,int align)
|
||||
|
||||
interface = Export(int p)
|
||||
| Import(int p)
|
||||
| Global(int p,int seg)
|
||||
| Local(int uid,symbol p) -- includes formals
|
||||
| Address(int uid,symbol q,int p,int n)
|
||||
| Segment(int seg)
|
||||
| Defaddress(int p)
|
||||
| Deflabel(int label)
|
||||
| Defconst(int suffix,int size,int value)
|
||||
| Defconstf(int size,real value)
|
||||
| Defstring(string s)
|
||||
| Space(int n)
|
||||
| Function(int f,int* caller,int* callee,int ncalls,interface* codelist)
|
||||
| Blockbeg
|
||||
| Blockend
|
||||
| Forest(node* nodes)
|
||||
|
||||
node = CNST(int value)
|
||||
| CNSTF(real value)
|
||||
| ARG(node left,int len,int align)
|
||||
| ASGN(node left,node right,int len,int align)
|
||||
| CVT(int op,node left,int fromsize)
|
||||
| CALL(node left,int type)
|
||||
| CALLB(node left,node right,int type)
|
||||
| RET
|
||||
| ADDRG(int uid)
|
||||
| ADDRL(int uid)
|
||||
| ADDRF(int uid)
|
||||
| Unary(int op,node left) -- INDIR RET JUMP NEG BCOM
|
||||
| Binary(int op,node left,node right) -- ADD SUB DIV MUL MOD BOR BAND BXOR RSH LSH
|
||||
| Compare(int op,node left,node right,int label) -- EQ NE GT GE LE LT
|
||||
| LABEL(int label)
|
||||
| BRANCH(int label)
|
||||
| CSE(int uid,node node)
|
||||
attributes(int suffix,int size)
|
||||
}
|
||||
|
|
102
lcc/src/run.sh
Normal file → Executable file
102
lcc/src/run.sh
Normal file → Executable file
|
@ -1,51 +1,51 @@
|
|||
#!/bin/sh
|
||||
# run .../target/os/tst/foo.s [ remotehost ]
|
||||
|
||||
# set -x
|
||||
target=`echo $1 | awk -F/ '{ print $(NF-3) }'`
|
||||
os=`echo $1 | awk -F/ '{ print $(NF-2) }'`
|
||||
dir=$target/$os
|
||||
|
||||
case "$1" in
|
||||
*symbolic/irix*) idir=include/mips/irix; remotehost=noexecute ;;
|
||||
*symbolic/osf*) idir=include/alpha/osf; remotehost=noexecute ;;
|
||||
*) idir=include/$dir; remotehost=${2-$REMOTEHOST} ;;
|
||||
esac
|
||||
|
||||
if [ ! -d "$target/$os" -o ! -d "$idir" ]; then
|
||||
echo 2>&1 $0: unknown combination '"'$target/$os'"'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
C=`basename $1 .s`
|
||||
BUILDDIR=${BUILDDIR-.} LCC="${LCC-${BUILDDIR}/lcc} -Wo-lccdir=$BUILDDIR"
|
||||
TSTDIR=${TSTDIR-${BUILDDIR}/$dir/tst}
|
||||
if [ ! -d $TSTDIR ]; then mkdir -p $TSTDIR; fi
|
||||
|
||||
echo ${BUILDDIR}/rcc$EXE -target=$target/$os $1: 1>&2
|
||||
$LCC -S -I$idir -Ualpha -Usun -Uvax -Umips -Ux86 \
|
||||
-Wf-errout=$TSTDIR/$C.2 -D$target -Wf-g0 \
|
||||
-Wf-target=$target/$os -o $1 tst/$C.c
|
||||
if [ $? != 0 ]; then remotehost=noexecute; fi
|
||||
if [ -r $dir/tst/$C.2bk ]; then
|
||||
diff $dir/tst/$C.2bk $TSTDIR/$C.2
|
||||
fi
|
||||
if [ -r $dir/tst/$C.sbk ]; then
|
||||
if diff $dir/tst/$C.sbk $TSTDIR/$C.s; then exit 0; fi
|
||||
fi
|
||||
|
||||
case "$remotehost" in
|
||||
noexecute) exit 0 ;;
|
||||
""|"-") $LCC -o $TSTDIR/$C$EXE $1; $TSTDIR/$C$EXE <tst/$C.0 >$TSTDIR/$C.1 ;;
|
||||
*) rcp $1 $remotehost:
|
||||
if expr "$remotehost" : '.*@' >/dev/null ; then
|
||||
remotehost="`expr $remotehost : '.*@\(.*\)'` -l `expr $remotehost : '\(.*\)@'`"
|
||||
fi
|
||||
rsh $remotehost "cc -o $C$EXE $C.s -lm;./$C$EXE;rm -f $C$EXE $C.[so]" <tst/$C.0 >$TSTDIR/$C.1
|
||||
;;
|
||||
esac
|
||||
if [ -r $dir/tst/$C.1bk ]; then
|
||||
diff $dir/tst/$C.1bk $TSTDIR/$C.1
|
||||
exit $?
|
||||
fi
|
||||
exit 0
|
||||
#!/bin/sh
|
||||
# run .../target/os/tst/foo.s [ remotehost ]
|
||||
|
||||
# set -x
|
||||
target=`echo $1 | awk -F/ '{ print $(NF-3) }'`
|
||||
os=`echo $1 | awk -F/ '{ print $(NF-2) }'`
|
||||
dir=$target/$os
|
||||
|
||||
case "$1" in
|
||||
*symbolic/irix*) idir=include/mips/irix; remotehost=noexecute ;;
|
||||
*symbolic/osf*) idir=include/alpha/osf; remotehost=noexecute ;;
|
||||
*) idir=include/$dir; remotehost=${2-$REMOTEHOST} ;;
|
||||
esac
|
||||
|
||||
if [ ! -d "$target/$os" -o ! -d "$idir" ]; then
|
||||
echo 2>&1 $0: unknown combination '"'$target/$os'"'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
C=`basename $1 .s`
|
||||
BUILDDIR=${BUILDDIR-.} LCC="${LCC-${BUILDDIR}/lcc} -Wo-lccdir=$BUILDDIR"
|
||||
TSTDIR=${TSTDIR-${BUILDDIR}/$dir/tst}
|
||||
if [ ! -d $TSTDIR ]; then mkdir -p $TSTDIR; fi
|
||||
|
||||
echo ${BUILDDIR}/rcc$EXE -target=$target/$os $1: 1>&2
|
||||
$LCC -S -I$idir -Ualpha -Usun -Uvax -Umips -Ux86 \
|
||||
-Wf-errout=$TSTDIR/$C.2 -D$target -Wf-g0 \
|
||||
-Wf-target=$target/$os -o $1 tst/$C.c
|
||||
if [ $? != 0 ]; then remotehost=noexecute; fi
|
||||
if [ -r $dir/tst/$C.2bk ]; then
|
||||
diff $dir/tst/$C.2bk $TSTDIR/$C.2
|
||||
fi
|
||||
if [ -r $dir/tst/$C.sbk ]; then
|
||||
if diff $dir/tst/$C.sbk $TSTDIR/$C.s; then exit 0; fi
|
||||
fi
|
||||
|
||||
case "$remotehost" in
|
||||
noexecute) exit 0 ;;
|
||||
""|"-") $LCC -o $TSTDIR/$C$EXE $1; $TSTDIR/$C$EXE <tst/$C.0 >$TSTDIR/$C.1 ;;
|
||||
*) rcp $1 $remotehost:
|
||||
if expr "$remotehost" : '.*@' >/dev/null ; then
|
||||
remotehost="`expr $remotehost : '.*@\(.*\)'` -l `expr $remotehost : '\(.*\)@'`"
|
||||
fi
|
||||
rsh $remotehost "cc -o $C$EXE $C.s -lm;./$C$EXE;rm -f $C$EXE $C.[so]" <tst/$C.0 >$TSTDIR/$C.1
|
||||
;;
|
||||
esac
|
||||
if [ -r $dir/tst/$C.1bk ]; then
|
||||
diff $dir/tst/$C.1bk $TSTDIR/$C.1
|
||||
exit $?
|
||||
fi
|
||||
exit 0
|
||||
|
|
1174
lcc/src/simp.c
Normal file → Executable file
1174
lcc/src/simp.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
2326
lcc/src/sparc.md
Normal file → Executable file
2326
lcc/src/sparc.md
Normal file → Executable file
File diff suppressed because it is too large
Load diff
660
lcc/src/stab.c
Normal file → Executable file
660
lcc/src/stab.c
Normal file → Executable file
|
@ -1,330 +1,330 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "c.h"
|
||||
#include "stab.h"
|
||||
|
||||
|
||||
static char *currentfile; /* current file name */
|
||||
static int ntypes;
|
||||
|
||||
extern Interface sparcIR;
|
||||
|
||||
char *stabprefix = "L";
|
||||
|
||||
extern char *stabprefix;
|
||||
extern void stabblock(int, int, Symbol*);
|
||||
extern void stabend(Coordinate *, Symbol, Coordinate **, Symbol *, Symbol *);
|
||||
extern void stabfend(Symbol, int);
|
||||
extern void stabinit(char *, int, char *[]);
|
||||
extern void stabline(Coordinate *);
|
||||
extern void stabsym(Symbol);
|
||||
extern void stabtype(Symbol);
|
||||
|
||||
static void asgncode(Type, int);
|
||||
static void dbxout(Type);
|
||||
static int dbxtype(Type);
|
||||
static int emittype(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 INT: case UNSIGNED: case FLOAT:
|
||||
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) {
|
||||
ty = unqual(ty);
|
||||
if (!ty->x.printed) {
|
||||
int col = 0;
|
||||
print(".stabs \""), col += 8;
|
||||
if (ty->u.sym && !(isfunc(ty) || isarray(ty) || isptr(ty)))
|
||||
print("%s", ty->u.sym->name), col += strlen(ty->u.sym->name);
|
||||
print(":%c", isstruct(ty) || isenum(ty) ? 'T' : 't'), col += 2;
|
||||
emittype(ty, 0, col);
|
||||
print("\",%d,0,0,0\n", N_LSYM);
|
||||
}
|
||||
}
|
||||
|
||||
/* dbxtype - emit a stabs entry for type ty, return type code */
|
||||
static int dbxtype(Type ty) {
|
||||
asgncode(ty, 0);
|
||||
dbxout(ty);
|
||||
return ty->x.typeno;
|
||||
}
|
||||
|
||||
/*
|
||||
* emittype - emit ty's type number, emitting its definition if necessary.
|
||||
* Returns the output column number after emission; col is the approximate
|
||||
* output column before emission and is used to emit continuation lines for long
|
||||
* struct, union, and enum types. Continuations are not emitted for other types,
|
||||
* even if the definition is long. lev is the depth of calls to emittype.
|
||||
*/
|
||||
static int emittype(Type ty, int lev, int col) {
|
||||
int tc = ty->x.typeno;
|
||||
|
||||
if (isconst(ty) || isvolatile(ty)) {
|
||||
col = emittype(ty->type, lev, col);
|
||||
ty->x.typeno = ty->type->x.typeno;
|
||||
ty->x.printed = 1;
|
||||
return col;
|
||||
}
|
||||
if (tc == 0) {
|
||||
ty->x.typeno = tc = ++ntypes;
|
||||
/* fprint(2,"`%t'=%d\n", ty, tc); */
|
||||
}
|
||||
print("%d", tc), col += 3;
|
||||
if (ty->x.printed)
|
||||
return col;
|
||||
ty->x.printed = 1;
|
||||
switch (ty->op) {
|
||||
case VOID: /* void is defined as itself */
|
||||
print("=%d", tc), col += 1+3;
|
||||
break;
|
||||
case INT:
|
||||
if (ty == chartype) /* plain char is a subrange of itself */
|
||||
print("=r%d;%d;%d;", tc, ty->u.sym->u.limits.min.i, ty->u.sym->u.limits.max.i),
|
||||
col += 2+3+2*2.408*ty->size+2;
|
||||
else /* other signed ints are subranges of int */
|
||||
print("=r1;%D;%D;", ty->u.sym->u.limits.min.i, ty->u.sym->u.limits.max.i),
|
||||
col += 4+2*2.408*ty->size+2;
|
||||
break;
|
||||
case UNSIGNED:
|
||||
if (ty == chartype) /* plain char is a subrange of itself */
|
||||
print("=r%d;0;%u;", tc, ty->u.sym->u.limits.max.i),
|
||||
col += 2+3+2+2.408*ty->size+1;
|
||||
else /* other signed ints are subranges of int */
|
||||
print("=r1;0;%U;", ty->u.sym->u.limits.max.i),
|
||||
col += 4+2.408*ty->size+1;
|
||||
break;
|
||||
case FLOAT: /* float, double, long double get sizes, not ranges */
|
||||
print("=r1;%d;0;", ty->size), col += 4+1+3;
|
||||
break;
|
||||
case POINTER:
|
||||
print("=*"), col += 2;
|
||||
col = emittype(ty->type, lev + 1, col);
|
||||
break;
|
||||
case FUNCTION:
|
||||
print("=f"), col += 2;
|
||||
col = emittype(ty->type, lev + 1, col);
|
||||
break;
|
||||
case ARRAY: /* array includes subscript as an int range */
|
||||
if (ty->size && ty->type->size)
|
||||
print("=ar1;0;%d;", ty->size/ty->type->size - 1), col += 7+3+1;
|
||||
else
|
||||
print("=ar1;0;-1;"), col += 10;
|
||||
col = emittype(ty->type, lev + 1, col);
|
||||
break;
|
||||
case STRUCT: case UNION: {
|
||||
Field p;
|
||||
if (!ty->u.sym->defined) {
|
||||
print("=x%c%s:", ty->op == STRUCT ? 's' : 'u', ty->u.sym->name);
|
||||
col += 2+1+strlen(ty->u.sym->name)+1;
|
||||
break;
|
||||
}
|
||||
if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9')) {
|
||||
ty->x.printed = 0;
|
||||
break;
|
||||
}
|
||||
print("=%c%d", ty->op == STRUCT ? 's' : 'u', ty->size), col += 1+1+3;
|
||||
for (p = fieldlist(ty); p; p = p->link) {
|
||||
if (p->name)
|
||||
print("%s:", p->name), col += strlen(p->name)+1;
|
||||
else
|
||||
print(":"), col += 1;
|
||||
col = emittype(p->type, lev + 1, col);
|
||||
if (p->lsb)
|
||||
print(",%d,%d;", 8*p->offset +
|
||||
(IR->little_endian ? fieldright(p) : fieldleft(p)),
|
||||
fieldsize(p));
|
||||
else
|
||||
print(",%d,%d;", 8*p->offset, 8*p->type->size);
|
||||
col += 1+3+1+3+1; /* accounts for ,%d,%d; */
|
||||
if (col >= 80 && p->link) {
|
||||
print("\\\\\",%d,0,0,0\n.stabs \"", N_LSYM);
|
||||
col = 8;
|
||||
}
|
||||
}
|
||||
print(";"), col += 1;
|
||||
break;
|
||||
}
|
||||
case ENUM: {
|
||||
Symbol *p;
|
||||
if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9')) {
|
||||
ty->x.printed = 0;
|
||||
break;
|
||||
}
|
||||
print("=e"), col += 2;
|
||||
for (p = ty->u.sym->u.idlist; *p; p++) {
|
||||
print("%s:%d,", (*p)->name, (*p)->u.value), col += strlen((*p)->name)+3;
|
||||
if (col >= 80 && p[1]) {
|
||||
print("\\\\\",%d,0,0,0\n.stabs \"", N_LSYM);
|
||||
col = 8;
|
||||
}
|
||||
}
|
||||
print(";"), col += 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
/* stabblock - output a stab entry for '{' or '}' at level lev */
|
||||
void stabblock(int brace, int lev, Symbol *p) {
|
||||
if (brace == '{')
|
||||
while (*p)
|
||||
stabsym(*p++);
|
||||
if (IR == &sparcIR)
|
||||
print(".stabd 0x%x,0,%d\n", brace == '{' ? N_LBRAC : N_RBRAC, lev);
|
||||
else {
|
||||
int lab = genlabel(1);
|
||||
print(".stabn 0x%x,0,%d,%s%d-%s\n", brace == '{' ? N_LBRAC : N_RBRAC, lev,
|
||||
stabprefix, lab, cfunc->x.name);
|
||||
print("%s%d:\n", stabprefix, lab);
|
||||
}
|
||||
}
|
||||
|
||||
/* stabinit - initialize stab output */
|
||||
void stabinit(char *file, int argc, char *argv[]) {
|
||||
typedef void (*Closure)(Symbol, void *);
|
||||
extern char *getcwd(char *, size_t);
|
||||
|
||||
print(".stabs \"lcc4_compiled.\",0x%x,0,0,0\n", N_OPT);
|
||||
if (file && *file) {
|
||||
char buf[1024], *cwd = getcwd(buf, sizeof buf);
|
||||
if (cwd)
|
||||
print(".stabs \"%s/\",0x%x,0,3,%stext0\n", cwd, N_SO, stabprefix);
|
||||
print(".stabs \"%s\",0x%x,0,3,%stext0\n", file, N_SO, stabprefix);
|
||||
(*IR->segment)(CODE);
|
||||
print("%stext0:\n", stabprefix, N_SO);
|
||||
currentfile = file;
|
||||
}
|
||||
dbxtype(inttype);
|
||||
dbxtype(chartype);
|
||||
dbxtype(doubletype);
|
||||
dbxtype(floattype);
|
||||
dbxtype(longdouble);
|
||||
dbxtype(longtype);
|
||||
dbxtype(longlong);
|
||||
dbxtype(shorttype);
|
||||
dbxtype(signedchar);
|
||||
dbxtype(unsignedchar);
|
||||
dbxtype(unsignedlong);
|
||||
dbxtype(unsignedlonglong);
|
||||
dbxtype(unsignedshort);
|
||||
dbxtype(unsignedtype);
|
||||
dbxtype(voidtype);
|
||||
foreach(types, GLOBAL, (Closure)stabtype, NULL);
|
||||
}
|
||||
|
||||
/* stabline - emit stab entry for source coordinate *cp */
|
||||
void stabline(Coordinate *cp) {
|
||||
if (cp->file && cp->file != currentfile) {
|
||||
int lab = genlabel(1);
|
||||
print(".stabs \"%s\",0x%x,0,0,%s%d\n", cp->file, N_SOL, stabprefix, lab);
|
||||
print("%s%d:\n", stabprefix, lab);
|
||||
currentfile = cp->file;
|
||||
}
|
||||
if (IR == &sparcIR)
|
||||
print(".stabd 0x%x,0,%d\n", N_SLINE, cp->y);
|
||||
else {
|
||||
int lab = genlabel(1);
|
||||
print(".stabn 0x%x,0,%d,%s%d-%s\n", N_SLINE, cp->y,
|
||||
stabprefix, lab, cfunc->x.name);
|
||||
print("%s%d:\n", stabprefix, lab);
|
||||
}
|
||||
}
|
||||
|
||||
/* stabsym - output a stab entry for symbol p */
|
||||
void stabsym(Symbol p) {
|
||||
int code, tc, sz = p->type->size;
|
||||
|
||||
if (p->generated || p->computed)
|
||||
return;
|
||||
if (isfunc(p->type)) {
|
||||
print(".stabs \"%s:%c%d\",%d,0,0,%s\n", p->name,
|
||||
p->sclass == STATIC ? 'f' : 'F', dbxtype(freturn(p->type)),
|
||||
N_FUN, p->x.name);
|
||||
return;
|
||||
}
|
||||
if (!IR->wants_argb && p->scope == PARAM && p->structarg) {
|
||||
assert(isptr(p->type) && isstruct(p->type->type));
|
||||
tc = dbxtype(p->type->type);
|
||||
sz = p->type->type->size;
|
||||
} else
|
||||
tc = dbxtype(p->type);
|
||||
if (p->sclass == AUTO && p->scope == GLOBAL || p->sclass == EXTERN) {
|
||||
print(".stabs \"%s:G", p->name);
|
||||
code = N_GSYM;
|
||||
} else if (p->sclass == STATIC) {
|
||||
print(".stabs \"%s:%c%d\",%d,0,0,%s\n", p->name, p->scope == GLOBAL ? 'S' : 'V',
|
||||
tc, p->u.seg == BSS ? N_LCSYM : N_STSYM, p->x.name);
|
||||
return;
|
||||
} else if (p->sclass == REGISTER) {
|
||||
if (p->x.regnode) {
|
||||
int r = p->x.regnode->number;
|
||||
if (p->x.regnode->set == FREG)
|
||||
r += 32; /* floating point */
|
||||
print(".stabs \"%s:%c%d\",%d,0,", p->name,
|
||||
p->scope == PARAM ? 'P' : 'r', tc, N_RSYM);
|
||||
print("%d,%d\n", sz, r);
|
||||
}
|
||||
return;
|
||||
} else if (p->scope == PARAM) {
|
||||
print(".stabs \"%s:p", p->name);
|
||||
code = N_PSYM;
|
||||
} else if (p->scope >= LOCAL) {
|
||||
print(".stabs \"%s:", p->name);
|
||||
code = N_LSYM;
|
||||
} else
|
||||
assert(0);
|
||||
print("%d\",%d,0,0,%s\n", tc, code,
|
||||
p->scope >= PARAM && p->sclass != EXTERN ? p->x.name : "0");
|
||||
}
|
||||
|
||||
/* stabtype - output a stab entry for type *p */
|
||||
void stabtype(Symbol p) {
|
||||
if (p->type) {
|
||||
if (p->sclass == 0)
|
||||
dbxtype(p->type);
|
||||
else if (p->sclass == TYPEDEF)
|
||||
print(".stabs \"%s:t%d\",%d,0,0,0\n", p->name, dbxtype(p->type), N_LSYM);
|
||||
}
|
||||
}
|
||||
|
||||
/* stabend - finalize a function */
|
||||
void stabfend(Symbol p, int lineno) {}
|
||||
|
||||
/* stabend - finalize stab output */
|
||||
void stabend(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {
|
||||
(*IR->segment)(CODE);
|
||||
print(".stabs \"\", %d, 0, 0,%setext\n", N_SO, stabprefix);
|
||||
print("%setext:\n", stabprefix);
|
||||
}
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "c.h"
|
||||
#include "stab.h"
|
||||
|
||||
|
||||
static char *currentfile; /* current file name */
|
||||
static int ntypes;
|
||||
|
||||
extern Interface sparcIR;
|
||||
|
||||
char *stabprefix = "L";
|
||||
|
||||
extern char *stabprefix;
|
||||
extern void stabblock(int, int, Symbol*);
|
||||
extern void stabend(Coordinate *, Symbol, Coordinate **, Symbol *, Symbol *);
|
||||
extern void stabfend(Symbol, int);
|
||||
extern void stabinit(char *, int, char *[]);
|
||||
extern void stabline(Coordinate *);
|
||||
extern void stabsym(Symbol);
|
||||
extern void stabtype(Symbol);
|
||||
|
||||
static void asgncode(Type, int);
|
||||
static void dbxout(Type);
|
||||
static int dbxtype(Type);
|
||||
static int emittype(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 INT: case UNSIGNED: case FLOAT:
|
||||
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) {
|
||||
ty = unqual(ty);
|
||||
if (!ty->x.printed) {
|
||||
int col = 0;
|
||||
print(".stabs \""), col += 8;
|
||||
if (ty->u.sym && !(isfunc(ty) || isarray(ty) || isptr(ty)))
|
||||
print("%s", ty->u.sym->name), col += strlen(ty->u.sym->name);
|
||||
print(":%c", isstruct(ty) || isenum(ty) ? 'T' : 't'), col += 2;
|
||||
emittype(ty, 0, col);
|
||||
print("\",%d,0,0,0\n", N_LSYM);
|
||||
}
|
||||
}
|
||||
|
||||
/* dbxtype - emit a stabs entry for type ty, return type code */
|
||||
static int dbxtype(Type ty) {
|
||||
asgncode(ty, 0);
|
||||
dbxout(ty);
|
||||
return ty->x.typeno;
|
||||
}
|
||||
|
||||
/*
|
||||
* emittype - emit ty's type number, emitting its definition if necessary.
|
||||
* Returns the output column number after emission; col is the approximate
|
||||
* output column before emission and is used to emit continuation lines for long
|
||||
* struct, union, and enum types. Continuations are not emitted for other types,
|
||||
* even if the definition is long. lev is the depth of calls to emittype.
|
||||
*/
|
||||
static int emittype(Type ty, int lev, int col) {
|
||||
int tc = ty->x.typeno;
|
||||
|
||||
if (isconst(ty) || isvolatile(ty)) {
|
||||
col = emittype(ty->type, lev, col);
|
||||
ty->x.typeno = ty->type->x.typeno;
|
||||
ty->x.printed = 1;
|
||||
return col;
|
||||
}
|
||||
if (tc == 0) {
|
||||
ty->x.typeno = tc = ++ntypes;
|
||||
/* fprint(2,"`%t'=%d\n", ty, tc); */
|
||||
}
|
||||
print("%d", tc), col += 3;
|
||||
if (ty->x.printed)
|
||||
return col;
|
||||
ty->x.printed = 1;
|
||||
switch (ty->op) {
|
||||
case VOID: /* void is defined as itself */
|
||||
print("=%d", tc), col += 1+3;
|
||||
break;
|
||||
case INT:
|
||||
if (ty == chartype) /* plain char is a subrange of itself */
|
||||
print("=r%d;%d;%d;", tc, ty->u.sym->u.limits.min.i, ty->u.sym->u.limits.max.i),
|
||||
col += 2+3+2*2.408*ty->size+2;
|
||||
else /* other signed ints are subranges of int */
|
||||
print("=r1;%D;%D;", ty->u.sym->u.limits.min.i, ty->u.sym->u.limits.max.i),
|
||||
col += 4+2*2.408*ty->size+2;
|
||||
break;
|
||||
case UNSIGNED:
|
||||
if (ty == chartype) /* plain char is a subrange of itself */
|
||||
print("=r%d;0;%u;", tc, ty->u.sym->u.limits.max.i),
|
||||
col += 2+3+2+2.408*ty->size+1;
|
||||
else /* other signed ints are subranges of int */
|
||||
print("=r1;0;%U;", ty->u.sym->u.limits.max.i),
|
||||
col += 4+2.408*ty->size+1;
|
||||
break;
|
||||
case FLOAT: /* float, double, long double get sizes, not ranges */
|
||||
print("=r1;%d;0;", ty->size), col += 4+1+3;
|
||||
break;
|
||||
case POINTER:
|
||||
print("=*"), col += 2;
|
||||
col = emittype(ty->type, lev + 1, col);
|
||||
break;
|
||||
case FUNCTION:
|
||||
print("=f"), col += 2;
|
||||
col = emittype(ty->type, lev + 1, col);
|
||||
break;
|
||||
case ARRAY: /* array includes subscript as an int range */
|
||||
if (ty->size && ty->type->size)
|
||||
print("=ar1;0;%d;", ty->size/ty->type->size - 1), col += 7+3+1;
|
||||
else
|
||||
print("=ar1;0;-1;"), col += 10;
|
||||
col = emittype(ty->type, lev + 1, col);
|
||||
break;
|
||||
case STRUCT: case UNION: {
|
||||
Field p;
|
||||
if (!ty->u.sym->defined) {
|
||||
print("=x%c%s:", ty->op == STRUCT ? 's' : 'u', ty->u.sym->name);
|
||||
col += 2+1+strlen(ty->u.sym->name)+1;
|
||||
break;
|
||||
}
|
||||
if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9')) {
|
||||
ty->x.printed = 0;
|
||||
break;
|
||||
}
|
||||
print("=%c%d", ty->op == STRUCT ? 's' : 'u', ty->size), col += 1+1+3;
|
||||
for (p = fieldlist(ty); p; p = p->link) {
|
||||
if (p->name)
|
||||
print("%s:", p->name), col += strlen(p->name)+1;
|
||||
else
|
||||
print(":"), col += 1;
|
||||
col = emittype(p->type, lev + 1, col);
|
||||
if (p->lsb)
|
||||
print(",%d,%d;", 8*p->offset +
|
||||
(IR->little_endian ? fieldright(p) : fieldleft(p)),
|
||||
fieldsize(p));
|
||||
else
|
||||
print(",%d,%d;", 8*p->offset, 8*p->type->size);
|
||||
col += 1+3+1+3+1; /* accounts for ,%d,%d; */
|
||||
if (col >= 80 && p->link) {
|
||||
print("\\\\\",%d,0,0,0\n.stabs \"", N_LSYM);
|
||||
col = 8;
|
||||
}
|
||||
}
|
||||
print(";"), col += 1;
|
||||
break;
|
||||
}
|
||||
case ENUM: {
|
||||
Symbol *p;
|
||||
if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9')) {
|
||||
ty->x.printed = 0;
|
||||
break;
|
||||
}
|
||||
print("=e"), col += 2;
|
||||
for (p = ty->u.sym->u.idlist; *p; p++) {
|
||||
print("%s:%d,", (*p)->name, (*p)->u.value), col += strlen((*p)->name)+3;
|
||||
if (col >= 80 && p[1]) {
|
||||
print("\\\\\",%d,0,0,0\n.stabs \"", N_LSYM);
|
||||
col = 8;
|
||||
}
|
||||
}
|
||||
print(";"), col += 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
/* stabblock - output a stab entry for '{' or '}' at level lev */
|
||||
void stabblock(int brace, int lev, Symbol *p) {
|
||||
if (brace == '{')
|
||||
while (*p)
|
||||
stabsym(*p++);
|
||||
if (IR == &sparcIR)
|
||||
print(".stabd 0x%x,0,%d\n", brace == '{' ? N_LBRAC : N_RBRAC, lev);
|
||||
else {
|
||||
int lab = genlabel(1);
|
||||
print(".stabn 0x%x,0,%d,%s%d-%s\n", brace == '{' ? N_LBRAC : N_RBRAC, lev,
|
||||
stabprefix, lab, cfunc->x.name);
|
||||
print("%s%d:\n", stabprefix, lab);
|
||||
}
|
||||
}
|
||||
|
||||
/* stabinit - initialize stab output */
|
||||
void stabinit(char *file, int argc, char *argv[]) {
|
||||
typedef void (*Closure)(Symbol, void *);
|
||||
extern char *getcwd(char *, size_t);
|
||||
|
||||
print(".stabs \"lcc4_compiled.\",0x%x,0,0,0\n", N_OPT);
|
||||
if (file && *file) {
|
||||
char buf[1024], *cwd = getcwd(buf, sizeof buf);
|
||||
if (cwd)
|
||||
print(".stabs \"%s/\",0x%x,0,3,%stext0\n", cwd, N_SO, stabprefix);
|
||||
print(".stabs \"%s\",0x%x,0,3,%stext0\n", file, N_SO, stabprefix);
|
||||
(*IR->segment)(CODE);
|
||||
print("%stext0:\n", stabprefix, N_SO);
|
||||
currentfile = file;
|
||||
}
|
||||
dbxtype(inttype);
|
||||
dbxtype(chartype);
|
||||
dbxtype(doubletype);
|
||||
dbxtype(floattype);
|
||||
dbxtype(longdouble);
|
||||
dbxtype(longtype);
|
||||
dbxtype(longlong);
|
||||
dbxtype(shorttype);
|
||||
dbxtype(signedchar);
|
||||
dbxtype(unsignedchar);
|
||||
dbxtype(unsignedlong);
|
||||
dbxtype(unsignedlonglong);
|
||||
dbxtype(unsignedshort);
|
||||
dbxtype(unsignedtype);
|
||||
dbxtype(voidtype);
|
||||
foreach(types, GLOBAL, (Closure)stabtype, NULL);
|
||||
}
|
||||
|
||||
/* stabline - emit stab entry for source coordinate *cp */
|
||||
void stabline(Coordinate *cp) {
|
||||
if (cp->file && cp->file != currentfile) {
|
||||
int lab = genlabel(1);
|
||||
print(".stabs \"%s\",0x%x,0,0,%s%d\n", cp->file, N_SOL, stabprefix, lab);
|
||||
print("%s%d:\n", stabprefix, lab);
|
||||
currentfile = cp->file;
|
||||
}
|
||||
if (IR == &sparcIR)
|
||||
print(".stabd 0x%x,0,%d\n", N_SLINE, cp->y);
|
||||
else {
|
||||
int lab = genlabel(1);
|
||||
print(".stabn 0x%x,0,%d,%s%d-%s\n", N_SLINE, cp->y,
|
||||
stabprefix, lab, cfunc->x.name);
|
||||
print("%s%d:\n", stabprefix, lab);
|
||||
}
|
||||
}
|
||||
|
||||
/* stabsym - output a stab entry for symbol p */
|
||||
void stabsym(Symbol p) {
|
||||
int code, tc, sz = p->type->size;
|
||||
|
||||
if (p->generated || p->computed)
|
||||
return;
|
||||
if (isfunc(p->type)) {
|
||||
print(".stabs \"%s:%c%d\",%d,0,0,%s\n", p->name,
|
||||
p->sclass == STATIC ? 'f' : 'F', dbxtype(freturn(p->type)),
|
||||
N_FUN, p->x.name);
|
||||
return;
|
||||
}
|
||||
if (!IR->wants_argb && p->scope == PARAM && p->structarg) {
|
||||
assert(isptr(p->type) && isstruct(p->type->type));
|
||||
tc = dbxtype(p->type->type);
|
||||
sz = p->type->type->size;
|
||||
} else
|
||||
tc = dbxtype(p->type);
|
||||
if (p->sclass == AUTO && p->scope == GLOBAL || p->sclass == EXTERN) {
|
||||
print(".stabs \"%s:G", p->name);
|
||||
code = N_GSYM;
|
||||
} else if (p->sclass == STATIC) {
|
||||
print(".stabs \"%s:%c%d\",%d,0,0,%s\n", p->name, p->scope == GLOBAL ? 'S' : 'V',
|
||||
tc, p->u.seg == BSS ? N_LCSYM : N_STSYM, p->x.name);
|
||||
return;
|
||||
} else if (p->sclass == REGISTER) {
|
||||
if (p->x.regnode) {
|
||||
int r = p->x.regnode->number;
|
||||
if (p->x.regnode->set == FREG)
|
||||
r += 32; /* floating point */
|
||||
print(".stabs \"%s:%c%d\",%d,0,", p->name,
|
||||
p->scope == PARAM ? 'P' : 'r', tc, N_RSYM);
|
||||
print("%d,%d\n", sz, r);
|
||||
}
|
||||
return;
|
||||
} else if (p->scope == PARAM) {
|
||||
print(".stabs \"%s:p", p->name);
|
||||
code = N_PSYM;
|
||||
} else if (p->scope >= LOCAL) {
|
||||
print(".stabs \"%s:", p->name);
|
||||
code = N_LSYM;
|
||||
} else
|
||||
assert(0);
|
||||
print("%d\",%d,0,0,%s\n", tc, code,
|
||||
p->scope >= PARAM && p->sclass != EXTERN ? p->x.name : "0");
|
||||
}
|
||||
|
||||
/* stabtype - output a stab entry for type *p */
|
||||
void stabtype(Symbol p) {
|
||||
if (p->type) {
|
||||
if (p->sclass == 0)
|
||||
dbxtype(p->type);
|
||||
else if (p->sclass == TYPEDEF)
|
||||
print(".stabs \"%s:t%d\",%d,0,0,0\n", p->name, dbxtype(p->type), N_LSYM);
|
||||
}
|
||||
}
|
||||
|
||||
/* stabend - finalize a function */
|
||||
void stabfend(Symbol p, int lineno) {}
|
||||
|
||||
/* stabend - finalize stab output */
|
||||
void stabend(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {
|
||||
(*IR->segment)(CODE);
|
||||
print(".stabs \"\", %d, 0, 0,%setext\n", N_SO, stabprefix);
|
||||
print("%setext:\n", stabprefix);
|
||||
}
|
||||
|
|
226
lcc/src/stab.h
Normal file → Executable file
226
lcc/src/stab.h
Normal file → Executable file
|
@ -1,113 +1,113 @@
|
|||
/* @(#)stab.h 1.11 92/05/11 SMI */
|
||||
/*
|
||||
* Copyright (c) 1990 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file gives definitions supplementing <a.out.h>
|
||||
* for permanent symbol table entries.
|
||||
* These must have one of the N_STAB bits on,
|
||||
* and are subject to relocation according to the masks in <a.out.h>.
|
||||
*/
|
||||
|
||||
#ifndef _STAB_H
|
||||
#define _STAB_H
|
||||
|
||||
|
||||
#if !defined(_a_out_h) && !defined(_A_OUT_H)
|
||||
/* this file contains fragments of a.out.h and stab.h relevant to
|
||||
* support of stabX processing within ELF files - see the
|
||||
* Format of a symbol table entry
|
||||
*/
|
||||
struct nlist {
|
||||
union {
|
||||
char *n_name; /* for use when in-core */
|
||||
long n_strx; /* index into file string table */
|
||||
} n_un;
|
||||
unsigned char n_type; /* type flag (N_TEXT,..) */
|
||||
char n_other; /* unused */
|
||||
short n_desc; /* see <stab.h> */
|
||||
unsigned long n_value; /* value of symbol (or sdb offset) */
|
||||
};
|
||||
|
||||
/*
|
||||
* Simple values for n_type.
|
||||
*/
|
||||
#define N_UNDF 0x0 /* undefined */
|
||||
#define N_ABS 0x2 /* absolute */
|
||||
#define N_TEXT 0x4 /* text */
|
||||
#define N_DATA 0x6 /* data */
|
||||
#define N_BSS 0x8 /* bss */
|
||||
#define N_COMM 0x12 /* common (internal to ld) */
|
||||
#define N_FN 0x1f /* file name symbol */
|
||||
|
||||
#define N_EXT 01 /* external bit, or'ed in */
|
||||
#define N_TYPE 0x1e /* mask for all the type bits */
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* for symbolic debugger, sdb(1):
|
||||
*/
|
||||
#define N_GSYM 0x20 /* global symbol: name,,0,type,0 */
|
||||
#define N_FNAME 0x22 /* procedure name (f77 kludge): name,,0 */
|
||||
#define N_FUN 0x24 /* procedure: name,,0,linenumber,address */
|
||||
#define N_STSYM 0x26 /* static symbol: name,,0,type,address */
|
||||
#define N_LCSYM 0x28 /* .lcomm symbol: name,,0,type,address */
|
||||
#define N_MAIN 0x2a /* name of main routine : name,,0,0,0 */
|
||||
#define N_ROSYM 0x2c /* ro_data objects */
|
||||
#define N_OBJ 0x38 /* object file path or name */
|
||||
#define N_OPT 0x3c /* compiler options */
|
||||
#define N_RSYM 0x40 /* register sym: name,,0,type,register */
|
||||
#define N_SLINE 0x44 /* src line: 0,,0,linenumber,address */
|
||||
#define N_FLINE 0x4c /* function start.end */
|
||||
#define N_SSYM 0x60 /* structure elt: name,,0,type,struct_offset */
|
||||
#define N_ENDM 0x62 /* last stab emitted for module */
|
||||
#define N_SO 0x64 /* source file name: name,,0,0,address */
|
||||
#define N_LSYM 0x80 /* local sym: name,,0,type,offset */
|
||||
#define N_BINCL 0x82 /* header file: name,,0,0,0 */
|
||||
#define N_SOL 0x84 /* #included file name: name,,0,0,address */
|
||||
#define N_PSYM 0xa0 /* parameter: name,,0,type,offset */
|
||||
#define N_EINCL 0xa2 /* end of include file */
|
||||
#define N_ENTRY 0xa4 /* alternate entry: name,linenumber,address */
|
||||
#define N_LBRAC 0xc0 /* left bracket: 0,,0,nesting level,address */
|
||||
#define N_EXCL 0xc2 /* excluded include file */
|
||||
#define N_RBRAC 0xe0 /* right bracket: 0,,0,nesting level,address */
|
||||
#define N_BCOMM 0xe2 /* begin common: name,, */
|
||||
#define N_ECOMM 0xe4 /* end common: name,, */
|
||||
#define N_ECOML 0xe8 /* end common (local name): ,,address */
|
||||
#define N_LENG 0xfe /* second stab entry with length information */
|
||||
|
||||
/*
|
||||
* for the berkeley pascal compiler, pc(1):
|
||||
*/
|
||||
#define N_PC 0x30 /* global pascal symbol: name,,0,subtype,line */
|
||||
#define N_WITH 0xea /* pascal with statement: type,,0,0,offset */
|
||||
|
||||
/*
|
||||
* for code browser only
|
||||
*/
|
||||
#define N_BROWS 0x48 /* path to associated .cb file */
|
||||
|
||||
/*
|
||||
* Optional langauge designations for N_SO
|
||||
*/
|
||||
#define N_SO_AS 1 /* Assembler */
|
||||
#define N_SO_C 2 /* C */
|
||||
#define N_SO_ANSI_C 3 /* ANSI C */
|
||||
#define N_SO_CC 4 /* C++ */
|
||||
#define N_SO_FORTRAN 5 /* Fortran 77 */
|
||||
#define N_SO_PASCAL 6 /* Pascal */
|
||||
|
||||
/*
|
||||
* Floating point type values
|
||||
*/
|
||||
#define NF_NONE 0 /* Undefined type */
|
||||
#define NF_SINGLE 1 /* IEEE 32 bit float */
|
||||
#define NF_DOUBLE 2 /* IEEE 64 bit float */
|
||||
#define NF_COMPLEX 3 /* Fortran complex */
|
||||
#define NF_COMPLEX16 4 /* Fortran double complex */
|
||||
#define NF_COMPLEX32 5 /* Fortran complex*16 */
|
||||
#define NF_LDOUBLE 6 /* Long double */
|
||||
|
||||
#endif
|
||||
/* @(#)stab.h 1.11 92/05/11 SMI */
|
||||
/*
|
||||
* Copyright (c) 1990 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file gives definitions supplementing <a.out.h>
|
||||
* for permanent symbol table entries.
|
||||
* These must have one of the N_STAB bits on,
|
||||
* and are subject to relocation according to the masks in <a.out.h>.
|
||||
*/
|
||||
|
||||
#ifndef _STAB_H
|
||||
#define _STAB_H
|
||||
|
||||
|
||||
#if !defined(_a_out_h) && !defined(_A_OUT_H)
|
||||
/* this file contains fragments of a.out.h and stab.h relevant to
|
||||
* support of stabX processing within ELF files - see the
|
||||
* Format of a symbol table entry
|
||||
*/
|
||||
struct nlist {
|
||||
union {
|
||||
char *n_name; /* for use when in-core */
|
||||
long n_strx; /* index into file string table */
|
||||
} n_un;
|
||||
unsigned char n_type; /* type flag (N_TEXT,..) */
|
||||
char n_other; /* unused */
|
||||
short n_desc; /* see <stab.h> */
|
||||
unsigned long n_value; /* value of symbol (or sdb offset) */
|
||||
};
|
||||
|
||||
/*
|
||||
* Simple values for n_type.
|
||||
*/
|
||||
#define N_UNDF 0x0 /* undefined */
|
||||
#define N_ABS 0x2 /* absolute */
|
||||
#define N_TEXT 0x4 /* text */
|
||||
#define N_DATA 0x6 /* data */
|
||||
#define N_BSS 0x8 /* bss */
|
||||
#define N_COMM 0x12 /* common (internal to ld) */
|
||||
#define N_FN 0x1f /* file name symbol */
|
||||
|
||||
#define N_EXT 01 /* external bit, or'ed in */
|
||||
#define N_TYPE 0x1e /* mask for all the type bits */
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* for symbolic debugger, sdb(1):
|
||||
*/
|
||||
#define N_GSYM 0x20 /* global symbol: name,,0,type,0 */
|
||||
#define N_FNAME 0x22 /* procedure name (f77 kludge): name,,0 */
|
||||
#define N_FUN 0x24 /* procedure: name,,0,linenumber,address */
|
||||
#define N_STSYM 0x26 /* static symbol: name,,0,type,address */
|
||||
#define N_LCSYM 0x28 /* .lcomm symbol: name,,0,type,address */
|
||||
#define N_MAIN 0x2a /* name of main routine : name,,0,0,0 */
|
||||
#define N_ROSYM 0x2c /* ro_data objects */
|
||||
#define N_OBJ 0x38 /* object file path or name */
|
||||
#define N_OPT 0x3c /* compiler options */
|
||||
#define N_RSYM 0x40 /* register sym: name,,0,type,register */
|
||||
#define N_SLINE 0x44 /* src line: 0,,0,linenumber,address */
|
||||
#define N_FLINE 0x4c /* function start.end */
|
||||
#define N_SSYM 0x60 /* structure elt: name,,0,type,struct_offset */
|
||||
#define N_ENDM 0x62 /* last stab emitted for module */
|
||||
#define N_SO 0x64 /* source file name: name,,0,0,address */
|
||||
#define N_LSYM 0x80 /* local sym: name,,0,type,offset */
|
||||
#define N_BINCL 0x82 /* header file: name,,0,0,0 */
|
||||
#define N_SOL 0x84 /* #included file name: name,,0,0,address */
|
||||
#define N_PSYM 0xa0 /* parameter: name,,0,type,offset */
|
||||
#define N_EINCL 0xa2 /* end of include file */
|
||||
#define N_ENTRY 0xa4 /* alternate entry: name,linenumber,address */
|
||||
#define N_LBRAC 0xc0 /* left bracket: 0,,0,nesting level,address */
|
||||
#define N_EXCL 0xc2 /* excluded include file */
|
||||
#define N_RBRAC 0xe0 /* right bracket: 0,,0,nesting level,address */
|
||||
#define N_BCOMM 0xe2 /* begin common: name,, */
|
||||
#define N_ECOMM 0xe4 /* end common: name,, */
|
||||
#define N_ECOML 0xe8 /* end common (local name): ,,address */
|
||||
#define N_LENG 0xfe /* second stab entry with length information */
|
||||
|
||||
/*
|
||||
* for the berkeley pascal compiler, pc(1):
|
||||
*/
|
||||
#define N_PC 0x30 /* global pascal symbol: name,,0,subtype,line */
|
||||
#define N_WITH 0xea /* pascal with statement: type,,0,0,offset */
|
||||
|
||||
/*
|
||||
* for code browser only
|
||||
*/
|
||||
#define N_BROWS 0x48 /* path to associated .cb file */
|
||||
|
||||
/*
|
||||
* Optional langauge designations for N_SO
|
||||
*/
|
||||
#define N_SO_AS 1 /* Assembler */
|
||||
#define N_SO_C 2 /* C */
|
||||
#define N_SO_ANSI_C 3 /* ANSI C */
|
||||
#define N_SO_CC 4 /* C++ */
|
||||
#define N_SO_FORTRAN 5 /* Fortran 77 */
|
||||
#define N_SO_PASCAL 6 /* Pascal */
|
||||
|
||||
/*
|
||||
* Floating point type values
|
||||
*/
|
||||
#define NF_NONE 0 /* Undefined type */
|
||||
#define NF_SINGLE 1 /* IEEE 32 bit float */
|
||||
#define NF_DOUBLE 2 /* IEEE 64 bit float */
|
||||
#define NF_COMPLEX 3 /* Fortran complex */
|
||||
#define NF_COMPLEX16 4 /* Fortran double complex */
|
||||
#define NF_COMPLEX32 5 /* Fortran complex*16 */
|
||||
#define NF_LDOUBLE 6 /* Long double */
|
||||
|
||||
#endif
|
||||
|
|
1394
lcc/src/stmt.c
Normal file → Executable file
1394
lcc/src/stmt.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
244
lcc/src/string.c
Normal file → Executable file
244
lcc/src/string.c
Normal file → Executable file
|
@ -1,122 +1,122 @@
|
|||
#include "c.h"
|
||||
|
||||
|
||||
static struct string {
|
||||
char *str;
|
||||
int len;
|
||||
struct string *link;
|
||||
} *buckets[1024];
|
||||
static int scatter[] = { /* map characters to random values */
|
||||
2078917053, 143302914, 1027100827, 1953210302, 755253631,
|
||||
2002600785, 1405390230, 45248011, 1099951567, 433832350,
|
||||
2018585307, 438263339, 813528929, 1703199216, 618906479,
|
||||
573714703, 766270699, 275680090, 1510320440, 1583583926,
|
||||
1723401032, 1965443329, 1098183682, 1636505764, 980071615,
|
||||
1011597961, 643279273, 1315461275, 157584038, 1069844923,
|
||||
471560540, 89017443, 1213147837, 1498661368, 2042227746,
|
||||
1968401469, 1353778505, 1300134328, 2013649480, 306246424,
|
||||
1733966678, 1884751139, 744509763, 400011959, 1440466707,
|
||||
1363416242, 973726663, 59253759, 1639096332, 336563455,
|
||||
1642837685, 1215013716, 154523136, 593537720, 704035832,
|
||||
1134594751, 1605135681, 1347315106, 302572379, 1762719719,
|
||||
269676381, 774132919, 1851737163, 1482824219, 125310639,
|
||||
1746481261, 1303742040, 1479089144, 899131941, 1169907872,
|
||||
1785335569, 485614972, 907175364, 382361684, 885626931,
|
||||
200158423, 1745777927, 1859353594, 259412182, 1237390611,
|
||||
48433401, 1902249868, 304920680, 202956538, 348303940,
|
||||
1008956512, 1337551289, 1953439621, 208787970, 1640123668,
|
||||
1568675693, 478464352, 266772940, 1272929208, 1961288571,
|
||||
392083579, 871926821, 1117546963, 1871172724, 1771058762,
|
||||
139971187, 1509024645, 109190086, 1047146551, 1891386329,
|
||||
994817018, 1247304975, 1489680608, 706686964, 1506717157,
|
||||
579587572, 755120366, 1261483377, 884508252, 958076904,
|
||||
1609787317, 1893464764, 148144545, 1415743291, 2102252735,
|
||||
1788268214, 836935336, 433233439, 2055041154, 2109864544,
|
||||
247038362, 299641085, 834307717, 1364585325, 23330161,
|
||||
457882831, 1504556512, 1532354806, 567072918, 404219416,
|
||||
1276257488, 1561889936, 1651524391, 618454448, 121093252,
|
||||
1010757900, 1198042020, 876213618, 124757630, 2082550272,
|
||||
1834290522, 1734544947, 1828531389, 1982435068, 1002804590,
|
||||
1783300476, 1623219634, 1839739926, 69050267, 1530777140,
|
||||
1802120822, 316088629, 1830418225, 488944891, 1680673954,
|
||||
1853748387, 946827723, 1037746818, 1238619545, 1513900641,
|
||||
1441966234, 367393385, 928306929, 946006977, 985847834,
|
||||
1049400181, 1956764878, 36406206, 1925613800, 2081522508,
|
||||
2118956479, 1612420674, 1668583807, 1800004220, 1447372094,
|
||||
523904750, 1435821048, 923108080, 216161028, 1504871315,
|
||||
306401572, 2018281851, 1820959944, 2136819798, 359743094,
|
||||
1354150250, 1843084537, 1306570817, 244413420, 934220434,
|
||||
672987810, 1686379655, 1301613820, 1601294739, 484902984,
|
||||
139978006, 503211273, 294184214, 176384212, 281341425,
|
||||
228223074, 147857043, 1893762099, 1896806882, 1947861263,
|
||||
1193650546, 273227984, 1236198663, 2116758626, 489389012,
|
||||
593586330, 275676551, 360187215, 267062626, 265012701,
|
||||
719930310, 1621212876, 2108097238, 2026501127, 1865626297,
|
||||
894834024, 552005290, 1404522304, 48964196, 5816381,
|
||||
1889425288, 188942202, 509027654, 36125855, 365326415,
|
||||
790369079, 264348929, 513183458, 536647531, 13672163,
|
||||
313561074, 1730298077, 286900147, 1549759737, 1699573055,
|
||||
776289160, 2143346068, 1975249606, 1136476375, 262925046,
|
||||
92778659, 1856406685, 1884137923, 53392249, 1735424165,
|
||||
1602280572
|
||||
};
|
||||
char *string(const char *str) {
|
||||
const char *s;
|
||||
|
||||
for (s = str; *s; s++)
|
||||
;
|
||||
return stringn(str, s - str);
|
||||
}
|
||||
char *stringd(long n) {
|
||||
char str[25], *s = str + sizeof (str);
|
||||
unsigned long m;
|
||||
|
||||
if (n == LONG_MIN)
|
||||
m = (unsigned long)LONG_MAX + 1;
|
||||
else if (n < 0)
|
||||
m = -n;
|
||||
else
|
||||
m = n;
|
||||
do
|
||||
*--s = m%10 + '0';
|
||||
while ((m /= 10) != 0);
|
||||
if (n < 0)
|
||||
*--s = '-';
|
||||
return stringn(s, str + sizeof (str) - s);
|
||||
}
|
||||
char *stringn(const char *str, int len) {
|
||||
int i;
|
||||
unsigned int h;
|
||||
const char *end;
|
||||
struct string *p;
|
||||
|
||||
assert(str);
|
||||
for (h = 0, i = len, end = str; i > 0; i--)
|
||||
h = (h<<1) + scatter[*(unsigned char *)end++];
|
||||
h &= NELEMS(buckets)-1;
|
||||
for (p = buckets[h]; p; p = p->link)
|
||||
if (len == p->len) {
|
||||
const char *s1 = str;
|
||||
char *s2 = p->str;
|
||||
do {
|
||||
if (s1 == end)
|
||||
return p->str;
|
||||
} while (*s1++ == *s2++);
|
||||
}
|
||||
{
|
||||
static char *next, *strlimit;
|
||||
if (len + 1 >= strlimit - next) {
|
||||
int n = len + 4*1024;
|
||||
next = allocate(n, PERM);
|
||||
strlimit = next + n;
|
||||
}
|
||||
NEW(p, PERM);
|
||||
p->len = len;
|
||||
for (p->str = next; str < end; )
|
||||
*next++ = *str++;
|
||||
*next++ = 0;
|
||||
p->link = buckets[h];
|
||||
buckets[h] = p;
|
||||
return p->str;
|
||||
}
|
||||
}
|
||||
#include "c.h"
|
||||
|
||||
|
||||
static struct string {
|
||||
char *str;
|
||||
int len;
|
||||
struct string *link;
|
||||
} *buckets[1024];
|
||||
static int scatter[] = { /* map characters to random values */
|
||||
2078917053, 143302914, 1027100827, 1953210302, 755253631,
|
||||
2002600785, 1405390230, 45248011, 1099951567, 433832350,
|
||||
2018585307, 438263339, 813528929, 1703199216, 618906479,
|
||||
573714703, 766270699, 275680090, 1510320440, 1583583926,
|
||||
1723401032, 1965443329, 1098183682, 1636505764, 980071615,
|
||||
1011597961, 643279273, 1315461275, 157584038, 1069844923,
|
||||
471560540, 89017443, 1213147837, 1498661368, 2042227746,
|
||||
1968401469, 1353778505, 1300134328, 2013649480, 306246424,
|
||||
1733966678, 1884751139, 744509763, 400011959, 1440466707,
|
||||
1363416242, 973726663, 59253759, 1639096332, 336563455,
|
||||
1642837685, 1215013716, 154523136, 593537720, 704035832,
|
||||
1134594751, 1605135681, 1347315106, 302572379, 1762719719,
|
||||
269676381, 774132919, 1851737163, 1482824219, 125310639,
|
||||
1746481261, 1303742040, 1479089144, 899131941, 1169907872,
|
||||
1785335569, 485614972, 907175364, 382361684, 885626931,
|
||||
200158423, 1745777927, 1859353594, 259412182, 1237390611,
|
||||
48433401, 1902249868, 304920680, 202956538, 348303940,
|
||||
1008956512, 1337551289, 1953439621, 208787970, 1640123668,
|
||||
1568675693, 478464352, 266772940, 1272929208, 1961288571,
|
||||
392083579, 871926821, 1117546963, 1871172724, 1771058762,
|
||||
139971187, 1509024645, 109190086, 1047146551, 1891386329,
|
||||
994817018, 1247304975, 1489680608, 706686964, 1506717157,
|
||||
579587572, 755120366, 1261483377, 884508252, 958076904,
|
||||
1609787317, 1893464764, 148144545, 1415743291, 2102252735,
|
||||
1788268214, 836935336, 433233439, 2055041154, 2109864544,
|
||||
247038362, 299641085, 834307717, 1364585325, 23330161,
|
||||
457882831, 1504556512, 1532354806, 567072918, 404219416,
|
||||
1276257488, 1561889936, 1651524391, 618454448, 121093252,
|
||||
1010757900, 1198042020, 876213618, 124757630, 2082550272,
|
||||
1834290522, 1734544947, 1828531389, 1982435068, 1002804590,
|
||||
1783300476, 1623219634, 1839739926, 69050267, 1530777140,
|
||||
1802120822, 316088629, 1830418225, 488944891, 1680673954,
|
||||
1853748387, 946827723, 1037746818, 1238619545, 1513900641,
|
||||
1441966234, 367393385, 928306929, 946006977, 985847834,
|
||||
1049400181, 1956764878, 36406206, 1925613800, 2081522508,
|
||||
2118956479, 1612420674, 1668583807, 1800004220, 1447372094,
|
||||
523904750, 1435821048, 923108080, 216161028, 1504871315,
|
||||
306401572, 2018281851, 1820959944, 2136819798, 359743094,
|
||||
1354150250, 1843084537, 1306570817, 244413420, 934220434,
|
||||
672987810, 1686379655, 1301613820, 1601294739, 484902984,
|
||||
139978006, 503211273, 294184214, 176384212, 281341425,
|
||||
228223074, 147857043, 1893762099, 1896806882, 1947861263,
|
||||
1193650546, 273227984, 1236198663, 2116758626, 489389012,
|
||||
593586330, 275676551, 360187215, 267062626, 265012701,
|
||||
719930310, 1621212876, 2108097238, 2026501127, 1865626297,
|
||||
894834024, 552005290, 1404522304, 48964196, 5816381,
|
||||
1889425288, 188942202, 509027654, 36125855, 365326415,
|
||||
790369079, 264348929, 513183458, 536647531, 13672163,
|
||||
313561074, 1730298077, 286900147, 1549759737, 1699573055,
|
||||
776289160, 2143346068, 1975249606, 1136476375, 262925046,
|
||||
92778659, 1856406685, 1884137923, 53392249, 1735424165,
|
||||
1602280572
|
||||
};
|
||||
char *string(const char *str) {
|
||||
const char *s;
|
||||
|
||||
for (s = str; *s; s++)
|
||||
;
|
||||
return stringn(str, s - str);
|
||||
}
|
||||
char *stringd(long n) {
|
||||
char str[25], *s = str + sizeof (str);
|
||||
unsigned long m;
|
||||
|
||||
if (n == LONG_MIN)
|
||||
m = (unsigned long)LONG_MAX + 1;
|
||||
else if (n < 0)
|
||||
m = -n;
|
||||
else
|
||||
m = n;
|
||||
do
|
||||
*--s = m%10 + '0';
|
||||
while ((m /= 10) != 0);
|
||||
if (n < 0)
|
||||
*--s = '-';
|
||||
return stringn(s, str + sizeof (str) - s);
|
||||
}
|
||||
char *stringn(const char *str, int len) {
|
||||
int i;
|
||||
unsigned int h;
|
||||
const char *end;
|
||||
struct string *p;
|
||||
|
||||
assert(str);
|
||||
for (h = 0, i = len, end = str; i > 0; i--)
|
||||
h = (h<<1) + scatter[*(unsigned char *)end++];
|
||||
h &= NELEMS(buckets)-1;
|
||||
for (p = buckets[h]; p; p = p->link)
|
||||
if (len == p->len) {
|
||||
const char *s1 = str;
|
||||
char *s2 = p->str;
|
||||
do {
|
||||
if (s1 == end)
|
||||
return p->str;
|
||||
} while (*s1++ == *s2++);
|
||||
}
|
||||
{
|
||||
static char *next, *strlimit;
|
||||
if (len + 1 >= strlimit - next) {
|
||||
int n = len + 4*1024;
|
||||
next = allocate(n, PERM);
|
||||
strlimit = next + n;
|
||||
}
|
||||
NEW(p, PERM);
|
||||
p->len = len;
|
||||
for (p->str = next; str < end; )
|
||||
*next++ = *str++;
|
||||
*next++ = 0;
|
||||
p->link = buckets[h];
|
||||
buckets[h] = p;
|
||||
return p->str;
|
||||
}
|
||||
}
|
||||
|
|
630
lcc/src/sym.c
Normal file → Executable file
630
lcc/src/sym.c
Normal file → Executable file
|
@ -1,315 +1,315 @@
|
|||
#include "c.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define equalp(x) v.x == p->sym.u.c.v.x
|
||||
|
||||
struct table {
|
||||
int level;
|
||||
Table previous;
|
||||
struct entry {
|
||||
struct symbol sym;
|
||||
struct entry *link;
|
||||
} *buckets[256];
|
||||
Symbol all;
|
||||
};
|
||||
#define HASHSIZE NELEMS(((Table)0)->buckets)
|
||||
static struct table
|
||||
cns = { CONSTANTS },
|
||||
ext = { GLOBAL },
|
||||
ids = { GLOBAL },
|
||||
tys = { GLOBAL };
|
||||
Table constants = &cns;
|
||||
Table externals = &ext;
|
||||
Table identifiers = &ids;
|
||||
Table globals = &ids;
|
||||
Table types = &tys;
|
||||
Table labels;
|
||||
int level = GLOBAL;
|
||||
static int tempid;
|
||||
List loci, symbols;
|
||||
|
||||
Table table(Table tp, int level) {
|
||||
Table new;
|
||||
|
||||
NEW0(new, FUNC);
|
||||
new->previous = tp;
|
||||
new->level = level;
|
||||
if (tp)
|
||||
new->all = tp->all;
|
||||
return new;
|
||||
}
|
||||
void foreach(Table tp, int lev, void (*apply)(Symbol, void *), void *cl) {
|
||||
assert(tp);
|
||||
while (tp && tp->level > lev)
|
||||
tp = tp->previous;
|
||||
if (tp && tp->level == lev) {
|
||||
Symbol p;
|
||||
Coordinate sav;
|
||||
sav = src;
|
||||
for (p = tp->all; p && p->scope == lev; p = p->up) {
|
||||
src = p->src;
|
||||
(*apply)(p, cl);
|
||||
}
|
||||
src = sav;
|
||||
}
|
||||
}
|
||||
void enterscope(void) {
|
||||
if (++level == LOCAL)
|
||||
tempid = 0;
|
||||
}
|
||||
void exitscope(void) {
|
||||
rmtypes(level);
|
||||
if (types->level == level)
|
||||
types = types->previous;
|
||||
if (identifiers->level == level) {
|
||||
if (Aflag >= 2) {
|
||||
int n = 0;
|
||||
Symbol p;
|
||||
for (p = identifiers->all; p && p->scope == level; p = p->up)
|
||||
if (++n > 127) {
|
||||
warning("more than 127 identifiers declared in a block\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
identifiers = identifiers->previous;
|
||||
}
|
||||
assert(level >= GLOBAL);
|
||||
--level;
|
||||
}
|
||||
Symbol install(const char *name, Table *tpp, int level, int arena) {
|
||||
Table tp = *tpp;
|
||||
struct entry *p;
|
||||
unsigned h = (unsigned long)name&(HASHSIZE-1);
|
||||
|
||||
assert(level == 0 || level >= tp->level);
|
||||
if (level > 0 && tp->level < level)
|
||||
tp = *tpp = table(tp, level);
|
||||
NEW0(p, arena);
|
||||
p->sym.name = (char *)name;
|
||||
p->sym.scope = level;
|
||||
p->sym.up = tp->all;
|
||||
tp->all = &p->sym;
|
||||
p->link = tp->buckets[h];
|
||||
tp->buckets[h] = p;
|
||||
return &p->sym;
|
||||
}
|
||||
Symbol relocate(const char *name, Table src, Table dst) {
|
||||
struct entry *p, **q;
|
||||
Symbol *r;
|
||||
unsigned h = (unsigned long)name&(HASHSIZE-1);
|
||||
|
||||
for (q = &src->buckets[h]; *q; q = &(*q)->link)
|
||||
if (name == (*q)->sym.name)
|
||||
break;
|
||||
assert(*q);
|
||||
/*
|
||||
Remove the entry from src's hash chain
|
||||
and from its list of all symbols.
|
||||
*/
|
||||
p = *q;
|
||||
*q = (*q)->link;
|
||||
for (r = &src->all; *r && *r != &p->sym; r = &(*r)->up)
|
||||
;
|
||||
assert(*r == &p->sym);
|
||||
*r = p->sym.up;
|
||||
/*
|
||||
Insert the entry into dst's hash chain
|
||||
and into its list of all symbols.
|
||||
Return the symbol-table entry.
|
||||
*/
|
||||
p->link = dst->buckets[h];
|
||||
dst->buckets[h] = p;
|
||||
p->sym.up = dst->all;
|
||||
dst->all = &p->sym;
|
||||
return &p->sym;
|
||||
}
|
||||
Symbol lookup(const char *name, Table tp) {
|
||||
struct entry *p;
|
||||
unsigned h = (unsigned long)name&(HASHSIZE-1);
|
||||
|
||||
assert(tp);
|
||||
do
|
||||
for (p = tp->buckets[h]; p; p = p->link)
|
||||
if (name == p->sym.name)
|
||||
return &p->sym;
|
||||
while ((tp = tp->previous) != NULL);
|
||||
return NULL;
|
||||
}
|
||||
int genlabel(int n) {
|
||||
static int label = 1;
|
||||
|
||||
label += n;
|
||||
return label - n;
|
||||
}
|
||||
Symbol findlabel(int lab) {
|
||||
struct entry *p;
|
||||
unsigned h = lab&(HASHSIZE-1);
|
||||
|
||||
for (p = labels->buckets[h]; p; p = p->link)
|
||||
if (lab == p->sym.u.l.label)
|
||||
return &p->sym;
|
||||
NEW0(p, FUNC);
|
||||
p->sym.name = stringd(lab);
|
||||
p->sym.scope = LABELS;
|
||||
p->sym.up = labels->all;
|
||||
labels->all = &p->sym;
|
||||
p->link = labels->buckets[h];
|
||||
labels->buckets[h] = p;
|
||||
p->sym.generated = 1;
|
||||
p->sym.u.l.label = lab;
|
||||
(*IR->defsymbol)(&p->sym);
|
||||
return &p->sym;
|
||||
}
|
||||
Symbol constant(Type ty, Value v) {
|
||||
struct entry *p;
|
||||
unsigned h = v.u&(HASHSIZE-1);
|
||||
|
||||
ty = unqual(ty);
|
||||
for (p = constants->buckets[h]; p; p = p->link)
|
||||
if (eqtype(ty, p->sym.type, 1))
|
||||
switch (ty->op) {
|
||||
case INT: if (equalp(i)) return &p->sym; break;
|
||||
case UNSIGNED: if (equalp(u)) return &p->sym; break;
|
||||
case FLOAT: if (equalp(d)) return &p->sym; break;
|
||||
case FUNCTION: if (equalp(g)) return &p->sym; break;
|
||||
case ARRAY:
|
||||
case POINTER: if (equalp(p)) return &p->sym; break;
|
||||
default: assert(0);
|
||||
}
|
||||
NEW0(p, PERM);
|
||||
p->sym.name = vtoa(ty, v);
|
||||
p->sym.scope = CONSTANTS;
|
||||
p->sym.type = ty;
|
||||
p->sym.sclass = STATIC;
|
||||
p->sym.u.c.v = v;
|
||||
p->link = constants->buckets[h];
|
||||
p->sym.up = constants->all;
|
||||
constants->all = &p->sym;
|
||||
constants->buckets[h] = p;
|
||||
if (ty->u.sym && !ty->u.sym->addressed)
|
||||
(*IR->defsymbol)(&p->sym);
|
||||
p->sym.defined = 1;
|
||||
return &p->sym;
|
||||
}
|
||||
Symbol intconst(int n) {
|
||||
Value v;
|
||||
|
||||
v.i = n;
|
||||
return constant(inttype, v);
|
||||
}
|
||||
Symbol genident(int scls, Type ty, int lev) {
|
||||
Symbol p;
|
||||
|
||||
NEW0(p, lev >= LOCAL ? FUNC : PERM);
|
||||
p->name = stringd(genlabel(1));
|
||||
p->scope = lev;
|
||||
p->sclass = scls;
|
||||
p->type = ty;
|
||||
p->generated = 1;
|
||||
if (lev == GLOBAL)
|
||||
(*IR->defsymbol)(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
Symbol temporary(int scls, Type ty) {
|
||||
Symbol p;
|
||||
|
||||
NEW0(p, FUNC);
|
||||
p->name = stringd(++tempid);
|
||||
p->scope = level < LOCAL ? LOCAL : level;
|
||||
p->sclass = scls;
|
||||
p->type = ty;
|
||||
p->temporary = 1;
|
||||
p->generated = 1;
|
||||
return p;
|
||||
}
|
||||
Symbol newtemp(int sclass, int tc, int size) {
|
||||
Symbol p = temporary(sclass, btot(tc, size));
|
||||
|
||||
(*IR->local)(p);
|
||||
p->defined = 1;
|
||||
return p;
|
||||
}
|
||||
|
||||
Symbol allsymbols(Table tp) {
|
||||
return tp->all;
|
||||
}
|
||||
|
||||
void locus(Table tp, Coordinate *cp) {
|
||||
loci = append(cp, loci);
|
||||
symbols = append(allsymbols(tp), symbols);
|
||||
}
|
||||
|
||||
void use(Symbol p, Coordinate src) {
|
||||
Coordinate *cp;
|
||||
|
||||
NEW(cp, PERM);
|
||||
*cp = src;
|
||||
p->uses = append(cp, p->uses);
|
||||
}
|
||||
/* findtype - find type ty in identifiers */
|
||||
Symbol findtype(Type ty) {
|
||||
Table tp = identifiers;
|
||||
int i;
|
||||
struct entry *p;
|
||||
|
||||
assert(tp);
|
||||
do
|
||||
for (i = 0; i < HASHSIZE; i++)
|
||||
for (p = tp->buckets[i]; p; p = p->link)
|
||||
if (p->sym.type == ty && p->sym.sclass == TYPEDEF)
|
||||
return &p->sym;
|
||||
while ((tp = tp->previous) != NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* mkstr - make a string constant */
|
||||
Symbol mkstr(char *str) {
|
||||
Value v;
|
||||
Symbol p;
|
||||
|
||||
v.p = str;
|
||||
p = constant(array(chartype, strlen(v.p) + 1, 0), v);
|
||||
if (p->u.c.loc == NULL)
|
||||
p->u.c.loc = genident(STATIC, p->type, GLOBAL);
|
||||
return p;
|
||||
}
|
||||
|
||||
/* mksymbol - make a symbol for name, install in &globals if sclass==EXTERN */
|
||||
Symbol mksymbol(int sclass, const char *name, Type ty) {
|
||||
Symbol p;
|
||||
|
||||
if (sclass == EXTERN)
|
||||
p = install(string(name), &globals, GLOBAL, PERM);
|
||||
else {
|
||||
NEW0(p, PERM);
|
||||
p->name = string(name);
|
||||
p->scope = GLOBAL;
|
||||
}
|
||||
p->sclass = sclass;
|
||||
p->type = ty;
|
||||
(*IR->defsymbol)(p);
|
||||
p->defined = 1;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* vtoa - return string for the constant v of type ty */
|
||||
char *vtoa(Type ty, Value v) {
|
||||
char buf[50];
|
||||
|
||||
ty = unqual(ty);
|
||||
switch (ty->op) {
|
||||
case INT: return stringd(v.i);
|
||||
case UNSIGNED: return stringf((v.u&~0x7FFF) ? "0x%X" : "%U", v.u);
|
||||
case FLOAT: return stringf("%g", (double)v.d);
|
||||
case ARRAY:
|
||||
if (ty->type == chartype || ty->type == signedchar
|
||||
|| ty->type == unsignedchar)
|
||||
return v.p;
|
||||
return stringf("%p", v.p);
|
||||
case POINTER: return stringf("%p", v.p);
|
||||
case FUNCTION: return stringf("%p", v.g);
|
||||
}
|
||||
assert(0); return NULL;
|
||||
}
|
||||
#include "c.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define equalp(x) v.x == p->sym.u.c.v.x
|
||||
|
||||
struct table {
|
||||
int level;
|
||||
Table previous;
|
||||
struct entry {
|
||||
struct symbol sym;
|
||||
struct entry *link;
|
||||
} *buckets[256];
|
||||
Symbol all;
|
||||
};
|
||||
#define HASHSIZE NELEMS(((Table)0)->buckets)
|
||||
static struct table
|
||||
cns = { CONSTANTS },
|
||||
ext = { GLOBAL },
|
||||
ids = { GLOBAL },
|
||||
tys = { GLOBAL };
|
||||
Table constants = &cns;
|
||||
Table externals = &ext;
|
||||
Table identifiers = &ids;
|
||||
Table globals = &ids;
|
||||
Table types = &tys;
|
||||
Table labels;
|
||||
int level = GLOBAL;
|
||||
static int tempid;
|
||||
List loci, symbols;
|
||||
|
||||
Table table(Table tp, int level) {
|
||||
Table new;
|
||||
|
||||
NEW0(new, FUNC);
|
||||
new->previous = tp;
|
||||
new->level = level;
|
||||
if (tp)
|
||||
new->all = tp->all;
|
||||
return new;
|
||||
}
|
||||
void foreach(Table tp, int lev, void (*apply)(Symbol, void *), void *cl) {
|
||||
assert(tp);
|
||||
while (tp && tp->level > lev)
|
||||
tp = tp->previous;
|
||||
if (tp && tp->level == lev) {
|
||||
Symbol p;
|
||||
Coordinate sav;
|
||||
sav = src;
|
||||
for (p = tp->all; p && p->scope == lev; p = p->up) {
|
||||
src = p->src;
|
||||
(*apply)(p, cl);
|
||||
}
|
||||
src = sav;
|
||||
}
|
||||
}
|
||||
void enterscope(void) {
|
||||
if (++level == LOCAL)
|
||||
tempid = 0;
|
||||
}
|
||||
void exitscope(void) {
|
||||
rmtypes(level);
|
||||
if (types->level == level)
|
||||
types = types->previous;
|
||||
if (identifiers->level == level) {
|
||||
if (Aflag >= 2) {
|
||||
int n = 0;
|
||||
Symbol p;
|
||||
for (p = identifiers->all; p && p->scope == level; p = p->up)
|
||||
if (++n > 127) {
|
||||
warning("more than 127 identifiers declared in a block\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
identifiers = identifiers->previous;
|
||||
}
|
||||
assert(level >= GLOBAL);
|
||||
--level;
|
||||
}
|
||||
Symbol install(const char *name, Table *tpp, int level, int arena) {
|
||||
Table tp = *tpp;
|
||||
struct entry *p;
|
||||
unsigned h = (unsigned long)name&(HASHSIZE-1);
|
||||
|
||||
assert(level == 0 || level >= tp->level);
|
||||
if (level > 0 && tp->level < level)
|
||||
tp = *tpp = table(tp, level);
|
||||
NEW0(p, arena);
|
||||
p->sym.name = (char *)name;
|
||||
p->sym.scope = level;
|
||||
p->sym.up = tp->all;
|
||||
tp->all = &p->sym;
|
||||
p->link = tp->buckets[h];
|
||||
tp->buckets[h] = p;
|
||||
return &p->sym;
|
||||
}
|
||||
Symbol relocate(const char *name, Table src, Table dst) {
|
||||
struct entry *p, **q;
|
||||
Symbol *r;
|
||||
unsigned h = (unsigned long)name&(HASHSIZE-1);
|
||||
|
||||
for (q = &src->buckets[h]; *q; q = &(*q)->link)
|
||||
if (name == (*q)->sym.name)
|
||||
break;
|
||||
assert(*q);
|
||||
/*
|
||||
Remove the entry from src's hash chain
|
||||
and from its list of all symbols.
|
||||
*/
|
||||
p = *q;
|
||||
*q = (*q)->link;
|
||||
for (r = &src->all; *r && *r != &p->sym; r = &(*r)->up)
|
||||
;
|
||||
assert(*r == &p->sym);
|
||||
*r = p->sym.up;
|
||||
/*
|
||||
Insert the entry into dst's hash chain
|
||||
and into its list of all symbols.
|
||||
Return the symbol-table entry.
|
||||
*/
|
||||
p->link = dst->buckets[h];
|
||||
dst->buckets[h] = p;
|
||||
p->sym.up = dst->all;
|
||||
dst->all = &p->sym;
|
||||
return &p->sym;
|
||||
}
|
||||
Symbol lookup(const char *name, Table tp) {
|
||||
struct entry *p;
|
||||
unsigned h = (unsigned long)name&(HASHSIZE-1);
|
||||
|
||||
assert(tp);
|
||||
do
|
||||
for (p = tp->buckets[h]; p; p = p->link)
|
||||
if (name == p->sym.name)
|
||||
return &p->sym;
|
||||
while ((tp = tp->previous) != NULL);
|
||||
return NULL;
|
||||
}
|
||||
int genlabel(int n) {
|
||||
static int label = 1;
|
||||
|
||||
label += n;
|
||||
return label - n;
|
||||
}
|
||||
Symbol findlabel(int lab) {
|
||||
struct entry *p;
|
||||
unsigned h = lab&(HASHSIZE-1);
|
||||
|
||||
for (p = labels->buckets[h]; p; p = p->link)
|
||||
if (lab == p->sym.u.l.label)
|
||||
return &p->sym;
|
||||
NEW0(p, FUNC);
|
||||
p->sym.name = stringd(lab);
|
||||
p->sym.scope = LABELS;
|
||||
p->sym.up = labels->all;
|
||||
labels->all = &p->sym;
|
||||
p->link = labels->buckets[h];
|
||||
labels->buckets[h] = p;
|
||||
p->sym.generated = 1;
|
||||
p->sym.u.l.label = lab;
|
||||
(*IR->defsymbol)(&p->sym);
|
||||
return &p->sym;
|
||||
}
|
||||
Symbol constant(Type ty, Value v) {
|
||||
struct entry *p;
|
||||
unsigned h = v.u&(HASHSIZE-1);
|
||||
|
||||
ty = unqual(ty);
|
||||
for (p = constants->buckets[h]; p; p = p->link)
|
||||
if (eqtype(ty, p->sym.type, 1))
|
||||
switch (ty->op) {
|
||||
case INT: if (equalp(i)) return &p->sym; break;
|
||||
case UNSIGNED: if (equalp(u)) return &p->sym; break;
|
||||
case FLOAT: if (equalp(d)) return &p->sym; break;
|
||||
case FUNCTION: if (equalp(g)) return &p->sym; break;
|
||||
case ARRAY:
|
||||
case POINTER: if (equalp(p)) return &p->sym; break;
|
||||
default: assert(0);
|
||||
}
|
||||
NEW0(p, PERM);
|
||||
p->sym.name = vtoa(ty, v);
|
||||
p->sym.scope = CONSTANTS;
|
||||
p->sym.type = ty;
|
||||
p->sym.sclass = STATIC;
|
||||
p->sym.u.c.v = v;
|
||||
p->link = constants->buckets[h];
|
||||
p->sym.up = constants->all;
|
||||
constants->all = &p->sym;
|
||||
constants->buckets[h] = p;
|
||||
if (ty->u.sym && !ty->u.sym->addressed)
|
||||
(*IR->defsymbol)(&p->sym);
|
||||
p->sym.defined = 1;
|
||||
return &p->sym;
|
||||
}
|
||||
Symbol intconst(int n) {
|
||||
Value v;
|
||||
|
||||
v.i = n;
|
||||
return constant(inttype, v);
|
||||
}
|
||||
Symbol genident(int scls, Type ty, int lev) {
|
||||
Symbol p;
|
||||
|
||||
NEW0(p, lev >= LOCAL ? FUNC : PERM);
|
||||
p->name = stringd(genlabel(1));
|
||||
p->scope = lev;
|
||||
p->sclass = scls;
|
||||
p->type = ty;
|
||||
p->generated = 1;
|
||||
if (lev == GLOBAL)
|
||||
(*IR->defsymbol)(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
Symbol temporary(int scls, Type ty) {
|
||||
Symbol p;
|
||||
|
||||
NEW0(p, FUNC);
|
||||
p->name = stringd(++tempid);
|
||||
p->scope = level < LOCAL ? LOCAL : level;
|
||||
p->sclass = scls;
|
||||
p->type = ty;
|
||||
p->temporary = 1;
|
||||
p->generated = 1;
|
||||
return p;
|
||||
}
|
||||
Symbol newtemp(int sclass, int tc, int size) {
|
||||
Symbol p = temporary(sclass, btot(tc, size));
|
||||
|
||||
(*IR->local)(p);
|
||||
p->defined = 1;
|
||||
return p;
|
||||
}
|
||||
|
||||
Symbol allsymbols(Table tp) {
|
||||
return tp->all;
|
||||
}
|
||||
|
||||
void locus(Table tp, Coordinate *cp) {
|
||||
loci = append(cp, loci);
|
||||
symbols = append(allsymbols(tp), symbols);
|
||||
}
|
||||
|
||||
void use(Symbol p, Coordinate src) {
|
||||
Coordinate *cp;
|
||||
|
||||
NEW(cp, PERM);
|
||||
*cp = src;
|
||||
p->uses = append(cp, p->uses);
|
||||
}
|
||||
/* findtype - find type ty in identifiers */
|
||||
Symbol findtype(Type ty) {
|
||||
Table tp = identifiers;
|
||||
int i;
|
||||
struct entry *p;
|
||||
|
||||
assert(tp);
|
||||
do
|
||||
for (i = 0; i < HASHSIZE; i++)
|
||||
for (p = tp->buckets[i]; p; p = p->link)
|
||||
if (p->sym.type == ty && p->sym.sclass == TYPEDEF)
|
||||
return &p->sym;
|
||||
while ((tp = tp->previous) != NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* mkstr - make a string constant */
|
||||
Symbol mkstr(char *str) {
|
||||
Value v;
|
||||
Symbol p;
|
||||
|
||||
v.p = str;
|
||||
p = constant(array(chartype, strlen(v.p) + 1, 0), v);
|
||||
if (p->u.c.loc == NULL)
|
||||
p->u.c.loc = genident(STATIC, p->type, GLOBAL);
|
||||
return p;
|
||||
}
|
||||
|
||||
/* mksymbol - make a symbol for name, install in &globals if sclass==EXTERN */
|
||||
Symbol mksymbol(int sclass, const char *name, Type ty) {
|
||||
Symbol p;
|
||||
|
||||
if (sclass == EXTERN)
|
||||
p = install(string(name), &globals, GLOBAL, PERM);
|
||||
else {
|
||||
NEW0(p, PERM);
|
||||
p->name = string(name);
|
||||
p->scope = GLOBAL;
|
||||
}
|
||||
p->sclass = sclass;
|
||||
p->type = ty;
|
||||
(*IR->defsymbol)(p);
|
||||
p->defined = 1;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* vtoa - return string for the constant v of type ty */
|
||||
char *vtoa(Type ty, Value v) {
|
||||
char buf[50];
|
||||
|
||||
ty = unqual(ty);
|
||||
switch (ty->op) {
|
||||
case INT: return stringd(v.i);
|
||||
case UNSIGNED: return stringf((v.u&~0x7FFF) ? "0x%X" : "%U", v.u);
|
||||
case FLOAT: return stringf("%g", (double)v.d);
|
||||
case ARRAY:
|
||||
if (ty->type == chartype || ty->type == signedchar
|
||||
|| ty->type == unsignedchar)
|
||||
return v.p;
|
||||
return stringf("%p", v.p);
|
||||
case POINTER: return stringf("%p", v.p);
|
||||
case FUNCTION: return stringf("%p", v.g);
|
||||
}
|
||||
assert(0); return NULL;
|
||||
}
|
||||
|
|
988
lcc/src/symbolic.c
Normal file → Executable file
988
lcc/src/symbolic.c
Normal file → Executable file
|
@ -1,494 +1,494 @@
|
|||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include "c.h"
|
||||
|
||||
#define I(f) s_##f
|
||||
|
||||
static Node *tail;
|
||||
static int off, maxoff, uid = 0, verbose = 0, html = 0;
|
||||
|
||||
static const char *yyBEGIN(const char *tag) {
|
||||
if (html)
|
||||
print("<%s>", tag);
|
||||
return tag;
|
||||
}
|
||||
|
||||
static void yyEND(const char *tag) {
|
||||
if (html)
|
||||
print("</%s>", tag);
|
||||
if (isupper(*tag))
|
||||
print("\n");
|
||||
}
|
||||
|
||||
#define BEGIN(tag) do { const char *yytag=yyBEGIN(#tag);
|
||||
#define END yyEND(yytag); } while (0)
|
||||
#define ITEM BEGIN(li)
|
||||
#define START BEGIN(LI)
|
||||
#define ANCHOR(attr,code) do { const char *yytag="a"; if (html) { printf("<a " #attr "=\""); code; print("\">"); }
|
||||
#define NEWLINE print(html ? "<br>\n" : "\n")
|
||||
|
||||
static void emitCoord(Coordinate src) {
|
||||
if (src.file && *src.file) {
|
||||
ANCHOR(href,print("%s", src.file)); print("%s", src.file); END;
|
||||
print(":");
|
||||
}
|
||||
print("%d.%d", src.y, src.x);
|
||||
}
|
||||
|
||||
static void emitString(int len, const char *s) {
|
||||
for ( ; len-- > 0; s++)
|
||||
if (*s == '&' && html)
|
||||
print("&");
|
||||
else if (*s == '<' && html)
|
||||
print("<");
|
||||
else if (*s == '>' && html)
|
||||
print("<");
|
||||
else if (*s == '"' || *s == '\\')
|
||||
print("\\%c", *s);
|
||||
else if (*s >= ' ' && *s < 0177)
|
||||
print("%c", *s);
|
||||
else
|
||||
print("\\%d%d%d", (*s>>6)&3, (*s>>3)&7, *s&7);
|
||||
}
|
||||
|
||||
static void emitSymRef(Symbol p) {
|
||||
(*IR->defsymbol)(p);
|
||||
ANCHOR(href,print("#%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END;
|
||||
}
|
||||
|
||||
static void emitSymbol(Symbol p) {
|
||||
(*IR->defsymbol)(p);
|
||||
ANCHOR(name,print("%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END;
|
||||
BEGIN(ul);
|
||||
#define xx(field,code) ITEM; if (!html) print(" "); print(#field "="); code; END
|
||||
if (verbose && (src.y || src.x))
|
||||
xx(src,emitCoord(p->src));
|
||||
xx(type,print("%t", p->type));
|
||||
xx(sclass,print("%k", p->sclass));
|
||||
switch (p->scope) {
|
||||
case CONSTANTS: xx(scope,print("CONSTANTS")); break;
|
||||
case LABELS: xx(scope,print("LABELS")); break;
|
||||
case GLOBAL: xx(scope,print("GLOBAL")); break;
|
||||
case PARAM: xx(scope,print("PARAM")); break;
|
||||
case LOCAL: xx(scope,print("LOCAL")); break;
|
||||
default:
|
||||
if (p->scope > LOCAL)
|
||||
xx(scope,print("LOCAL+%d", p->scope-LOCAL));
|
||||
else
|
||||
xx(scope,print("%d", p->scope));
|
||||
}
|
||||
if (p->scope >= PARAM && p->sclass != STATIC)
|
||||
xx(offset,print("%d", p->x.offset));
|
||||
xx(ref,print("%f", p->ref));
|
||||
if (p->temporary && p->u.t.cse)
|
||||
xx(u.t.cse,print("%p", p->u.t.cse));
|
||||
END;
|
||||
#undef xx
|
||||
}
|
||||
|
||||
/* address - initialize q for addressing expression p+n */
|
||||
static void I(address)(Symbol q, Symbol p, long n) {
|
||||
q->name = stringf("%s%s%D", p->name, n > 0 ? "+" : "", n);
|
||||
(*IR->defsymbol)(q);
|
||||
START; print("address "); emitSymbol(q); END;
|
||||
}
|
||||
|
||||
/* blockbeg - start a block */
|
||||
static void I(blockbeg)(Env *e) {
|
||||
e->offset = off;
|
||||
START; print("blockbeg off=%d", off); END;
|
||||
}
|
||||
|
||||
/* blockend - start a block */
|
||||
static void I(blockend)(Env *e) {
|
||||
if (off > maxoff)
|
||||
maxoff = off;
|
||||
START; print("blockend off=%d", off); END;
|
||||
off = e->offset;
|
||||
}
|
||||
|
||||
/* defaddress - initialize an address */
|
||||
static void I(defaddress)(Symbol p){
|
||||
START; print("defaddress "); emitSymRef(p); END;
|
||||
}
|
||||
|
||||
/* defconst - define a constant */
|
||||
static void I(defconst)(int suffix, int size, Value v) {
|
||||
START;
|
||||
print("defconst ");
|
||||
switch (suffix) {
|
||||
case I:
|
||||
print("int.%d ", size);
|
||||
BEGIN(code);
|
||||
if (size > sizeof (int))
|
||||
print("%D", v.i);
|
||||
else
|
||||
print("%d", (int)v.i);
|
||||
END;
|
||||
break;
|
||||
case U:
|
||||
print("unsigned.%d ", size);
|
||||
BEGIN(code);
|
||||
if (size > sizeof (unsigned))
|
||||
print("%U", v.u);
|
||||
else
|
||||
print("%u", (unsigned)v.u);
|
||||
END;
|
||||
break;
|
||||
case P: print("void*.%d ", size); BEGIN(code); print("%p", v.p); END; break;
|
||||
case F: print("float.%d ", size); BEGIN(code); print("%g", (double)v.d); END; break;
|
||||
default: assert(0);
|
||||
}
|
||||
END;
|
||||
}
|
||||
|
||||
/* defstring - emit a string constant */
|
||||
static void I(defstring)(int len, char *s) {
|
||||
START; print("defstring ");
|
||||
BEGIN(code); print("\""); emitString(len, s); print("\""); END;
|
||||
END;
|
||||
}
|
||||
|
||||
/* defsymbol - define a symbol: initialize p->x */
|
||||
static void I(defsymbol)(Symbol p) {
|
||||
if (p->x.name == NULL)
|
||||
p->x.name = stringd(++uid);
|
||||
}
|
||||
|
||||
/* emit - emit the dags on list p */
|
||||
static void I(emit)(Node p){
|
||||
ITEM;
|
||||
if (!html)
|
||||
print(" ");
|
||||
for (; p; p = p->x.next) {
|
||||
if (p->op == LABEL+V) {
|
||||
assert(p->syms[0]);
|
||||
ANCHOR(name,print("%s", p->syms[0]->x.name));
|
||||
BEGIN(code); print("%s", p->syms[0]->name); END;
|
||||
END;
|
||||
print(":");
|
||||
} else {
|
||||
int i;
|
||||
if (p->x.listed) {
|
||||
BEGIN(strong); print("%d", p->x.inst); END; print("'");
|
||||
print(" %s", opname(p->op));
|
||||
} else
|
||||
print("%d. %s", p->x.inst, opname(p->op));
|
||||
if (p->count > 1)
|
||||
print(" count=%d", p->count);
|
||||
for (i = 0; i < NELEMS(p->kids) && p->kids[i]; i++)
|
||||
print(" #%d", p->kids[i]->x.inst);
|
||||
if (generic(p->op) == CALL && p->syms[0] && p->syms[0]->type)
|
||||
print(" {%t}", p->syms[0]->type);
|
||||
else
|
||||
for (i = 0; i < NELEMS(p->syms) && p->syms[i]; i++) {
|
||||
print(" ");
|
||||
if (p->syms[i]->scope == CONSTANTS)
|
||||
print(p->syms[i]->name);
|
||||
else
|
||||
emitSymRef(p->syms[i]);
|
||||
}
|
||||
}
|
||||
NEWLINE;
|
||||
}
|
||||
END;
|
||||
}
|
||||
|
||||
/* export - announce p as exported */
|
||||
static void I(export)(Symbol p) {
|
||||
START; print("export "); emitSymRef(p); END;
|
||||
}
|
||||
|
||||
/* function - generate code for a function */
|
||||
static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
|
||||
int i;
|
||||
|
||||
(*IR->defsymbol)(f);
|
||||
off = 0;
|
||||
for (i = 0; caller[i] && callee[i]; i++) {
|
||||
off = roundup(off, caller[i]->type->align);
|
||||
caller[i]->x.offset = callee[i]->x.offset = off;
|
||||
off += caller[i]->type->size;
|
||||
}
|
||||
if (!html) {
|
||||
print("function ");
|
||||
emitSymbol(f);
|
||||
print(" ncalls=%d\n", ncalls);
|
||||
for (i = 0; caller[i]; i++)
|
||||
START; print("caller "); emitSymbol(caller[i]); END;
|
||||
for (i = 0; callee[i]; i++)
|
||||
START; print("callee "); emitSymbol(callee[i]); END;
|
||||
} else {
|
||||
START;
|
||||
print("function");
|
||||
BEGIN(UL);
|
||||
#define xx(field,code) ITEM; print(#field "="); code; END
|
||||
xx(f,emitSymbol(f));
|
||||
xx(ncalls,print("%d", ncalls));
|
||||
if (caller[0]) {
|
||||
ITEM; print("caller"); BEGIN(OL);
|
||||
for (i = 0; caller[i]; i++)
|
||||
ITEM; emitSymbol(caller[i]); END;
|
||||
END; END;
|
||||
ITEM; print("callee"); BEGIN(OL);
|
||||
for (i = 0; callee[i]; i++)
|
||||
ITEM; emitSymbol(callee[i]); END;
|
||||
END; END;
|
||||
} else {
|
||||
xx(caller,BEGIN(em); print("empty"); END);
|
||||
xx(callee,BEGIN(em); print("empty"); END);
|
||||
}
|
||||
END;
|
||||
END;
|
||||
}
|
||||
maxoff = off = 0;
|
||||
gencode(caller, callee);
|
||||
if (html)
|
||||
START; print("emitcode"); BEGIN(ul); emitcode(); END; END;
|
||||
else
|
||||
emitcode();
|
||||
START; print("maxoff=%d", maxoff); END;
|
||||
#undef xx
|
||||
}
|
||||
|
||||
/* visit - generate code for *p */
|
||||
static int visit(Node p, int n) {
|
||||
if (p && p->x.inst == 0) {
|
||||
p->x.inst = ++n;
|
||||
n = visit(p->kids[0], n);
|
||||
n = visit(p->kids[1], n);
|
||||
*tail = p;
|
||||
tail = &p->x.next;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* gen0 - generate code for the dags on list p */
|
||||
static Node I(gen)(Node p) {
|
||||
int n;
|
||||
Node nodelist;
|
||||
|
||||
tail = &nodelist;
|
||||
for (n = 0; p; p = p->link) {
|
||||
switch (generic(p->op)) { /* check for valid forest */
|
||||
case CALL:
|
||||
assert(IR->wants_dag || p->count == 0);
|
||||
break;
|
||||
case ARG:
|
||||
case ASGN: case JUMP: case LABEL: case RET:
|
||||
case EQ: case GE: case GT: case LE: case LT: case NE:
|
||||
assert(p->count == 0);
|
||||
break;
|
||||
case INDIR:
|
||||
assert(IR->wants_dag && p->count > 0);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
check(p);
|
||||
p->x.listed = 1;
|
||||
n = visit(p, n);
|
||||
}
|
||||
*tail = 0;
|
||||
return nodelist;
|
||||
}
|
||||
|
||||
/* global - announce a global */
|
||||
static void I(global)(Symbol p) {
|
||||
START; print("global "); emitSymbol(p); END;
|
||||
}
|
||||
|
||||
/* import - import a symbol */
|
||||
static void I(import)(Symbol p) {
|
||||
START; print("import "); emitSymRef(p); END;
|
||||
}
|
||||
|
||||
/* local - local variable */
|
||||
static void I(local)(Symbol p) {
|
||||
if (p->temporary)
|
||||
p->name = stringf("t%s", p->name);
|
||||
(*IR->defsymbol)(p);
|
||||
off = roundup(off, p->type->align);
|
||||
p->x.offset = off;
|
||||
off += p->type->size;
|
||||
START; print(p->temporary ? "temporary " : "local "); emitSymbol(p); END;
|
||||
}
|
||||
|
||||
/* progbeg - beginning of program */
|
||||
static void I(progbeg)(int argc, char *argv[]) {
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
if (strcmp(argv[i], "-v") == 0)
|
||||
verbose++;
|
||||
else if (strcmp(argv[i], "-html") == 0)
|
||||
html++;
|
||||
if (html) {
|
||||
print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n");
|
||||
print("<html>");
|
||||
BEGIN(head);
|
||||
if (firstfile && *firstfile)
|
||||
BEGIN(title); emitString(strlen(firstfile), firstfile); END;
|
||||
print("<link rev=made href=\"mailto:drh@microsoft.com\">\n");
|
||||
END;
|
||||
print("<body>\n");
|
||||
if (firstfile && *firstfile)
|
||||
BEGIN(h1); emitString(strlen(firstfile), firstfile); END;
|
||||
BEGIN(P); BEGIN(em);
|
||||
print("Links lead from uses of identifiers and labels to their definitions.");
|
||||
END; END;
|
||||
print("<ul>\n");
|
||||
START;
|
||||
print("progbeg");
|
||||
BEGIN(ol);
|
||||
for (i = 1; i < argc; i++) {
|
||||
ITEM;
|
||||
BEGIN(code); print("\""); emitString(strlen(argv[i]), argv[i]); print("\""); END;
|
||||
END;
|
||||
}
|
||||
END;
|
||||
END;
|
||||
}
|
||||
}
|
||||
|
||||
/* progend - end of program */
|
||||
static void I(progend)(void) {
|
||||
START; print("progend"); END;
|
||||
if (html) {
|
||||
time_t t;
|
||||
print("</ul>\n");
|
||||
time(&t);
|
||||
print("<hr><address>%s</address>\n", ctime(&t));
|
||||
print("</body></html>\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* segment - switch to segment s */
|
||||
static void I(segment)(int s) {
|
||||
START; print("segment %s", &"text\0bss\0.data\0lit\0.sym\0."[5*s-5]); END;
|
||||
}
|
||||
|
||||
/* space - initialize n bytes of space */
|
||||
static void I(space)(int n) {
|
||||
START; print("space %d", n); END;
|
||||
}
|
||||
|
||||
static void I(stabblock)(int brace, int lev, Symbol *p) {}
|
||||
|
||||
/* stabend - finalize stab output */
|
||||
static void I(stabend)(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {
|
||||
int i;
|
||||
|
||||
if (p)
|
||||
emitSymRef(p);
|
||||
print("\n");
|
||||
if (cpp && sp)
|
||||
for (i = 0; cpp[i] && sp[i]; i++) {
|
||||
print("%w.%d: ", cpp[i], cpp[i]->x);
|
||||
emitSymRef(sp[i]);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void I(stabfend)(Symbol p, int lineno) {}
|
||||
static void I(stabinit)(char *file, int argc, char *argv[]) {}
|
||||
|
||||
/* stabline - emit line number information for source coordinate *cp */
|
||||
static void I(stabline)(Coordinate *cp) {
|
||||
if (cp->file)
|
||||
print("%s:", cp->file);
|
||||
print("%d.%d:\n", cp->y, cp->x);
|
||||
}
|
||||
|
||||
static void I(stabsym)(Symbol p) {}
|
||||
static void I(stabtype)(Symbol p) {}
|
||||
|
||||
Interface symbolicIR = {
|
||||
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 */
|
||||
1, /* wants_argb */
|
||||
1, /* left_to_right */
|
||||
1, /* 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),
|
||||
I(stabblock),
|
||||
I(stabend),
|
||||
I(stabfend),
|
||||
I(stabinit),
|
||||
I(stabline),
|
||||
I(stabsym),
|
||||
I(stabtype)
|
||||
};
|
||||
|
||||
Interface symbolic64IR = {
|
||||
1, 1, 0, /* char */
|
||||
2, 2, 0, /* short */
|
||||
4, 4, 0, /* int */
|
||||
8, 8, 0, /* long */
|
||||
8, 8, 0, /* long long */
|
||||
4, 4, 1, /* float */
|
||||
8, 8, 1, /* double */
|
||||
8, 8, 1, /* long double */
|
||||
8, 8, 0, /* T* */
|
||||
0, 1, 0, /* struct */
|
||||
1, /* little_endian */
|
||||
0, /* mulops_calls */
|
||||
0, /* wants_callb */
|
||||
1, /* wants_argb */
|
||||
1, /* left_to_right */
|
||||
1, /* 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),
|
||||
I(stabblock),
|
||||
I(stabend),
|
||||
I(stabfend),
|
||||
I(stabinit),
|
||||
I(stabline),
|
||||
I(stabsym),
|
||||
I(stabtype)
|
||||
};
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include "c.h"
|
||||
|
||||
#define I(f) s_##f
|
||||
|
||||
static Node *tail;
|
||||
static int off, maxoff, uid = 0, verbose = 0, html = 0;
|
||||
|
||||
static const char *yyBEGIN(const char *tag) {
|
||||
if (html)
|
||||
print("<%s>", tag);
|
||||
return tag;
|
||||
}
|
||||
|
||||
static void yyEND(const char *tag) {
|
||||
if (html)
|
||||
print("</%s>", tag);
|
||||
if (isupper(*tag))
|
||||
print("\n");
|
||||
}
|
||||
|
||||
#define BEGIN(tag) do { const char *yytag=yyBEGIN(#tag);
|
||||
#define END yyEND(yytag); } while (0)
|
||||
#define ITEM BEGIN(li)
|
||||
#define START BEGIN(LI)
|
||||
#define ANCHOR(attr,code) do { const char *yytag="a"; if (html) { printf("<a " #attr "=\""); code; print("\">"); }
|
||||
#define NEWLINE print(html ? "<br>\n" : "\n")
|
||||
|
||||
static void emitCoord(Coordinate src) {
|
||||
if (src.file && *src.file) {
|
||||
ANCHOR(href,print("%s", src.file)); print("%s", src.file); END;
|
||||
print(":");
|
||||
}
|
||||
print("%d.%d", src.y, src.x);
|
||||
}
|
||||
|
||||
static void emitString(int len, const char *s) {
|
||||
for ( ; len-- > 0; s++)
|
||||
if (*s == '&' && html)
|
||||
print("&");
|
||||
else if (*s == '<' && html)
|
||||
print("<");
|
||||
else if (*s == '>' && html)
|
||||
print("<");
|
||||
else if (*s == '"' || *s == '\\')
|
||||
print("\\%c", *s);
|
||||
else if (*s >= ' ' && *s < 0177)
|
||||
print("%c", *s);
|
||||
else
|
||||
print("\\%d%d%d", (*s>>6)&3, (*s>>3)&7, *s&7);
|
||||
}
|
||||
|
||||
static void emitSymRef(Symbol p) {
|
||||
(*IR->defsymbol)(p);
|
||||
ANCHOR(href,print("#%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END;
|
||||
}
|
||||
|
||||
static void emitSymbol(Symbol p) {
|
||||
(*IR->defsymbol)(p);
|
||||
ANCHOR(name,print("%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END;
|
||||
BEGIN(ul);
|
||||
#define xx(field,code) ITEM; if (!html) print(" "); print(#field "="); code; END
|
||||
if (verbose && (src.y || src.x))
|
||||
xx(src,emitCoord(p->src));
|
||||
xx(type,print("%t", p->type));
|
||||
xx(sclass,print("%k", p->sclass));
|
||||
switch (p->scope) {
|
||||
case CONSTANTS: xx(scope,print("CONSTANTS")); break;
|
||||
case LABELS: xx(scope,print("LABELS")); break;
|
||||
case GLOBAL: xx(scope,print("GLOBAL")); break;
|
||||
case PARAM: xx(scope,print("PARAM")); break;
|
||||
case LOCAL: xx(scope,print("LOCAL")); break;
|
||||
default:
|
||||
if (p->scope > LOCAL)
|
||||
xx(scope,print("LOCAL+%d", p->scope-LOCAL));
|
||||
else
|
||||
xx(scope,print("%d", p->scope));
|
||||
}
|
||||
if (p->scope >= PARAM && p->sclass != STATIC)
|
||||
xx(offset,print("%d", p->x.offset));
|
||||
xx(ref,print("%f", p->ref));
|
||||
if (p->temporary && p->u.t.cse)
|
||||
xx(u.t.cse,print("%p", p->u.t.cse));
|
||||
END;
|
||||
#undef xx
|
||||
}
|
||||
|
||||
/* address - initialize q for addressing expression p+n */
|
||||
static void I(address)(Symbol q, Symbol p, long n) {
|
||||
q->name = stringf("%s%s%D", p->name, n > 0 ? "+" : "", n);
|
||||
(*IR->defsymbol)(q);
|
||||
START; print("address "); emitSymbol(q); END;
|
||||
}
|
||||
|
||||
/* blockbeg - start a block */
|
||||
static void I(blockbeg)(Env *e) {
|
||||
e->offset = off;
|
||||
START; print("blockbeg off=%d", off); END;
|
||||
}
|
||||
|
||||
/* blockend - start a block */
|
||||
static void I(blockend)(Env *e) {
|
||||
if (off > maxoff)
|
||||
maxoff = off;
|
||||
START; print("blockend off=%d", off); END;
|
||||
off = e->offset;
|
||||
}
|
||||
|
||||
/* defaddress - initialize an address */
|
||||
static void I(defaddress)(Symbol p){
|
||||
START; print("defaddress "); emitSymRef(p); END;
|
||||
}
|
||||
|
||||
/* defconst - define a constant */
|
||||
static void I(defconst)(int suffix, int size, Value v) {
|
||||
START;
|
||||
print("defconst ");
|
||||
switch (suffix) {
|
||||
case I:
|
||||
print("int.%d ", size);
|
||||
BEGIN(code);
|
||||
if (size > sizeof (int))
|
||||
print("%D", v.i);
|
||||
else
|
||||
print("%d", (int)v.i);
|
||||
END;
|
||||
break;
|
||||
case U:
|
||||
print("unsigned.%d ", size);
|
||||
BEGIN(code);
|
||||
if (size > sizeof (unsigned))
|
||||
print("%U", v.u);
|
||||
else
|
||||
print("%u", (unsigned)v.u);
|
||||
END;
|
||||
break;
|
||||
case P: print("void*.%d ", size); BEGIN(code); print("%p", v.p); END; break;
|
||||
case F: print("float.%d ", size); BEGIN(code); print("%g", (double)v.d); END; break;
|
||||
default: assert(0);
|
||||
}
|
||||
END;
|
||||
}
|
||||
|
||||
/* defstring - emit a string constant */
|
||||
static void I(defstring)(int len, char *s) {
|
||||
START; print("defstring ");
|
||||
BEGIN(code); print("\""); emitString(len, s); print("\""); END;
|
||||
END;
|
||||
}
|
||||
|
||||
/* defsymbol - define a symbol: initialize p->x */
|
||||
static void I(defsymbol)(Symbol p) {
|
||||
if (p->x.name == NULL)
|
||||
p->x.name = stringd(++uid);
|
||||
}
|
||||
|
||||
/* emit - emit the dags on list p */
|
||||
static void I(emit)(Node p){
|
||||
ITEM;
|
||||
if (!html)
|
||||
print(" ");
|
||||
for (; p; p = p->x.next) {
|
||||
if (p->op == LABEL+V) {
|
||||
assert(p->syms[0]);
|
||||
ANCHOR(name,print("%s", p->syms[0]->x.name));
|
||||
BEGIN(code); print("%s", p->syms[0]->name); END;
|
||||
END;
|
||||
print(":");
|
||||
} else {
|
||||
int i;
|
||||
if (p->x.listed) {
|
||||
BEGIN(strong); print("%d", p->x.inst); END; print("'");
|
||||
print(" %s", opname(p->op));
|
||||
} else
|
||||
print("%d. %s", p->x.inst, opname(p->op));
|
||||
if (p->count > 1)
|
||||
print(" count=%d", p->count);
|
||||
for (i = 0; i < NELEMS(p->kids) && p->kids[i]; i++)
|
||||
print(" #%d", p->kids[i]->x.inst);
|
||||
if (generic(p->op) == CALL && p->syms[0] && p->syms[0]->type)
|
||||
print(" {%t}", p->syms[0]->type);
|
||||
else
|
||||
for (i = 0; i < NELEMS(p->syms) && p->syms[i]; i++) {
|
||||
print(" ");
|
||||
if (p->syms[i]->scope == CONSTANTS)
|
||||
print(p->syms[i]->name);
|
||||
else
|
||||
emitSymRef(p->syms[i]);
|
||||
}
|
||||
}
|
||||
NEWLINE;
|
||||
}
|
||||
END;
|
||||
}
|
||||
|
||||
/* export - announce p as exported */
|
||||
static void I(export)(Symbol p) {
|
||||
START; print("export "); emitSymRef(p); END;
|
||||
}
|
||||
|
||||
/* function - generate code for a function */
|
||||
static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
|
||||
int i;
|
||||
|
||||
(*IR->defsymbol)(f);
|
||||
off = 0;
|
||||
for (i = 0; caller[i] && callee[i]; i++) {
|
||||
off = roundup(off, caller[i]->type->align);
|
||||
caller[i]->x.offset = callee[i]->x.offset = off;
|
||||
off += caller[i]->type->size;
|
||||
}
|
||||
if (!html) {
|
||||
print("function ");
|
||||
emitSymbol(f);
|
||||
print(" ncalls=%d\n", ncalls);
|
||||
for (i = 0; caller[i]; i++)
|
||||
START; print("caller "); emitSymbol(caller[i]); END;
|
||||
for (i = 0; callee[i]; i++)
|
||||
START; print("callee "); emitSymbol(callee[i]); END;
|
||||
} else {
|
||||
START;
|
||||
print("function");
|
||||
BEGIN(UL);
|
||||
#define xx(field,code) ITEM; print(#field "="); code; END
|
||||
xx(f,emitSymbol(f));
|
||||
xx(ncalls,print("%d", ncalls));
|
||||
if (caller[0]) {
|
||||
ITEM; print("caller"); BEGIN(OL);
|
||||
for (i = 0; caller[i]; i++)
|
||||
ITEM; emitSymbol(caller[i]); END;
|
||||
END; END;
|
||||
ITEM; print("callee"); BEGIN(OL);
|
||||
for (i = 0; callee[i]; i++)
|
||||
ITEM; emitSymbol(callee[i]); END;
|
||||
END; END;
|
||||
} else {
|
||||
xx(caller,BEGIN(em); print("empty"); END);
|
||||
xx(callee,BEGIN(em); print("empty"); END);
|
||||
}
|
||||
END;
|
||||
END;
|
||||
}
|
||||
maxoff = off = 0;
|
||||
gencode(caller, callee);
|
||||
if (html)
|
||||
START; print("emitcode"); BEGIN(ul); emitcode(); END; END;
|
||||
else
|
||||
emitcode();
|
||||
START; print("maxoff=%d", maxoff); END;
|
||||
#undef xx
|
||||
}
|
||||
|
||||
/* visit - generate code for *p */
|
||||
static int visit(Node p, int n) {
|
||||
if (p && p->x.inst == 0) {
|
||||
p->x.inst = ++n;
|
||||
n = visit(p->kids[0], n);
|
||||
n = visit(p->kids[1], n);
|
||||
*tail = p;
|
||||
tail = &p->x.next;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* gen0 - generate code for the dags on list p */
|
||||
static Node I(gen)(Node p) {
|
||||
int n;
|
||||
Node nodelist;
|
||||
|
||||
tail = &nodelist;
|
||||
for (n = 0; p; p = p->link) {
|
||||
switch (generic(p->op)) { /* check for valid forest */
|
||||
case CALL:
|
||||
assert(IR->wants_dag || p->count == 0);
|
||||
break;
|
||||
case ARG:
|
||||
case ASGN: case JUMP: case LABEL: case RET:
|
||||
case EQ: case GE: case GT: case LE: case LT: case NE:
|
||||
assert(p->count == 0);
|
||||
break;
|
||||
case INDIR:
|
||||
assert(IR->wants_dag && p->count > 0);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
check(p);
|
||||
p->x.listed = 1;
|
||||
n = visit(p, n);
|
||||
}
|
||||
*tail = 0;
|
||||
return nodelist;
|
||||
}
|
||||
|
||||
/* global - announce a global */
|
||||
static void I(global)(Symbol p) {
|
||||
START; print("global "); emitSymbol(p); END;
|
||||
}
|
||||
|
||||
/* import - import a symbol */
|
||||
static void I(import)(Symbol p) {
|
||||
START; print("import "); emitSymRef(p); END;
|
||||
}
|
||||
|
||||
/* local - local variable */
|
||||
static void I(local)(Symbol p) {
|
||||
if (p->temporary)
|
||||
p->name = stringf("t%s", p->name);
|
||||
(*IR->defsymbol)(p);
|
||||
off = roundup(off, p->type->align);
|
||||
p->x.offset = off;
|
||||
off += p->type->size;
|
||||
START; print(p->temporary ? "temporary " : "local "); emitSymbol(p); END;
|
||||
}
|
||||
|
||||
/* progbeg - beginning of program */
|
||||
static void I(progbeg)(int argc, char *argv[]) {
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
if (strcmp(argv[i], "-v") == 0)
|
||||
verbose++;
|
||||
else if (strcmp(argv[i], "-html") == 0)
|
||||
html++;
|
||||
if (html) {
|
||||
print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n");
|
||||
print("<html>");
|
||||
BEGIN(head);
|
||||
if (firstfile && *firstfile)
|
||||
BEGIN(title); emitString(strlen(firstfile), firstfile); END;
|
||||
print("<link rev=made href=\"mailto:drh@microsoft.com\">\n");
|
||||
END;
|
||||
print("<body>\n");
|
||||
if (firstfile && *firstfile)
|
||||
BEGIN(h1); emitString(strlen(firstfile), firstfile); END;
|
||||
BEGIN(P); BEGIN(em);
|
||||
print("Links lead from uses of identifiers and labels to their definitions.");
|
||||
END; END;
|
||||
print("<ul>\n");
|
||||
START;
|
||||
print("progbeg");
|
||||
BEGIN(ol);
|
||||
for (i = 1; i < argc; i++) {
|
||||
ITEM;
|
||||
BEGIN(code); print("\""); emitString(strlen(argv[i]), argv[i]); print("\""); END;
|
||||
END;
|
||||
}
|
||||
END;
|
||||
END;
|
||||
}
|
||||
}
|
||||
|
||||
/* progend - end of program */
|
||||
static void I(progend)(void) {
|
||||
START; print("progend"); END;
|
||||
if (html) {
|
||||
time_t t;
|
||||
print("</ul>\n");
|
||||
time(&t);
|
||||
print("<hr><address>%s</address>\n", ctime(&t));
|
||||
print("</body></html>\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* segment - switch to segment s */
|
||||
static void I(segment)(int s) {
|
||||
START; print("segment %s", &"text\0bss\0.data\0lit\0.sym\0."[5*s-5]); END;
|
||||
}
|
||||
|
||||
/* space - initialize n bytes of space */
|
||||
static void I(space)(int n) {
|
||||
START; print("space %d", n); END;
|
||||
}
|
||||
|
||||
static void I(stabblock)(int brace, int lev, Symbol *p) {}
|
||||
|
||||
/* stabend - finalize stab output */
|
||||
static void I(stabend)(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {
|
||||
int i;
|
||||
|
||||
if (p)
|
||||
emitSymRef(p);
|
||||
print("\n");
|
||||
if (cpp && sp)
|
||||
for (i = 0; cpp[i] && sp[i]; i++) {
|
||||
print("%w.%d: ", cpp[i], cpp[i]->x);
|
||||
emitSymRef(sp[i]);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void I(stabfend)(Symbol p, int lineno) {}
|
||||
static void I(stabinit)(char *file, int argc, char *argv[]) {}
|
||||
|
||||
/* stabline - emit line number information for source coordinate *cp */
|
||||
static void I(stabline)(Coordinate *cp) {
|
||||
if (cp->file)
|
||||
print("%s:", cp->file);
|
||||
print("%d.%d:\n", cp->y, cp->x);
|
||||
}
|
||||
|
||||
static void I(stabsym)(Symbol p) {}
|
||||
static void I(stabtype)(Symbol p) {}
|
||||
|
||||
Interface symbolicIR = {
|
||||
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 */
|
||||
1, /* wants_argb */
|
||||
1, /* left_to_right */
|
||||
1, /* 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),
|
||||
I(stabblock),
|
||||
I(stabend),
|
||||
I(stabfend),
|
||||
I(stabinit),
|
||||
I(stabline),
|
||||
I(stabsym),
|
||||
I(stabtype)
|
||||
};
|
||||
|
||||
Interface symbolic64IR = {
|
||||
1, 1, 0, /* char */
|
||||
2, 2, 0, /* short */
|
||||
4, 4, 0, /* int */
|
||||
8, 8, 0, /* long */
|
||||
8, 8, 0, /* long long */
|
||||
4, 4, 1, /* float */
|
||||
8, 8, 1, /* double */
|
||||
8, 8, 1, /* long double */
|
||||
8, 8, 0, /* T* */
|
||||
0, 1, 0, /* struct */
|
||||
1, /* little_endian */
|
||||
0, /* mulops_calls */
|
||||
0, /* wants_callb */
|
||||
1, /* wants_argb */
|
||||
1, /* left_to_right */
|
||||
1, /* 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),
|
||||
I(stabblock),
|
||||
I(stabend),
|
||||
I(stabfend),
|
||||
I(stabinit),
|
||||
I(stabline),
|
||||
I(stabsym),
|
||||
I(stabtype)
|
||||
};
|
||||
|
|
266
lcc/src/token.h
Normal file → Executable file
266
lcc/src/token.h
Normal file → Executable file
|
@ -1,133 +1,133 @@
|
|||
/*
|
||||
xx(symbol, value, prec, op, optree, kind, string)
|
||||
*/
|
||||
yy(0, 0, 0, 0, 0, 0, 0)
|
||||
xx(FLOAT, 1, 0, 0, 0, CHAR, "float")
|
||||
xx(DOUBLE, 2, 0, 0, 0, CHAR, "double")
|
||||
xx(CHAR, 3, 0, 0, 0, CHAR, "char")
|
||||
xx(SHORT, 4, 0, 0, 0, CHAR, "short")
|
||||
xx(INT, 5, 0, 0, 0, CHAR, "int")
|
||||
xx(UNSIGNED, 6, 0, 0, 0, CHAR, "unsigned")
|
||||
xx(POINTER, 7, 0, 0, 0, 0, "pointer")
|
||||
xx(VOID, 8, 0, 0, 0, CHAR, "void")
|
||||
xx(STRUCT, 9, 0, 0, 0, CHAR, "struct")
|
||||
xx(UNION, 10, 0, 0, 0, CHAR, "union")
|
||||
xx(FUNCTION, 11, 0, 0, 0, 0, "function")
|
||||
xx(ARRAY, 12, 0, 0, 0, 0, "array")
|
||||
xx(ENUM, 13, 0, 0, 0, CHAR, "enum")
|
||||
xx(LONG, 14, 0, 0, 0, CHAR, "long")
|
||||
xx(CONST, 15, 0, 0, 0, CHAR, "const")
|
||||
xx(VOLATILE, 16, 0, 0, 0, CHAR, "volatile")
|
||||
yy(0, 17, 0, 0, 0, 0, 0)
|
||||
yy(0, 18, 0, 0, 0, 0, 0)
|
||||
yy(0, 19, 0, 0, 0, 0, 0)
|
||||
yy(0, 20, 0, 0, 0, 0, 0)
|
||||
yy(0, 21, 0, 0, 0, 0, 0)
|
||||
yy(0, 22, 0, 0, 0, 0, 0)
|
||||
yy(0, 23, 0, 0, 0, 0, 0)
|
||||
yy(0, 24, 0, 0, 0, 0, 0)
|
||||
yy(0, 25, 0, 0, 0, 0, 0)
|
||||
yy(0, 26, 0, 0, 0, 0, 0)
|
||||
yy(0, 27, 0, 0, 0, 0, 0)
|
||||
yy(0, 28, 0, 0, 0, 0, "long long")
|
||||
yy(0, 29, 0, 0, 0, 0, 0)
|
||||
yy(0, 30, 0, 0, 0, 0, 0)
|
||||
yy(0, 31, 0, 0, 0, 0, "const volatile")
|
||||
xx(ID, 32, 0, 0, 0, ID, "identifier")
|
||||
yy(0, 33, 0, 0, 0, ID, "!")
|
||||
xx(FCON, 34, 0, 0, 0, ID, "floating constant")
|
||||
xx(ICON, 35, 0, 0, 0, ID, "integer constant")
|
||||
xx(SCON, 36, 0, 0, 0, ID, "string constant")
|
||||
yy(0, 37, 13, MOD, bittree,'%', "%")
|
||||
yy(0, 38, 8, BAND, bittree,ID, "&")
|
||||
xx(INCR, 39, 0, ADD, addtree,ID, "++")
|
||||
yy(0, 40, 0, 0, 0, ID, "(")
|
||||
yy(0, 41, 0, 0, 0, ')', ")")
|
||||
yy(0, 42, 13, MUL, multree,ID, "*")
|
||||
yy(0, 43, 12, ADD, addtree,ID, "+")
|
||||
yy(0, 44, 1, 0, 0, ',', ",")
|
||||
yy(0, 45, 12, SUB, subtree,ID, "-")
|
||||
yy(0, 46, 0, 0, 0, '.', ".")
|
||||
yy(0, 47, 13, DIV, multree,'/', "/")
|
||||
xx(DECR, 48, 0, SUB, subtree,ID, "--")
|
||||
xx(DEREF, 49, 0, 0, 0, DEREF, "->")
|
||||
xx(ANDAND, 50, 5, AND, andtree,ANDAND, "&&")
|
||||
xx(OROR, 51, 4, OR, andtree,OROR, "||")
|
||||
xx(LEQ, 52, 10, LE, cmptree,LEQ, "<=")
|
||||
xx(EQL, 53, 9, EQ, eqtree, EQL, "==")
|
||||
xx(NEQ, 54, 9, NE, eqtree, NEQ, "!=")
|
||||
xx(GEQ, 55, 10, GE, cmptree,GEQ, ">=")
|
||||
xx(RSHIFT, 56, 11, RSH, shtree, RSHIFT, ">>")
|
||||
xx(LSHIFT, 57, 11, LSH, shtree, LSHIFT, "<<")
|
||||
yy(0, 58, 0, 0, 0, ':', ":")
|
||||
yy(0, 59, 0, 0, 0, IF, ";")
|
||||
yy(0, 60, 10, LT, cmptree,'<', "<")
|
||||
yy(0, 61, 2, ASGN, asgntree,'=', "=")
|
||||
yy(0, 62, 10, GT, cmptree,'>', ">")
|
||||
yy(0, 63, 0, 0, 0, '?', "?")
|
||||
xx(ELLIPSIS, 64, 0, 0, 0, ELLIPSIS,"...")
|
||||
xx(SIZEOF, 65, 0, 0, 0, ID, "sizeof")
|
||||
yy(0, 66, 0, 0, 0, 0, 0)
|
||||
xx(AUTO, 67, 0, 0, 0, STATIC, "auto")
|
||||
xx(BREAK, 68, 0, 0, 0, IF, "break")
|
||||
xx(CASE, 69, 0, 0, 0, IF, "case")
|
||||
xx(CONTINUE, 70, 0, 0, 0, IF, "continue")
|
||||
xx(DEFAULT, 71, 0, 0, 0, IF, "default")
|
||||
xx(DO, 72, 0, 0, 0, IF, "do")
|
||||
xx(ELSE, 73, 0, 0, 0, IF, "else")
|
||||
xx(EXTERN, 74, 0, 0, 0, STATIC, "extern")
|
||||
xx(FOR, 75, 0, 0, 0, IF, "for")
|
||||
xx(GOTO, 76, 0, 0, 0, IF, "goto")
|
||||
xx(IF, 77, 0, 0, 0, IF, "if")
|
||||
xx(REGISTER, 78, 0, 0, 0, STATIC, "register")
|
||||
xx(RETURN, 79, 0, 0, 0, IF, "return")
|
||||
xx(SIGNED, 80, 0, 0, 0, CHAR, "signed")
|
||||
xx(STATIC, 81, 0, 0, 0, STATIC, "static")
|
||||
xx(SWITCH, 82, 0, 0, 0, IF, "switch")
|
||||
xx(TYPEDEF, 83, 0, 0, 0, STATIC, "typedef")
|
||||
xx(WHILE, 84, 0, 0, 0, IF, "while")
|
||||
xx(TYPECODE, 85, 0, 0, 0, ID, "__typecode")
|
||||
xx(FIRSTARG, 86, 0, 0, 0, ID, "__firstarg")
|
||||
yy(0, 87, 0, 0, 0, 0, 0)
|
||||
yy(0, 88, 0, 0, 0, 0, 0)
|
||||
yy(0, 89, 0, 0, 0, 0, 0)
|
||||
yy(0, 90, 0, 0, 0, 0, 0)
|
||||
yy(0, 91, 0, 0, 0, '[', "[")
|
||||
yy(0, 92, 0, 0, 0, 0, 0)
|
||||
yy(0, 93, 0, 0, 0, ']', "]")
|
||||
yy(0, 94, 7, BXOR, bittree,'^', "^")
|
||||
yy(0, 95, 0, 0, 0, 0, 0)
|
||||
yy(0, 96, 0, 0, 0, 0, 0)
|
||||
yy(0, 97, 0, 0, 0, 0, 0)
|
||||
yy(0, 98, 0, 0, 0, 0, 0)
|
||||
yy(0, 99, 0, 0, 0, 0, 0)
|
||||
yy(0, 100, 0, 0, 0, 0, 0)
|
||||
yy(0, 101, 0, 0, 0, 0, 0)
|
||||
yy(0, 102, 0, 0, 0, 0, 0)
|
||||
yy(0, 103, 0, 0, 0, 0, 0)
|
||||
yy(0, 104, 0, 0, 0, 0, 0)
|
||||
yy(0, 105, 0, 0, 0, 0, 0)
|
||||
yy(0, 106, 0, 0, 0, 0, 0)
|
||||
yy(0, 107, 0, 0, 0, 0, 0)
|
||||
yy(0, 108, 0, 0, 0, 0, 0)
|
||||
yy(0, 109, 0, 0, 0, 0, 0)
|
||||
yy(0, 110, 0, 0, 0, 0, 0)
|
||||
yy(0, 111, 0, 0, 0, 0, 0)
|
||||
yy(0, 112, 0, 0, 0, 0, 0)
|
||||
yy(0, 113, 0, 0, 0, 0, 0)
|
||||
yy(0, 114, 0, 0, 0, 0, 0)
|
||||
yy(0, 115, 0, 0, 0, 0, 0)
|
||||
yy(0, 116, 0, 0, 0, 0, 0)
|
||||
yy(0, 117, 0, 0, 0, 0, 0)
|
||||
yy(0, 118, 0, 0, 0, 0, 0)
|
||||
yy(0, 119, 0, 0, 0, 0, 0)
|
||||
yy(0, 120, 0, 0, 0, 0, 0)
|
||||
yy(0, 121, 0, 0, 0, 0, 0)
|
||||
yy(0, 122, 0, 0, 0, 0, 0)
|
||||
yy(0, 123, 0, 0, 0, IF, "{")
|
||||
yy(0, 124, 6, BOR, bittree,'|', "|")
|
||||
yy(0, 125, 0, 0, 0, '}', "}")
|
||||
yy(0, 126, 0, BCOM, 0, ID, "~")
|
||||
xx(EOI, 127, 0, 0, 0, EOI, "end of input")
|
||||
#undef xx
|
||||
#undef yy
|
||||
/*
|
||||
xx(symbol, value, prec, op, optree, kind, string)
|
||||
*/
|
||||
yy(0, 0, 0, 0, 0, 0, 0)
|
||||
xx(FLOAT, 1, 0, 0, 0, CHAR, "float")
|
||||
xx(DOUBLE, 2, 0, 0, 0, CHAR, "double")
|
||||
xx(CHAR, 3, 0, 0, 0, CHAR, "char")
|
||||
xx(SHORT, 4, 0, 0, 0, CHAR, "short")
|
||||
xx(INT, 5, 0, 0, 0, CHAR, "int")
|
||||
xx(UNSIGNED, 6, 0, 0, 0, CHAR, "unsigned")
|
||||
xx(POINTER, 7, 0, 0, 0, 0, "pointer")
|
||||
xx(VOID, 8, 0, 0, 0, CHAR, "void")
|
||||
xx(STRUCT, 9, 0, 0, 0, CHAR, "struct")
|
||||
xx(UNION, 10, 0, 0, 0, CHAR, "union")
|
||||
xx(FUNCTION, 11, 0, 0, 0, 0, "function")
|
||||
xx(ARRAY, 12, 0, 0, 0, 0, "array")
|
||||
xx(ENUM, 13, 0, 0, 0, CHAR, "enum")
|
||||
xx(LONG, 14, 0, 0, 0, CHAR, "long")
|
||||
xx(CONST, 15, 0, 0, 0, CHAR, "const")
|
||||
xx(VOLATILE, 16, 0, 0, 0, CHAR, "volatile")
|
||||
yy(0, 17, 0, 0, 0, 0, 0)
|
||||
yy(0, 18, 0, 0, 0, 0, 0)
|
||||
yy(0, 19, 0, 0, 0, 0, 0)
|
||||
yy(0, 20, 0, 0, 0, 0, 0)
|
||||
yy(0, 21, 0, 0, 0, 0, 0)
|
||||
yy(0, 22, 0, 0, 0, 0, 0)
|
||||
yy(0, 23, 0, 0, 0, 0, 0)
|
||||
yy(0, 24, 0, 0, 0, 0, 0)
|
||||
yy(0, 25, 0, 0, 0, 0, 0)
|
||||
yy(0, 26, 0, 0, 0, 0, 0)
|
||||
yy(0, 27, 0, 0, 0, 0, 0)
|
||||
yy(0, 28, 0, 0, 0, 0, "long long")
|
||||
yy(0, 29, 0, 0, 0, 0, 0)
|
||||
yy(0, 30, 0, 0, 0, 0, 0)
|
||||
yy(0, 31, 0, 0, 0, 0, "const volatile")
|
||||
xx(ID, 32, 0, 0, 0, ID, "identifier")
|
||||
yy(0, 33, 0, 0, 0, ID, "!")
|
||||
xx(FCON, 34, 0, 0, 0, ID, "floating constant")
|
||||
xx(ICON, 35, 0, 0, 0, ID, "integer constant")
|
||||
xx(SCON, 36, 0, 0, 0, ID, "string constant")
|
||||
yy(0, 37, 13, MOD, bittree,'%', "%")
|
||||
yy(0, 38, 8, BAND, bittree,ID, "&")
|
||||
xx(INCR, 39, 0, ADD, addtree,ID, "++")
|
||||
yy(0, 40, 0, 0, 0, ID, "(")
|
||||
yy(0, 41, 0, 0, 0, ')', ")")
|
||||
yy(0, 42, 13, MUL, multree,ID, "*")
|
||||
yy(0, 43, 12, ADD, addtree,ID, "+")
|
||||
yy(0, 44, 1, 0, 0, ',', ",")
|
||||
yy(0, 45, 12, SUB, subtree,ID, "-")
|
||||
yy(0, 46, 0, 0, 0, '.', ".")
|
||||
yy(0, 47, 13, DIV, multree,'/', "/")
|
||||
xx(DECR, 48, 0, SUB, subtree,ID, "--")
|
||||
xx(DEREF, 49, 0, 0, 0, DEREF, "->")
|
||||
xx(ANDAND, 50, 5, AND, andtree,ANDAND, "&&")
|
||||
xx(OROR, 51, 4, OR, andtree,OROR, "||")
|
||||
xx(LEQ, 52, 10, LE, cmptree,LEQ, "<=")
|
||||
xx(EQL, 53, 9, EQ, eqtree, EQL, "==")
|
||||
xx(NEQ, 54, 9, NE, eqtree, NEQ, "!=")
|
||||
xx(GEQ, 55, 10, GE, cmptree,GEQ, ">=")
|
||||
xx(RSHIFT, 56, 11, RSH, shtree, RSHIFT, ">>")
|
||||
xx(LSHIFT, 57, 11, LSH, shtree, LSHIFT, "<<")
|
||||
yy(0, 58, 0, 0, 0, ':', ":")
|
||||
yy(0, 59, 0, 0, 0, IF, ";")
|
||||
yy(0, 60, 10, LT, cmptree,'<', "<")
|
||||
yy(0, 61, 2, ASGN, asgntree,'=', "=")
|
||||
yy(0, 62, 10, GT, cmptree,'>', ">")
|
||||
yy(0, 63, 0, 0, 0, '?', "?")
|
||||
xx(ELLIPSIS, 64, 0, 0, 0, ELLIPSIS,"...")
|
||||
xx(SIZEOF, 65, 0, 0, 0, ID, "sizeof")
|
||||
yy(0, 66, 0, 0, 0, 0, 0)
|
||||
xx(AUTO, 67, 0, 0, 0, STATIC, "auto")
|
||||
xx(BREAK, 68, 0, 0, 0, IF, "break")
|
||||
xx(CASE, 69, 0, 0, 0, IF, "case")
|
||||
xx(CONTINUE, 70, 0, 0, 0, IF, "continue")
|
||||
xx(DEFAULT, 71, 0, 0, 0, IF, "default")
|
||||
xx(DO, 72, 0, 0, 0, IF, "do")
|
||||
xx(ELSE, 73, 0, 0, 0, IF, "else")
|
||||
xx(EXTERN, 74, 0, 0, 0, STATIC, "extern")
|
||||
xx(FOR, 75, 0, 0, 0, IF, "for")
|
||||
xx(GOTO, 76, 0, 0, 0, IF, "goto")
|
||||
xx(IF, 77, 0, 0, 0, IF, "if")
|
||||
xx(REGISTER, 78, 0, 0, 0, STATIC, "register")
|
||||
xx(RETURN, 79, 0, 0, 0, IF, "return")
|
||||
xx(SIGNED, 80, 0, 0, 0, CHAR, "signed")
|
||||
xx(STATIC, 81, 0, 0, 0, STATIC, "static")
|
||||
xx(SWITCH, 82, 0, 0, 0, IF, "switch")
|
||||
xx(TYPEDEF, 83, 0, 0, 0, STATIC, "typedef")
|
||||
xx(WHILE, 84, 0, 0, 0, IF, "while")
|
||||
xx(TYPECODE, 85, 0, 0, 0, ID, "__typecode")
|
||||
xx(FIRSTARG, 86, 0, 0, 0, ID, "__firstarg")
|
||||
yy(0, 87, 0, 0, 0, 0, 0)
|
||||
yy(0, 88, 0, 0, 0, 0, 0)
|
||||
yy(0, 89, 0, 0, 0, 0, 0)
|
||||
yy(0, 90, 0, 0, 0, 0, 0)
|
||||
yy(0, 91, 0, 0, 0, '[', "[")
|
||||
yy(0, 92, 0, 0, 0, 0, 0)
|
||||
yy(0, 93, 0, 0, 0, ']', "]")
|
||||
yy(0, 94, 7, BXOR, bittree,'^', "^")
|
||||
yy(0, 95, 0, 0, 0, 0, 0)
|
||||
yy(0, 96, 0, 0, 0, 0, 0)
|
||||
yy(0, 97, 0, 0, 0, 0, 0)
|
||||
yy(0, 98, 0, 0, 0, 0, 0)
|
||||
yy(0, 99, 0, 0, 0, 0, 0)
|
||||
yy(0, 100, 0, 0, 0, 0, 0)
|
||||
yy(0, 101, 0, 0, 0, 0, 0)
|
||||
yy(0, 102, 0, 0, 0, 0, 0)
|
||||
yy(0, 103, 0, 0, 0, 0, 0)
|
||||
yy(0, 104, 0, 0, 0, 0, 0)
|
||||
yy(0, 105, 0, 0, 0, 0, 0)
|
||||
yy(0, 106, 0, 0, 0, 0, 0)
|
||||
yy(0, 107, 0, 0, 0, 0, 0)
|
||||
yy(0, 108, 0, 0, 0, 0, 0)
|
||||
yy(0, 109, 0, 0, 0, 0, 0)
|
||||
yy(0, 110, 0, 0, 0, 0, 0)
|
||||
yy(0, 111, 0, 0, 0, 0, 0)
|
||||
yy(0, 112, 0, 0, 0, 0, 0)
|
||||
yy(0, 113, 0, 0, 0, 0, 0)
|
||||
yy(0, 114, 0, 0, 0, 0, 0)
|
||||
yy(0, 115, 0, 0, 0, 0, 0)
|
||||
yy(0, 116, 0, 0, 0, 0, 0)
|
||||
yy(0, 117, 0, 0, 0, 0, 0)
|
||||
yy(0, 118, 0, 0, 0, 0, 0)
|
||||
yy(0, 119, 0, 0, 0, 0, 0)
|
||||
yy(0, 120, 0, 0, 0, 0, 0)
|
||||
yy(0, 121, 0, 0, 0, 0, 0)
|
||||
yy(0, 122, 0, 0, 0, 0, 0)
|
||||
yy(0, 123, 0, 0, 0, IF, "{")
|
||||
yy(0, 124, 6, BOR, bittree,'|', "|")
|
||||
yy(0, 125, 0, 0, 0, '}', "}")
|
||||
yy(0, 126, 0, BCOM, 0, ID, "~")
|
||||
xx(EOI, 127, 0, 0, 0, EOI, "end of input")
|
||||
#undef xx
|
||||
#undef yy
|
||||
|
|
360
lcc/src/trace.c
Normal file → Executable file
360
lcc/src/trace.c
Normal file → Executable file
|
@ -1,180 +1,180 @@
|
|||
#include "c.h"
|
||||
|
||||
|
||||
static char *fmt, *fp, *fmtend; /* format string, current & limit pointer */
|
||||
static Tree args; /* printf arguments */
|
||||
static Symbol frameno; /* local holding frame number */
|
||||
|
||||
/* appendstr - append str to the evolving format string, expanding it if necessary */
|
||||
static void appendstr(char *str) {
|
||||
do
|
||||
if (fp == fmtend)
|
||||
if (fp) {
|
||||
char *s = allocate(2*(fmtend - fmt), FUNC);
|
||||
strncpy(s, fmt, fmtend - fmt);
|
||||
fp = s + (fmtend - fmt);
|
||||
fmtend = s + 2*(fmtend - fmt);
|
||||
fmt = s;
|
||||
} else {
|
||||
fp = fmt = allocate(80, FUNC);
|
||||
fmtend = fmt + 80;
|
||||
}
|
||||
while ((*fp++ = *str++) != 0);
|
||||
fp--;
|
||||
}
|
||||
|
||||
/* tracevalue - append format and argument to print the value of e */
|
||||
static void tracevalue(Tree e, int lev) {
|
||||
Type ty = unqual(e->type);
|
||||
|
||||
switch (ty->op) {
|
||||
case INT:
|
||||
if (ty == chartype || ty == signedchar)
|
||||
appendstr("'\\x%02x'");
|
||||
else if (ty == longtype)
|
||||
appendstr("0x%ld");
|
||||
else
|
||||
appendstr("0x%d");
|
||||
break;
|
||||
case UNSIGNED:
|
||||
if (ty == chartype || ty == unsignedchar)
|
||||
appendstr("'\\x%02x'");
|
||||
else if (ty == unsignedlong)
|
||||
appendstr("0x%lx");
|
||||
else
|
||||
appendstr("0x%x");
|
||||
break;
|
||||
case FLOAT:
|
||||
if (ty == longdouble)
|
||||
appendstr("%Lg");
|
||||
else
|
||||
appendstr("%g");
|
||||
break;
|
||||
case POINTER:
|
||||
if (unqual(ty->type) == chartype
|
||||
|| unqual(ty->type) == signedchar
|
||||
|| unqual(ty->type) == unsignedchar) {
|
||||
static Symbol null;
|
||||
if (null == NULL)
|
||||
null = mkstr("(null)");
|
||||
tracevalue(cast(e, unsignedtype), lev + 1);
|
||||
appendstr(" \"%.30s\"");
|
||||
e = condtree(e, e, pointer(idtree(null->u.c.loc)));
|
||||
} else {
|
||||
appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x");
|
||||
}
|
||||
break;
|
||||
case STRUCT: {
|
||||
Field q;
|
||||
appendstr("("); appendstr(typestring(ty, "")); appendstr("){");
|
||||
for (q = ty->u.sym->u.s.flist; q; q = q->link) {
|
||||
appendstr(q->name); appendstr("=");
|
||||
tracevalue(field(addrof(e), q->name), lev + 1);
|
||||
if (q->link)
|
||||
appendstr(",");
|
||||
}
|
||||
appendstr("}");
|
||||
return;
|
||||
}
|
||||
case UNION:
|
||||
appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}");
|
||||
return;
|
||||
case ARRAY:
|
||||
if (lev && ty->type->size > 0) {
|
||||
int i;
|
||||
e = pointer(e);
|
||||
appendstr("{");
|
||||
for (i = 0; i < ty->size/ty->type->size; i++) {
|
||||
Tree p = (*optree['+'])(ADD, e, consttree(i, inttype));
|
||||
if (isptr(p->type) && isarray(p->type->type))
|
||||
p = retype(p, p->type->type);
|
||||
else
|
||||
p = rvalue(p);
|
||||
if (i)
|
||||
appendstr(",");
|
||||
tracevalue(p, lev + 1);
|
||||
}
|
||||
appendstr("}");
|
||||
} else
|
||||
appendstr(typestring(ty, ""));
|
||||
return;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
e = cast(e, promote(ty));
|
||||
args = tree(mkop(ARG,e->type), e->type, e, args);
|
||||
}
|
||||
|
||||
/* tracefinis - complete & generate the trace call to print */
|
||||
static void tracefinis(Symbol printer) {
|
||||
Tree *ap;
|
||||
Symbol p;
|
||||
|
||||
*fp = 0;
|
||||
p = mkstr(string(fmt));
|
||||
for (ap = &args; *ap; ap = &(*ap)->kids[1])
|
||||
;
|
||||
*ap = tree(ARG+P, charptype, pointer(idtree(p->u.c.loc)), 0);
|
||||
walk(calltree(pointer(idtree(printer)), freturn(printer->type), args, NULL), 0, 0);
|
||||
args = 0;
|
||||
fp = fmtend = 0;
|
||||
}
|
||||
|
||||
/* tracecall - generate code to trace entry to f */
|
||||
static void tracecall(Symbol printer, Symbol f) {
|
||||
int i;
|
||||
Symbol counter = genident(STATIC, inttype, GLOBAL);
|
||||
|
||||
defglobal(counter, BSS);
|
||||
(*IR->space)(counter->type->size);
|
||||
frameno = genident(AUTO, inttype, level);
|
||||
addlocal(frameno);
|
||||
appendstr(f->name); appendstr("#");
|
||||
tracevalue(asgn(frameno, incr(INCR, idtree(counter), consttree(1, inttype))), 0);
|
||||
appendstr("(");
|
||||
for (i = 0; f->u.f.callee[i]; i++) {
|
||||
if (i)
|
||||
appendstr(",");
|
||||
appendstr(f->u.f.callee[i]->name); appendstr("=");
|
||||
tracevalue(idtree(f->u.f.callee[i]), 0);
|
||||
}
|
||||
if (variadic(f->type))
|
||||
appendstr(",...");
|
||||
appendstr(") called\n");
|
||||
tracefinis(printer);
|
||||
}
|
||||
|
||||
/* tracereturn - generate code to trace return e */
|
||||
static void tracereturn(Symbol printer, Symbol f, Tree e) {
|
||||
appendstr(f->name); appendstr("#");
|
||||
tracevalue(idtree(frameno), 0);
|
||||
appendstr(" returned");
|
||||
if (freturn(f->type) != voidtype && e) {
|
||||
appendstr(" ");
|
||||
tracevalue(e, 0);
|
||||
}
|
||||
appendstr("\n");
|
||||
tracefinis(printer);
|
||||
}
|
||||
|
||||
/* trace_init - initialize for tracing */
|
||||
void trace_init(int argc, char *argv[]) {
|
||||
int i;
|
||||
static int inited;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
inited = 1;
|
||||
type_init(argc, argv);
|
||||
if (IR)
|
||||
for (i = 1; i < argc; i++)
|
||||
if (strncmp(argv[i], "-t", 2) == 0 && strchr(argv[i], '=') == NULL) {
|
||||
Symbol printer = mksymbol(EXTERN,
|
||||
argv[i][2] ? &argv[i][2] : "printf",
|
||||
ftype(inttype, ptr(qual(CONST, chartype))));
|
||||
printer->defined = 0;
|
||||
attach((Apply)tracecall, printer, &events.entry);
|
||||
attach((Apply)tracereturn, printer, &events.returns);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#include "c.h"
|
||||
|
||||
|
||||
static char *fmt, *fp, *fmtend; /* format string, current & limit pointer */
|
||||
static Tree args; /* printf arguments */
|
||||
static Symbol frameno; /* local holding frame number */
|
||||
|
||||
/* appendstr - append str to the evolving format string, expanding it if necessary */
|
||||
static void appendstr(char *str) {
|
||||
do
|
||||
if (fp == fmtend)
|
||||
if (fp) {
|
||||
char *s = allocate(2*(fmtend - fmt), FUNC);
|
||||
strncpy(s, fmt, fmtend - fmt);
|
||||
fp = s + (fmtend - fmt);
|
||||
fmtend = s + 2*(fmtend - fmt);
|
||||
fmt = s;
|
||||
} else {
|
||||
fp = fmt = allocate(80, FUNC);
|
||||
fmtend = fmt + 80;
|
||||
}
|
||||
while ((*fp++ = *str++) != 0);
|
||||
fp--;
|
||||
}
|
||||
|
||||
/* tracevalue - append format and argument to print the value of e */
|
||||
static void tracevalue(Tree e, int lev) {
|
||||
Type ty = unqual(e->type);
|
||||
|
||||
switch (ty->op) {
|
||||
case INT:
|
||||
if (ty == chartype || ty == signedchar)
|
||||
appendstr("'\\x%02x'");
|
||||
else if (ty == longtype)
|
||||
appendstr("0x%ld");
|
||||
else
|
||||
appendstr("0x%d");
|
||||
break;
|
||||
case UNSIGNED:
|
||||
if (ty == chartype || ty == unsignedchar)
|
||||
appendstr("'\\x%02x'");
|
||||
else if (ty == unsignedlong)
|
||||
appendstr("0x%lx");
|
||||
else
|
||||
appendstr("0x%x");
|
||||
break;
|
||||
case FLOAT:
|
||||
if (ty == longdouble)
|
||||
appendstr("%Lg");
|
||||
else
|
||||
appendstr("%g");
|
||||
break;
|
||||
case POINTER:
|
||||
if (unqual(ty->type) == chartype
|
||||
|| unqual(ty->type) == signedchar
|
||||
|| unqual(ty->type) == unsignedchar) {
|
||||
static Symbol null;
|
||||
if (null == NULL)
|
||||
null = mkstr("(null)");
|
||||
tracevalue(cast(e, unsignedtype), lev + 1);
|
||||
appendstr(" \"%.30s\"");
|
||||
e = condtree(e, e, pointer(idtree(null->u.c.loc)));
|
||||
} else {
|
||||
appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x");
|
||||
}
|
||||
break;
|
||||
case STRUCT: {
|
||||
Field q;
|
||||
appendstr("("); appendstr(typestring(ty, "")); appendstr("){");
|
||||
for (q = ty->u.sym->u.s.flist; q; q = q->link) {
|
||||
appendstr(q->name); appendstr("=");
|
||||
tracevalue(field(addrof(e), q->name), lev + 1);
|
||||
if (q->link)
|
||||
appendstr(",");
|
||||
}
|
||||
appendstr("}");
|
||||
return;
|
||||
}
|
||||
case UNION:
|
||||
appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}");
|
||||
return;
|
||||
case ARRAY:
|
||||
if (lev && ty->type->size > 0) {
|
||||
int i;
|
||||
e = pointer(e);
|
||||
appendstr("{");
|
||||
for (i = 0; i < ty->size/ty->type->size; i++) {
|
||||
Tree p = (*optree['+'])(ADD, e, consttree(i, inttype));
|
||||
if (isptr(p->type) && isarray(p->type->type))
|
||||
p = retype(p, p->type->type);
|
||||
else
|
||||
p = rvalue(p);
|
||||
if (i)
|
||||
appendstr(",");
|
||||
tracevalue(p, lev + 1);
|
||||
}
|
||||
appendstr("}");
|
||||
} else
|
||||
appendstr(typestring(ty, ""));
|
||||
return;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
e = cast(e, promote(ty));
|
||||
args = tree(mkop(ARG,e->type), e->type, e, args);
|
||||
}
|
||||
|
||||
/* tracefinis - complete & generate the trace call to print */
|
||||
static void tracefinis(Symbol printer) {
|
||||
Tree *ap;
|
||||
Symbol p;
|
||||
|
||||
*fp = 0;
|
||||
p = mkstr(string(fmt));
|
||||
for (ap = &args; *ap; ap = &(*ap)->kids[1])
|
||||
;
|
||||
*ap = tree(ARG+P, charptype, pointer(idtree(p->u.c.loc)), 0);
|
||||
walk(calltree(pointer(idtree(printer)), freturn(printer->type), args, NULL), 0, 0);
|
||||
args = 0;
|
||||
fp = fmtend = 0;
|
||||
}
|
||||
|
||||
/* tracecall - generate code to trace entry to f */
|
||||
static void tracecall(Symbol printer, Symbol f) {
|
||||
int i;
|
||||
Symbol counter = genident(STATIC, inttype, GLOBAL);
|
||||
|
||||
defglobal(counter, BSS);
|
||||
(*IR->space)(counter->type->size);
|
||||
frameno = genident(AUTO, inttype, level);
|
||||
addlocal(frameno);
|
||||
appendstr(f->name); appendstr("#");
|
||||
tracevalue(asgn(frameno, incr(INCR, idtree(counter), consttree(1, inttype))), 0);
|
||||
appendstr("(");
|
||||
for (i = 0; f->u.f.callee[i]; i++) {
|
||||
if (i)
|
||||
appendstr(",");
|
||||
appendstr(f->u.f.callee[i]->name); appendstr("=");
|
||||
tracevalue(idtree(f->u.f.callee[i]), 0);
|
||||
}
|
||||
if (variadic(f->type))
|
||||
appendstr(",...");
|
||||
appendstr(") called\n");
|
||||
tracefinis(printer);
|
||||
}
|
||||
|
||||
/* tracereturn - generate code to trace return e */
|
||||
static void tracereturn(Symbol printer, Symbol f, Tree e) {
|
||||
appendstr(f->name); appendstr("#");
|
||||
tracevalue(idtree(frameno), 0);
|
||||
appendstr(" returned");
|
||||
if (freturn(f->type) != voidtype && e) {
|
||||
appendstr(" ");
|
||||
tracevalue(e, 0);
|
||||
}
|
||||
appendstr("\n");
|
||||
tracefinis(printer);
|
||||
}
|
||||
|
||||
/* trace_init - initialize for tracing */
|
||||
void trace_init(int argc, char *argv[]) {
|
||||
int i;
|
||||
static int inited;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
inited = 1;
|
||||
type_init(argc, argv);
|
||||
if (IR)
|
||||
for (i = 1; i < argc; i++)
|
||||
if (strncmp(argv[i], "-t", 2) == 0 && strchr(argv[i], '=') == NULL) {
|
||||
Symbol printer = mksymbol(EXTERN,
|
||||
argv[i][2] ? &argv[i][2] : "printf",
|
||||
ftype(inttype, ptr(qual(CONST, chartype))));
|
||||
printer->defined = 0;
|
||||
attach((Apply)tracecall, printer, &events.entry);
|
||||
attach((Apply)tracereturn, printer, &events.returns);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
446
lcc/src/tree.c
Normal file → Executable file
446
lcc/src/tree.c
Normal file → Executable file
|
@ -1,223 +1,223 @@
|
|||
#include "c.h"
|
||||
|
||||
|
||||
int where = STMT;
|
||||
static int warn;
|
||||
static int nid = 1; /* identifies trees & nodes in debugging output */
|
||||
static struct nodeid {
|
||||
int printed;
|
||||
Tree node;
|
||||
} ids[500]; /* if ids[i].node == p, then p's id is i */
|
||||
|
||||
static void printtree1(Tree, int, int);
|
||||
|
||||
Tree tree(int op, Type type, Tree left, Tree right) {
|
||||
Tree p;
|
||||
|
||||
NEW0(p, where);
|
||||
p->op = op;
|
||||
p->type = type;
|
||||
p->kids[0] = left;
|
||||
p->kids[1] = right;
|
||||
return p;
|
||||
}
|
||||
|
||||
Tree texpr(Tree (*f)(int), int tok, int a) {
|
||||
int save = where;
|
||||
Tree p;
|
||||
|
||||
where = a;
|
||||
p = (*f)(tok);
|
||||
where = save;
|
||||
return p;
|
||||
}
|
||||
static Tree root1(Tree p) {
|
||||
if (p == NULL)
|
||||
return p;
|
||||
if (p->type == voidtype)
|
||||
warn++;
|
||||
switch (generic(p->op)) {
|
||||
case COND: {
|
||||
Tree q = p->kids[1];
|
||||
assert(q && q->op == RIGHT);
|
||||
if (p->u.sym && q->kids[0] && generic(q->kids[0]->op) == ASGN)
|
||||
q->kids[0] = root1(q->kids[0]->kids[1]);
|
||||
else
|
||||
q->kids[0] = root1(q->kids[0]);
|
||||
if (p->u.sym && q->kids[1] && generic(q->kids[1]->op) == ASGN)
|
||||
q->kids[1] = root1(q->kids[1]->kids[1]);
|
||||
else
|
||||
q->kids[1] = root1(q->kids[1]);
|
||||
p->u.sym = 0;
|
||||
if (q->kids[0] == 0 && q->kids[1] == 0)
|
||||
p = root1(p->kids[0]);
|
||||
}
|
||||
break;
|
||||
case AND: case OR:
|
||||
if ((p->kids[1] = root1(p->kids[1])) == 0)
|
||||
p = root1(p->kids[0]);
|
||||
break;
|
||||
case NOT:
|
||||
if (warn++ == 0)
|
||||
warning("expression with no effect elided\n");
|
||||
return root1(p->kids[0]);
|
||||
case RIGHT:
|
||||
if (p->kids[1] == 0)
|
||||
return root1(p->kids[0]);
|
||||
if (p->kids[0] && p->kids[0]->op == CALL+B
|
||||
&& p->kids[1] && p->kids[1]->op == INDIR+B)
|
||||
/* avoid premature release of the CALL+B temporary */
|
||||
return p->kids[0];
|
||||
if (p->kids[0] && p->kids[0]->op == RIGHT
|
||||
&& p->kids[1] == p->kids[0]->kids[0])
|
||||
/* de-construct e++ construction */
|
||||
return p->kids[0]->kids[1];
|
||||
p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1]));
|
||||
return p->kids[0] || p->kids[1] ? p : (Tree)0;
|
||||
case EQ: case NE: case GT: case GE: case LE: case LT:
|
||||
case ADD: case SUB: case MUL: case DIV: case MOD:
|
||||
case LSH: case RSH: case BAND: case BOR: case BXOR:
|
||||
if (warn++ == 0)
|
||||
warning("expression with no effect elided\n");
|
||||
p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1]));
|
||||
return p->kids[0] || p->kids[1] ? p : (Tree)0;
|
||||
case INDIR:
|
||||
if (p->type->size == 0 && unqual(p->type) != voidtype)
|
||||
warning("reference to `%t' elided\n", p->type);
|
||||
if (isptr(p->kids[0]->type) && isvolatile(p->kids[0]->type->type))
|
||||
warning("reference to `volatile %t' elided\n", p->type);
|
||||
/* fall thru */
|
||||
case CVI: case CVF: case CVU: case CVP:
|
||||
case NEG: case BCOM: case FIELD:
|
||||
if (warn++ == 0)
|
||||
warning("expression with no effect elided\n");
|
||||
return root1(p->kids[0]);
|
||||
case ADDRL: case ADDRG: case ADDRF: case CNST:
|
||||
if (needconst)
|
||||
return p;
|
||||
if (warn++ == 0)
|
||||
warning("expression with no effect elided\n");
|
||||
return NULL;
|
||||
case ARG: case ASGN: case CALL: case JUMP: case LABEL:
|
||||
break;
|
||||
default: assert(0);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
Tree root(Tree p) {
|
||||
warn = 0;
|
||||
return root1(p);
|
||||
}
|
||||
|
||||
char *opname(int op) {
|
||||
static char *opnames[] = {
|
||||
"",
|
||||
"CNST",
|
||||
"ARG",
|
||||
"ASGN",
|
||||
"INDIR",
|
||||
"CVC",
|
||||
"CVD",
|
||||
"CVF",
|
||||
"CVI",
|
||||
"CVP",
|
||||
"CVS",
|
||||
"CVU",
|
||||
"NEG",
|
||||
"CALL",
|
||||
"*LOAD*",
|
||||
"RET",
|
||||
"ADDRG",
|
||||
"ADDRF",
|
||||
"ADDRL",
|
||||
"ADD",
|
||||
"SUB",
|
||||
"LSH",
|
||||
"MOD",
|
||||
"RSH",
|
||||
"BAND",
|
||||
"BCOM",
|
||||
"BOR",
|
||||
"BXOR",
|
||||
"DIV",
|
||||
"MUL",
|
||||
"EQ",
|
||||
"GE",
|
||||
"GT",
|
||||
"LE",
|
||||
"LT",
|
||||
"NE",
|
||||
"JUMP",
|
||||
"LABEL",
|
||||
"AND",
|
||||
"NOT",
|
||||
"OR",
|
||||
"COND",
|
||||
"RIGHT",
|
||||
"FIELD"
|
||||
}, *suffixes[] = {
|
||||
"0", "F", "D", "C", "S", "I", "U", "P", "V", "B",
|
||||
"10","11","12","13","14","15"
|
||||
};
|
||||
|
||||
if (generic(op) >= AND && generic(op) <= FIELD && opsize(op) == 0)
|
||||
return opnames[opindex(op)];
|
||||
return stringf("%s%s%s",
|
||||
opindex(op) > 0 && opindex(op) < NELEMS(opnames) ?
|
||||
opnames[opindex(op)] : stringd(opindex(op)),
|
||||
suffixes[optype(op)], opsize(op) > 0 ? stringd(opsize(op)) : "");
|
||||
}
|
||||
|
||||
int nodeid(Tree p) {
|
||||
int i = 1;
|
||||
|
||||
ids[nid].node = p;
|
||||
while (ids[i].node != p)
|
||||
i++;
|
||||
if (i == nid)
|
||||
ids[nid++].printed = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* printed - return pointer to ids[id].printed */
|
||||
int *printed(int id) {
|
||||
if (id)
|
||||
return &ids[id].printed;
|
||||
nid = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* printtree - print tree p on fd */
|
||||
void printtree(Tree p, int fd) {
|
||||
(void)printed(0);
|
||||
printtree1(p, fd, 1);
|
||||
}
|
||||
|
||||
/* printtree1 - recursively print tree p */
|
||||
static void printtree1(Tree p, int fd, int lev) {
|
||||
FILE *f = fd == 1 ? stdout : stderr;
|
||||
int i;
|
||||
static char blanks[] = " ";
|
||||
|
||||
if (p == 0 || *printed(i = nodeid(p)))
|
||||
return;
|
||||
fprint(f, "#%d%S%S", i, blanks, i < 10 ? 2 : i < 100 ? 1 : 0, blanks, lev);
|
||||
fprint(f, "%s %t", opname(p->op), p->type);
|
||||
*printed(i) = 1;
|
||||
for (i = 0; i < NELEMS(p->kids); i++)
|
||||
if (p->kids[i])
|
||||
fprint(f, " #%d", nodeid(p->kids[i]));
|
||||
if (p->op == FIELD && p->u.field)
|
||||
fprint(f, " %s %d..%d", p->u.field->name,
|
||||
fieldsize(p->u.field) + fieldright(p->u.field), fieldright(p->u.field));
|
||||
else if (generic(p->op) == CNST)
|
||||
fprint(f, " %s", vtoa(p->type, p->u.v));
|
||||
else if (p->u.sym)
|
||||
fprint(f, " %s", p->u.sym->name);
|
||||
if (p->node)
|
||||
fprint(f, " node=%p", p->node);
|
||||
fprint(f, "\n");
|
||||
for (i = 0; i < NELEMS(p->kids); i++)
|
||||
printtree1(p->kids[i], fd, lev + 1);
|
||||
}
|
||||
#include "c.h"
|
||||
|
||||
|
||||
int where = STMT;
|
||||
static int warn;
|
||||
static int nid = 1; /* identifies trees & nodes in debugging output */
|
||||
static struct nodeid {
|
||||
int printed;
|
||||
Tree node;
|
||||
} ids[500]; /* if ids[i].node == p, then p's id is i */
|
||||
|
||||
static void printtree1(Tree, int, int);
|
||||
|
||||
Tree tree(int op, Type type, Tree left, Tree right) {
|
||||
Tree p;
|
||||
|
||||
NEW0(p, where);
|
||||
p->op = op;
|
||||
p->type = type;
|
||||
p->kids[0] = left;
|
||||
p->kids[1] = right;
|
||||
return p;
|
||||
}
|
||||
|
||||
Tree texpr(Tree (*f)(int), int tok, int a) {
|
||||
int save = where;
|
||||
Tree p;
|
||||
|
||||
where = a;
|
||||
p = (*f)(tok);
|
||||
where = save;
|
||||
return p;
|
||||
}
|
||||
static Tree root1(Tree p) {
|
||||
if (p == NULL)
|
||||
return p;
|
||||
if (p->type == voidtype)
|
||||
warn++;
|
||||
switch (generic(p->op)) {
|
||||
case COND: {
|
||||
Tree q = p->kids[1];
|
||||
assert(q && q->op == RIGHT);
|
||||
if (p->u.sym && q->kids[0] && generic(q->kids[0]->op) == ASGN)
|
||||
q->kids[0] = root1(q->kids[0]->kids[1]);
|
||||
else
|
||||
q->kids[0] = root1(q->kids[0]);
|
||||
if (p->u.sym && q->kids[1] && generic(q->kids[1]->op) == ASGN)
|
||||
q->kids[1] = root1(q->kids[1]->kids[1]);
|
||||
else
|
||||
q->kids[1] = root1(q->kids[1]);
|
||||
p->u.sym = 0;
|
||||
if (q->kids[0] == 0 && q->kids[1] == 0)
|
||||
p = root1(p->kids[0]);
|
||||
}
|
||||
break;
|
||||
case AND: case OR:
|
||||
if ((p->kids[1] = root1(p->kids[1])) == 0)
|
||||
p = root1(p->kids[0]);
|
||||
break;
|
||||
case NOT:
|
||||
if (warn++ == 0)
|
||||
warning("expression with no effect elided\n");
|
||||
return root1(p->kids[0]);
|
||||
case RIGHT:
|
||||
if (p->kids[1] == 0)
|
||||
return root1(p->kids[0]);
|
||||
if (p->kids[0] && p->kids[0]->op == CALL+B
|
||||
&& p->kids[1] && p->kids[1]->op == INDIR+B)
|
||||
/* avoid premature release of the CALL+B temporary */
|
||||
return p->kids[0];
|
||||
if (p->kids[0] && p->kids[0]->op == RIGHT
|
||||
&& p->kids[1] == p->kids[0]->kids[0])
|
||||
/* de-construct e++ construction */
|
||||
return p->kids[0]->kids[1];
|
||||
p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1]));
|
||||
return p->kids[0] || p->kids[1] ? p : (Tree)0;
|
||||
case EQ: case NE: case GT: case GE: case LE: case LT:
|
||||
case ADD: case SUB: case MUL: case DIV: case MOD:
|
||||
case LSH: case RSH: case BAND: case BOR: case BXOR:
|
||||
if (warn++ == 0)
|
||||
warning("expression with no effect elided\n");
|
||||
p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1]));
|
||||
return p->kids[0] || p->kids[1] ? p : (Tree)0;
|
||||
case INDIR:
|
||||
if (p->type->size == 0 && unqual(p->type) != voidtype)
|
||||
warning("reference to `%t' elided\n", p->type);
|
||||
if (isptr(p->kids[0]->type) && isvolatile(p->kids[0]->type->type))
|
||||
warning("reference to `volatile %t' elided\n", p->type);
|
||||
/* fall thru */
|
||||
case CVI: case CVF: case CVU: case CVP:
|
||||
case NEG: case BCOM: case FIELD:
|
||||
if (warn++ == 0)
|
||||
warning("expression with no effect elided\n");
|
||||
return root1(p->kids[0]);
|
||||
case ADDRL: case ADDRG: case ADDRF: case CNST:
|
||||
if (needconst)
|
||||
return p;
|
||||
if (warn++ == 0)
|
||||
warning("expression with no effect elided\n");
|
||||
return NULL;
|
||||
case ARG: case ASGN: case CALL: case JUMP: case LABEL:
|
||||
break;
|
||||
default: assert(0);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
Tree root(Tree p) {
|
||||
warn = 0;
|
||||
return root1(p);
|
||||
}
|
||||
|
||||
char *opname(int op) {
|
||||
static char *opnames[] = {
|
||||
"",
|
||||
"CNST",
|
||||
"ARG",
|
||||
"ASGN",
|
||||
"INDIR",
|
||||
"CVC",
|
||||
"CVD",
|
||||
"CVF",
|
||||
"CVI",
|
||||
"CVP",
|
||||
"CVS",
|
||||
"CVU",
|
||||
"NEG",
|
||||
"CALL",
|
||||
"*LOAD*",
|
||||
"RET",
|
||||
"ADDRG",
|
||||
"ADDRF",
|
||||
"ADDRL",
|
||||
"ADD",
|
||||
"SUB",
|
||||
"LSH",
|
||||
"MOD",
|
||||
"RSH",
|
||||
"BAND",
|
||||
"BCOM",
|
||||
"BOR",
|
||||
"BXOR",
|
||||
"DIV",
|
||||
"MUL",
|
||||
"EQ",
|
||||
"GE",
|
||||
"GT",
|
||||
"LE",
|
||||
"LT",
|
||||
"NE",
|
||||
"JUMP",
|
||||
"LABEL",
|
||||
"AND",
|
||||
"NOT",
|
||||
"OR",
|
||||
"COND",
|
||||
"RIGHT",
|
||||
"FIELD"
|
||||
}, *suffixes[] = {
|
||||
"0", "F", "D", "C", "S", "I", "U", "P", "V", "B",
|
||||
"10","11","12","13","14","15"
|
||||
};
|
||||
|
||||
if (generic(op) >= AND && generic(op) <= FIELD && opsize(op) == 0)
|
||||
return opnames[opindex(op)];
|
||||
return stringf("%s%s%s",
|
||||
opindex(op) > 0 && opindex(op) < NELEMS(opnames) ?
|
||||
opnames[opindex(op)] : stringd(opindex(op)),
|
||||
suffixes[optype(op)], opsize(op) > 0 ? stringd(opsize(op)) : "");
|
||||
}
|
||||
|
||||
int nodeid(Tree p) {
|
||||
int i = 1;
|
||||
|
||||
ids[nid].node = p;
|
||||
while (ids[i].node != p)
|
||||
i++;
|
||||
if (i == nid)
|
||||
ids[nid++].printed = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* printed - return pointer to ids[id].printed */
|
||||
int *printed(int id) {
|
||||
if (id)
|
||||
return &ids[id].printed;
|
||||
nid = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* printtree - print tree p on fd */
|
||||
void printtree(Tree p, int fd) {
|
||||
(void)printed(0);
|
||||
printtree1(p, fd, 1);
|
||||
}
|
||||
|
||||
/* printtree1 - recursively print tree p */
|
||||
static void printtree1(Tree p, int fd, int lev) {
|
||||
FILE *f = fd == 1 ? stdout : stderr;
|
||||
int i;
|
||||
static char blanks[] = " ";
|
||||
|
||||
if (p == 0 || *printed(i = nodeid(p)))
|
||||
return;
|
||||
fprint(f, "#%d%S%S", i, blanks, i < 10 ? 2 : i < 100 ? 1 : 0, blanks, lev);
|
||||
fprint(f, "%s %t", opname(p->op), p->type);
|
||||
*printed(i) = 1;
|
||||
for (i = 0; i < NELEMS(p->kids); i++)
|
||||
if (p->kids[i])
|
||||
fprint(f, " #%d", nodeid(p->kids[i]));
|
||||
if (p->op == FIELD && p->u.field)
|
||||
fprint(f, " %s %d..%d", p->u.field->name,
|
||||
fieldsize(p->u.field) + fieldright(p->u.field), fieldright(p->u.field));
|
||||
else if (generic(p->op) == CNST)
|
||||
fprint(f, " %s", vtoa(p->type, p->u.v));
|
||||
else if (p->u.sym)
|
||||
fprint(f, " %s", p->u.sym->name);
|
||||
if (p->node)
|
||||
fprint(f, " node=%p", p->node);
|
||||
fprint(f, "\n");
|
||||
for (i = 0; i < NELEMS(p->kids); i++)
|
||||
printtree1(p->kids[i], fd, lev + 1);
|
||||
}
|
||||
|
|
1496
lcc/src/types.c
Normal file → Executable file
1496
lcc/src/types.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1996
lcc/src/x86.md
Normal file → Executable file
1996
lcc/src/x86.md
Normal file → Executable file
File diff suppressed because it is too large
Load diff
2162
lcc/src/x86linux.md
Normal file → Executable file
2162
lcc/src/x86linux.md
Normal file → Executable file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue