* Moved lcc and q3asm into code/tools

This commit is contained in:
Tim Angus 2005-10-04 15:18:22 +00:00
parent b1cef6352e
commit ad118b9baf
452 changed files with 0 additions and 0 deletions

555
code/tools/lcc/src/2html.c Normal file
View file

@ -0,0 +1,555 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "c.h"
#include "rcc.h"
#if WIN32
#include <fcntl.h>
#include <io.h>
#endif
static void do_int(int x) {
printf("%d", x);
}
static void do_scope(int x) {
#define xx(c) if (x == c) { printf(#c); return; }
xx(CONSTANTS)
xx(LABELS)
xx(GLOBAL)
xx(PARAM)
xx(LOCAL)
#undef xx
if (x > LOCAL)
printf("LOCAL+%d", x-LOCAL);
else
do_int(x);
}
static void do_sclass(int x) {
#define xx(c) if (x == c) { printf(#c); return; }
xx(REGISTER)
xx(AUTO)
xx(EXTERN)
xx(STATIC)
xx(TYPEDEF)
#undef xx
do_int(x);
}
static void do_flags(int x) {
char *bar = "";
#define xx(f,n) if ((x>>n)&1) { printf("%s" #f, bar); bar = "|"; }
xx(structarg,0)
xx(addressed,1)
xx(computed,2)
xx(temporary,3)
xx(generated,4)
#undef xx
if (*bar == '\0')
do_int(x);
}
static void do_seg(int x) {
#define xx(s) if (x == s) { printf(#s); return; }
xx(CODE)
xx(BSS)
xx(DATA)
xx(LIT)
#undef xx
do_int(x);
}
#define xx(ptr,field,type) do { printf("<li>" #field " = "); do_##type(ptr->field); printf("</li>\n"); } while (0)
static void do_op(int x) {
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"
};
int op = opindex(x);
if (op < 1 || op >= sizeof opnames/sizeof opnames[0])
printf("%d", x);
else
printf("%s", opnames[op]);
}
static void do_define_uid(int x) {
printf("<strong id=uid%d>%d</strong>", x, x);
}
static void do_define_label(int x) {
printf("<strong id=ll%d>%d</strong>", x, x);
}
static void do_uid(int x) {
printf("<a href='#%d'>%d</a>", x, x, x);
}
static void do_label(int x) {
printf("<a href='#L%d'>%d</a>", x, x, x);
}
static int nextid;
static void do_list(list_ty x, void do_one(void *), char *type, char *listhtml, char *separator) {
int count = Seq_length(x);
if (count == 0)
printf("<em>empty %s list</em>\n", type);
else {
int i;
printf("<em>%s list</em>", type);
if (listhtml != NULL)
printf("<%s>\n", listhtml);
for (i = 0; i < count; i++) {
if (listhtml != NULL)
printf("<li>");
printf(separator);
do_one(Seq_get(x, i));
if (listhtml != NULL)
printf("</li>\n");
}
if (listhtml != NULL)
printf("</%s>\n", listhtml);
}
}
static void do_uid_list(list_ty x) {
int i, count = Seq_length(x);
if (count == 0)
printf("<em>empty int list</em>\n");
else {
int i;
printf("<em>int list</em>");
for (i= 0; i < count; i++) {
printf(" ");
do_uid(*(int *)Seq_get(x, i));
}
}
}
static void do_identifier(const char *x) {
printf("%s", x);
}
static void do_real(rcc_real_ty x) {
double d;
unsigned *p = (unsigned *)&d;
static union { int x; char endian; } little = { 1 };
p[1-little.endian] = x->msb;
p[little.endian] = x->lsb;
printf("(%#X,%#X) = %g", x->msb, x->lsb, d);
}
static void do_suffix(int x) {
static char suffixes[] = "0F234IUPVB";
if (x < 0 || x >= (sizeof suffixes/sizeof suffixes[0]) - 1)
printf("%d", x);
else
printf("%c", suffixes[x]);
}
static void do_enum(void *x) {
rcc_enum__ty e = x;
do_identifier(e->id);
printf("=");
do_int(e->value);
}
static void do_enum_list(list_ty x) {
do_list(x, do_enum, "enum", NULL, " ");
}
static void do_field(void *x) {
rcc_field_ty f = x;
printf("<em>field</em><ul>\n");
xx(f,id,identifier);
xx(f,type,uid);
xx(f,offset,int);
xx(f,bitsize,int);
xx(f,lsb,int);
printf("</ul>\n");
}
static void do_field_list(list_ty x) {
do_list(x, do_field, "field", "ol", "");
}
static void do_symbol(rcc_symbol_ty x) {
printf("<em>symbol</em><ul>\n");
xx(x,id,identifier);
xx(x,type,uid);
xx(x,scope,scope);
xx(x,sclass,sclass);
xx(x,ref,int);
xx(x,flags,flags);
printf("</ul>\n");
}
#define caselabel(kind) case rcc_##kind##_enum: \
printf("<strong>" #kind "</strong> : <em>%s</em>", typename); \
printf("<ul>\n"); attributes
#define yy(kind,field,type) xx((&x->v.rcc_##kind),field,type)
static void do_type(rcc_type_ty x) {
#define attributes xx(x,size,int); xx(x,align,int)
switch (x->kind) {
static char *typename = "type";
caselabel(INT); break;
caselabel(UNSIGNED); break;
caselabel(FLOAT); break;
caselabel(VOID); break;
caselabel(POINTER);
yy(POINTER,type,uid);
break;
caselabel(ENUM);
yy(ENUM,tag,identifier);
yy(ENUM,ids,enum_list);
break;
caselabel(STRUCT);
yy(STRUCT,tag,identifier);
yy(STRUCT,fields,field_list);
break;
caselabel(UNION);
yy(UNION,tag,identifier);
yy(UNION,fields,field_list);
break;
caselabel(ARRAY);
yy(ARRAY,type,uid);
break;
caselabel(FUNCTION);
yy(FUNCTION,type,uid);
yy(FUNCTION,formals,uid_list);
break;
caselabel(CONST);
yy(CONST,type,uid);
break;
caselabel(VOLATILE);
yy(VOLATILE,type,uid);
break;
default: assert(0);
}
#undef attributes
printf("</ul>\n");
}
static void do_item(rcc_item_ty x) {
printf("<a name='%d'>", x->uid);
#define attributes xx(x,uid,define_uid)
printf("</a>");
switch (x->kind) {
static char *typename = "item";
caselabel(Symbol);
yy(Symbol,symbol,symbol);
break;
caselabel(Type);
yy(Type,type,type);
break;
default: assert(0);
}
#undef attributes
printf("</ul>\n");
}
static void do_item_list(list_ty x) {
int count = Seq_length(x);
if (count == 0)
printf("<em>empty item list</em>\n");
else {
int i;
printf("<em>item list</em>");
printf("<ol>\n");
for (i = 0; i < count; i++) {
rcc_item_ty item = Seq_get(x, i);
printf("<li value=%d>", item->uid);
do_item(item);
printf("</li>\n");
}
printf("</ol>\n");
}
}
static void do_string(string_ty x) {
printf("%d,<code>'%s'</code>", x.len, x.str);
}
static void do_generic_string(void *x) {
do_string(*(string_ty *)x);
}
static void do_string_list(list_ty x) {
do_list(x, do_generic_string, "string", "ol", "");
}
static void do_node(void *y) {
rcc_node_ty x = y;
if (x->kind == rcc_LABEL_enum)
printf("<a name='L%d'></a>", x->v.rcc_LABEL.label);
#define attributes xx(x,suffix,suffix); xx(x,size,int)
switch (x->kind) {
static char *typename = "node";
caselabel(CNST);
yy(CNST,value,int);
break;
caselabel(CNSTF);
yy(CNSTF,value,real);
break;
caselabel(ARG);
yy(ARG,left,node);
yy(ARG,len,int);
yy(ARG,align,int);
break;
caselabel(ASGN);
yy(ASGN,left,node);
yy(ASGN,right,node);
yy(ASGN,len,int);
yy(ASGN,align,int);
break;
caselabel(CVT);
yy(CVT,op,op);
yy(CVT,left,node);
yy(CVT,fromsize,int);
break;
caselabel(CALL);
yy(CALL,left,node);
yy(CALL,type,uid);
break;
caselabel(CALLB);
yy(CALLB,left,node);
yy(CALLB,right,node);
yy(CALLB,type,uid);
break;
caselabel(RET); break;
caselabel(ADDRG);
yy(ADDRG,uid,uid);
break;
caselabel(ADDRL);
yy(ADDRL,uid,uid);
break;
caselabel(ADDRF);
yy(ADDRF,uid,uid);
break;
caselabel(Unary);
yy(Unary,op,op);
yy(Unary,left,node);
break;
caselabel(Binary);
yy(Binary,op,op);
yy(Binary,left,node);
yy(Binary,right,node);
break;
caselabel(Compare);
yy(Compare,op,op);
yy(Compare,left,node);
yy(Compare,right,node);
yy(Compare,label,label);
break;
caselabel(LABEL);
yy(LABEL,label,define_label);
break;
caselabel(BRANCH);
yy(BRANCH,label,label);
break;
caselabel(CSE);
yy(CSE,uid,uid);
yy(CSE,node,node);
break;
default: assert(0);
}
#undef attributes
printf("</ul>");
}
static void do_node_list(list_ty x) {
do_list(x, do_node, "node", "ol", "");
}
static void do_interface(void *);
static void do_interface_list(list_ty x) {
do_list(x, do_interface, "interface", "ol", "");
}
static void do_interface(void *y) {
rcc_interface_ty x = y;
if (x->kind == rcc_Address_enum)
printf("<a name='%d'></a>", x->v.rcc_Address.uid);
else if (x->kind == rcc_Local_enum)
printf("<a name='%d'></a>", x->v.rcc_Local.uid);
#define attributes
switch (x->kind) {
static char *typename = "interface";
caselabel(Export);
yy(Export,p,uid);
break;
caselabel(Import);
yy(Import,p,uid);
break;
caselabel(Global);
yy(Global,p,uid);
yy(Global,seg,seg);
break;
caselabel(Local);
yy(Local,uid,define_uid);
yy(Local,p,symbol);
break;
caselabel(Address);
yy(Address,uid,define_uid);
yy(Address,q,symbol);
yy(Address,p,uid);
yy(Address,n,int);
break;
caselabel(Segment);
yy(Segment,seg,seg);
break;
caselabel(Defaddress);
yy(Defaddress,p,uid);
break;
caselabel(Deflabel);
yy(Deflabel,label,label);
break;
caselabel(Defconst);
yy(Defconst,suffix,suffix);
yy(Defconst,size,int);
yy(Defconst,value,int);
break;
caselabel(Defconstf);
yy(Defconstf,size,int);
yy(Defconstf,value,real);
break;
caselabel(Defstring);
yy(Defstring,s,string);
break;
caselabel(Space);
yy(Space,n,int);
break;
caselabel(Function);
yy(Function,f,uid);
yy(Function,caller,uid_list);
yy(Function,callee,uid_list);
yy(Function,ncalls,int);
yy(Function,codelist,interface_list);
break;
caselabel(Forest);
yy(Forest,nodes,node_list);
break;
case rcc_Blockbeg_enum: printf("<strong>Blockbeg</strong> : <em>%s</em>", typename); return;
case rcc_Blockend_enum: printf("<strong>Blockend</strong> : <em>%s</em>", typename); return;
default: assert(0);
}
#undef attributes
printf("</ul>\n");
}
static void do_program(rcc_program_ty x) {
printf("<ul>\n");
xx(x,nuids,int);
xx(x,nlabels,int);
xx(x,items,item_list);
xx(x,interfaces,interface_list);
xx(x,argc,int);
xx(x,argv,string_list);
printf("</ul>\n");
}
int main(int argc, char *argv[]) {
int i, version;
float stamp = (assert(strstr(rcsid, ",v")), strtod(strstr(rcsid, ",v")+2, NULL))
;
char *infile = NULL, *outfile = NULL;
rcc_program_ty pickle;
for (i = 1; i < argc; i++)
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, "rb", stdin) == NULL) {
fprintf(stderr, "%s: can't read `%s'\n", argv[0], infile);
exit(EXIT_FAILURE);
}
if (infile == NULL || strcmp(infile, "-") == 0)
infile = "Standard Input";
#if WIN32
else
_setmode(_fileno(stdin), _O_BINARY);
#endif
if (outfile != NULL && strcmp(outfile, "-") != 0
&& freopen(outfile, "w", stdout) == NULL) {
fprintf(stderr, "%s: can't write `%s'\n", argv[0], outfile);
exit(EXIT_FAILURE);
}
version = read_int(stdin);
assert(version/100 == (int)stamp);
pickle = rcc_read_program(stdin);
printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\"\n");
printf("<html><head><title>%s</title>\n"
"<link rev=made href=\"mailto:drh@microsoft.com\">\n"
"</head><body>\n<h1>%s</h1>\n", infile, infile);
printf("<p>version = %d.%d</p>", version/100, version%100);
do_program(pickle);
{
time_t t;
time(&t);
printf("<hr><address>%s</address>\n", ctime(&t));
}
printf("</body></html>\n");
return EXIT_SUCCESS;
}

View file

@ -0,0 +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

1192
code/tools/lcc/src/alpha.md Normal file

File diff suppressed because it is too large Load diff

399
code/tools/lcc/src/asdl.c Normal file
View file

@ -0,0 +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 */
}
}

23
code/tools/lcc/src/bind.c Normal file
View file

@ -0,0 +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 },
};

View file

@ -0,0 +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) */
};

723
code/tools/lcc/src/c.h Normal file
View file

@ -0,0 +1,723 @@
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#define NEW(p,a) ((p) = allocate(sizeof *(p), (a)))
#define NEW0(p,a) memset(NEW((p),(a)), 0, sizeof *(p))
#define isaddrop(op) (specific(op)==ADDRG+P || specific(op)==ADDRL+P \
|| specific(op)==ADDRF+P)
#define MAXLINE 512
#define BUFSIZE 4096
#define istypename(t,tsym) (kind[t] == CHAR \
|| (t == ID && tsym && tsym->sclass == TYPEDEF))
#define sizeop(n) ((n)<<10)
#define generic(op) ((op)&0x3F0)
#define specific(op) ((op)&0x3FF)
#define opindex(op) (((op)>>4)&0x3F)
#define opkind(op) ((op)&~0x3F0)
#define opsize(op) ((op)>>10)
#define optype(op) ((op)&0xF)
#ifdef __LCC__
#ifndef __STDC__
#define __STDC__
#endif
#endif
#define NELEMS(a) ((int)(sizeof (a)/sizeof ((a)[0])))
#undef roundup
#define roundup(x,n) (((x)+((n)-1))&(~((n)-1)))
#define mkop(op,ty) (specific((op) + ttob(ty)))
#define extend(x,ty) ((x)&(1<<(8*(ty)->size-1)) ? (x)|((~0UL)<<(8*(ty)->size-1)) : (x)&ones(8*(ty)->size))
#define ones(n) ((n)>=8*sizeof (unsigned long) ? ~0UL : ~((~0UL)<<(n)))
#define isqual(t) ((t)->op >= CONST)
#define unqual(t) (isqual(t) ? (t)->type : (t))
#define isvolatile(t) ((t)->op == VOLATILE \
|| (t)->op == CONST+VOLATILE)
#define isconst(t) ((t)->op == CONST \
|| (t)->op == CONST+VOLATILE)
#define isarray(t) (unqual(t)->op == ARRAY)
#define isstruct(t) (unqual(t)->op == STRUCT \
|| unqual(t)->op == UNION)
#define isunion(t) (unqual(t)->op == UNION)
#define isfunc(t) (unqual(t)->op == FUNCTION)
#define isptr(t) (unqual(t)->op == POINTER)
#define ischar(t) ((t)->size == 1 && isint(t))
#define isint(t) (unqual(t)->op == INT \
|| unqual(t)->op == UNSIGNED)
#define isfloat(t) (unqual(t)->op == FLOAT)
#define isarith(t) (unqual(t)->op <= UNSIGNED)
#define isunsigned(t) (unqual(t)->op == UNSIGNED)
#define isscalar(t) (unqual(t)->op <= POINTER \
|| unqual(t)->op == ENUM)
#define isenum(t) (unqual(t)->op == ENUM)
#define fieldsize(p) (p)->bitsize
#define fieldright(p) ((p)->lsb - 1)
#define fieldleft(p) (8*(p)->type->size - \
fieldsize(p) - fieldright(p))
#define fieldmask(p) (~(~(unsigned)0<<fieldsize(p)))
typedef struct node *Node;
typedef struct list *List;
typedef struct code *Code;
typedef struct swtch *Swtch;
typedef struct symbol *Symbol;
typedef struct coord {
char *file;
unsigned x, y;
} Coordinate;
typedef struct table *Table;
typedef union value {
long i;
unsigned long u;
long double d;
void *p;
void (*g)(void);
} Value;
typedef struct tree *Tree;
typedef struct type *Type;
typedef struct field *Field;
typedef struct {
unsigned printed:1;
unsigned marked;
unsigned short typeno;
void *xt;
} Xtype;
#include "config.h"
typedef struct metrics {
unsigned char size, align, outofline;
} Metrics;
typedef struct interface {
Metrics charmetric;
Metrics shortmetric;
Metrics intmetric;
Metrics longmetric;
Metrics longlongmetric;
Metrics floatmetric;
Metrics doublemetric;
Metrics longdoublemetric;
Metrics ptrmetric;
Metrics structmetric;
unsigned little_endian:1;
unsigned mulops_calls:1;
unsigned wants_callb:1;
unsigned wants_argb:1;
unsigned left_to_right:1;
unsigned wants_dag:1;
unsigned unsigned_char:1;
void (*address)(Symbol p, Symbol q, long n);
void (*blockbeg)(Env *);
void (*blockend)(Env *);
void (*defaddress)(Symbol);
void (*defconst) (int suffix, int size, Value v);
void (*defstring)(int n, char *s);
void (*defsymbol)(Symbol);
void (*emit) (Node);
void (*export)(Symbol);
void (*function)(Symbol, Symbol[], Symbol[], int);
Node (*gen) (Node);
void (*global)(Symbol);
void (*import)(Symbol);
void (*local)(Symbol);
void (*progbeg)(int argc, char *argv[]);
void (*progend)(void);
void (*segment)(int);
void (*space)(int);
void (*stabblock)(int, int, Symbol*);
void (*stabend) (Coordinate *, Symbol, Coordinate **, Symbol *, Symbol *);
void (*stabfend) (Symbol, int);
void (*stabinit) (char *, int, char *[]);
void (*stabline) (Coordinate *);
void (*stabsym) (Symbol);
void (*stabtype) (Symbol);
Xinterface x;
} Interface;
typedef struct binding {
char *name;
Interface *ir;
} Binding;
extern Binding bindings[];
extern Interface *IR;
typedef struct {
List blockentry;
List blockexit;
List entry;
List exit;
List returns;
List points;
List calls;
List end;
} Events;
enum {
#define xx(a,b,c,d,e,f,g) a=b,
#define yy(a,b,c,d,e,f,g)
#include "token.h"
LAST
};
struct node {
short op;
short count;
Symbol syms[3];
Node kids[2];
Node link;
Xnode x;
};
enum {
F=FLOAT,
I=INT,
U=UNSIGNED,
P=POINTER,
V=VOID,
B=STRUCT
};
#define gop(name,value) name=value<<4,
#define op(name,type,sizes)
enum { gop(CNST,1)
op(CNST,F,fdx)
op(CNST,I,csilh)
op(CNST,P,p)
op(CNST,U,csilh)
gop(ARG,2)
op(ARG,B,-)
op(ARG,F,fdx)
op(ARG,I,ilh)
op(ARG,P,p)
op(ARG,U,ilh)
gop(ASGN,3)
op(ASGN,B,-)
op(ASGN,F,fdx)
op(ASGN,I,csilh)
op(ASGN,P,p)
op(ASGN,U,csilh)
gop(INDIR,4)
op(INDIR,B,-)
op(INDIR,F,fdx)
op(INDIR,I,csilh)
op(INDIR,P,p)
op(INDIR,U,csilh)
gop(CVF,7)
op(CVF,F,fdx)
op(CVF,I,ilh)
gop(CVI,8)
op(CVI,F,fdx)
op(CVI,I,csilh)
op(CVI,U,csilhp)
gop(CVP,9)
op(CVP,U,p)
gop(CVU,11)
op(CVU,I,csilh)
op(CVU,P,p)
op(CVU,U,csilh)
gop(NEG,12)
op(NEG,F,fdx)
op(NEG,I,ilh)
gop(CALL,13)
op(CALL,B,-)
op(CALL,F,fdx)
op(CALL,I,ilh)
op(CALL,P,p)
op(CALL,U,ilh)
op(CALL,V,-)
gop(RET,15)
op(RET,F,fdx)
op(RET,I,ilh)
op(RET,P,p)
op(RET,U,ilh)
op(RET,V,-)
gop(ADDRG,16)
op(ADDRG,P,p)
gop(ADDRF,17)
op(ADDRF,P,p)
gop(ADDRL,18)
op(ADDRL,P,p)
gop(ADD,19)
op(ADD,F,fdx)
op(ADD,I,ilh)
op(ADD,P,p)
op(ADD,U,ilhp)
gop(SUB,20)
op(SUB,F,fdx)
op(SUB,I,ilh)
op(SUB,P,p)
op(SUB,U,ilhp)
gop(LSH,21)
op(LSH,I,ilh)
op(LSH,U,ilh)
gop(MOD,22)
op(MOD,I,ilh)
op(MOD,U,ilh)
gop(RSH,23)
op(RSH,I,ilh)
op(RSH,U,ilh)
gop(BAND,24)
op(BAND,I,ilh)
op(BAND,U,ilh)
gop(BCOM,25)
op(BCOM,I,ilh)
op(BCOM,U,ilh)
gop(BOR,26)
op(BOR,I,ilh)
op(BOR,U,ilh)
gop(BXOR,27)
op(BXOR,I,ilh)
op(BXOR,U,ilh)
gop(DIV,28)
op(DIV,F,fdx)
op(DIV,I,ilh)
op(DIV,U,ilh)
gop(MUL,29)
op(MUL,F,fdx)
op(MUL,I,ilh)
op(MUL,U,ilh)
gop(EQ,30)
op(EQ,F,fdx)
op(EQ,I,ilh)
op(EQ,U,ilhp)
gop(GE,31)
op(GE,F,fdx)
op(GE,I,ilh)
op(GE,U,ilhp)
gop(GT,32)
op(GT,F,fdx)
op(GT,I,ilh)
op(GT,U,ilhp)
gop(LE,33)
op(LE,F,fdx)
op(LE,I,ilh)
op(LE,U,ilhp)
gop(LT,34)
op(LT,F,fdx)
op(LT,I,ilh)
op(LT,U,ilhp)
gop(NE,35)
op(NE,F,fdx)
op(NE,I,ilh)
op(NE,U,ilhp)
gop(JUMP,36)
op(JUMP,V,-)
gop(LABEL,37)
op(LABEL,V,-)
gop(LOAD,14)
op(LOAD,B,-)
op(LOAD,F,fdx)
op(LOAD,I,csilh)
op(LOAD,P,p)
op(LOAD,U,csilhp) LASTOP };
#undef gop
#undef op
enum { CODE=1, BSS, DATA, LIT };
enum { PERM=0, FUNC, STMT };
struct list {
void *x;
List link;
};
struct code {
enum { Blockbeg, Blockend, Local, Address, Defpoint,
Label, Start, Gen, Jump, Switch
} kind;
Code prev, next;
union {
struct {
int level;
Symbol *locals;
Table identifiers, types;
Env x;
} block;
Code begin;
Symbol var;
struct {
Symbol sym;
Symbol base;
long offset;
} addr;
struct {
Coordinate src;
int point;
} point;
Node forest;
struct {
Symbol sym;
Symbol table;
Symbol deflab;
int size;
long *values;
Symbol *labels;
} swtch;
} u;
};
struct swtch {
Symbol sym;
int lab;
Symbol deflab;
int ncases;
int size;
long *values;
Symbol *labels;
};
struct symbol {
char *name;
int scope;
Coordinate src;
Symbol up;
List uses;
int sclass;
unsigned structarg:1;
unsigned addressed:1;
unsigned computed:1;
unsigned temporary:1;
unsigned generated:1;
unsigned defined:1;
Type type;
float ref;
union {
struct {
int label;
Symbol equatedto;
} l;
struct {
unsigned cfields:1;
unsigned vfields:1;
Table ftab; /* omit */
Field flist;
} s;
int value;
Symbol *idlist;
struct {
Value min, max;
} limits;
struct {
Value v;
Symbol loc;
} c;
struct {
Coordinate pt;
int label;
int ncalls;
Symbol *callee;
} f;
int seg;
Symbol alias;
struct {
Node cse;
int replace;
Symbol next;
} t;
} u;
Xsymbol x;
};
enum { CONSTANTS=1, LABELS, GLOBAL, PARAM, LOCAL };
struct tree {
int op;
Type type;
Tree kids[2];
Node node;
union {
Value v;
Symbol sym;
Field field;
} u;
};
enum {
AND=38<<4,
NOT=39<<4,
OR=40<<4,
COND=41<<4,
RIGHT=42<<4,
FIELD=43<<4
};
struct type {
int op;
Type type;
int align;
int size;
union {
Symbol sym;
struct {
unsigned oldstyle:1;
Type *proto;
} f;
} u;
Xtype x;
};
struct field {
char *name;
Type type;
int offset;
short bitsize;
short lsb;
Field link;
};
extern int assignargs;
extern int prunetemps;
extern int nodecount;
extern Symbol cfunc;
extern Symbol retv;
extern Tree (*optree[])(int, Tree, Tree);
extern char kind[];
extern int errcnt;
extern int errlimit;
extern int wflag;
extern Events events;
extern float refinc;
extern unsigned char *cp;
extern unsigned char *limit;
extern char *firstfile;
extern char *file;
extern char *line;
extern int lineno;
extern int t;
extern char *token;
extern Symbol tsym;
extern Coordinate src;
extern int Aflag;
extern int Pflag;
extern Symbol YYnull;
extern Symbol YYcheck;
extern int glevel;
extern int xref;
extern int ncalled;
extern int npoints;
extern int needconst;
extern int explicitCast;
extern struct code codehead;
extern Code codelist;
extern Table stmtlabs;
extern float density;
extern Table constants;
extern Table externals;
extern Table globals;
extern Table identifiers;
extern Table labels;
extern Table types;
extern int level;
extern List loci, symbols;
extern List symbols;
extern int where;
extern Type chartype;
extern Type doubletype;
extern Type floattype;
extern Type inttype;
extern Type longdouble;
extern Type longtype;
extern Type longlong;
extern Type shorttype;
extern Type signedchar;
extern Type unsignedchar;
extern Type unsignedlonglong;
extern Type unsignedlong;
extern Type unsignedshort;
extern Type unsignedtype;
extern Type charptype;
extern Type funcptype;
extern Type voidptype;
extern Type voidtype;
extern Type unsignedptr;
extern Type signedptr;
extern Type widechar;
extern void *allocate(unsigned long n, unsigned a);
extern void deallocate(unsigned a);
extern void *newarray(unsigned long m, unsigned long n, unsigned a);
extern void walk(Tree e, int tlab, int flab);
extern Node listnodes(Tree e, int tlab, int flab);
extern Node newnode(int op, Node left, Node right, Symbol p);
extern Tree cvtconst(Tree);
extern void printdag(Node, int);
extern void compound(int, Swtch, int);
extern void defglobal(Symbol, int);
extern void finalize(void);
extern void program(void);
extern Tree vcall(Symbol func, Type ty, ...);
extern Tree addrof(Tree);
extern Tree asgn(Symbol, Tree);
extern Tree asgntree(int, Tree, Tree);
extern Type assign(Type, Tree);
extern Tree bittree(int, Tree, Tree);
extern Tree call(Tree, Type, Coordinate);
extern Tree calltree(Tree, Type, Tree, Symbol);
extern Tree condtree(Tree, Tree, Tree);
extern Tree cnsttree(Type, ...);
extern Tree consttree(unsigned int, Type);
extern Tree eqtree(int, Tree, Tree);
extern int iscallb(Tree);
extern Tree shtree(int, Tree, Tree);
extern void typeerror(int, Tree, Tree);
extern void test(int tok, char set[]);
extern void expect(int tok);
extern void skipto(int tok, char set[]);
extern void error(const char *, ...);
extern int fatal(const char *, const char *, int);
extern void warning(const char *, ...);
typedef void (*Apply)(void *, void *, void *);
extern void attach(Apply, void *, List *);
extern void apply(List event, void *arg1, void *arg2);
extern Tree retype(Tree p, Type ty);
extern Tree rightkid(Tree p);
extern int hascall(Tree p);
extern Type binary(Type, Type);
extern Tree cast(Tree, Type);
extern Tree cond(Tree);
extern Tree expr0(int);
extern Tree expr(int);
extern Tree expr1(int);
extern Tree field(Tree, const char *);
extern char *funcname(Tree);
extern Tree idtree(Symbol);
extern Tree incr(int, Tree, Tree);
extern Tree lvalue(Tree);
extern Tree nullcall(Type, Symbol, Tree, Tree);
extern Tree pointer(Tree);
extern Tree rvalue(Tree);
extern Tree value(Tree);
extern void defpointer(Symbol);
extern Type initializer(Type, int);
extern void swtoseg(int);
extern void input_init(int, char *[]);
extern void fillbuf(void);
extern void nextline(void);
extern int getchr(void);
extern int gettok(void);
extern void emitcode(void);
extern void gencode (Symbol[], Symbol[]);
extern void fprint(FILE *f, const char *fmt, ...);
extern char *stringf(const char *, ...);
extern void check(Node);
extern void print(const char *, ...);
extern List append(void *x, List list);
extern int length(List list);
extern void *ltov (List *list, unsigned a);
extern void init(int, char *[]);
extern Type typename(void);
extern void checklab(Symbol p, void *cl);
extern Type enumdcl(void);
extern void main_init(int, char *[]);
extern int main(int, char *[]);
extern void vfprint(FILE *, char *, const char *, va_list);
extern int process(char *);
extern int findfunc(char *, char *);
extern int findcount(char *, int, int);
extern Tree constexpr(int);
extern int intexpr(int, int);
extern Tree simplify(int, Type, Tree, Tree);
extern int ispow2(unsigned long u);
extern int reachable(int);
extern void addlocal(Symbol);
extern void branch(int);
extern Code code(int);
extern void definelab(int);
extern void definept(Coordinate *);
extern void equatelab(Symbol, Symbol);
extern Node jump(int);
extern void retcode(Tree);
extern void statement(int, Swtch, int);
extern void swcode(Swtch, int *, int, int);
extern void swgen(Swtch);
extern char * string(const char *str);
extern char *stringn(const char *str, int len);
extern char *stringd(long n);
extern Symbol relocate(const char *name, Table src, Table dst);
extern void use(Symbol p, Coordinate src);
extern void locus(Table tp, Coordinate *cp);
extern Symbol allsymbols(Table);
extern Symbol constant(Type, Value);
extern void enterscope(void);
extern void exitscope(void);
extern Symbol findlabel(int);
extern Symbol findtype(Type);
extern void foreach(Table, int, void (*)(Symbol, void *), void *);
extern Symbol genident(int, Type, int);
extern int genlabel(int);
extern Symbol install(const char *, Table *, int, int);
extern Symbol intconst(int);
extern Symbol lookup(const char *, Table);
extern Symbol mkstr(char *);
extern Symbol mksymbol(int, const char *, Type);
extern Symbol newtemp(int, int, int);
extern Table table(Table, int);
extern Symbol temporary(int, Type);
extern char *vtoa(Type, Value);
extern int nodeid(Tree);
extern char *opname(int);
extern int *printed(int);
extern void printtree(Tree, int);
extern Tree root(Tree);
extern Tree texpr(Tree (*)(int), int, int);
extern Tree tree(int, Type, Tree, Tree);
extern void type_init(int, char *[]);
extern Type signedint(Type);
extern int hasproto(Type);
extern void outtype(Type, FILE *);
extern void printdecl (Symbol p, Type ty);
extern void printproto(Symbol p, Symbol args[]);
extern char *typestring(Type ty, char *id);
extern Field fieldref(const char *name, Type ty);
extern Type array(Type, int, int);
extern Type atop(Type);
extern Type btot(int, int);
extern Type compose(Type, Type);
extern Type deref(Type);
extern int eqtype(Type, Type, int);
extern Field fieldlist(Type);
extern Type freturn(Type);
extern Type ftype(Type, Type);
extern Type func(Type, Type *, int);
extern Field newfield(char *, Type, Type);
extern Type newstruct(int, char *);
extern void printtype(Type, int);
extern Type promote(Type);
extern Type ptr(Type);
extern Type qual(int, Type);
extern void rmtypes(int);
extern int ttob(Type);
extern int variadic(Type);

102
code/tools/lcc/src/config.h Normal file
View file

@ -0,0 +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

736
code/tools/lcc/src/dag.c Normal file
View file

@ -0,0 +1,736 @@
#include "c.h"
#define iscall(op) (generic(op) == CALL \
|| (IR->mulops_calls \
&& (generic(op)==DIV||generic(op)==MOD||generic(op)==MUL) \
&& ( optype(op)==U || optype(op)==I)))
static Node forest;
static struct dag {
struct node node;
struct dag *hlink;
} *buckets[16];
int nodecount;
static Tree firstarg;
int assignargs = 1;
int prunetemps = -1;
static Node *tail;
static int depth = 0;
static Node replace(Node);
static Node prune(Node);
static Node asgnnode(Symbol, Node);
static struct dag *dagnode(int, Node, Node, Symbol);
static Symbol equated(Symbol);
static void fixup(Node);
static void labelnode(int);
static void list(Node);
static void kill(Symbol);
static Node node(int, Node, Node, Symbol);
static void printdag1(Node, int, int);
static void printnode(Node, int, int);
static void reset(void);
static Node tmpnode(Node);
static void typestab(Symbol, void *);
static Node undag(Node);
static Node visit(Node, int);
static void unlist(void);
void walk(Tree tp, int tlab, int flab) {
listnodes(tp, tlab, flab);
if (forest) {
Node list = forest->link;
forest->link = NULL;
if (!IR->wants_dag)
list = undag(list);
code(Gen)->u.forest = list;
forest = NULL;
}
reset();
deallocate(STMT);
}
static Node node(int op, Node l, Node r, Symbol sym) {
int i;
struct dag *p;
i = (opindex(op)^((unsigned long)sym>>2))&(NELEMS(buckets)-1);
for (p = buckets[i]; p; p = p->hlink)
if (p->node.op == op && p->node.syms[0] == sym
&& p->node.kids[0] == l && p->node.kids[1] == r)
return &p->node;
p = dagnode(op, l, r, sym);
p->hlink = buckets[i];
buckets[i] = p;
++nodecount;
return &p->node;
}
static struct dag *dagnode(int op, Node l, Node r, Symbol sym) {
struct dag *p;
NEW0(p, FUNC);
p->node.op = op;
if ((p->node.kids[0] = l) != NULL)
++l->count;
if ((p->node.kids[1] = r) != NULL)
++r->count;
p->node.syms[0] = sym;
return p;
}
Node newnode(int op, Node l, Node r, Symbol sym) {
return &dagnode(op, l, r, sym)->node;
}
static void kill(Symbol p) {
int i;
struct dag **q;
for (i = 0; i < NELEMS(buckets); i++)
for (q = &buckets[i]; *q; )
if (generic((*q)->node.op) == INDIR &&
(!isaddrop((*q)->node.kids[0]->op)
|| (*q)->node.kids[0]->syms[0] == p)) {
*q = (*q)->hlink;
--nodecount;
} else
q = &(*q)->hlink;
}
static void reset(void) {
if (nodecount > 0)
memset(buckets, 0, sizeof buckets);
nodecount = 0;
}
Node listnodes(Tree tp, int tlab, int flab) {
Node p = NULL, l, r;
int op;
assert(tlab || flab || (tlab == 0 && flab == 0));
if (tp == NULL)
return NULL;
if (tp->node)
return tp->node;
op = tp->op + sizeop(tp->type->size);
switch (generic(tp->op)) {
case AND: { if (depth++ == 0) reset();
if (flab) {
listnodes(tp->kids[0], 0, flab);
listnodes(tp->kids[1], 0, flab);
} else {
listnodes(tp->kids[0], 0, flab = genlabel(1));
listnodes(tp->kids[1], tlab, 0);
labelnode(flab);
}
depth--; } break;
case OR: { if (depth++ == 0)
reset();
if (tlab) {
listnodes(tp->kids[0], tlab, 0);
listnodes(tp->kids[1], tlab, 0);
} else {
tlab = genlabel(1);
listnodes(tp->kids[0], tlab, 0);
listnodes(tp->kids[1], 0, flab);
labelnode(tlab);
}
depth--;
} break;
case NOT: { return listnodes(tp->kids[0], flab, tlab); }
case COND: { Tree q = tp->kids[1];
assert(tlab == 0 && flab == 0);
if (tp->u.sym)
addlocal(tp->u.sym);
flab = genlabel(2);
listnodes(tp->kids[0], 0, flab);
assert(q && q->op == RIGHT);
reset();
listnodes(q->kids[0], 0, 0);
if (forest->op == LABEL+V) {
equatelab(forest->syms[0], findlabel(flab + 1));
unlist();
}
list(jump(flab + 1));
labelnode(flab);
listnodes(q->kids[1], 0, 0);
if (forest->op == LABEL+V) {
equatelab(forest->syms[0], findlabel(flab + 1));
unlist();
}
labelnode(flab + 1);
if (tp->u.sym)
p = listnodes(idtree(tp->u.sym), 0, 0); } break;
case CNST: { Type ty = unqual(tp->type);
assert(ty->u.sym);
if (tlab || flab) {
assert(ty == inttype);
if (tlab && tp->u.v.i != 0)
list(jump(tlab));
else if (flab && tp->u.v.i == 0)
list(jump(flab));
}
else if (ty->u.sym->addressed)
p = listnodes(cvtconst(tp), 0, 0);
else
p = node(op, NULL, NULL, constant(ty, tp->u.v)); } break;
case RIGHT: { if ( tp->kids[0] && tp->kids[1]
&& generic(tp->kids[1]->op) == ASGN
&& ((generic(tp->kids[0]->op) == INDIR
&& tp->kids[0]->kids[0] == tp->kids[1]->kids[0])
|| (tp->kids[0]->op == FIELD
&& tp->kids[0] == tp->kids[1]->kids[0]))) {
assert(tlab == 0 && flab == 0);
if (generic(tp->kids[0]->op) == INDIR) {
p = listnodes(tp->kids[0], 0, 0);
list(p);
listnodes(tp->kids[1], 0, 0);
}
else {
assert(generic(tp->kids[0]->kids[0]->op) == INDIR);
list(listnodes(tp->kids[0]->kids[0], 0, 0));
p = listnodes(tp->kids[0], 0, 0);
listnodes(tp->kids[1], 0, 0);
}
} else if (tp->kids[1]) {
listnodes(tp->kids[0], 0, 0);
p = listnodes(tp->kids[1], tlab, flab);
} else
p = listnodes(tp->kids[0], tlab, flab); } break;
case JUMP: { assert(tlab == 0 && flab == 0);
assert(tp->u.sym == 0);
assert(tp->kids[0]);
l = listnodes(tp->kids[0], 0, 0);
list(newnode(JUMP+V, l, NULL, NULL));
reset(); } break;
case CALL: { Tree save = firstarg;
firstarg = NULL;
assert(tlab == 0 && flab == 0);
if (tp->op == CALL+B && !IR->wants_callb) {
Tree arg0 = tree(ARG+P, tp->kids[1]->type,
tp->kids[1], NULL);
if (IR->left_to_right)
firstarg = arg0;
l = listnodes(tp->kids[0], 0, 0);
if (!IR->left_to_right || firstarg) {
firstarg = NULL;
listnodes(arg0, 0, 0);
}
p = newnode(CALL+V, l, NULL, NULL);
} else {
l = listnodes(tp->kids[0], 0, 0);
r = listnodes(tp->kids[1], 0, 0);
p = newnode(tp->op == CALL+B ? tp->op : op, l, r, NULL);
}
NEW0(p->syms[0], FUNC);
assert(isptr(tp->kids[0]->type));
assert(isfunc(tp->kids[0]->type->type));
p->syms[0]->type = tp->kids[0]->type->type;
list(p);
reset();
cfunc->u.f.ncalls++;
firstarg = save;
} break;
case ARG: { assert(tlab == 0 && flab == 0);
if (IR->left_to_right)
listnodes(tp->kids[1], 0, 0);
if (firstarg) {
Tree arg = firstarg;
firstarg = NULL;
listnodes(arg, 0, 0);
}
l = listnodes(tp->kids[0], 0, 0);
list(newnode(tp->op == ARG+B ? tp->op : op, l, NULL, NULL));
forest->syms[0] = intconst(tp->type->size);
forest->syms[1] = intconst(tp->type->align);
if (!IR->left_to_right)
listnodes(tp->kids[1], 0, 0); } break;
case EQ: case NE: case GT: case GE: case LE:
case LT: { assert(tp->u.sym == 0);
assert(errcnt || tlab || flab);
l = listnodes(tp->kids[0], 0, 0);
r = listnodes(tp->kids[1], 0, 0);
assert(errcnt || opkind(l->op) == opkind(r->op));
assert(errcnt || optype(op) == optype(l->op));
if (tlab)
assert(flab == 0),
list(newnode(generic(tp->op) + opkind(l->op), l, r, findlabel(tlab)));
else if (flab) {
switch (generic(tp->op)) {
case EQ: op = NE; break;
case NE: op = EQ; break;
case GT: op = LE; break;
case LT: op = GE; break;
case GE: op = LT; break;
case LE: op = GT; break;
default: assert(0);
}
list(newnode(op + opkind(l->op), l, r, findlabel(flab)));
}
if (forest && forest->syms[0])
forest->syms[0]->ref++; } break;
case ASGN: { assert(tlab == 0 && flab == 0);
if (tp->kids[0]->op == FIELD) {
Tree x = tp->kids[0]->kids[0];
Field f = tp->kids[0]->u.field;
assert(generic(x->op) == INDIR);
reset();
l = listnodes(lvalue(x), 0, 0);
if (fieldsize(f) < 8*f->type->size) {
unsigned int fmask = fieldmask(f);
unsigned int mask = fmask<<fieldright(f);
Tree q = tp->kids[1];
if ((q->op == CNST+I && q->u.v.i == 0)
|| (q->op == CNST+U && q->u.v.u == 0))
q = bittree(BAND, x, cnsttree(unsignedtype, (unsigned long)~mask));
else if ((q->op == CNST+I && (q->u.v.i&fmask) == fmask)
|| (q->op == CNST+U && (q->u.v.u&fmask) == fmask))
q = bittree(BOR, x, cnsttree(unsignedtype, (unsigned long)mask));
else {
listnodes(q, 0, 0);
q = bittree(BOR,
bittree(BAND, rvalue(lvalue(x)),
cnsttree(unsignedtype, (unsigned long)~mask)),
bittree(BAND, shtree(LSH, cast(q, unsignedtype),
cnsttree(unsignedtype, (unsigned long)fieldright(f))),
cnsttree(unsignedtype, (unsigned long)mask)));
}
r = listnodes(q, 0, 0);
op = ASGN + ttob(q->type);
} else {
r = listnodes(tp->kids[1], 0, 0);
op = ASGN + ttob(tp->kids[1]->type);
}
} else {
l = listnodes(tp->kids[0], 0, 0);
r = listnodes(tp->kids[1], 0, 0);
}
list(newnode(tp->op == ASGN+B ? tp->op : op, l, r, NULL));
forest->syms[0] = intconst(tp->kids[1]->type->size);
forest->syms[1] = intconst(tp->kids[1]->type->align);
if (isaddrop(tp->kids[0]->op)
&& !tp->kids[0]->u.sym->computed)
kill(tp->kids[0]->u.sym);
else
reset();
p = listnodes(tp->kids[1], 0, 0); } break;
case BOR: case BAND: case BXOR:
case ADD: case SUB: case RSH:
case LSH: { assert(tlab == 0 && flab == 0);
l = listnodes(tp->kids[0], 0, 0);
r = listnodes(tp->kids[1], 0, 0);
p = node(op, l, r, NULL); } break;
case DIV: case MUL:
case MOD: { assert(tlab == 0 && flab == 0);
l = listnodes(tp->kids[0], 0, 0);
r = listnodes(tp->kids[1], 0, 0);
p = node(op, l, r, NULL);
if (IR->mulops_calls && isint(tp->type)) {
list(p);
cfunc->u.f.ncalls++;
} } break;
case RET: { assert(tlab == 0 && flab == 0);
l = listnodes(tp->kids[0], 0, 0);
list(newnode(op, l, NULL, NULL)); } break;
case CVF: case CVI: case CVP:
case CVU: { assert(tlab == 0 && flab == 0);
assert(optype(tp->kids[0]->op) != optype(tp->op) || tp->kids[0]->type->size != tp->type->size);
l = listnodes(tp->kids[0], 0, 0);
p = node(op, l, NULL, intconst(tp->kids[0]->type->size));
} break;
case BCOM:
case NEG: { assert(tlab == 0 && flab == 0);
l = listnodes(tp->kids[0], 0, 0);
p = node(op, l, NULL, NULL); } break;
case INDIR: { Type ty = tp->kids[0]->type;
assert(tlab == 0 && flab == 0);
l = listnodes(tp->kids[0], 0, 0);
if (isptr(ty))
ty = unqual(ty)->type;
if (isvolatile(ty)
|| (isstruct(ty) && unqual(ty)->u.sym->u.s.vfields))
p = newnode(tp->op == INDIR+B ? tp->op : op, l, NULL, NULL);
else
p = node(tp->op == INDIR+B ? tp->op : op, l, NULL, NULL); } break;
case FIELD: { Tree q = tp->kids[0];
if (tp->type == inttype) {
long n = fieldleft(tp->u.field);
q = shtree(RSH,
shtree(LSH, q, cnsttree(inttype, n)),
cnsttree(inttype, n + fieldright(tp->u.field)));
} else if (fieldsize(tp->u.field) < 8*tp->u.field->type->size)
q = bittree(BAND,
shtree(RSH, q, cnsttree(inttype, (long)fieldright(tp->u.field))),
cnsttree(unsignedtype, (unsigned long)fieldmask(tp->u.field)));
assert(tlab == 0 && flab == 0);
p = listnodes(q, 0, 0); } break;
case ADDRG:
case ADDRF: { assert(tlab == 0 && flab == 0);
p = node(tp->op + sizeop(voidptype->size), NULL, NULL, tp->u.sym);
} break;
case ADDRL: { assert(tlab == 0 && flab == 0);
if (tp->u.sym->temporary)
addlocal(tp->u.sym);
p = node(tp->op + sizeop(voidptype->size), NULL, NULL, tp->u.sym); } break;
default:assert(0);
}
tp->node = p;
return p;
}
static void list(Node p) {
if (p && p->link == NULL) {
if (forest) {
p->link = forest->link;
forest->link = p;
} else
p->link = p;
forest = p;
}
}
static void labelnode(int lab) {
assert(lab);
if (forest && forest->op == LABEL+V)
equatelab(findlabel(lab), forest->syms[0]);
else
list(newnode(LABEL+V, NULL, NULL, findlabel(lab)));
reset();
}
static void unlist(void) {
Node p;
assert(forest);
assert(forest != forest->link);
p = forest->link;
while (p->link != forest)
p = p->link;
p->link = forest->link;
forest = p;
}
Tree cvtconst(Tree p) {
Symbol q = constant(p->type, p->u.v);
Tree e;
if (q->u.c.loc == NULL)
q->u.c.loc = genident(STATIC, p->type, GLOBAL);
if (isarray(p->type)) {
e = simplify(ADDRG, atop(p->type), NULL, NULL);
e->u.sym = q->u.c.loc;
} else
e = idtree(q->u.c.loc);
return e;
}
void gencode(Symbol caller[], Symbol callee[]) {
Code cp;
Coordinate save;
if (prunetemps == -1)
prunetemps = !IR->wants_dag;
save = src;
if (assignargs) {
int i;
Symbol p, q;
cp = codehead.next->next;
codelist = codehead.next;
for (i = 0; (p = callee[i]) != NULL
&& (q = caller[i]) != NULL; i++)
if (p->sclass != q->sclass || p->type != q->type)
walk(asgn(p, idtree(q)), 0, 0);
codelist->next = cp;
cp->prev = codelist;
}
if (glevel && IR->stabsym) {
int i;
Symbol p, q;
for (i = 0; (p = callee[i]) != NULL
&& (q = caller[i]) != NULL; i++) {
(*IR->stabsym)(p);
if (p->sclass != q->sclass || p->type != q->type)
(*IR->stabsym)(q);
}
swtoseg(CODE);
}
cp = codehead.next;
for ( ; errcnt <= 0 && cp; cp = cp->next)
switch (cp->kind) {
case Address: (*IR->address)(cp->u.addr.sym, cp->u.addr.base,
cp->u.addr.offset); break;
case Blockbeg: {
Symbol *p = cp->u.block.locals;
(*IR->blockbeg)(&cp->u.block.x);
for ( ; *p; p++)
if ((*p)->ref != 0.0)
(*IR->local)(*p);
else if (glevel) (*IR->local)(*p);
}
break;
case Blockend: (*IR->blockend)(&cp->u.begin->u.block.x); break;
case Defpoint: src = cp->u.point.src; break;
case Gen: case Jump:
case Label: if (prunetemps)
cp->u.forest = prune(cp->u.forest);
fixup(cp->u.forest);
cp->u.forest = (*IR->gen)(cp->u.forest); break;
case Local: (*IR->local)(cp->u.var); break;
case Switch: break;
default: assert(0);
}
src = save;
}
static void fixup(Node p) {
for ( ; p; p = p->link)
switch (generic(p->op)) {
case JUMP:
if (specific(p->kids[0]->op) == ADDRG+P)
p->kids[0]->syms[0] =
equated(p->kids[0]->syms[0]);
break;
case LABEL: assert(p->syms[0] == equated(p->syms[0])); break;
case EQ: case GE: case GT: case LE: case LT: case NE:
assert(p->syms[0]);
p->syms[0] = equated(p->syms[0]);
}
}
static Symbol equated(Symbol p) {
{ Symbol q; for (q = p->u.l.equatedto; q; q = q->u.l.equatedto) assert(p != q); }
while (p->u.l.equatedto)
p = p->u.l.equatedto;
return p;
}
void emitcode(void) {
Code cp;
Coordinate save;
save = src;
cp = codehead.next;
for ( ; errcnt <= 0 && cp; cp = cp->next)
switch (cp->kind) {
case Address: break;
case Blockbeg: if (glevel && IR->stabblock) {
(*IR->stabblock)('{', cp->u.block.level - LOCAL, cp->u.block.locals);
swtoseg(CODE);
}
break;
case Blockend: if (glevel && IR->stabblock) {
Code bp = cp->u.begin;
foreach(bp->u.block.identifiers, bp->u.block.level, typestab, NULL);
foreach(bp->u.block.types, bp->u.block.level, typestab, NULL);
(*IR->stabblock)('}', bp->u.block.level - LOCAL, bp->u.block.locals);
swtoseg(CODE);
}
break;
case Defpoint: src = cp->u.point.src;
if (glevel > 0 && IR->stabline) {
(*IR->stabline)(&cp->u.point.src); swtoseg(CODE); } break;
case Gen: case Jump:
case Label: if (cp->u.forest)
(*IR->emit)(cp->u.forest); break;
case Local: if (glevel && IR->stabsym) {
(*IR->stabsym)(cp->u.var);
swtoseg(CODE);
} break;
case Switch: { int i;
defglobal(cp->u.swtch.table, LIT);
(*IR->defaddress)(equated(cp->u.swtch.labels[0]));
for (i = 1; i < cp->u.swtch.size; i++) {
long k = cp->u.swtch.values[i-1];
while (++k < cp->u.swtch.values[i])
assert(k < LONG_MAX),
(*IR->defaddress)(equated(cp->u.swtch.deflab));
(*IR->defaddress)(equated(cp->u.swtch.labels[i]));
}
swtoseg(CODE);
} break;
default: assert(0);
}
src = save;
}
static Node undag(Node forest) {
Node p;
tail = &forest;
for (p = forest; p; p = p->link)
if (generic(p->op) == INDIR) {
assert(p->count >= 1);
visit(p, 1);
if (p->syms[2]) {
assert(p->syms[2]->u.t.cse);
p->syms[2]->u.t.cse = NULL;
addlocal(p->syms[2]);
}
} else if (iscall(p->op) && p->count >= 1)
visit(p, 1);
else {
assert(p->count == 0),
visit(p, 1);
*tail = p;
tail = &p->link;
}
*tail = NULL;
return forest;
}
static Node replace(Node p) {
if (p && ( generic(p->op) == INDIR
&& generic(p->kids[0]->op) == ADDRL
&& p->kids[0]->syms[0]->temporary
&& p->kids[0]->syms[0]->u.t.replace)) {
p = p->kids[0]->syms[0]->u.t.cse;
if (generic(p->op) == INDIR && isaddrop(p->kids[0]->op))
p = newnode(p->op, newnode(p->kids[0]->op, NULL, NULL,
p->kids[0]->syms[0]), NULL, NULL);
else if (generic(p->op) == ADDRG)
p = newnode(p->op, NULL, NULL, p->syms[0]);
else
assert(0);
p->count = 1;
} else if (p) {
p->kids[0] = replace(p->kids[0]);
p->kids[1] = replace(p->kids[1]);
}
return p;
}
static Node prune(Node forest) {
Node p, *tail = &forest;
int count = 0;
for (p = forest; p; p = p->link) {
if (count > 0) {
p->kids[0] = replace(p->kids[0]);
p->kids[1] = replace(p->kids[1]);
}
if (( generic(p->op) == ASGN
&& generic(p->kids[0]->op) == ADDRL
&& p->kids[0]->syms[0]->temporary
&& p->kids[0]->syms[0]->u.t.cse == p->kids[1])) {
Symbol tmp = p->kids[0]->syms[0];
if (!tmp->defined)
(*IR->local)(tmp);
tmp->defined = 1;
if (( generic(p->kids[1]->op) == INDIR
&& isaddrop(p->kids[1]->kids[0]->op)
&& p->kids[1]->kids[0]->syms[0]->sclass == REGISTER)
|| (( generic(p->kids[1]->op) == INDIR
&& isaddrop(p->kids[1]->kids[0]->op)) && tmp->sclass == AUTO)
|| (generic(p->kids[1]->op) == ADDRG && tmp->sclass == AUTO)) {
tmp->u.t.replace = 1;
count++;
continue; /* and omit the assignment */
}
}
/* keep the assignment and other roots */
*tail = p;
tail = &(*tail)->link;
}
assert(*tail == NULL);
return forest;
}
static Node visit(Node p, int listed) {
if (p) {
if (p->syms[2])
p = tmpnode(p);
else if ((p->count <= 1 && !iscall(p->op))
|| (p->count == 0 && iscall(p->op))) {
p->kids[0] = visit(p->kids[0], 0);
p->kids[1] = visit(p->kids[1], 0);
}
else if (specific(p->op) == ADDRL+P || specific(p->op) == ADDRF+P) {
assert(!listed);
p = newnode(p->op, NULL, NULL, p->syms[0]);
p->count = 1;
}
else if (p->op == INDIR+B) {
p = newnode(p->op, p->kids[0], NULL, NULL);
p->count = 1;
p->kids[0] = visit(p->kids[0], 0);
p->kids[1] = visit(p->kids[1], 0);
}
else {
p->kids[0] = visit(p->kids[0], 0);
p->kids[1] = visit(p->kids[1], 0);
p->syms[2] = temporary(REGISTER, btot(p->op, opsize(p->op)));
assert(!p->syms[2]->defined);
p->syms[2]->ref = 1;
p->syms[2]->u.t.cse = p;
*tail = asgnnode(p->syms[2], p);
tail = &(*tail)->link;
if (!listed)
p = tmpnode(p);
};
}
return p;
}
static Node tmpnode(Node p) {
Symbol tmp = p->syms[2];
assert(tmp);
if (--p->count == 0)
p->syms[2] = NULL;
p = newnode(INDIR + ttob(tmp->type),
newnode(ADDRL + ttob(voidptype), NULL, NULL, tmp), NULL, NULL);
p->count = 1;
return p;
}
static Node asgnnode(Symbol tmp, Node p) {
p = newnode(ASGN + ttob(tmp->type),
newnode(ADDRL + ttob(voidptype), NULL, NULL, tmp), p, NULL);
p->syms[0] = intconst(tmp->type->size);
p->syms[1] = intconst(tmp->type->align);
return p;
}
/* printdag - print dag p on fd, or the node list if p == 0 */
void printdag(Node p, int fd) {
FILE *f = fd == 1 ? stdout : stderr;
printed(0);
if (p == 0) {
if ((p = forest) != NULL)
do {
p = p->link;
printdag1(p, fd, 0);
} while (p != forest);
} else if (*printed(nodeid((Tree)p)))
fprint(f, "node'%d printed above\n", nodeid((Tree)p));
else
printdag1(p, fd, 0);
}
/* printdag1 - recursively print dag p */
static void printdag1(Node p, int fd, int lev) {
int id, i;
if (p == 0 || *printed(id = nodeid((Tree)p)))
return;
*printed(id) = 1;
for (i = 0; i < NELEMS(p->kids); i++)
printdag1(p->kids[i], fd, lev + 1);
printnode(p, fd, lev);
}
/* printnode - print fields of dag p */
static void printnode(Node p, int fd, int lev) {
if (p) {
FILE *f = fd == 1 ? stdout : stderr;
int i, id = nodeid((Tree)p);
fprint(f, "%c%d%s", lev == 0 ? '\'' : '#', id,
&" "[id < 10 ? 0 : id < 100 ? 1 : 2]);
fprint(f, "%s count=%d", opname(p->op), p->count);
for (i = 0; i < NELEMS(p->kids) && p->kids[i]; i++)
fprint(f, " #%d", nodeid((Tree)p->kids[i]));
if (generic(p->op) == CALL && p->syms[0] && p->syms[0]->type)
fprint(f, " {%t}", p->syms[0]->type);
else
for (i = 0; i < NELEMS(p->syms) && p->syms[i]; i++)
if (p->syms[i]->name)
fprint(f, " %s", p->syms[i]->name);
else
fprint(f, " %p", p->syms[i]);
fprint(f, "\n");
}
}
/* typestab - emit stab entries for p */
static void typestab(Symbol p, void *cl) {
if (!isfunc(p->type) && (p->sclass == EXTERN || p->sclass == STATIC) && IR->stabsym)
(*IR->stabsym)(p);
else if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype)
(*IR->stabtype)(p);
}

View file

@ -0,0 +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);
}

1162
code/tools/lcc/src/decl.c Normal file

File diff suppressed because it is too large Load diff

545
code/tools/lcc/src/enode.c Normal file
View file

@ -0,0 +1,545 @@
#include "c.h"
static Tree addtree(int, Tree, Tree);
static Tree andtree(int, Tree, Tree);
static Tree cmptree(int, Tree, Tree);
static int compatible(Type, Type);
static int isnullptr(Tree e);
static Tree multree(int, Tree, Tree);
static Tree subtree(int, Tree, Tree);
#define isvoidptr(ty) \
(isptr(ty) && unqual(ty->type) == voidtype)
Tree (*optree[])(int, Tree, Tree) = {
#define xx(a,b,c,d,e,f,g) e,
#define yy(a,b,c,d,e,f,g) e,
#include "token.h"
};
Tree call(Tree f, Type fty, Coordinate src) {
int n = 0;
Tree args = NULL, r = NULL, e;
Type *proto, rty = unqual(freturn(fty));
Symbol t3 = NULL;
if (fty->u.f.oldstyle)
proto = NULL;
else
proto = fty->u.f.proto;
if (hascall(f))
r = f;
if (isstruct(rty))
{
t3 = temporary(AUTO, unqual(rty));
if (rty->size == 0)
error("illegal use of incomplete type `%t'\n", rty);
}
if (t != ')')
for (;;) {
Tree q = pointer(expr1(0));
if (proto && *proto && *proto != voidtype)
{
Type aty;
q = value(q);
aty = assign(*proto, q);
if (aty)
q = cast(q, aty);
else
error("type error in argument %d to %s; found `%t' expected `%t'\n", n + 1, funcname(f),
q->type, *proto);
if ((isint(q->type) || isenum(q->type))
&& q->type->size != inttype->size)
q = cast(q, promote(q->type));
++proto;
}
else
{
if (!fty->u.f.oldstyle && *proto == NULL)
error("too many arguments to %s\n", funcname(f));
q = value(q);
if (isarray(q->type) || q->type->size == 0)
error("type error in argument %d to %s; `%t' is illegal\n", n + 1, funcname(f), q->type);
else
q = cast(q, promote(q->type));
}
if (!IR->wants_argb && isstruct(q->type)) {
if (iscallb(q))
q = addrof(q);
else {
Symbol t1 = temporary(AUTO, unqual(q->type));
q = asgn(t1, q);
q = tree(RIGHT, ptr(t1->type),
root(q), lvalue(idtree(t1)));
}
}
if (q->type->size == 0)
q->type = inttype;
if (hascall(q))
r = r ? tree(RIGHT, voidtype, r, q) : q;
args = tree(mkop(ARG, q->type), q->type, q, args);
n++;
if (Aflag >= 2 && n == 32)
warning("more than 31 arguments in a call to %s\n",
funcname(f));
if (t != ',')
break;
t = gettok();
}
expect(')');
if (proto && *proto && *proto != voidtype)
error("insufficient number of arguments to %s\n",
funcname(f));
if (r)
args = tree(RIGHT, voidtype, r, args);
e = calltree(f, rty, args, t3);
if (events.calls)
apply(events.calls, &src, &e);
return e;
}
Tree calltree(Tree f, Type ty, Tree args, Symbol t3) {
Tree p;
if (args)
f = tree(RIGHT, f->type, args, f);
if (isstruct(ty))
assert(t3),
p = tree(RIGHT, ty,
tree(CALL+B, ty, f, addrof(idtree(t3))),
idtree(t3));
else {
Type rty = ty;
if (isenum(ty))
rty = unqual(ty)->type;
if (!isfloat(rty))
rty = promote(rty);
p = tree(mkop(CALL, rty), rty, f, NULL);
if (isptr(ty) || p->type->size > ty->size)
p = cast(p, ty);
}
return p;
}
Tree vcall(Symbol func, Type ty, ...) {
va_list ap;
Tree args = NULL, e, f = pointer(idtree(func)), r = NULL;
assert(isfunc(func->type));
if (ty == NULL)
ty = freturn(func->type);
va_start(ap, ty);
while ((e = va_arg(ap, Tree)) != NULL) {
if (hascall(e))
r = r == NULL ? e : tree(RIGHT, voidtype, r, e);
args = tree(mkop(ARG, e->type), e->type, e, args);
}
va_end(ap);
if (r != NULL)
args = tree(RIGHT, voidtype, r, args);
return calltree(f, ty, args, NULL);
}
int iscallb(Tree e) {
return e->op == RIGHT && e->kids[0] && e->kids[1]
&& e->kids[0]->op == CALL+B
&& e->kids[1]->op == INDIR+B
&& isaddrop(e->kids[1]->kids[0]->op)
&& e->kids[1]->kids[0]->u.sym->temporary;
}
static Tree addtree(int op, Tree l, Tree r) {
Type ty = inttype;
if (isarith(l->type) && isarith(r->type)) {
ty = binary(l->type, r->type);
l = cast(l, ty);
r = cast(r, ty);
} else if (isptr(l->type) && isint(r->type))
return addtree(ADD, r, l);
else if ( isptr(r->type) && isint(l->type)
&& !isfunc(r->type->type))
{
long n;
ty = unqual(r->type);
n = unqual(ty->type)->size;
if (n == 0)
error("unknown size for type `%t'\n", ty->type);
l = cast(l, promote(l->type));
if (n > 1)
l = multree(MUL, cnsttree(signedptr, n), l);
if (YYcheck && !isaddrop(r->op)) /* omit */
return nullcall(ty, YYcheck, r, l); /* omit */
return simplify(ADD, ty, l, r);
}
else
typeerror(op, l, r);
return simplify(op, ty, l, r);
}
Tree cnsttree(Type ty, ...) {
Tree p = tree(mkop(CNST,ty), ty, NULL, NULL);
va_list ap;
va_start(ap, ty);
switch (ty->op) {
case INT: p->u.v.i = va_arg(ap, long); break;
case UNSIGNED:p->u.v.u = va_arg(ap, unsigned long)&ones(8*ty->size); break;
case FLOAT: p->u.v.d = va_arg(ap, long double); break;
case POINTER: p->u.v.p = va_arg(ap, void *); break;
default: assert(0);
}
va_end(ap);
return p;
}
Tree consttree(unsigned n, Type ty) {
if (isarray(ty))
ty = atop(ty);
else assert(isint(ty));
return cnsttree(ty, (unsigned long)n);
}
static Tree cmptree(int op, Tree l, Tree r) {
Type ty;
if (isarith(l->type) && isarith(r->type)) {
ty = binary(l->type, r->type);
l = cast(l, ty);
r = cast(r, ty);
} else if (compatible(l->type, r->type)) {
ty = unsignedptr;
l = cast(l, ty);
r = cast(r, ty);
} else {
ty = unsignedtype;
typeerror(op, l, r);
}
return simplify(mkop(op,ty), inttype, l, r);
}
static int compatible(Type ty1, Type ty2) {
return isptr(ty1) && !isfunc(ty1->type)
&& isptr(ty2) && !isfunc(ty2->type)
&& eqtype(unqual(ty1->type), unqual(ty2->type), 0);
}
static int isnullptr(Tree e) {
Type ty = unqual(e->type);
return generic(e->op) == CNST
&& ((ty->op == INT && e->u.v.i == 0)
|| (ty->op == UNSIGNED && e->u.v.u == 0)
|| (isvoidptr(ty) && e->u.v.p == NULL));
}
Tree eqtree(int op, Tree l, Tree r) {
Type xty = l->type, yty = r->type;
if ((isptr(xty) && isnullptr(r))
|| (isptr(xty) && !isfunc(xty->type) && isvoidptr(yty))
|| (isptr(xty) && isptr(yty)
&& eqtype(unqual(xty->type), unqual(yty->type), 1))) {
Type ty = unsignedptr;
l = cast(l, ty);
r = cast(r, ty);
return simplify(mkop(op,ty), inttype, l, r);
}
if ((isptr(yty) && isnullptr(l))
|| (isptr(yty) && !isfunc(yty->type) && isvoidptr(xty)))
return eqtree(op, r, l);
return cmptree(op, l, r);
}
Type assign(Type xty, Tree e) {
Type yty = unqual(e->type);
xty = unqual(xty);
if (isenum(xty))
xty = xty->type;
if (xty->size == 0 || yty->size == 0)
return NULL;
if ( (isarith(xty) && isarith(yty))
|| (isstruct(xty) && xty == yty))
return xty;
if (isptr(xty) && isnullptr(e))
return xty;
if (((isvoidptr(xty) && isptr(yty))
|| (isptr(xty) && isvoidptr(yty)))
&& ( (isconst(xty->type) || !isconst(yty->type))
&& (isvolatile(xty->type) || !isvolatile(yty->type))))
return xty;
if ((isptr(xty) && isptr(yty)
&& eqtype(unqual(xty->type), unqual(yty->type), 1))
&& ( (isconst(xty->type) || !isconst(yty->type))
&& (isvolatile(xty->type) || !isvolatile(yty->type))))
return xty;
if (isptr(xty) && isptr(yty)
&& ( (isconst(xty->type) || !isconst(yty->type))
&& (isvolatile(xty->type) || !isvolatile(yty->type)))) {
Type lty = unqual(xty->type), rty = unqual(yty->type);
if ((isenum(lty) && rty == inttype)
|| (isenum(rty) && lty == inttype)) {
if (Aflag >= 1)
warning("assignment between `%t' and `%t' is compiler-dependent\n",
xty, yty);
return xty;
}
}
return NULL;
}
Tree asgntree(int op, Tree l, Tree r) {
Type aty, ty;
r = pointer(r);
ty = assign(l->type, r);
if (ty)
r = cast(r, ty);
else {
typeerror(ASGN, l, r);
if (r->type == voidtype)
r = retype(r, inttype);
ty = r->type;
}
if (l->op != FIELD)
l = lvalue(l);
aty = l->type;
if (isptr(aty))
aty = unqual(aty)->type;
if ( isconst(aty)
|| (isstruct(aty) && unqual(aty)->u.sym->u.s.cfields)) {
if (isaddrop(l->op)
&& !l->u.sym->computed && !l->u.sym->generated)
error("assignment to const identifier `%s'\n",
l->u.sym->name);
else
error("assignment to const location\n");
}
if (l->op == FIELD) {
long n = 8*l->u.field->type->size - fieldsize(l->u.field);
if (n > 0 && isunsigned(l->u.field->type))
r = bittree(BAND, r,
cnsttree(r->type, (unsigned long)fieldmask(l->u.field)));
else if (n > 0) {
if (r->op == CNST+I) {
n = r->u.v.i;
if (n&(1<<(fieldsize(l->u.field)-1)))
n |= ~0UL<<fieldsize(l->u.field);
r = cnsttree(r->type, n);
} else
r = shtree(RSH,
shtree(LSH, r, cnsttree(inttype, n)),
cnsttree(inttype, n));
}
}
if (isstruct(ty) && isaddrop(l->op) && iscallb(r))
return tree(RIGHT, ty,
tree(CALL+B, ty, r->kids[0]->kids[0], l),
idtree(l->u.sym));
return tree(mkop(op,ty), ty, l, r);
}
Tree condtree(Tree e, Tree l, Tree r) {
Symbol t1;
Type ty, xty = l->type, yty = r->type;
Tree p;
if (isarith(xty) && isarith(yty))
ty = binary(xty, yty);
else if (eqtype(xty, yty, 1))
ty = unqual(xty);
else if (isptr(xty) && isnullptr(r))
ty = xty;
else if (isnullptr(l) && isptr(yty))
ty = yty;
else if ((isptr(xty) && !isfunc(xty->type) && isvoidptr(yty))
|| (isptr(yty) && !isfunc(yty->type) && isvoidptr(xty)))
ty = voidptype;
else if ((isptr(xty) && isptr(yty)
&& eqtype(unqual(xty->type), unqual(yty->type), 1)))
ty = xty;
else {
typeerror(COND, l, r);
return consttree(0, inttype);
}
if (isptr(ty)) {
ty = unqual(unqual(ty)->type);
if ((isptr(xty) && isconst(unqual(xty)->type))
|| (isptr(yty) && isconst(unqual(yty)->type)))
ty = qual(CONST, ty);
if ((isptr(xty) && isvolatile(unqual(xty)->type))
|| (isptr(yty) && isvolatile(unqual(yty)->type)))
ty = qual(VOLATILE, ty);
ty = ptr(ty);
}
switch (e->op) {
case CNST+I: return cast(e->u.v.i != 0 ? l : r, ty);
case CNST+U: return cast(e->u.v.u != 0 ? l : r, ty);
case CNST+P: return cast(e->u.v.p != 0 ? l : r, ty);
case CNST+F: return cast(e->u.v.d != 0.0 ? l : r, ty);
}
if (ty != voidtype && ty->size > 0) {
t1 = genident(REGISTER, unqual(ty), level);
/* t1 = temporary(REGISTER, unqual(ty)); */
l = asgn(t1, l);
r = asgn(t1, r);
} else
t1 = NULL;
p = tree(COND, ty, cond(e),
tree(RIGHT, ty, root(l), root(r)));
p->u.sym = t1;
return p;
}
/* addrof - address of p */
Tree addrof(Tree p) {
Tree q = p;
for (;;)
switch (generic(q->op)) {
case RIGHT:
assert(q->kids[0] || q->kids[1]);
q = q->kids[1] ? q->kids[1] : q->kids[0];
continue;
case ASGN:
q = q->kids[1];
continue;
case COND: {
Symbol t1 = q->u.sym;
q->u.sym = 0;
q = idtree(t1);
/* fall thru */
}
case INDIR:
if (p == q)
return q->kids[0];
q = q->kids[0];
return tree(RIGHT, q->type, root(p), q);
default:
error("addressable object required\n");
return value(p);
}
}
/* andtree - construct tree for l [&& ||] r */
static Tree andtree(int op, Tree l, Tree r) {
if (!isscalar(l->type) || !isscalar(r->type))
typeerror(op, l, r);
return simplify(op, inttype, cond(l), cond(r));
}
/* asgn - generate tree for assignment of expr e to symbol p sans qualifiers */
Tree asgn(Symbol p, Tree e) {
if (isarray(p->type))
e = tree(ASGN+B, p->type, idtree(p),
tree(INDIR+B, e->type, e, NULL));
else {
Type ty = p->type;
p->type = unqual(p->type);
if (isstruct(p->type) && p->type->u.sym->u.s.cfields) {
p->type->u.sym->u.s.cfields = 0;
e = asgntree(ASGN, idtree(p), e);
p->type->u.sym->u.s.cfields = 1;
} else
e = asgntree(ASGN, idtree(p), e);
p->type = ty;
}
return e;
}
/* bittree - construct tree for l [& | ^ %] r */
Tree bittree(int op, Tree l, Tree r) {
Type ty = inttype;
if (isint(l->type) && isint(r->type)) {
ty = binary(l->type, r->type);
l = cast(l, ty);
r = cast(r, ty);
} else
typeerror(op, l, r);
return simplify(op, ty, l, r);
}
/* multree - construct tree for l [* /] r */
static Tree multree(int op, Tree l, Tree r) {
Type ty = inttype;
if (isarith(l->type) && isarith(r->type)) {
ty = binary(l->type, r->type);
l = cast(l, ty);
r = cast(r, ty);
} else
typeerror(op, l, r);
return simplify(op, ty, l, r);
}
/* shtree - construct tree for l [>> <<] r */
Tree shtree(int op, Tree l, Tree r) {
Type ty = inttype;
if (isint(l->type) && isint(r->type)) {
ty = promote(l->type);
l = cast(l, ty);
r = cast(r, inttype);
} else
typeerror(op, l, r);
return simplify(op, ty, l, r);
}
/* subtree - construct tree for l - r */
static Tree subtree(int op, Tree l, Tree r) {
long n;
Type ty = inttype;
if (isarith(l->type) && isarith(r->type)) {
ty = binary(l->type, r->type);
l = cast(l, ty);
r = cast(r, ty);
} else if (isptr(l->type) && !isfunc(l->type->type) && isint(r->type)) {
ty = unqual(l->type);
n = unqual(ty->type)->size;
if (n == 0)
error("unknown size for type `%t'\n", ty->type);
r = cast(r, promote(r->type));
if (n > 1)
r = multree(MUL, cnsttree(signedptr, n), r);
if (isunsigned(r->type))
r = cast(r, unsignedptr);
else
r = cast(r, signedptr);
return simplify(SUB+P, ty, l, r);
} else if (compatible(l->type, r->type)) {
ty = unqual(l->type);
n = unqual(ty->type)->size;
if (n == 0)
error("unknown size for type `%t'\n", ty->type);
l = simplify(SUB+U, unsignedptr,
cast(l, unsignedptr), cast(r, unsignedptr));
return simplify(DIV+I, longtype,
cast(l, longtype), cnsttree(longtype, n));
} else
typeerror(op, l, r);
return simplify(op, ty, l, r);
}
/* typeerror - issue "operands of op have illegal types `l' and `r'" */
void typeerror(int op, Tree l, Tree r) {
int i;
static struct { int op; char *name; } ops[] = {
{ASGN, "="}, {INDIR, "*"}, {NEG, "-"},
{ADD, "+"}, {SUB, "-"}, {LSH, "<<"},
{MOD, "%"}, {RSH, ">>"}, {BAND, "&"},
{BCOM, "~"}, {BOR, "|"}, {BXOR, "^"},
{DIV, "/"}, {MUL, "*"}, {EQ, "=="},
{GE, ">="}, {GT, ">"}, {LE, "<="},
{LT, "<"}, {NE, "!="}, {AND, "&&"},
{NOT, "!"}, {OR, "||"}, {COND, "?:"},
{0, 0}
};
op = generic(op);
for (i = 0; ops[i].op; i++)
if (op == ops[i].op)
break;
assert(ops[i].name);
if (r)
error("operands of %s have illegal types `%t' and `%t'\n",
ops[i].name, l->type, r->type);
else
error("operand of unary %s has illegal type `%t'\n", ops[i].name,
l->type);
}

137
code/tools/lcc/src/error.c Normal file
View file

@ -0,0 +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);
}

View file

@ -0,0 +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);
}
}

711
code/tools/lcc/src/expr.c Normal file
View file

@ -0,0 +1,711 @@
#include "c.h"
static char prec[] = {
#define xx(a,b,c,d,e,f,g) c,
#define yy(a,b,c,d,e,f,g) c,
#include "token.h"
};
static int oper[] = {
#define xx(a,b,c,d,e,f,g) d,
#define yy(a,b,c,d,e,f,g) d,
#include "token.h"
};
float refinc = 1.0;
static Tree expr2(void);
static Tree expr3(int);
static Tree nullcheck(Tree);
static Tree postfix(Tree);
static Tree unary(void);
static Tree primary(void);
static Type super(Type ty);
static Type super(Type ty) {
switch (ty->op) {
case INT:
if (ty->size < inttype->size)
return inttype;
break;
case UNSIGNED:
if (ty->size < unsignedtype->size)
return unsignedtype;
break;
case POINTER:
return unsignedptr;
}
return ty;
}
Tree expr(int tok) {
static char stop[] = { IF, ID, '}', 0 };
Tree p = expr1(0);
while (t == ',') {
Tree q;
t = gettok();
q = pointer(expr1(0));
p = tree(RIGHT, q->type, root(value(p)), q);
}
if (tok)
test(tok, stop);
return p;
}
Tree expr0(int tok) {
return root(expr(tok));
}
Tree expr1(int tok) {
static char stop[] = { IF, ID, 0 };
Tree p = expr2();
if (t == '='
|| (prec[t] >= 6 && prec[t] <= 8)
|| (prec[t] >= 11 && prec[t] <= 13)) {
int op = t;
t = gettok();
if (oper[op] == ASGN)
p = asgntree(ASGN, p, value(expr1(0)));
else
{
expect('=');
p = incr(op, p, expr1(0));
}
}
if (tok)
test(tok, stop);
return p;
}
Tree incr(int op, Tree v, Tree e) {
return asgntree(ASGN, v, (*optree[op])(oper[op], v, e));
}
static Tree expr2(void) {
Tree p = expr3(4);
if (t == '?') {
Tree l, r;
Coordinate pts[2];
if (Aflag > 1 && isfunc(p->type))
warning("%s used in a conditional expression\n",
funcname(p));
p = pointer(p);
t = gettok();
pts[0] = src;
l = pointer(expr(':'));
pts[1] = src;
r = pointer(expr2());
if (events.points)
{
apply(events.points, &pts[0], &l);
apply(events.points, &pts[1], &r);
}
p = condtree(p, l, r);
}
return p;
}
Tree value(Tree p) {
int op = generic(rightkid(p)->op);
if (p->type != voidtype
&& (op==AND || op==OR || op==NOT || op==EQ || op==NE
|| op== LE || op==LT || op== GE || op==GT))
p = condtree(p, consttree(1, inttype),
consttree(0, inttype));
return p;
}
static Tree expr3(int k) {
int k1;
Tree p = unary();
for (k1 = prec[t]; k1 >= k; k1--)
while (prec[t] == k1 && *cp != '=') {
Tree r;
Coordinate pt;
int op = t;
t = gettok();
pt = src;
p = pointer(p);
if (op == ANDAND || op == OROR) {
r = pointer(expr3(k1));
if (events.points)
apply(events.points, &pt, &r);
} else
r = pointer(expr3(k1 + 1));
p = (*optree[op])(oper[op], p, r);
}
return p;
}
static Tree unary(void) {
Tree p;
switch (t) {
case '*': t = gettok(); p = unary(); p = pointer(p);
if (isptr(p->type)
&& (isfunc(p->type->type) || isarray(p->type->type)))
p = retype(p, p->type->type);
else {
if (YYnull)
p = nullcheck(p);
p = rvalue(p);
} break;
case '&': t = gettok(); p = unary(); if (isarray(p->type) || isfunc(p->type))
p = retype(p, ptr(p->type));
else
p = lvalue(p);
if (isaddrop(p->op) && p->u.sym->sclass == REGISTER)
error("invalid operand of unary &; `%s' is declared register\n", p->u.sym->name);
else if (isaddrop(p->op))
p->u.sym->addressed = 1;
break;
case '+': t = gettok(); p = unary(); p = pointer(p);
if (isarith(p->type))
p = cast(p, promote(p->type));
else
typeerror(ADD, p, NULL); break;
case '-': t = gettok(); p = unary(); p = pointer(p);
if (isarith(p->type)) {
Type ty = promote(p->type);
p = cast(p, ty);
if (isunsigned(ty)) {
warning("unsigned operand of unary -\n");
p = simplify(ADD, ty, simplify(BCOM, ty, p, NULL), cnsttree(ty, 1UL));
} else
p = simplify(NEG, ty, p, NULL);
} else
typeerror(SUB, p, NULL); break;
case '~': t = gettok(); p = unary(); p = pointer(p);
if (isint(p->type)) {
Type ty = promote(p->type);
p = simplify(BCOM, ty, cast(p, ty), NULL);
} else
typeerror(BCOM, p, NULL); break;
case '!': t = gettok(); p = unary(); p = pointer(p);
if (isscalar(p->type))
p = simplify(NOT, inttype, cond(p), NULL);
else
typeerror(NOT, p, NULL); break;
case INCR: t = gettok(); p = unary(); p = incr(INCR, pointer(p), consttree(1, inttype)); break;
case DECR: t = gettok(); p = unary(); p = incr(DECR, pointer(p), consttree(1, inttype)); break;
case TYPECODE: case SIZEOF: { int op = t;
Type ty;
p = NULL;
t = gettok();
if (t == '(') {
t = gettok();
if (istypename(t, tsym)) {
ty = typename();
expect(')');
} else {
p = postfix(expr(')'));
ty = p->type;
}
} else {
p = unary();
ty = p->type;
}
assert(ty);
if (op == TYPECODE)
p = cnsttree(inttype, (long)ty->op);
else {
if (isfunc(ty) || ty->size == 0)
error("invalid type argument `%t' to `sizeof'\n", ty);
else if (p && rightkid(p)->op == FIELD)
error("`sizeof' applied to a bit field\n");
p = cnsttree(unsignedlong, (unsigned long)ty->size);
} } break;
case '(':
t = gettok();
if (istypename(t, tsym)) {
Type ty, ty1 = typename(), pty;
expect(')');
ty = unqual(ty1);
if (isenum(ty)) {
Type ty2 = ty->type;
if (isconst(ty1))
ty2 = qual(CONST, ty2);
if (isvolatile(ty1))
ty2 = qual(VOLATILE, ty2);
ty1 = ty2;
ty = ty->type;
}
p = pointer(unary());
pty = p->type;
if (isenum(pty))
pty = pty->type;
if ((isarith(pty) && isarith(ty))
|| (isptr(pty) && isptr(ty))) {
explicitCast++;
p = cast(p, ty);
explicitCast--;
} else if ((isptr(pty) && isint(ty))
|| (isint(pty) && isptr(ty))) {
if (Aflag >= 1 && ty->size < pty->size)
warning("conversion from `%t' to `%t' is compiler dependent\n", p->type, ty);
p = cast(p, ty);
} else if (ty != voidtype) {
error("cast from `%t' to `%t' is illegal\n",
p->type, ty1);
ty1 = inttype;
}
if (generic(p->op) == INDIR || ty->size == 0)
p = tree(RIGHT, ty1, NULL, p);
else
p = retype(p, ty1);
} else
p = postfix(expr(')'));
break;
default:
p = postfix(primary());
}
return p;
}
static Tree postfix(Tree p) {
for (;;)
switch (t) {
case INCR: p = tree(RIGHT, p->type,
tree(RIGHT, p->type,
p,
incr(t, p, consttree(1, inttype))),
p);
t = gettok(); break;
case DECR: p = tree(RIGHT, p->type,
tree(RIGHT, p->type,
p,
incr(t, p, consttree(1, inttype))),
p);
t = gettok(); break;
case '[': {
Tree q;
t = gettok();
q = expr(']');
if (YYnull) {
if (isptr(p->type))
p = nullcheck(p);
else if (isptr(q->type))
q = nullcheck(q);
}
p = (*optree['+'])(ADD, pointer(p), pointer(q));
if (isptr(p->type) && isarray(p->type->type))
p = retype(p, p->type->type);
else
p = rvalue(p);
} break;
case '(': {
Type ty;
Coordinate pt;
p = pointer(p);
if (isptr(p->type) && isfunc(p->type->type))
ty = p->type->type;
else {
error("found `%t' expected a function\n", p->type);
ty = func(voidtype, NULL, 1);
p = retype(p, ptr(ty));
}
pt = src;
t = gettok();
p = call(p, ty, pt);
} break;
case '.': t = gettok();
if (t == ID) {
if (isstruct(p->type)) {
Tree q = addrof(p);
p = field(q, token);
q = rightkid(q);
if (isaddrop(q->op) && q->u.sym->temporary)
p = tree(RIGHT, p->type, p, NULL);
} else
error("left operand of . has incompatible type `%t'\n",
p->type);
t = gettok();
} else
error("field name expected\n"); break;
case DEREF: t = gettok();
p = pointer(p);
if (t == ID) {
if (isptr(p->type) && isstruct(p->type->type)) {
if (YYnull)
p = nullcheck(p);
p = field(p, token);
} else
error("left operand of -> has incompatible type `%t'\n", p->type);
t = gettok();
} else
error("field name expected\n"); break;
default:
return p;
}
}
static Tree primary(void) {
Tree p;
assert(t != '(');
switch (t) {
case ICON:
case FCON: p = tree(mkop(CNST,tsym->type), tsym->type, NULL, NULL);
p->u.v = tsym->u.c.v;
break;
case SCON: if (ischar(tsym->type->type))
tsym->u.c.v.p = stringn(tsym->u.c.v.p, tsym->type->size);
else
tsym->u.c.v.p = memcpy(allocate(tsym->type->size, PERM), tsym->u.c.v.p, tsym->type->size);
tsym = constant(tsym->type, tsym->u.c.v);
if (tsym->u.c.loc == NULL)
tsym->u.c.loc = genident(STATIC, tsym->type, GLOBAL);
p = idtree(tsym->u.c.loc); break;
case ID: if (tsym == NULL)
{
Symbol p = install(token, &identifiers, level, FUNC);
p->src = src;
if (getchr() == '(') {
Symbol q = lookup(token, externals);
p->type = func(inttype, NULL, 1);
p->sclass = EXTERN;
if (Aflag >= 1)
warning("missing prototype\n");
if (q && !eqtype(q->type, p->type, 1))
warning("implicit declaration of `%s' does not match previous declaration at %w\n", q->name, &q->src);
if (q == NULL) {
q = install(p->name, &externals, GLOBAL, PERM);
q->type = p->type;
q->sclass = EXTERN;
q->src = src;
(*IR->defsymbol)(q);
}
p->u.alias = q;
} else {
error("undeclared identifier `%s'\n", p->name);
p->sclass = AUTO;
p->type = inttype;
if (p->scope == GLOBAL)
(*IR->defsymbol)(p);
else
addlocal(p);
}
t = gettok();
if (xref)
use(p, src);
return idtree(p);
}
if (xref)
use(tsym, src);
if (tsym->sclass == ENUM)
p = consttree(tsym->u.value, inttype);
else {
if (tsym->sclass == TYPEDEF)
error("illegal use of type name `%s'\n", tsym->name);
p = idtree(tsym);
} break;
case FIRSTARG:
if (level > PARAM && cfunc && cfunc->u.f.callee[0])
p = idtree(cfunc->u.f.callee[0]);
else {
error("illegal use of `%k'\n", FIRSTARG);
p = cnsttree(inttype, 0L);
}
break;
default:
error("illegal expression\n");
p = cnsttree(inttype, 0L);
}
t = gettok();
return p;
}
Tree idtree(Symbol p) {
int op;
Tree e;
Type ty = p->type ? unqual(p->type) : voidptype;
if (p->scope == GLOBAL || p->sclass == STATIC)
op = ADDRG;
else if (p->scope == PARAM) {
op = ADDRF;
if (isstruct(p->type) && !IR->wants_argb)
{
e = tree(mkop(op,voidptype), ptr(ptr(p->type)), NULL, NULL);
e->u.sym = p;
return rvalue(rvalue(e));
}
} else if (p->sclass == EXTERN) {
assert(p->u.alias);
p = p->u.alias;
op = ADDRG;
} else
op = ADDRL;
p->ref += refinc;
if (isarray(ty))
e = tree(mkop(op,voidptype), p->type, NULL, NULL);
else if (isfunc(ty))
e = tree(mkop(op,funcptype), p->type, NULL, NULL);
else
e = tree(mkop(op,voidptype), ptr(p->type), NULL, NULL);
e->u.sym = p;
if (isptr(e->type))
e = rvalue(e);
return e;
}
Tree rvalue(Tree p) {
Type ty = deref(p->type);
ty = unqual(ty);
return tree(mkop(INDIR,ty), ty, p, NULL);
}
Tree lvalue(Tree p) {
if (generic(p->op) != INDIR) {
error("lvalue required\n");
return value(p);
} else if (unqual(p->type) == voidtype)
warning("`%t' used as an lvalue\n", p->type);
return p->kids[0];
}
Tree retype(Tree p, Type ty) {
Tree q;
if (p->type == ty)
return p;
q = tree(p->op, ty, p->kids[0], p->kids[1]);
q->node = p->node;
q->u = p->u;
return q;
}
Tree rightkid(Tree p) {
while (p && p->op == RIGHT)
if (p->kids[1])
p = p->kids[1];
else if (p->kids[0])
p = p->kids[0];
else
assert(0);
assert(p);
return p;
}
int hascall(Tree p) {
if (p == 0)
return 0;
if (generic(p->op) == CALL || (IR->mulops_calls &&
(p->op == DIV+I || p->op == MOD+I || p->op == MUL+I
|| p->op == DIV+U || p->op == MOD+U || p->op == MUL+U)))
return 1;
return hascall(p->kids[0]) || hascall(p->kids[1]);
}
Type binary(Type xty, Type yty) {
#define xx(t) if (xty == t || yty == t) return t
xx(longdouble);
xx(doubletype);
xx(floattype);
xx(unsignedlonglong);
xx(longlong);
xx(unsignedlong);
if ((xty == longtype && yty == unsignedtype)
|| (xty == unsignedtype && yty == longtype)) {
if (longtype->size > unsignedtype->size)
return longtype;
else
return unsignedlong;
}
xx(longtype);
xx(unsignedtype);
return inttype;
#undef xx
}
Tree pointer(Tree p) {
if (isarray(p->type))
/* assert(p->op != RIGHT || p->u.sym == NULL), */
p = retype(p, atop(p->type));
else if (isfunc(p->type))
p = retype(p, ptr(p->type));
return p;
}
Tree cond(Tree p) {
int op = generic(rightkid(p)->op);
if (op == AND || op == OR || op == NOT
|| op == EQ || op == NE
|| op == LE || op == LT || op == GE || op == GT)
return p;
p = pointer(p);
return (*optree[NEQ])(NE, p, consttree(0, inttype));
}
Tree cast(Tree p, Type type) {
Type src, dst;
p = value(p);
if (p->type == type)
return p;
dst = unqual(type);
src = unqual(p->type);
if (src->op != dst->op || src->size != dst->size) {
switch (src->op) {
case INT:
if (src->size < inttype->size)
p = simplify(CVI, inttype, p, NULL);
break;
case UNSIGNED:
if (src->size < inttype->size)
p = simplify(CVU, inttype, p, NULL);
else if (src->size < unsignedtype->size)
p = simplify(CVU, unsignedtype, p, NULL);
break;
case ENUM:
p = retype(p, inttype);
break;
case POINTER:
if (isint(dst) && src->size > dst->size)
warning("conversion from `%t' to `%t' is undefined\n", p->type, type);
p = simplify(CVP, super(src), p, NULL);
break;
case FLOAT:
break;
default: assert(0);
}
{
src = unqual(p->type);
dst = super(dst);
if (src->op != dst->op)
switch (src->op) {
case INT:
p = simplify(CVI, dst, p, NULL);
break;
case UNSIGNED:
if (isfloat(dst)) {
Type ssrc = signedint(src);
Tree two = cnsttree(longdouble, (long double)2.0);
p = (*optree['+'])(ADD,
(*optree['*'])(MUL,
two,
simplify(CVU, ssrc,
simplify(RSH, src,
p, consttree(1, inttype)), NULL)),
simplify(CVU, ssrc,
simplify(BAND, src,
p, consttree(1, unsignedtype)), NULL));
} else
p = simplify(CVU, dst, p, NULL);
break;
case FLOAT:
if (isunsigned(dst)) {
Type sdst = signedint(dst);
Tree c = cast(cnsttree(longdouble, (long double)sdst->u.sym->u.limits.max.i + 1), src);
p = condtree(
simplify(GE, src, p, c),
(*optree['+'])(ADD,
cast(cast(simplify(SUB, src, p, c), sdst), dst),
cast(cnsttree(unsignedlong, (unsigned long)sdst->u.sym->u.limits.max.i + 1), dst)),
simplify(CVF, sdst, p, NULL));
} else
p = simplify(CVF, dst, p, NULL);
break;
default: assert(0);
}
dst = unqual(type);
}
}
src = unqual(p->type);
switch (src->op) {
case INT:
if (src->op != dst->op || src->size != dst->size)
p = simplify(CVI, dst, p, NULL);
break;
case UNSIGNED:
if (src->op != dst->op || src->size != dst->size)
p = simplify(CVU, dst, p, NULL);
break;
case FLOAT:
if (src->op != dst->op || src->size != dst->size)
p = simplify(CVF, dst, p, NULL);
break;
case POINTER:
if (src->op != dst->op)
p = simplify(CVP, dst, p, NULL);
else {
if ((isfunc(src->type) && !isfunc(dst->type))
|| (!isfunc(src->type) && isfunc(dst->type)))
warning("conversion from `%t' to `%t' is compiler dependent\n", p->type, type);
if (src->size != dst->size)
p = simplify(CVP, dst, p, NULL);
}
break;
default: assert(0);
}
return retype(p, type);
}
Tree field(Tree p, const char *name) {
Field q;
Type ty1, ty = p->type;
if (isptr(ty))
ty = deref(ty);
ty1 = ty;
ty = unqual(ty);
if ((q = fieldref(name, ty)) != NULL) {
if (isarray(q->type)) {
ty = q->type->type;
if (isconst(ty1) && !isconst(ty))
ty = qual(CONST, ty);
if (isvolatile(ty1) && !isvolatile(ty))
ty = qual(VOLATILE, ty);
ty = array(ty, q->type->size/ty->size, q->type->align);
} else {
ty = q->type;
if (isconst(ty1) && !isconst(ty))
ty = qual(CONST, ty);
if (isvolatile(ty1) && !isvolatile(ty))
ty = qual(VOLATILE, ty);
ty = ptr(ty);
}
if (YYcheck && !isaddrop(p->op) && q->offset > 0) /* omit */
p = nullcall(ty, YYcheck, p, consttree(q->offset, inttype)); /* omit */
else /* omit */
p = simplify(ADD+P, ty, p, consttree(q->offset, inttype));
if (q->lsb) {
p = tree(FIELD, ty->type, rvalue(p), NULL);
p->u.field = q;
} else if (!isarray(q->type))
p = rvalue(p);
} else {
error("unknown field `%s' of `%t'\n", name, ty);
p = rvalue(retype(p, ptr(inttype)));
}
return p;
}
/* funcname - return name of function f or a function' */
char *funcname(Tree f) {
if (isaddrop(f->op))
return stringf("`%s'", f->u.sym->name);
return "a function";
}
static Tree nullcheck(Tree p) {
if (!needconst && YYnull && isptr(p->type)) {
p = value(p);
if (strcmp(YYnull->name, "_YYnull") == 0) {
Symbol t1 = temporary(REGISTER, voidptype);
p = tree(RIGHT, p->type,
tree(OR, voidtype,
cond(asgn(t1, cast(p, voidptype))),
vcall(YYnull, voidtype, (file && *file ? pointer(idtree(mkstr(file)->u.c.loc)) : cnsttree(voidptype, NULL)), cnsttree(inttype, (long)lineno) , NULL)),
idtree(t1));
}
else
p = nullcall(p->type, YYnull, p, cnsttree(inttype, 0L));
}
return p;
}
Tree nullcall(Type pty, Symbol f, Tree p, Tree e) {
Type ty;
if (isarray(pty))
return retype(nullcall(atop(pty), f, p, e), pty);
ty = unqual(unqual(p->type)->type);
return vcall(f, pty,
p, e,
cnsttree(inttype, (long)ty->size),
cnsttree(inttype, (long)ty->align),
(file && *file ? pointer(idtree(mkstr(file)->u.c.loc)) : cnsttree(voidptype, NULL)), cnsttree(inttype, (long)lineno) , NULL);
}

830
code/tools/lcc/src/gen.c Normal file
View file

@ -0,0 +1,830 @@
#include "c.h"
#define readsreg(p) \
(generic((p)->op)==INDIR && (p)->kids[0]->op==VREG+P)
#define setsrc(d) ((d) && (d)->x.regnode && \
(d)->x.regnode->set == src->x.regnode->set && \
(d)->x.regnode->mask&src->x.regnode->mask)
#define relink(a, b) ((b)->x.prev = (a), (a)->x.next = (b))
static Symbol askfixedreg(Symbol);
static Symbol askreg(Symbol, unsigned*);
static void blkunroll(int, int, int, int, int, int, int[]);
static void docall(Node);
static void dumpcover(Node, int, int);
static void dumpregs(char *, char *, char *);
static void dumprule(int);
static void dumptree(Node);
static unsigned emitasm(Node, int);
static void genreload(Node, Symbol, int);
static void genspill(Symbol, Node, Symbol);
static Symbol getreg(Symbol, unsigned*, Node);
static int getrule(Node, int);
static void linearize(Node, Node);
static int moveself(Node);
static void prelabel(Node);
static Node* prune(Node, Node*);
static void putreg(Symbol);
static void ralloc(Node);
static void reduce(Node, int);
static int reprune(Node*, int, int, Node);
static int requate(Node);
static Node reuse(Node, int);
static void rewrite(Node);
static Symbol spillee(Symbol, unsigned mask[], Node);
static void spillr(Symbol, Node);
static int uses(Node, Regnode);
int offset;
int maxoffset;
int framesize;
int argoffset;
int maxargoffset;
int dalign, salign;
int bflag = 0; /* omit */
int dflag = 0;
int swap;
unsigned (*emitter)(Node, int) = emitasm;
static char NeedsReg[] = {
0, /* unused */
1, /* CNST */
0, 0, /* ARG ASGN */
1, /* INDIR */
0, 0, 1, 1, /* - - CVF CVI */
1, 0, 1, 1, /* CVP - CVU NEG */
1, /* CALL */
1, /* LOAD */
0, /* RET */
1, 1, 1, /* ADDRG ADDRF ADDRL */
1, 1, 1, 1, 1, /* ADD SUB LSH MOD RSH */
1, 1, 1, 1, /* BAND BCOM BOR BXOR */
1, 1, /* DIV MUL */
0, 0, 0, 0, 0, 0, /* EQ GE GT LE LT NE */
0, 0 /* JUMP LABEL */
};
Node head;
unsigned freemask[2];
unsigned usedmask[2];
unsigned tmask[2];
unsigned vmask[2];
Symbol mkreg(char *fmt, int n, int mask, int set) {
Symbol p;
NEW0(p, PERM);
p->name = p->x.name = stringf(fmt, n);
NEW0(p->x.regnode, PERM);
p->x.regnode->number = n;
p->x.regnode->mask = mask<<n;
p->x.regnode->set = set;
return p;
}
Symbol mkwildcard(Symbol *syms) {
Symbol p;
NEW0(p, PERM);
p->name = p->x.name = "wildcard";
p->x.wildcard = syms;
return p;
}
void mkauto(Symbol p) {
assert(p->sclass == AUTO);
offset = roundup(offset + p->type->size, p->type->align);
p->x.offset = -offset;
p->x.name = stringd(-offset);
}
void blockbeg(Env *e) {
e->offset = offset;
e->freemask[IREG] = freemask[IREG];
e->freemask[FREG] = freemask[FREG];
}
void blockend(Env *e) {
if (offset > maxoffset)
maxoffset = offset;
offset = e->offset;
freemask[IREG] = e->freemask[IREG];
freemask[FREG] = e->freemask[FREG];
}
int mkactual(int align, int size) {
int n = roundup(argoffset, align);
argoffset = n + size;
return n;
}
static void docall(Node p) {
p->syms[1] = p->syms[0];
p->syms[0] = intconst(argoffset);
if (argoffset > maxargoffset)
maxargoffset = argoffset;
argoffset = 0;
}
void blkcopy(int dreg, int doff, int sreg, int soff, int size, int tmp[]) {
assert(size >= 0);
if (size == 0)
return;
else if (size <= 2)
blkunroll(size, dreg, doff, sreg, soff, size, tmp);
else if (size == 3) {
blkunroll(2, dreg, doff, sreg, soff, 2, tmp);
blkunroll(1, dreg, doff+2, sreg, soff+2, 1, tmp);
}
else if (size <= 16) {
blkunroll(4, dreg, doff, sreg, soff, size&~3, tmp);
blkcopy(dreg, doff+(size&~3),
sreg, soff+(size&~3), size&3, tmp);
}
else
(*IR->x.blkloop)(dreg, doff, sreg, soff, size, tmp);
}
static void blkunroll(int k, int dreg, int doff, int sreg, int soff, int size, int tmp[]) {
int i;
assert(IR->x.max_unaligned_load);
if (k > IR->x.max_unaligned_load
&& (k > salign || k > dalign))
k = IR->x.max_unaligned_load;
for (i = 0; i+k < size; i += 2*k) {
(*IR->x.blkfetch)(k, soff+i, sreg, tmp[0]);
(*IR->x.blkfetch)(k, soff+i+k, sreg, tmp[1]);
(*IR->x.blkstore)(k, doff+i, dreg, tmp[0]);
(*IR->x.blkstore)(k, doff+i+k, dreg, tmp[1]);
}
if (i < size) {
(*IR->x.blkfetch)(k, i+soff, sreg, tmp[0]);
(*IR->x.blkstore)(k, i+doff, dreg, tmp[0]);
}
}
void parseflags(int argc, char *argv[]) {
int i;
for (i = 0; i < argc; i++)
if (strcmp(argv[i], "-d") == 0)
dflag = 1;
else if (strcmp(argv[i], "-b") == 0) /* omit */
bflag = 1; /* omit */
}
static int getrule(Node p, int nt) {
int rulenum;
assert(p);
rulenum = (*IR->x._rule)(p->x.state, nt);
if (!rulenum) {
fprint(stderr, "(%x->op=%s at %w is corrupt.)\n", p, opname(p->op), &src);
assert(0);
}
return rulenum;
}
static void reduce(Node p, int nt) {
int rulenum, i;
short *nts;
Node kids[10];
p = reuse(p, nt);
rulenum = getrule(p, nt);
nts = IR->x._nts[rulenum];
(*IR->x._kids)(p, rulenum, kids);
for (i = 0; nts[i]; i++)
reduce(kids[i], nts[i]);
if (IR->x._isinstruction[rulenum]) {
assert(p->x.inst == 0 || p->x.inst == nt);
p->x.inst = nt;
if (p->syms[RX] && p->syms[RX]->temporary) {
debug(fprint(stderr, "(using %s)\n", p->syms[RX]->name));
p->syms[RX]->x.usecount++;
}
}
}
static Node reuse(Node p, int nt) {
struct _state {
short cost[1];
};
Symbol r = p->syms[RX];
if (generic(p->op) == INDIR && p->kids[0]->op == VREG+P
&& r->u.t.cse && p->x.mayrecalc
&& ((struct _state*)r->u.t.cse->x.state)->cost[nt] == 0)
return r->u.t.cse;
else
return p;
}
int mayrecalc(Node p) {
int op;
assert(p && p->syms[RX]);
if (p->syms[RX]->u.t.cse == NULL)
return 0;
op = generic(p->syms[RX]->u.t.cse->op);
if (op == CNST || op == ADDRF || op == ADDRG || op == ADDRL) {
p->x.mayrecalc = 1;
return 1;
} else
return 0;
}
static Node *prune(Node p, Node pp[]) {
if (p == NULL)
return pp;
p->x.kids[0] = p->x.kids[1] = p->x.kids[2] = NULL;
if (p->x.inst == 0)
return prune(p->kids[1], prune(p->kids[0], pp));
else if (p->syms[RX] && p->syms[RX]->temporary
&& p->syms[RX]->x.usecount < 2) {
p->x.inst = 0;
debug(fprint(stderr, "(clobbering %s)\n", p->syms[RX]->name));
return prune(p->kids[1], prune(p->kids[0], pp));
}
else {
prune(p->kids[1], prune(p->kids[0], &p->x.kids[0]));
*pp = p;
return pp + 1;
}
}
#define ck(i) return (i) ? 0 : LBURG_MAX
int range(Node p, int lo, int hi) {
Symbol s = p->syms[0];
switch (specific(p->op)) {
case ADDRF+P:
case ADDRL+P: ck(s->x.offset >= lo && s->x.offset <= hi);
case CNST+I: ck(s->u.c.v.i >= lo && s->u.c.v.i <= hi);
case CNST+U: ck(s->u.c.v.u >= lo && s->u.c.v.u <= hi);
case CNST+P: ck(s->u.c.v.p == 0 && lo <= 0 && hi >= 0);
}
return LBURG_MAX;
}
static void dumptree(Node p) {
if (p->op == VREG+P && p->syms[0]) {
fprint(stderr, "VREGP(%s)", p->syms[0]->name);
return;
} else if (generic(p->op) == LOAD) {
fprint(stderr, "LOAD(");
dumptree(p->kids[0]);
fprint(stderr, ")");
return;
}
fprint(stderr, "%s(", opname(p->op));
switch (generic(p->op)) {
case CNST: case LABEL:
case ADDRG: case ADDRF: case ADDRL:
if (p->syms[0])
fprint(stderr, "%s", p->syms[0]->name);
break;
case RET:
if (p->kids[0])
dumptree(p->kids[0]);
break;
case CVF: case CVI: case CVP: case CVU: case JUMP:
case ARG: case BCOM: case NEG: case INDIR:
dumptree(p->kids[0]);
break;
case CALL:
if (optype(p->op) != B) {
dumptree(p->kids[0]);
break;
}
/* else fall thru */
case EQ: case NE: case GT: case GE: case LE: case LT:
case ASGN: case BOR: case BAND: case BXOR: case RSH: case LSH:
case ADD: case SUB: case DIV: case MUL: case MOD:
dumptree(p->kids[0]);
fprint(stderr, ", ");
dumptree(p->kids[1]);
break;
default: assert(0);
}
fprint(stderr, ")");
}
static void dumpcover(Node p, int nt, int in) {
int rulenum, i;
short *nts;
Node kids[10];
p = reuse(p, nt);
rulenum = getrule(p, nt);
nts = IR->x._nts[rulenum];
fprint(stderr, "dumpcover(%x) = ", p);
for (i = 0; i < in; i++)
fprint(stderr, " ");
dumprule(rulenum);
(*IR->x._kids)(p, rulenum, kids);
for (i = 0; nts[i]; i++)
dumpcover(kids[i], nts[i], in+1);
}
static void dumprule(int rulenum) {
assert(rulenum);
fprint(stderr, "%s / %s", IR->x._string[rulenum],
IR->x._templates[rulenum]);
if (!IR->x._isinstruction[rulenum])
fprint(stderr, "\n");
}
static unsigned emitasm(Node p, int nt) {
int rulenum;
short *nts;
char *fmt;
Node kids[10];
p = reuse(p, nt);
rulenum = getrule(p, nt);
nts = IR->x._nts[rulenum];
fmt = IR->x._templates[rulenum];
assert(fmt);
if (IR->x._isinstruction[rulenum] && p->x.emitted)
print("%s", p->syms[RX]->x.name);
else if (*fmt == '#')
(*IR->x.emit2)(p);
else {
if (*fmt == '?') {
fmt++;
assert(p->kids[0]);
if (p->syms[RX] == p->x.kids[0]->syms[RX])
while (*fmt++ != '\n')
;
}
for ((*IR->x._kids)(p, rulenum, kids); *fmt; fmt++)
if (*fmt != '%')
(void)putchar(*fmt);
else if (*++fmt == 'F')
print("%d", framesize);
else if (*fmt >= '0' && *fmt <= '9')
emitasm(kids[*fmt - '0'], nts[*fmt - '0']);
else if (*fmt >= 'a' && *fmt < 'a' + NELEMS(p->syms))
fputs(p->syms[*fmt - 'a']->x.name, stdout);
else
(void)putchar(*fmt);
}
return 0;
}
void emit(Node p) {
for (; p; p = p->x.next) {
assert(p->x.registered);
if ((p->x.equatable && requate(p)) || moveself(p))
;
else
(*emitter)(p, p->x.inst);
p->x.emitted = 1;
}
}
static int moveself(Node p) {
return p->x.copy
&& p->syms[RX]->x.name == p->x.kids[0]->syms[RX]->x.name;
}
int move(Node p) {
p->x.copy = 1;
return 1;
}
static int requate(Node q) {
Symbol src = q->x.kids[0]->syms[RX];
Symbol tmp = q->syms[RX];
Node p;
int n = 0;
debug(fprint(stderr, "(requate(%x): tmp=%s src=%s)\n", q, tmp->x.name, src->x.name));
for (p = q->x.next; p; p = p->x.next)
if (p->x.copy && p->syms[RX] == src
&& p->x.kids[0]->syms[RX] == tmp)
debug(fprint(stderr, "(requate arm 0 at %x)\n", p)),
p->syms[RX] = tmp;
else if (setsrc(p->syms[RX]) && !moveself(p) && !readsreg(p))
return 0;
else if (p->x.spills)
return 0;
else if (generic(p->op) == CALL && p->x.next)
return 0;
else if (p->op == LABEL+V && p->x.next)
return 0;
else if (p->syms[RX] == tmp && readsreg(p))
debug(fprint(stderr, "(requate arm 5 at %x)\n", p)),
n++;
else if (p->syms[RX] == tmp)
break;
debug(fprint(stderr, "(requate arm 7 at %x)\n", p));
assert(n > 0);
for (p = q->x.next; p; p = p->x.next)
if (p->syms[RX] == tmp && readsreg(p)) {
p->syms[RX] = src;
if (--n <= 0)
break;
}
return 1;
}
static void prelabel(Node p) {
if (p == NULL)
return;
prelabel(p->kids[0]);
prelabel(p->kids[1]);
if (NeedsReg[opindex(p->op)])
setreg(p, (*IR->x.rmap)(opkind(p->op)));
switch (generic(p->op)) {
case ADDRF: case ADDRL:
if (p->syms[0]->sclass == REGISTER)
p->op = VREG+P;
break;
case INDIR:
if (p->kids[0]->op == VREG+P)
setreg(p, p->kids[0]->syms[0]);
break;
case ASGN:
if (p->kids[0]->op == VREG+P)
rtarget(p, 1, p->kids[0]->syms[0]);
break;
case CVI: case CVU: case CVP:
if (optype(p->op) != F
&& opsize(p->op) <= p->syms[0]->u.c.v.i)
p->op = LOAD + opkind(p->op);
break;
}
(IR->x.target)(p);
}
void setreg(Node p, Symbol r) {
p->syms[RX] = r;
}
void rtarget(Node p, int n, Symbol r) {
Node q = p->kids[n];
assert(q);
assert(r);
assert(r->sclass == REGISTER || !r->x.wildcard);
assert(q->syms[RX]);
if (r != q->syms[RX] && !q->syms[RX]->x.wildcard) {
q = newnode(LOAD + opkind(q->op),
q, NULL, q->syms[0]);
if (r->u.t.cse == p->kids[n])
r->u.t.cse = q;
p->kids[n] = p->x.kids[n] = q;
q->x.kids[0] = q->kids[0];
}
setreg(q, r);
debug(fprint(stderr, "(targeting %x->x.kids[%d]=%x to %s)\n", p, n, p->kids[n], r->x.name));
}
static void rewrite(Node p) {
assert(p->x.inst == 0);
prelabel(p);
debug(dumptree(p));
debug(fprint(stderr, "\n"));
(*IR->x._label)(p);
debug(dumpcover(p, 1, 0));
reduce(p, 1);
}
Node gen(Node forest) {
int i;
struct node sentinel;
Node dummy, p;
head = forest;
for (p = forest; p; p = p->link) {
assert(p->count == 0);
if (generic(p->op) == CALL)
docall(p);
else if ( generic(p->op) == ASGN
&& generic(p->kids[1]->op) == CALL)
docall(p->kids[1]);
else if (generic(p->op) == ARG)
(*IR->x.doarg)(p);
rewrite(p);
p->x.listed = 1;
}
for (p = forest; p; p = p->link)
prune(p, &dummy);
relink(&sentinel, &sentinel);
for (p = forest; p; p = p->link)
linearize(p, &sentinel);
forest = sentinel.x.next;
assert(forest);
sentinel.x.next->x.prev = NULL;
sentinel.x.prev->x.next = NULL;
for (p = forest; p; p = p->x.next)
for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
assert(p->x.kids[i]->syms[RX]);
if (p->x.kids[i]->syms[RX]->temporary) {
p->x.kids[i]->x.prevuse =
p->x.kids[i]->syms[RX]->x.lastuse;
p->x.kids[i]->syms[RX]->x.lastuse = p->x.kids[i];
}
}
for (p = forest; p; p = p->x.next) {
ralloc(p);
if (p->x.listed && NeedsReg[opindex(p->op)]
&& (*IR->x.rmap)(opkind(p->op))) {
assert(generic(p->op) == CALL || generic(p->op) == LOAD);
putreg(p->syms[RX]);
}
}
return forest;
}
int notarget(Node p) {
return p->syms[RX]->x.wildcard ? 0 : LBURG_MAX;
}
static void putreg(Symbol r) {
assert(r && r->x.regnode);
freemask[r->x.regnode->set] |= r->x.regnode->mask;
debug(dumpregs("(freeing %s)\n", r->x.name, NULL));
}
static Symbol askfixedreg(Symbol s) {
Regnode r = s->x.regnode;
int n = r->set;
if (r->mask&~freemask[n])
return NULL;
else {
freemask[n] &= ~r->mask;
usedmask[n] |= r->mask;
return s;
}
}
static Symbol askreg(Symbol rs, unsigned rmask[]) {
int i;
if (rs->x.wildcard == NULL)
return askfixedreg(rs);
for (i = 31; i >= 0; i--) {
Symbol r = rs->x.wildcard[i];
if (r != NULL
&& !(r->x.regnode->mask&~rmask[r->x.regnode->set])
&& askfixedreg(r))
return r;
}
return NULL;
}
static Symbol getreg(Symbol s, unsigned mask[], Node p) {
Symbol r = askreg(s, mask);
if (r == NULL) {
r = spillee(s, mask, p);
assert(r && r->x.regnode);
spill(r->x.regnode->mask, r->x.regnode->set, p);
r = askreg(s, mask);
}
assert(r && r->x.regnode);
r->x.regnode->vbl = NULL;
return r;
}
int askregvar(Symbol p, Symbol regs) {
Symbol r;
assert(p);
if (p->sclass != REGISTER)
return 0;
else if (!isscalar(p->type)) {
p->sclass = AUTO;
return 0;
}
else if (p->temporary) {
p->x.name = "?";
return 1;
}
else if ((r = askreg(regs, vmask)) != NULL) {
p->x.regnode = r->x.regnode;
p->x.regnode->vbl = p;
p->x.name = r->x.name;
debug(dumpregs("(allocating %s to symbol %s)\n", p->x.name, p->name));
return 1;
}
else {
p->sclass = AUTO;
return 0;
}
}
static void linearize(Node p, Node next) {
int i;
for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
linearize(p->x.kids[i], next);
relink(next->x.prev, p);
relink(p, next);
debug(fprint(stderr, "(listing %x)\n", p));
}
static void ralloc(Node p) {
int i;
unsigned mask[2];
mask[0] = tmask[0];
mask[1] = tmask[1];
assert(p);
debug(fprint(stderr, "(rallocing %x)\n", p));
for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
Node kid = p->x.kids[i];
Symbol r = kid->syms[RX];
assert(r && kid->x.registered);
if (r->sclass != REGISTER && r->x.lastuse == kid)
putreg(r);
}
if (!p->x.registered && NeedsReg[opindex(p->op)]
&& (*IR->x.rmap)(opkind(p->op))) {
Symbol sym = p->syms[RX], set = sym;
assert(sym);
if (sym->temporary)
set = (*IR->x.rmap)(opkind(p->op));
assert(set);
if (set->sclass != REGISTER) {
Symbol r;
if (*IR->x._templates[getrule(p, p->x.inst)] == '?')
for (i = 1; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
Symbol r = p->x.kids[i]->syms[RX];
assert(p->x.kids[i]->x.registered);
assert(r && r->x.regnode);
assert(sym->x.wildcard || sym != r);
mask[r->x.regnode->set] &= ~r->x.regnode->mask;
}
r = getreg(set, mask, p);
if (sym->temporary) {
Node q;
r->x.lastuse = sym->x.lastuse;
for (q = sym->x.lastuse; q; q = q->x.prevuse) {
q->syms[RX] = r;
q->x.registered = 1;
if (sym->u.t.cse && q->x.copy)
q->x.equatable = 1;
}
} else {
p->syms[RX] = r;
r->x.lastuse = p;
}
debug(dumpregs("(allocating %s to node %x)\n", r->x.name, (char *) p));
}
}
p->x.registered = 1;
(*IR->x.clobber)(p);
}
static Symbol spillee(Symbol set, unsigned mask[], Node here) {
Symbol bestreg = NULL;
int bestdist = -1, i;
assert(set);
if (!set->x.wildcard)
bestreg = set;
else {
for (i = 31; i >= 0; i--) {
Symbol ri = set->x.wildcard[i];
if (
ri != NULL &&
ri->x.lastuse &&
(ri->x.regnode->mask&tmask[ri->x.regnode->set]&mask[ri->x.regnode->set])
) {
Regnode rn = ri->x.regnode;
Node q = here;
int dist = 0;
for (; q && !uses(q, rn); q = q->x.next)
dist++;
if (q && dist > bestdist) {
bestdist = dist;
bestreg = ri;
}
}
}
}
assert(bestreg); /* Must be able to spill something. Reconfigure the register allocator
to ensure that we can allocate a register for all nodes without spilling
the node's necessary input regs. */
assert(bestreg->x.regnode->vbl == NULL); /* Can't spill register variables because
the reload site might be in other blocks. Reconfigure the register allocator
to ensure that this register is never allocated to a variable. */
return bestreg;
}
static int uses(Node p, Regnode rn) {
int i;
for (i = 0; i < NELEMS(p->x.kids); i++)
if (
p->x.kids[i] &&
p->x.kids[i]->x.registered &&
rn->set == p->x.kids[i]->syms[RX]->x.regnode->set &&
(rn->mask&p->x.kids[i]->syms[RX]->x.regnode->mask)
)
return 1;
return 0;
}
static void spillr(Symbol r, Node here) {
int i;
Symbol tmp;
Node p = r->x.lastuse;
assert(p);
while (p->x.prevuse)
assert(r == p->syms[RX]),
p = p->x.prevuse;
assert(p->x.registered && !readsreg(p));
tmp = newtemp(AUTO, optype(p->op), opsize(p->op));
genspill(r, p, tmp);
for (p = here->x.next; p; p = p->x.next)
for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
Node k = p->x.kids[i];
if (k->x.registered && k->syms[RX] == r)
genreload(p, tmp, i);
}
putreg(r);
}
static void genspill(Symbol r, Node last, Symbol tmp) {
Node p, q;
Symbol s;
unsigned ty;
debug(fprint(stderr, "(spilling %s to local %s)\n", r->x.name, tmp->x.name));
debug(fprint(stderr, "(genspill: "));
debug(dumptree(last));
debug(fprint(stderr, ")\n"));
ty = opkind(last->op);
NEW0(s, FUNC);
s->sclass = REGISTER;
s->name = s->x.name = r->x.name;
s->x.regnode = r->x.regnode;
q = newnode(ADDRL+P + sizeop(IR->ptrmetric.size), NULL, NULL, s);
q = newnode(INDIR + ty, q, NULL, NULL);
p = newnode(ADDRL+P + sizeop(IR->ptrmetric.size), NULL, NULL, tmp);
p = newnode(ASGN + ty, p, q, NULL);
p->x.spills = 1;
rewrite(p);
prune(p, &q);
q = last->x.next;
linearize(p, q);
for (p = last->x.next; p != q; p = p->x.next) {
ralloc(p);
assert(!p->x.listed || !NeedsReg[opindex(p->op)] || !(*IR->x.rmap)(opkind(p->op)));
}
}
static void genreload(Node p, Symbol tmp, int i) {
Node q;
int ty;
debug(fprint(stderr, "(replacing %x with a reload from %s)\n", p->x.kids[i], tmp->x.name));
debug(fprint(stderr, "(genreload: "));
debug(dumptree(p->x.kids[i]));
debug(fprint(stderr, ")\n"));
ty = opkind(p->x.kids[i]->op);
q = newnode(ADDRL+P + sizeop(IR->ptrmetric.size), NULL, NULL, tmp);
p->x.kids[i] = newnode(INDIR + ty, q, NULL, NULL);
rewrite(p->x.kids[i]);
prune(p->x.kids[i], &q);
reprune(&p->kids[1], reprune(&p->kids[0], 0, i, p), i, p);
prune(p, &q);
linearize(p->x.kids[i], p);
}
static int reprune(Node *pp, int k, int n, Node p) {
struct node x, *q = *pp;
if (q == NULL || k > n)
return k;
else if (q->x.inst == 0)
return reprune(&q->kids[1],
reprune(&q->kids[0], k, n, p), n, p);
if (k == n) {
debug(fprint(stderr, "(reprune changes %x from %x to %x)\n", pp, *pp, p->x.kids[n]));
*pp = p->x.kids[n];
x = *p;
(IR->x.target)(&x);
}
return k + 1;
}
void spill(unsigned mask, int n, Node here) {
int i;
Node p;
here->x.spills = 1;
usedmask[n] |= mask;
if (mask&~freemask[n]) {
assert( /* It makes no sense for a node to clobber() its target. */
here->x.registered == 0 || /* call isn't coming through clobber() */
here->syms[RX] == NULL ||
here->syms[RX]->x.regnode == NULL ||
here->syms[RX]->x.regnode->set != n ||
(here->syms[RX]->x.regnode->mask&mask) == 0
);
for (p = here; p; p = p->x.next)
for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
Symbol r = p->x.kids[i]->syms[RX];
assert(r);
if (p->x.kids[i]->x.registered && r->x.regnode->set == n
&& r->x.regnode->mask&mask)
spillr(r, here);
}
}
}
static void dumpregs(char *msg, char *a, char *b) {
fprint(stderr, msg, a, b);
fprint(stderr, "(free[0]=%x)\n", freemask[0]);
fprint(stderr, "(free[1]=%x)\n", freemask[1]);
}
int getregnum(Node p) {
assert(p && p->syms[RX] && p->syms[RX]->x.regnode);
return p->syms[RX]->x.regnode->number;
}
unsigned regloc(Symbol p) {
assert(p && p->sclass == REGISTER && p->sclass == REGISTER && p->x.regnode);
return p->x.regnode->set<<8 | p->x.regnode->number;
}

318
code/tools/lcc/src/init.c Normal file
View file

@ -0,0 +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;
}

View file

@ -0,0 +1,7 @@
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);}
}

135
code/tools/lcc/src/input.c Normal file
View file

@ -0,0 +1,135 @@
#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;
}
}

923
code/tools/lcc/src/lex.c Normal file
View file

@ -0,0 +1,923 @@
#include "c.h"
#include <float.h>
#include <errno.h>
#define MAXTOKEN 32
enum { BLANK=01, NEWLINE=02, LETTER=04,
DIGIT=010, HEX=020, OTHER=040 };
static unsigned char map[256] = { /* 000 nul */ 0,
/* 001 soh */ 0,
/* 002 stx */ 0,
/* 003 etx */ 0,
/* 004 eot */ 0,
/* 005 enq */ 0,
/* 006 ack */ 0,
/* 007 bel */ 0,
/* 010 bs */ 0,
/* 011 ht */ BLANK,
/* 012 nl */ NEWLINE,
/* 013 vt */ BLANK,
/* 014 ff */ BLANK,
/* 015 cr */ 0,
/* 016 so */ 0,
/* 017 si */ 0,
/* 020 dle */ 0,
/* 021 dc1 */ 0,
/* 022 dc2 */ 0,
/* 023 dc3 */ 0,
/* 024 dc4 */ 0,
/* 025 nak */ 0,
/* 026 syn */ 0,
/* 027 etb */ 0,
/* 030 can */ 0,
/* 031 em */ 0,
/* 032 sub */ 0,
/* 033 esc */ 0,
/* 034 fs */ 0,
/* 035 gs */ 0,
/* 036 rs */ 0,
/* 037 us */ 0,
/* 040 sp */ BLANK,
/* 041 ! */ OTHER,
/* 042 " */ OTHER,
/* 043 # */ OTHER,
/* 044 $ */ 0,
/* 045 % */ OTHER,
/* 046 & */ OTHER,
/* 047 ' */ OTHER,
/* 050 ( */ OTHER,
/* 051 ) */ OTHER,
/* 052 * */ OTHER,
/* 053 + */ OTHER,
/* 054 , */ OTHER,
/* 055 - */ OTHER,
/* 056 . */ OTHER,
/* 057 / */ OTHER,
/* 060 0 */ DIGIT,
/* 061 1 */ DIGIT,
/* 062 2 */ DIGIT,
/* 063 3 */ DIGIT,
/* 064 4 */ DIGIT,
/* 065 5 */ DIGIT,
/* 066 6 */ DIGIT,
/* 067 7 */ DIGIT,
/* 070 8 */ DIGIT,
/* 071 9 */ DIGIT,
/* 072 : */ OTHER,
/* 073 ; */ OTHER,
/* 074 < */ OTHER,
/* 075 = */ OTHER,
/* 076 > */ OTHER,
/* 077 ? */ OTHER,
/* 100 @ */ 0,
/* 101 A */ LETTER|HEX,
/* 102 B */ LETTER|HEX,
/* 103 C */ LETTER|HEX,
/* 104 D */ LETTER|HEX,
/* 105 E */ LETTER|HEX,
/* 106 F */ LETTER|HEX,
/* 107 G */ LETTER,
/* 110 H */ LETTER,
/* 111 I */ LETTER,
/* 112 J */ LETTER,
/* 113 K */ LETTER,
/* 114 L */ LETTER,
/* 115 M */ LETTER,
/* 116 N */ LETTER,
/* 117 O */ LETTER,
/* 120 P */ LETTER,
/* 121 Q */ LETTER,
/* 122 R */ LETTER,
/* 123 S */ LETTER,
/* 124 T */ LETTER,
/* 125 U */ LETTER,
/* 126 V */ LETTER,
/* 127 W */ LETTER,
/* 130 X */ LETTER,
/* 131 Y */ LETTER,
/* 132 Z */ LETTER,
/* 133 [ */ OTHER,
/* 134 \ */ OTHER,
/* 135 ] */ OTHER,
/* 136 ^ */ OTHER,
/* 137 _ */ LETTER,
/* 140 ` */ 0,
/* 141 a */ LETTER|HEX,
/* 142 b */ LETTER|HEX,
/* 143 c */ LETTER|HEX,
/* 144 d */ LETTER|HEX,
/* 145 e */ LETTER|HEX,
/* 146 f */ LETTER|HEX,
/* 147 g */ LETTER,
/* 150 h */ LETTER,
/* 151 i */ LETTER,
/* 152 j */ LETTER,
/* 153 k */ LETTER,
/* 154 l */ LETTER,
/* 155 m */ LETTER,
/* 156 n */ LETTER,
/* 157 o */ LETTER,
/* 160 p */ LETTER,
/* 161 q */ LETTER,
/* 162 r */ LETTER,
/* 163 s */ LETTER,
/* 164 t */ LETTER,
/* 165 u */ LETTER,
/* 166 v */ LETTER,
/* 167 w */ LETTER,
/* 170 x */ LETTER,
/* 171 y */ LETTER,
/* 172 z */ LETTER,
/* 173 { */ OTHER,
/* 174 | */ OTHER,
/* 175 } */ OTHER,
/* 176 ~ */ OTHER, };
static struct symbol tval;
static char cbuf[BUFSIZE+1];
static unsigned int wcbuf[BUFSIZE+1];
Coordinate src; /* current source coordinate */
int t;
char *token; /* current token */
Symbol tsym; /* symbol table entry for current token */
static void *cput(int c, void *cl);
static void *wcput(int c, void *cl);
static void *scon(int q, void *put(int c, void *cl), void *cl);
static int backslash(int q);
static Symbol fcon(void);
static Symbol icon(unsigned long, int, int);
static void ppnumber(char *);
int gettok(void) {
for (;;) {
register unsigned char *rcp = cp;
while (map[*rcp]&BLANK)
rcp++;
if (limit - rcp < MAXTOKEN) {
cp = rcp;
fillbuf();
rcp = cp;
}
src.file = file;
src.x = (char *)rcp - line;
src.y = lineno;
cp = rcp + 1;
switch (*rcp++) {
case '/': if (*rcp == '*') {
int c = 0;
for (rcp++; *rcp != '/' || c != '*'; )
if (map[*rcp]&NEWLINE) {
if (rcp < limit)
c = *rcp;
cp = rcp + 1;
nextline();
rcp = cp;
if (rcp == limit)
break;
} else
c = *rcp++;
if (rcp < limit)
rcp++;
else
error("unclosed comment\n");
cp = rcp;
continue;
}
return '/';
case '<':
if (*rcp == '=') return cp++, LEQ;
if (*rcp == '<') return cp++, LSHIFT;
return '<';
case '>':
if (*rcp == '=') return cp++, GEQ;
if (*rcp == '>') return cp++, RSHIFT;
return '>';
case '-':
if (*rcp == '>') return cp++, DEREF;
if (*rcp == '-') return cp++, DECR;
return '-';
case '=': return *rcp == '=' ? cp++, EQL : '=';
case '!': return *rcp == '=' ? cp++, NEQ : '!';
case '|': return *rcp == '|' ? cp++, OROR : '|';
case '&': return *rcp == '&' ? cp++, ANDAND : '&';
case '+': return *rcp == '+' ? cp++, INCR : '+';
case ';': case ',': case ':':
case '*': case '~': case '%': case '^': case '?':
case '[': case ']': case '{': case '}': case '(': case ')':
return rcp[-1];
case '\n': case '\v': case '\r': case '\f':
nextline();
if (cp == limit) {
tsym = NULL;
return EOI;
}
continue;
case 'i':
if (rcp[0] == 'f'
&& !(map[rcp[1]]&(DIGIT|LETTER))) {
cp = rcp + 1;
return IF;
}
if (rcp[0] == 'n'
&& rcp[1] == 't'
&& !(map[rcp[2]]&(DIGIT|LETTER))) {
cp = rcp + 2;
tsym = inttype->u.sym;
return INT;
}
goto id;
case 'h': case 'j': case 'k': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'x': case 'y': case 'z':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
case 'G': case 'H': case 'I': case 'J': case 'K':
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
case 'Y': case 'Z':
id:
if (limit - rcp < MAXLINE) {
cp = rcp - 1;
fillbuf();
rcp = ++cp;
}
assert(cp == rcp);
token = (char *)rcp - 1;
while (map[*rcp]&(DIGIT|LETTER))
rcp++;
token = stringn(token, (char *)rcp - token);
tsym = lookup(token, identifiers);
cp = rcp;
return ID;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
unsigned long n = 0;
if (limit - rcp < MAXLINE) {
cp = rcp - 1;
fillbuf();
rcp = ++cp;
}
assert(cp == rcp);
token = (char *)rcp - 1;
if (*token == '0' && (*rcp == 'x' || *rcp == 'X')) {
int d, overflow = 0;
while (*++rcp) {
if (map[*rcp]&DIGIT)
d = *rcp - '0';
else if (*rcp >= 'a' && *rcp <= 'f')
d = *rcp - 'a' + 10;
else if (*rcp >= 'A' && *rcp <= 'F')
d = *rcp - 'A' + 10;
else
break;
if (n&~(~0UL >> 4))
overflow = 1;
else
n = (n<<4) + d;
}
if ((char *)rcp - token <= 2)
error("invalid hexadecimal constant `%S'\n", token, (char *)rcp-token);
cp = rcp;
tsym = icon(n, overflow, 16);
} else if (*token == '0') {
int err = 0, overflow = 0;
for ( ; map[*rcp]&DIGIT; rcp++) {
if (*rcp == '8' || *rcp == '9')
err = 1;
if (n&~(~0UL >> 3))
overflow = 1;
else
n = (n<<3) + (*rcp - '0');
}
if (*rcp == '.' || *rcp == 'e' || *rcp == 'E') {
cp = rcp;
tsym = fcon();
return FCON;
}
cp = rcp;
tsym = icon(n, overflow, 8);
if (err)
error("invalid octal constant `%S'\n", token, (char*)cp-token);
} else {
int overflow = 0;
for (n = *token - '0'; map[*rcp]&DIGIT; ) {
int d = *rcp++ - '0';
if (n > (ULONG_MAX - d)/10)
overflow = 1;
else
n = 10*n + d;
}
if (*rcp == '.' || *rcp == 'e' || *rcp == 'E') {
cp = rcp;
tsym = fcon();
return FCON;
}
cp = rcp;
tsym = icon(n, overflow, 10);
}
return ICON;
}
case '.':
if (rcp[0] == '.' && rcp[1] == '.') {
cp += 2;
return ELLIPSIS;
}
if ((map[*rcp]&DIGIT) == 0)
return '.';
if (limit - rcp < MAXLINE) {
cp = rcp - 1;
fillbuf();
rcp = ++cp;
}
assert(cp == rcp);
cp = rcp - 1;
token = (char *)cp;
tsym = fcon();
return FCON;
case 'L':
if (*rcp == '\'') {
unsigned int *s = scon(*cp, wcput, wcbuf);
if (s - wcbuf > 2)
warning("excess characters in wide-character literal ignored\n");
tval.type = widechar;
tval.u.c.v.u = wcbuf[0];
tsym = &tval;
return ICON;
} else if (*rcp == '"') {
unsigned int *s = scon(*cp, wcput, wcbuf);
tval.type = array(widechar, s - wcbuf, 0);
tval.u.c.v.p = wcbuf;
tsym = &tval;
return SCON;
} else
goto id;
case '\'': {
char *s = scon(*--cp, cput, cbuf);
if (s - cbuf > 2)
warning("excess characters in multibyte character literal ignored\n");
tval.type = inttype;
if (chartype->op == INT)
tval.u.c.v.i = extend(cbuf[0], chartype);
else
tval.u.c.v.i = cbuf[0]&0xFF;
tsym = &tval;
return ICON;
}
case '"': {
char *s = scon(*--cp, cput, cbuf);
tval.type = array(chartype, s - cbuf, 0);
tval.u.c.v.p = cbuf;
tsym = &tval;
return SCON;
}
case 'a':
if (rcp[0] == 'u'
&& rcp[1] == 't'
&& rcp[2] == 'o'
&& !(map[rcp[3]]&(DIGIT|LETTER))) {
cp = rcp + 3;
return AUTO;
}
goto id;
case 'b':
if (rcp[0] == 'r'
&& rcp[1] == 'e'
&& rcp[2] == 'a'
&& rcp[3] == 'k'
&& !(map[rcp[4]]&(DIGIT|LETTER))) {
cp = rcp + 4;
return BREAK;
}
goto id;
case 'c':
if (rcp[0] == 'a'
&& rcp[1] == 's'
&& rcp[2] == 'e'
&& !(map[rcp[3]]&(DIGIT|LETTER))) {
cp = rcp + 3;
return CASE;
}
if (rcp[0] == 'h'
&& rcp[1] == 'a'
&& rcp[2] == 'r'
&& !(map[rcp[3]]&(DIGIT|LETTER))) {
cp = rcp + 3;
tsym = chartype->u.sym;
return CHAR;
}
if (rcp[0] == 'o'
&& rcp[1] == 'n'
&& rcp[2] == 's'
&& rcp[3] == 't'
&& !(map[rcp[4]]&(DIGIT|LETTER))) {
cp = rcp + 4;
return CONST;
}
if (rcp[0] == 'o'
&& rcp[1] == 'n'
&& rcp[2] == 't'
&& rcp[3] == 'i'
&& rcp[4] == 'n'
&& rcp[5] == 'u'
&& rcp[6] == 'e'
&& !(map[rcp[7]]&(DIGIT|LETTER))) {
cp = rcp + 7;
return CONTINUE;
}
goto id;
case 'd':
if (rcp[0] == 'e'
&& rcp[1] == 'f'
&& rcp[2] == 'a'
&& rcp[3] == 'u'
&& rcp[4] == 'l'
&& rcp[5] == 't'
&& !(map[rcp[6]]&(DIGIT|LETTER))) {
cp = rcp + 6;
return DEFAULT;
}
if (rcp[0] == 'o'
&& rcp[1] == 'u'
&& rcp[2] == 'b'
&& rcp[3] == 'l'
&& rcp[4] == 'e'
&& !(map[rcp[5]]&(DIGIT|LETTER))) {
cp = rcp + 5;
tsym = doubletype->u.sym;
return DOUBLE;
}
if (rcp[0] == 'o'
&& !(map[rcp[1]]&(DIGIT|LETTER))) {
cp = rcp + 1;
return DO;
}
goto id;
case 'e':
if (rcp[0] == 'l'
&& rcp[1] == 's'
&& rcp[2] == 'e'
&& !(map[rcp[3]]&(DIGIT|LETTER))) {
cp = rcp + 3;
return ELSE;
}
if (rcp[0] == 'n'
&& rcp[1] == 'u'
&& rcp[2] == 'm'
&& !(map[rcp[3]]&(DIGIT|LETTER))) {
cp = rcp + 3;
return ENUM;
}
if (rcp[0] == 'x'
&& rcp[1] == 't'
&& rcp[2] == 'e'
&& rcp[3] == 'r'
&& rcp[4] == 'n'
&& !(map[rcp[5]]&(DIGIT|LETTER))) {
cp = rcp + 5;
return EXTERN;
}
goto id;
case 'f':
if (rcp[0] == 'l'
&& rcp[1] == 'o'
&& rcp[2] == 'a'
&& rcp[3] == 't'
&& !(map[rcp[4]]&(DIGIT|LETTER))) {
cp = rcp + 4;
tsym = floattype->u.sym;
return FLOAT;
}
if (rcp[0] == 'o'
&& rcp[1] == 'r'
&& !(map[rcp[2]]&(DIGIT|LETTER))) {
cp = rcp + 2;
return FOR;
}
goto id;
case 'g':
if (rcp[0] == 'o'
&& rcp[1] == 't'
&& rcp[2] == 'o'
&& !(map[rcp[3]]&(DIGIT|LETTER))) {
cp = rcp + 3;
return GOTO;
}
goto id;
case 'l':
if (rcp[0] == 'o'
&& rcp[1] == 'n'
&& rcp[2] == 'g'
&& !(map[rcp[3]]&(DIGIT|LETTER))) {
cp = rcp + 3;
return LONG;
}
goto id;
case 'r':
if (rcp[0] == 'e'
&& rcp[1] == 'g'
&& rcp[2] == 'i'
&& rcp[3] == 's'
&& rcp[4] == 't'
&& rcp[5] == 'e'
&& rcp[6] == 'r'
&& !(map[rcp[7]]&(DIGIT|LETTER))) {
cp = rcp + 7;
return REGISTER;
}
if (rcp[0] == 'e'
&& rcp[1] == 't'
&& rcp[2] == 'u'
&& rcp[3] == 'r'
&& rcp[4] == 'n'
&& !(map[rcp[5]]&(DIGIT|LETTER))) {
cp = rcp + 5;
return RETURN;
}
goto id;
case 's':
if (rcp[0] == 'h'
&& rcp[1] == 'o'
&& rcp[2] == 'r'
&& rcp[3] == 't'
&& !(map[rcp[4]]&(DIGIT|LETTER))) {
cp = rcp + 4;
return SHORT;
}
if (rcp[0] == 'i'
&& rcp[1] == 'g'
&& rcp[2] == 'n'
&& rcp[3] == 'e'
&& rcp[4] == 'd'
&& !(map[rcp[5]]&(DIGIT|LETTER))) {
cp = rcp + 5;
return SIGNED;
}
if (rcp[0] == 'i'
&& rcp[1] == 'z'
&& rcp[2] == 'e'
&& rcp[3] == 'o'
&& rcp[4] == 'f'
&& !(map[rcp[5]]&(DIGIT|LETTER))) {
cp = rcp + 5;
return SIZEOF;
}
if (rcp[0] == 't'
&& rcp[1] == 'a'
&& rcp[2] == 't'
&& rcp[3] == 'i'
&& rcp[4] == 'c'
&& !(map[rcp[5]]&(DIGIT|LETTER))) {
cp = rcp + 5;
return STATIC;
}
if (rcp[0] == 't'
&& rcp[1] == 'r'
&& rcp[2] == 'u'
&& rcp[3] == 'c'
&& rcp[4] == 't'
&& !(map[rcp[5]]&(DIGIT|LETTER))) {
cp = rcp + 5;
return STRUCT;
}
if (rcp[0] == 'w'
&& rcp[1] == 'i'
&& rcp[2] == 't'
&& rcp[3] == 'c'
&& rcp[4] == 'h'
&& !(map[rcp[5]]&(DIGIT|LETTER))) {
cp = rcp + 5;
return SWITCH;
}
goto id;
case 't':
if (rcp[0] == 'y'
&& rcp[1] == 'p'
&& rcp[2] == 'e'
&& rcp[3] == 'd'
&& rcp[4] == 'e'
&& rcp[5] == 'f'
&& !(map[rcp[6]]&(DIGIT|LETTER))) {
cp = rcp + 6;
return TYPEDEF;
}
goto id;
case 'u':
if (rcp[0] == 'n'
&& rcp[1] == 'i'
&& rcp[2] == 'o'
&& rcp[3] == 'n'
&& !(map[rcp[4]]&(DIGIT|LETTER))) {
cp = rcp + 4;
return UNION;
}
if (rcp[0] == 'n'
&& rcp[1] == 's'
&& rcp[2] == 'i'
&& rcp[3] == 'g'
&& rcp[4] == 'n'
&& rcp[5] == 'e'
&& rcp[6] == 'd'
&& !(map[rcp[7]]&(DIGIT|LETTER))) {
cp = rcp + 7;
return UNSIGNED;
}
goto id;
case 'v':
if (rcp[0] == 'o'
&& rcp[1] == 'i'
&& rcp[2] == 'd'
&& !(map[rcp[3]]&(DIGIT|LETTER))) {
cp = rcp + 3;
tsym = voidtype->u.sym;
return VOID;
}
if (rcp[0] == 'o'
&& rcp[1] == 'l'
&& rcp[2] == 'a'
&& rcp[3] == 't'
&& rcp[4] == 'i'
&& rcp[5] == 'l'
&& rcp[6] == 'e'
&& !(map[rcp[7]]&(DIGIT|LETTER))) {
cp = rcp + 7;
return VOLATILE;
}
goto id;
case 'w':
if (rcp[0] == 'h'
&& rcp[1] == 'i'
&& rcp[2] == 'l'
&& rcp[3] == 'e'
&& !(map[rcp[4]]&(DIGIT|LETTER))) {
cp = rcp + 4;
return WHILE;
}
goto id;
case '_':
if (rcp[0] == '_'
&& rcp[1] == 't'
&& rcp[2] == 'y'
&& rcp[3] == 'p'
&& rcp[4] == 'e'
&& rcp[5] == 'c'
&& rcp[6] == 'o'
&& rcp[7] == 'd'
&& rcp[8] == 'e'
&& !(map[rcp[9]]&(DIGIT|LETTER))) {
cp = rcp + 9;
return TYPECODE;
}
if (rcp[0] == '_'
&& rcp[1] == 'f'
&& rcp[2] == 'i'
&& rcp[3] == 'r'
&& rcp[4] == 's'
&& rcp[5] == 't'
&& rcp[6] == 'a'
&& rcp[7] == 'r'
&& rcp[8] == 'g'
&& !(map[rcp[9]]&(DIGIT|LETTER))) {
cp = rcp + 9;
return FIRSTARG;
}
goto id;
default:
if ((map[cp[-1]]&BLANK) == 0) {
if (cp[-1] < ' ' || cp[-1] >= 0177)
error("illegal character `\\0%o'\n", cp[-1]);
else
error("illegal character `%c'\n", cp[-1]);
}
}
}
}
static Symbol icon(unsigned long n, int overflow, int base) {
if (((*cp=='u'||*cp=='U') && (cp[1]=='l'||cp[1]=='L'))
|| ((*cp=='l'||*cp=='L') && (cp[1]=='u'||cp[1]=='U'))) {
tval.type = unsignedlong;
cp += 2;
} else if (*cp == 'u' || *cp == 'U') {
if (overflow || n > unsignedtype->u.sym->u.limits.max.i)
tval.type = unsignedlong;
else
tval.type = unsignedtype;
cp += 1;
} else if (*cp == 'l' || *cp == 'L') {
if (overflow || n > longtype->u.sym->u.limits.max.i)
tval.type = unsignedlong;
else
tval.type = longtype;
cp += 1;
} else if (overflow || n > longtype->u.sym->u.limits.max.i)
tval.type = unsignedlong;
else if (n > inttype->u.sym->u.limits.max.i)
tval.type = longtype;
else if (base != 10 && n > inttype->u.sym->u.limits.max.i)
tval.type = unsignedtype;
else
tval.type = inttype;
switch (tval.type->op) {
case INT:
if (overflow || n > tval.type->u.sym->u.limits.max.i) {
warning("overflow in constant `%S'\n", token,
(char*)cp - token);
tval.u.c.v.i = tval.type->u.sym->u.limits.max.i;
} else
tval.u.c.v.i = n;
break;
case UNSIGNED:
if (overflow || n > tval.type->u.sym->u.limits.max.u) {
warning("overflow in constant `%S'\n", token,
(char*)cp - token);
tval.u.c.v.u = tval.type->u.sym->u.limits.max.u;
} else
tval.u.c.v.u = n;
break;
default: assert(0);
}
ppnumber("integer");
return &tval;
}
static void ppnumber(char *which) {
unsigned char *rcp = cp--;
for ( ; (map[*cp]&(DIGIT|LETTER)) || *cp == '.'; cp++)
if ((cp[0] == 'E' || cp[0] == 'e')
&& (cp[1] == '-' || cp[1] == '+'))
cp++;
if (cp > rcp)
error("`%S' is a preprocessing number but an invalid %s constant\n", token,
(char*)cp-token, which);
}
static Symbol fcon(void) {
if (*cp == '.')
do
cp++;
while (map[*cp]&DIGIT);
if (*cp == 'e' || *cp == 'E') {
if (*++cp == '-' || *cp == '+')
cp++;
if (map[*cp]&DIGIT)
do
cp++;
while (map[*cp]&DIGIT);
else
error("invalid floating constant `%S'\n", token,
(char*)cp - token);
}
errno = 0;
tval.u.c.v.d = strtod(token, NULL);
if (errno == ERANGE)
warning("overflow in floating constant `%S'\n", token,
(char*)cp - token);
if (*cp == 'f' || *cp == 'F') {
++cp;
if (tval.u.c.v.d > floattype->u.sym->u.limits.max.d)
warning("overflow in floating constant `%S'\n", token,
(char*)cp - token);
tval.type = floattype;
} else if (*cp == 'l' || *cp == 'L') {
cp++;
tval.type = longdouble;
} else {
if (tval.u.c.v.d > doubletype->u.sym->u.limits.max.d)
warning("overflow in floating constant `%S'\n", token,
(char*)cp - token);
tval.type = doubletype;
}
ppnumber("floating");
return &tval;
}
static void *cput(int c, void *cl) {
char *s = cl;
if (c < 0 || c > 255)
warning("overflow in escape sequence with resulting value `%d'\n", c);
*s++ = c;
return s;
}
static void *wcput(int c, void *cl) {
unsigned int *s = cl;
*s++ = c;
return s;
}
static void *scon(int q, void *put(int c, void *cl), void *cl) {
int n = 0, nbad = 0;
do {
cp++;
while (*cp != q) {
int c;
if (map[*cp]&NEWLINE) {
if (cp < limit)
break;
cp++;
nextline();
if (cp == limit)
break;
continue;
}
c = *cp++;
if (c == '\\') {
if (map[*cp]&NEWLINE) {
if (cp < limit)
break;
cp++;
nextline();
}
if (limit - cp < MAXTOKEN)
fillbuf();
c = backslash(q);
} else if (c < 0 || c > 255 || map[c] == 0)
nbad++;
if (n++ < BUFSIZE)
cl = put(c, cl);
}
if (*cp == q)
cp++;
else
error("missing %c\n", q);
} while (q == '"' && getchr() == '"');
cl = put(0, cl);
if (n >= BUFSIZE)
error("%s literal too long\n", q == '"' ? "string" : "character");
if (Aflag >= 2 && q == '"' && n > 509)
warning("more than 509 characters in a string literal\n");
if (Aflag >= 2 && nbad > 0)
warning("%s literal contains non-portable characters\n",
q == '"' ? "string" : "character");
return cl;
}
int getchr(void) {
for (;;) {
while (map[*cp]&BLANK)
cp++;
if (!(map[*cp]&NEWLINE))
return *cp;
cp++;
nextline();
if (cp == limit)
return EOI;
}
}
static int backslash(int q) {
unsigned int c;
switch (*cp++) {
case 'a': return 7;
case 'b': return '\b';
case 'f': return '\f';
case 'n': return '\n';
case 'r': return '\r';
case 't': return '\t';
case 'v': return '\v';
case '\'': case '"': case '\\': case '\?': break;
case 'x': {
int overflow = 0;
if ((map[*cp]&(DIGIT|HEX)) == 0) {
if (*cp < ' ' || *cp == 0177)
error("ill-formed hexadecimal escape sequence\n");
else
error("ill-formed hexadecimal escape sequence `\\x%c'\n", *cp);
if (*cp != q)
cp++;
return 0;
}
for (c = 0; map[*cp]&(DIGIT|HEX); cp++) {
if (c >> (8*widechar->size - 4))
overflow = 1;
if (map[*cp]&DIGIT)
c = (c<<4) + *cp - '0';
else
c = (c<<4) + (*cp&~040) - 'A' + 10;
}
if (overflow)
warning("overflow in hexadecimal escape sequence\n");
return c&ones(8*widechar->size);
}
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
c = *(cp-1) - '0';
if (*cp >= '0' && *cp <= '7') {
c = (c<<3) + *cp++ - '0';
if (*cp >= '0' && *cp <= '7')
c = (c<<3) + *cp++ - '0';
}
return c;
default:
if (cp[-1] < ' ' || cp[-1] >= 0177)
warning("unrecognized character escape sequence\n");
else
warning("unrecognized character escape sequence `\\%c'\n", cp[-1]);
}
return cp[-1];
}

56
code/tools/lcc/src/list.c Normal file
View file

@ -0,0 +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;
}

225
code/tools/lcc/src/main.c Normal file
View file

@ -0,0 +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);
}

1120
code/tools/lcc/src/mips.md Normal file

File diff suppressed because it is too large Load diff

74
code/tools/lcc/src/null.c Normal file
View file

@ -0,0 +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)
};

135
code/tools/lcc/src/output.c Normal file
View file

@ -0,0 +1,135 @@
#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';
}

665
code/tools/lcc/src/pass2.c Normal file
View file

@ -0,0 +1,665 @@
#include "c.h"
#include "rcc.h"
#if WIN32
#include <fcntl.h>
#include <io.h>
#endif
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 int verbose = 1;
#define VERBOSE(n,arg) (verbose >= n ? (void)(arg):(void)0)
static int nuids;
static rcc_item_ty *items;
static void **itemmap;
static void *uid2type(int uid) {
assert(uid >= 0 && uid < nuids);
if (itemmap[uid] == NULL) {
Type ty;
rcc_type_ty type = (void *)items[uid];
assert(items[uid]);
assert(items[uid]->uid == uid);
assert(items[uid]->kind == rcc_Type_enum);
type = items[uid]->v.rcc_Type.type;
assert(type);
switch (type->kind) {
case rcc_INT_enum:
ty = btot(INT, type->size);
assert(ty->align == type->align);
break;
case rcc_UNSIGNED_enum:
ty = btot(UNSIGNED, type->size);
assert(ty->align == type->align);
break;
case rcc_FLOAT_enum:
ty = btot(FLOAT, type->size);
assert(ty->align == type->align);
break;
case rcc_VOID_enum:
ty = voidtype;
break;
case rcc_POINTER_enum:
ty = ptr(uid2type(type->v.rcc_POINTER.type));
break;
case rcc_ARRAY_enum:
ty = uid2type(type->v.rcc_ARRAY.type);
assert(ty->size > 0);
ty = array(ty, type->size/ty->size, 0);
break;
case rcc_CONST_enum:
ty = qual(CONST, uid2type(type->v.rcc_CONST.type));
break;
case rcc_VOLATILE_enum:
ty = qual(VOLATILE, uid2type(type->v.rcc_VOLATILE.type));
break;
case rcc_ENUM_enum: {
int i, n = Seq_length(type->v.rcc_ENUM.ids);
ty = newstruct(ENUM, string(type->v.rcc_ENUM.tag));
ty->type = inttype;
ty->size = ty->type->size;
ty->align = ty->type->align;
ty->u.sym->u.idlist = newarray(n + 1, sizeof *ty->u.sym->u.idlist, PERM);
for (i = 0; i < n; i++) {
rcc_enum__ty e = Seq_remlo(type->v.rcc_ENUM.ids);
Symbol p = install(e->id, &identifiers, GLOBAL, PERM);
p->type = ty;
p->sclass = ENUM;
p->u.value = e->value;
ty->u.sym->u.idlist[i] = p;
free(e);
}
ty->u.sym->u.idlist[i] = NULL;
Seq_free(&type->v.rcc_ENUM.ids);
break;
}
case rcc_STRUCT_enum: case rcc_UNION_enum: {
int i, n;
Field *tail;
list_ty fields;
if (type->kind == rcc_STRUCT_enum) {
ty = newstruct(STRUCT, string(type->v.rcc_STRUCT.tag));
fields = type->v.rcc_STRUCT.fields;
} else {
ty = newstruct(UNION, string(type->v.rcc_UNION.tag));
fields = type->v.rcc_UNION.fields;
}
itemmap[uid] = ty; /* recursive types */
ty->size = type->size;
ty->align = type->align;
tail = &ty->u.sym->u.s.flist;
n = Seq_length(fields);
for (i = 0; i < n; i++) {
rcc_field_ty field = Seq_remlo(fields);
NEW0(*tail, PERM);
(*tail)->name = (char *)field->id;
(*tail)->type = uid2type(field->type);
(*tail)->offset = field->offset;
(*tail)->bitsize = field->bitsize;
(*tail)->lsb = field->lsb;
if (isconst((*tail)->type))
ty->u.sym->u.s.cfields = 1;
if (isvolatile((*tail)->type))
ty->u.sym->u.s.vfields = 1;
tail = &(*tail)->link;
free(field);
}
Seq_free(&fields);
break;
}
case rcc_FUNCTION_enum: {
int n = Seq_length(type->v.rcc_FUNCTION.formals);
if (n > 0) {
int i;
Type *proto = newarray(n + 1, sizeof *proto, PERM);
for (i = 0; i < n; i++) {
int *formal = Seq_remlo(type->v.rcc_FUNCTION.formals);
proto[i] = uid2type(*formal);
free(formal);
}
proto[i] = NULL;
ty = func(uid2type(type->v.rcc_FUNCTION.type), proto, 0);
} else
ty = func(uid2type(type->v.rcc_FUNCTION.type), NULL, 1);
Seq_free(&type->v.rcc_FUNCTION.formals);
break;
}
default: assert(0);
}
if (itemmap[uid] == NULL) {
itemmap[uid] = ty;
free(type);
free(items[uid]);
items[uid] = NULL;
} else
assert(itemmap[uid] == ty);
}
return itemmap[uid];
}
static Symbol uid2symbol(int uid) {
assert(uid >= 0 && uid < nuids);
if (itemmap[uid] == NULL) {
Symbol p;
rcc_symbol_ty symbol;
assert(items[uid]);
assert(items[uid]->uid == uid);
assert(items[uid]->kind == rcc_Symbol_enum);
symbol = items[uid]->v.rcc_Symbol.symbol;
assert(symbol);
NEW0(p, PERM);
p->name = (char *)symbol->id;
p->scope = symbol->scope;
p->sclass = symbol->sclass;
p->type = uid2type(symbol->type);
#define xx(f,n) p->f = symbol->flags>>n;
xx(structarg,0)
xx(addressed,1)
xx(computed,2)
xx(temporary,3)
xx(generated,4)
#undef xx
p->ref = symbol->ref/10000.0;
assert(p->scope != CONSTANTS && p->scope != LABELS);
if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN)
(*IR->defsymbol)(p);
itemmap[uid] = p;
free(symbol);
free(items[uid]);
items[uid] = NULL;
}
return itemmap[uid];
}
#define xx(s) static void do##s(rcc_interface_ty);
xx(Export)
xx(Import)
xx(Global)
xx(Local)
xx(Address)
xx(Segment)
xx(Defaddress)
xx(Deflabel)
xx(Defconst)
xx(Defconstf)
xx(Defstring)
xx(Space)
xx(Function)
xx(Blockbeg)
xx(Blockend)
xx(Forest)
#undef xx
static void (*doX[])(rcc_interface_ty in) = {
#define xx(s) 0,
xx(Export)
xx(Import)
xx(Global)
xx(Local)
xx(Address)
xx(Segment)
xx(Defaddress)
xx(Deflabel)
xx(Defconst)
xx(Defconstf)
xx(Defstring)
xx(Space)
xx(Function)
xx(Blockbeg)
xx(Blockend)
xx(Forest)
0
#undef xx
};
static void interface(rcc_interface_ty in) {
assert(in);
(*doX[in->kind])(in);
free(in);
}
static void doExport(rcc_interface_ty in) {
(*IR->export)(uid2symbol(in->v.rcc_Export.p));
}
static void doImport(rcc_interface_ty in) {
Symbol p = uid2symbol(in->v.rcc_Export.p);
(*IR->import)(p);
p->defined = 1;
}
static void doGlobal(rcc_interface_ty in) {
Symbol p = uid2symbol(in->v.rcc_Global.p);
p->u.seg = in->v.rcc_Global.seg;
(*IR->global)(p);
p->defined = 1;
}
static void doLocal(rcc_interface_ty in) {
int uid = in->v.rcc_Local.uid;
assert(uid >= 0 && uid < nuids);
assert(items[uid] == NULL);
items[uid] = rcc_Symbol(uid, in->v.rcc_Local.p);
if (in->v.rcc_Local.p->scope >= LOCAL)
addlocal(uid2symbol(uid));
}
static void doAddress(rcc_interface_ty in) {
int uid = in->v.rcc_Address.uid;
Symbol p = uid2symbol(in->v.rcc_Address.p);
assert(uid >= 0 && uid < nuids);
assert(items[uid] == NULL);
items[uid] = rcc_Symbol(uid, in->v.rcc_Address.q);
if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN)
(*IR->address)(uid2symbol(uid), p, in->v.rcc_Address.n);
else {
Code cp = code(Address);
cp->u.addr.sym = uid2symbol(uid);
cp->u.addr.base = p;
cp->u.addr.offset = in->v.rcc_Address.n;
}
}
static void doSegment(rcc_interface_ty in) {
(*IR->segment)(in->v.rcc_Segment.seg);
}
static void doDefaddress(rcc_interface_ty in) {
(*IR->defaddress)(uid2symbol(in->v.rcc_Defaddress.p));
}
static void doDeflabel(rcc_interface_ty in) {
(*IR->defaddress)(findlabel(in->v.rcc_Deflabel.label));
}
static void doDefconst(rcc_interface_ty in) {
Value v;
v.i = in->v.rcc_Defconst.value;
(*IR->defconst)(in->v.rcc_Defconst.suffix, in->v.rcc_Defconst.size, v);
}
static void doDefconstf(rcc_interface_ty in) {
Value v;
unsigned *p = (unsigned *)&v.d;
p[swap] = in->v.rcc_Defconstf.value->msb;
p[1-swap] = in->v.rcc_Defconstf.value->lsb;
(*IR->defconst)(F, in->v.rcc_Defconstf.size, v);
free(in->v.rcc_Defconstf.value);
}
static void doDefstring(rcc_interface_ty in) {
(*IR->defstring)(in->v.rcc_Defstring.s.len, (char *)in->v.rcc_Defstring.s.str);
free((char *)in->v.rcc_Defstring.s.str);
}
static void doSpace(rcc_interface_ty in) {
(*IR->space)(in->v.rcc_Space.n);
}
static void doFunction(rcc_interface_ty in) {
int i, n;
Symbol *caller, *callee;
/*
Initialize:
define the function symbol,
initialize callee and caller arrays.
*/
cfunc = uid2symbol(in->v.rcc_Function.f);
labels = table(NULL, LABELS);
enterscope();
n = Seq_length(in->v.rcc_Function.caller);
caller = newarray(n + 1, sizeof *caller, FUNC);
for (i = 0; i < n; i++) {
int *uid = Seq_remlo(in->v.rcc_Function.caller);
caller[i] = uid2symbol(*uid);
free(uid);
}
caller[i] = NULL;
Seq_free(&in->v.rcc_Function.caller);
callee = newarray(n + 1, sizeof *callee, FUNC);
for (i = 0; i < n; i++) {
int *uid = Seq_remlo(in->v.rcc_Function.callee);
callee[i] = uid2symbol(*uid);
free(uid);
}
callee[i] = NULL;
Seq_free(&in->v.rcc_Function.callee);
cfunc->u.f.callee = callee;
cfunc->defined = 1;
/*
Initialize the code list,
traverse the interfaces inside the function;
each call appends code list entries.
*/
codelist = &codehead;
codelist->next = NULL;
n = Seq_length(in->v.rcc_Function.codelist);
for (i = 0; i < n; i++)
interface(Seq_remlo(in->v.rcc_Function.codelist));
Seq_free(&in->v.rcc_Function.codelist);
/*
Call the back end,
Wrap-up.
*/
exitscope();
(*IR->function)(cfunc, caller, callee, in->v.rcc_Function.ncalls);
cfunc = NULL;
labels = NULL;
}
static struct block {
Code begin;
struct block *prev;
} *blockstack = NULL;
static void doBlockbeg(rcc_interface_ty in) {
struct block *b;
Code cp = code(Blockbeg);
enterscope();
cp->u.block.level = level;
cp->u.block.locals = newarray(1, sizeof *cp->u.block.locals, FUNC);
cp->u.block.locals[0] = NULL;
cp->u.block.identifiers = NULL;
cp->u.block.types = NULL;
NEW(b, FUNC);
b->begin = cp;
b->prev = blockstack;
blockstack = b;
}
static void doBlockend(rcc_interface_ty in) {
assert(blockstack);
code(Blockend)->u.begin = blockstack->begin;
blockstack = blockstack->prev;
exitscope();
}
static Node visit(rcc_node_ty node) {
int op;
Node left = NULL, right = NULL, p = NULL;
Symbol sym = NULL;
switch (node->kind) {
#define T(x) rcc_##x##_enum
case T(CSE): {
Symbol q = uid2symbol(node->v.rcc_CSE.uid);
assert(q->temporary);
q->u.t.cse = p = visit(node->v.rcc_CSE.node);
break;
}
case T(CNST): {
Value v;
v.i = node->v.rcc_CNST.value;
sym = constant(btot(node->suffix, node->size), v);
op = CNST;
break;
}
case T(CNSTF): {
Value v;
unsigned *p = (unsigned *)&v.d;
p[swap] = node->v.rcc_CNSTF.value->msb;
p[1-swap] = node->v.rcc_CNSTF.value->lsb;
sym = constant(btot(node->suffix, node->size), v);
free(node->v.rcc_CNSTF.value);
op = CNST;
break;
}
case T(ARG):
p = newnode(ARG + node->suffix + sizeop(node->size),
visit(node->v.rcc_ARG.left), NULL,
intconst(node->v.rcc_ARG.len));
p->syms[1] = intconst(node->v.rcc_ARG.align);
break;
case T(ASGN):
p = newnode(ASGN + node->suffix + sizeop(node->size),
visit(node->v.rcc_ASGN.left), visit(node->v.rcc_ASGN.right),
intconst(node->v.rcc_ASGN.len));
p->syms[1] = intconst(node->v.rcc_ASGN.align);
break;
case T(CVT):
op = node->v.rcc_CVT.op;
left = visit(node->v.rcc_CVT.left);
sym = intconst(node->v.rcc_CVT.fromsize);
break;
case T(CALL):
op = CALL;
left = visit(node->v.rcc_CALL.left);
NEW0(sym, FUNC);
sym->type = uid2type(node->v.rcc_CALL.type);
break;
case T(CALLB):
op = CALL;
left = visit(node->v.rcc_CALLB.left);
right = visit(node->v.rcc_CALLB.right);
NEW0(sym, FUNC);
sym->type = uid2type(node->v.rcc_CALLB.type);
break;
case T(RET):
op = RET;
break;
case T(ADDRG):
op = ADDRG;
sym = uid2symbol(node->v.rcc_ADDRG.uid);
break;
case T(ADDRL):
op = ADDRL;
sym = uid2symbol(node->v.rcc_ADDRG.uid);
break;
case T(ADDRF):
op = ADDRF;
sym = uid2symbol(node->v.rcc_ADDRG.uid);
break;
case T(Unary):
op = node->v.rcc_Unary.op;
left = visit(node->v.rcc_Unary.left);
break;
case T(Binary):
op = node->v.rcc_Binary.op;
left = visit(node->v.rcc_Binary.left);
right = visit(node->v.rcc_Binary.right);
break;
case T(Compare):
op = node->v.rcc_Compare.op;
left = visit(node->v.rcc_Compare.left);
right = visit(node->v.rcc_Compare.right);
sym = findlabel(node->v.rcc_Compare.label);
break;
case T(LABEL):
op = LABEL;
sym = findlabel(node->v.rcc_LABEL.label);
break;
case T(BRANCH):
op = JUMP;
left = newnode(ADDRG+P+sizeop(voidptype->size), NULL, NULL, findlabel(node->v.rcc_BRANCH.label));
break;
#undef T
default: assert(0);
}
if (p == NULL)
p = newnode(op + node->suffix + sizeop(node->size), left, right, sym);
free(node);
return p;
}
static void doForest(rcc_interface_ty in) {
Node *tail = &code(Gen)->u.forest;
int i, n = Seq_length(in->v.rcc_Forest.nodes);
for (i = 0; i < n; i++) {
*tail = visit(Seq_remlo(in->v.rcc_Forest.nodes));
assert(*tail);
tail = &(*tail)->link;
}
*tail = NULL;
Seq_free(&in->v.rcc_Forest.nodes);
}
int main(int argc, char *argv[]) {
int i, version;
float stamp = (assert(strstr(rcsid, ",v")), strtod(strstr(rcsid, ",v")+2, NULL))
;
char *infile = NULL, *outfile = NULL;
rcc_program_ty pickle;
for (i = 1; i < argc; i++)
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, "rb", stdin) == NULL) {
fprint(stderr, "%s: can't read `%s'\n", argv[0], infile);
exit(EXIT_FAILURE);
}
#if WIN32
else
_setmode(_fileno(stdin), _O_BINARY);
#endif
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);
}
version = read_int(stdin);
assert(version/100 == (int)stamp);
pickle = rcc_read_program(stdin);
argc = pickle->argc;
argv = newarray(argc + 1, sizeof *argv, PERM);
{
for (i = 0; i < argc; i++) {
string_ty *arg = Seq_remlo(pickle->argv);
argv[i] = (char *)arg->str;
free(arg);
}
argv[i] = NULL;
assert(i == argc);
Seq_free(&pickle->argv);
}
for (i = argc - 1; i > 0; i--)
if (strncmp(argv[i], "-target=", 8) == 0)
break;
if (i > 0) {
int j;
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 (!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);
}
IR->wants_dag = 0; /* pickle's hold trees */
init(argc, argv);
genlabel(pickle->nlabels);
level = GLOBAL;
{
int i, count;
nuids = pickle->nuids;
items = newarray(nuids, sizeof *items, PERM);
itemmap = newarray(nuids, sizeof *items, PERM);
for (i = 0; i < nuids; i++) {
itemmap[i] = NULL;
items[i] = NULL;
}
(*IR->progbeg)(argc, argv);
count = Seq_length(pickle->items);
for (i = 0; i < count; i++) {
rcc_item_ty item = Seq_remlo(pickle->items);
int uid = item->uid;
assert(uid >= 0 && uid < nuids);
assert(items[uid] == NULL);
items[uid] = item;
}
Seq_free(&pickle->items);
#define xx(s) assert(rcc_##s##_enum < sizeof doX/sizeof doX[0] && doX[rcc_##s##_enum]==0); \
doX[rcc_##s##_enum] = do##s;
xx(Export)
xx(Import)
xx(Global)
xx(Local)
xx(Address)
xx(Segment)
xx(Defaddress)
xx(Deflabel)
xx(Defconst)
xx(Defconstf)
xx(Defstring)
xx(Space)
xx(Function)
xx(Blockbeg)
xx(Blockend)
xx(Forest)
#undef xx
count = Seq_length(pickle->interfaces);
for (i = 0; i < count; i++)
interface(Seq_remlo(pickle->interfaces));
Seq_free(&pickle->interfaces);
free(pickle);
(*IR->progend)();
}
deallocate(PERM);
return errcnt > 0;
}
/* main_init - process program arguments */
void main_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], "-g") == 0 || strcmp(argv[i], "-g2") == 0)
glevel = 2;
else if (strcmp(argv[i], "-w") == 0)
wflag++;
else if (strcmp(argv[i], "-v") == 0) {
fprint(stderr, "%s %s\n", argv[0], rcsid);
verbose++;
} 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;
}
}
void init(int argc, char *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);}
}

228
code/tools/lcc/src/prof.c Normal file
View file

@ -0,0 +1,228 @@
#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);
}
}
}
}

276
code/tools/lcc/src/profio.c Normal file
View file

@ -0,0 +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;
}

View file

@ -0,0 +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)
}

51
code/tools/lcc/src/run.sh Normal file
View file

@ -0,0 +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

587
code/tools/lcc/src/simp.c Normal file
View file

@ -0,0 +1,587 @@
#include "c.h"
#include <float.h>
#define foldcnst(TYPE,VAR,OP) \
if (l->op == CNST+TYPE && r->op == CNST+TYPE) \
return cnsttree(ty, l->u.v.VAR OP r->u.v.VAR)
#define commute(L,R) \
if (generic(R->op) == CNST && generic(L->op) != CNST) \
do { Tree t = L; L = R; R = t; } while(0)
#define xfoldcnst(TYPE,VAR,OP,FUNC)\
if (l->op == CNST+TYPE && r->op == CNST+TYPE\
&& FUNC(l->u.v.VAR,r->u.v.VAR,\
ty->u.sym->u.limits.min.VAR,\
ty->u.sym->u.limits.max.VAR, needconst)) \
return cnsttree(ty, l->u.v.VAR OP r->u.v.VAR)
#define xcvtcnst(FTYPE,SRC,DST,VAR,EXPR) \
if (l->op == CNST+FTYPE) do {\
if (!explicitCast\
&& ((SRC) < DST->u.sym->u.limits.min.VAR || (SRC) > DST->u.sym->u.limits.max.VAR))\
warning("overflow in converting constant expression from `%t' to `%t'\n", l->type, DST);\
if (needconst\
|| !((SRC) < DST->u.sym->u.limits.min.VAR || (SRC) > DST->u.sym->u.limits.max.VAR))\
return cnsttree(ty, (EXPR)); } while(0)
#define identity(X,Y,TYPE,VAR,VAL) \
if (X->op == CNST+TYPE && X->u.v.VAR == VAL) return Y
#define zerofield(OP,TYPE,VAR) \
if (l->op == FIELD \
&& r->op == CNST+TYPE && r->u.v.VAR == 0)\
return eqtree(OP, bittree(BAND, l->kids[0],\
cnsttree(unsignedtype, \
(unsigned long)fieldmask(l->u.field)<<fieldright(l->u.field))), r)
#define cfoldcnst(TYPE,VAR,OP) \
if (l->op == CNST+TYPE && r->op == CNST+TYPE) \
return cnsttree(inttype, (long)(l->u.v.VAR OP r->u.v.VAR))
#define foldaddp(L,R,RTYPE,VAR) \
if (L->op == CNST+P && R->op == CNST+RTYPE) { \
Tree e = tree(CNST+P, ty, NULL, NULL);\
e->u.v.p = (char *)L->u.v.p + R->u.v.VAR;\
return e; }
#define ufoldcnst(TYPE,EXP) if (l->op == CNST+TYPE) return EXP
#define sfoldcnst(OP) \
if (l->op == CNST+U && r->op == CNST+I \
&& r->u.v.i >= 0 && r->u.v.i < 8*l->type->size) \
return cnsttree(ty, (unsigned long)(l->u.v.u OP r->u.v.i))
#define geu(L,R,V) \
if (R->op == CNST+U && R->u.v.u == 0) do { \
warning("result of unsigned comparison is constant\n"); \
return tree(RIGHT, inttype, root(L), cnsttree(inttype, (long)(V))); } while(0)
#define idempotent(OP) if (l->op == OP) return l->kids[0]
int needconst;
int explicitCast;
static int addi(long x, long y, long min, long max, int needconst) {
int cond = x == 0 || y == 0
|| (x < 0 && y < 0 && x >= min - y)
|| (x < 0 && y > 0)
|| (x > 0 && y < 0)
|| (x > 0 && y > 0 && x <= max - y);
if (!cond && needconst) {
warning("overflow in constant expression\n");
cond = 1;
}
return cond;
}
static int addd(double x, double y, double min, double max, int needconst) {
int cond = x == 0 || y == 0
|| (x < 0 && y < 0 && x >= min - y)
|| (x < 0 && y > 0)
|| (x > 0 && y < 0)
|| (x > 0 && y > 0 && x <= max - y);
if (!cond && needconst) {
warning("overflow in constant expression\n");
cond = 1;
}
return cond;
}
static Tree addrtree(Tree e, long n, Type ty) {
Symbol p = e->u.sym, q;
if (p->scope == GLOBAL
|| p->sclass == STATIC || p->sclass == EXTERN)
NEW0(q, PERM);
else
NEW0(q, FUNC);
q->name = stringd(genlabel(1));
q->sclass = p->sclass;
q->scope = p->scope;
assert(isptr(ty) || isarray(ty));
q->type = isptr(ty) ? ty->type : ty;
q->temporary = p->temporary;
q->generated = p->generated;
q->addressed = p->addressed;
q->computed = 1;
q->defined = 1;
q->ref = 1;
if (p->scope == GLOBAL
|| p->sclass == STATIC || p->sclass == EXTERN) {
if (p->sclass == AUTO)
q->sclass = STATIC;
(*IR->address)(q, p, n);
} else {
Code cp;
addlocal(p);
cp = code(Address);
cp->u.addr.sym = q;
cp->u.addr.base = p;
cp->u.addr.offset = n;
}
e = tree(e->op, ty, NULL, NULL);
e->u.sym = q;
return e;
}
/* div[id] - return 1 if min <= x/y <= max, 0 otherwise */
static int divi(long x, long y, long min, long max, int needconst) {
int cond = y != 0 && !(x == min && y == -1);
if (!cond && needconst) {
warning("overflow in constant expression\n");
cond = 1;
}
return cond;
}
static int divd(double x, double y, double min, double max, int needconst) {
int cond;
if (x < 0) x = -x;
if (y < 0) y = -y;
cond = y != 0 && !(y < 1 && x > max*y);
if (!cond && needconst) {
warning("overflow in constant expression\n");
cond = 1;
}
return cond;
}
/* mul[id] - return 1 if min <= x*y <= max, 0 otherwise */
static int muli(long x, long y, long min, long max, int needconst) {
int cond = (x > -1 && x <= 1) || (y > -1 && y <= 1)
|| (x < 0 && y < 0 && -x <= max/-y)
|| (x < 0 && y > 0 && x >= min/y)
|| (x > 0 && y < 0 && y >= min/x)
|| (x > 0 && y > 0 && x <= max/y);
if (!cond && needconst) {
warning("overflow in constant expression\n");
cond = 1;
}
return cond;
}
static int muld(double x, double y, double min, double max, int needconst) {
int cond = (x >= -1 && x <= 1) || (y >= -1 && y <= 1)
|| (x < 0 && y < 0 && -x <= max/-y)
|| (x < 0 && y > 0 && x >= min/y)
|| (x > 0 && y < 0 && y >= min/x)
|| (x > 0 && y > 0 && x <= max/y);
if (!cond && needconst) {
warning("overflow in constant expression\n");
cond = 1;
}
return cond;
}
/* sub[id] - return 1 if min <= x-y <= max, 0 otherwise */
static int subi(long x, long y, long min, long max, int needconst) {
return addi(x, -y, min, max, needconst);
}
static int subd(double x, double y, double min, double max, int needconst) {
return addd(x, -y, min, max, needconst);
}
Tree constexpr(int tok) {
Tree p;
needconst++;
p = expr1(tok);
needconst--;
return p;
}
int intexpr(int tok, int n) {
Tree p = constexpr(tok);
needconst++;
if (p->op == CNST+I || p->op == CNST+U)
n = cast(p, inttype)->u.v.i;
else
error("integer expression must be constant\n");
needconst--;
return n;
}
Tree simplify(int op, Type ty, Tree l, Tree r) {
int n;
if (optype(op) == 0)
op = mkop(op, ty);
switch (op) {
case ADD+U:
foldcnst(U,u,+);
commute(r,l);
identity(r,l,U,u,0);
break;
case ADD+I:
xfoldcnst(I,i,+,addi);
commute(r,l);
identity(r,l,I,i,0);
break;
case CVI+I:
xcvtcnst(I,l->u.v.i,ty,i,(long)extend(l->u.v.i,ty));
break;
case CVU+I:
if (l->op == CNST+U) {
if (!explicitCast && l->u.v.u > ty->u.sym->u.limits.max.i)
warning("overflow in converting constant expression from `%t' to `%t'\n", l->type, ty);
if (needconst || !(l->u.v.u > ty->u.sym->u.limits.max.i))
return cnsttree(ty, (long)extend(l->u.v.u,ty));
}
break;
case CVP+U:
xcvtcnst(P,(unsigned long)l->u.v.p,ty,u,(unsigned long)l->u.v.p);
break;
case CVU+P:
xcvtcnst(U,(void*)l->u.v.u,ty,p,(void*)l->u.v.u);
break;
case CVP+P:
xcvtcnst(P,l->u.v.p,ty,p,l->u.v.p);
break;
case CVI+U:
xcvtcnst(I,l->u.v.i,ty,u,((unsigned long)l->u.v.i)&ones(8*ty->size));
break;
case CVU+U:
xcvtcnst(U,l->u.v.u,ty,u,l->u.v.u&ones(8*ty->size));
break;
case CVI+F:
xcvtcnst(I,l->u.v.i,ty,d,(long double)l->u.v.i);
case CVU+F:
xcvtcnst(U,l->u.v.u,ty,d,(long double)l->u.v.u);
break;
case CVF+I:
xcvtcnst(F,l->u.v.d,ty,i,(long)l->u.v.d);
break;
case CVF+F: {
float d;
if (l->op == CNST+F) {
if (l->u.v.d < ty->u.sym->u.limits.min.d)
d = ty->u.sym->u.limits.min.d;
else if (l->u.v.d > ty->u.sym->u.limits.max.d)
d = ty->u.sym->u.limits.max.d;
else
d = l->u.v.d;
}
xcvtcnst(F,l->u.v.d,ty,d,(long double)d);
break;
}
case BAND+U:
foldcnst(U,u,&);
commute(r,l);
identity(r,l,U,u,ones(8*ty->size));
if (r->op == CNST+U && r->u.v.u == 0)
return tree(RIGHT, ty, root(l), cnsttree(ty, 0UL));
break;
case BAND+I:
foldcnst(I,i,&);
commute(r,l);
identity(r,l,I,i,ones(8*ty->size));
if (r->op == CNST+I && r->u.v.u == 0)
return tree(RIGHT, ty, root(l), cnsttree(ty, 0L));
break;
case MUL+U:
commute(l,r);
if (l->op == CNST+U && (n = ispow2(l->u.v.u)) != 0)
return simplify(LSH, ty, r, cnsttree(inttype, (long)n));
foldcnst(U,u,*);
identity(r,l,U,u,1);
break;
case NE+I:
cfoldcnst(I,i,!=);
commute(r,l);
zerofield(NE,I,i);
break;
case EQ+I:
cfoldcnst(I,i,==);
commute(r,l);
zerofield(EQ,I,i);
break;
case ADD+P:
foldaddp(l,r,I,i);
foldaddp(l,r,U,u);
foldaddp(r,l,I,i);
foldaddp(r,l,U,u);
commute(r,l);
identity(r,retype(l,ty),I,i,0);
identity(r,retype(l,ty),U,u,0);
if (isaddrop(l->op)
&& ((r->op == CNST+I && r->u.v.i <= longtype->u.sym->u.limits.max.i
&& r->u.v.i >= longtype->u.sym->u.limits.min.i)
|| (r->op == CNST+U && r->u.v.u <= longtype->u.sym->u.limits.max.i)))
return addrtree(l, cast(r, longtype)->u.v.i, ty);
if (l->op == ADD+P && isaddrop(l->kids[1]->op)
&& ((r->op == CNST+I && r->u.v.i <= longtype->u.sym->u.limits.max.i
&& r->u.v.i >= longtype->u.sym->u.limits.min.i)
|| (r->op == CNST+U && r->u.v.u <= longtype->u.sym->u.limits.max.i)))
return simplify(ADD+P, ty, l->kids[0],
addrtree(l->kids[1], cast(r, longtype)->u.v.i, ty));
if ((l->op == ADD+I || l->op == SUB+I)
&& l->kids[1]->op == CNST+I && isaddrop(r->op))
return simplify(ADD+P, ty, l->kids[0],
simplify(generic(l->op)+P, ty, r, l->kids[1]));
if (l->op == ADD+P && generic(l->kids[1]->op) == CNST
&& generic(r->op) == CNST)
return simplify(ADD+P, ty, l->kids[0],
simplify(ADD, l->kids[1]->type, l->kids[1], r));
if (l->op == ADD+I && generic(l->kids[1]->op) == CNST
&& r->op == ADD+P && generic(r->kids[1]->op) == CNST)
return simplify(ADD+P, ty, l->kids[0],
simplify(ADD+P, ty, r->kids[0],
simplify(ADD, r->kids[1]->type, l->kids[1], r->kids[1])));
if (l->op == RIGHT && l->kids[1])
return tree(RIGHT, ty, l->kids[0],
simplify(ADD+P, ty, l->kids[1], r));
else if (l->op == RIGHT && l->kids[0])
return tree(RIGHT, ty,
simplify(ADD+P, ty, l->kids[0], r), NULL);
break;
case ADD+F:
xfoldcnst(F,d,+,addd);
commute(r,l);
break;
case AND+I:
op = AND;
ufoldcnst(I,l->u.v.i ? cond(r) : l); /* 0&&r => 0, 1&&r => r */
break;
case OR+I:
op = OR;
/* 0||r => r, 1||r => 1 */
ufoldcnst(I,l->u.v.i ? cnsttree(ty, 1L) : cond(r));
break;
case BCOM+I:
ufoldcnst(I,cnsttree(ty, (long)extend((~l->u.v.i)&ones(8*ty->size), ty)));
idempotent(BCOM+U);
break;
case BCOM+U:
ufoldcnst(U,cnsttree(ty, (unsigned long)((~l->u.v.u)&ones(8*ty->size))));
idempotent(BCOM+U);
break;
case BOR+U:
foldcnst(U,u,|);
commute(r,l);
identity(r,l,U,u,0);
break;
case BOR+I:
foldcnst(I,i,|);
commute(r,l);
identity(r,l,I,i,0);
break;
case BXOR+U:
foldcnst(U,u,^);
commute(r,l);
identity(r,l,U,u,0);
break;
case BXOR+I:
foldcnst(I,i,^);
commute(r,l);
identity(r,l,I,i,0);
break;
case DIV+F:
xfoldcnst(F,d,/,divd);
break;
case DIV+I:
identity(r,l,I,i,1);
if ((r->op == CNST+I && r->u.v.i == 0)
|| (l->op == CNST+I && l->u.v.i == ty->u.sym->u.limits.min.i
&& r->op == CNST+I && r->u.v.i == -1))
break;
xfoldcnst(I,i,/,divi);
break;
case DIV+U:
identity(r,l,U,u,1);
if (r->op == CNST+U && r->u.v.u == 0)
break;
if (r->op == CNST+U && (n = ispow2(r->u.v.u)) != 0)
return simplify(RSH, ty, l, cnsttree(inttype, (long)n));
foldcnst(U,u,/);
break;
case EQ+F:
cfoldcnst(F,d,==);
commute(r,l);
break;
case EQ+U:
cfoldcnst(U,u,==);
commute(r,l);
zerofield(EQ,U,u);
break;
case GE+F: cfoldcnst(F,d,>=); break;
case GE+I: cfoldcnst(I,i,>=); break;
case GE+U:
geu(l,r,1); /* l >= 0 => (l,1) */
cfoldcnst(U,u,>=);
if (l->op == CNST+U && l->u.v.u == 0) /* 0 >= r => r == 0 */
return eqtree(EQ, r, l);
break;
case GT+F: cfoldcnst(F,d, >); break;
case GT+I: cfoldcnst(I,i, >); break;
case GT+U:
geu(r,l,0); /* 0 > r => (r,0) */
cfoldcnst(U,u, >);
if (r->op == CNST+U && r->u.v.u == 0) /* l > 0 => l != 0 */
return eqtree(NE, l, r);
break;
case LE+F: cfoldcnst(F,d,<=); break;
case LE+I: cfoldcnst(I,i,<=); break;
case LE+U:
geu(r,l,1); /* 0 <= r => (r,1) */
cfoldcnst(U,u,<=);
if (r->op == CNST+U && r->u.v.u == 0) /* l <= 0 => l == 0 */
return eqtree(EQ, l, r);
break;
case LSH+I:
identity(r,l,I,i,0);
if (l->op == CNST+I && r->op == CNST+I
&& r->u.v.i >= 0 && r->u.v.i < 8*l->type->size
&& muli(l->u.v.i, 1<<r->u.v.i, ty->u.sym->u.limits.min.i, ty->u.sym->u.limits.max.i, needconst))
return cnsttree(ty, (long)(l->u.v.i<<r->u.v.i));
if (r->op == CNST+I && (r->u.v.i >= 8*ty->size || r->u.v.i < 0)) {
warning("shifting an `%t' by %d bits is undefined\n", ty, r->u.v.i);
break;
}
break;
case LSH+U:
identity(r,l,I,i,0);
sfoldcnst(<<);
if (r->op == CNST+I && (r->u.v.i >= 8*ty->size || r->u.v.i < 0)) {
warning("shifting an `%t' by %d bits is undefined\n", ty, r->u.v.i);
break;
}
break;
case LT+F: cfoldcnst(F,d, <); break;
case LT+I: cfoldcnst(I,i, <); break;
case LT+U:
geu(l,r,0); /* l < 0 => (l,0) */
cfoldcnst(U,u, <);
if (l->op == CNST+U && l->u.v.u == 0) /* 0 < r => r != 0 */
return eqtree(NE, r, l);
break;
case MOD+I:
if (r->op == CNST+I && r->u.v.i == 1) /* l%1 => (l,0) */
return tree(RIGHT, ty, root(l), cnsttree(ty, 0L));
if ((r->op == CNST+I && r->u.v.i == 0)
|| (l->op == CNST+I && l->u.v.i == ty->u.sym->u.limits.min.i
&& r->op == CNST+I && r->u.v.i == -1))
break;
xfoldcnst(I,i,%,divi);
break;
case MOD+U:
if (r->op == CNST+U && ispow2(r->u.v.u)) /* l%2^n => l&(2^n-1) */
return bittree(BAND, l, cnsttree(ty, r->u.v.u - 1));
if (r->op == CNST+U && r->u.v.u == 0)
break;
foldcnst(U,u,%);
break;
case MUL+F:
xfoldcnst(F,d,*,muld);
commute(l,r);
break;
case MUL+I:
commute(l,r);
xfoldcnst(I,i,*,muli);
if (l->op == CNST+I && r->op == ADD+I && r->kids[1]->op == CNST+I)
/* c1*(x + c2) => c1*x + c1*c2 */
return simplify(ADD, ty, simplify(MUL, ty, l, r->kids[0]),
simplify(MUL, ty, l, r->kids[1]));
if (l->op == CNST+I && r->op == SUB+I && r->kids[1]->op == CNST+I)
/* c1*(x - c2) => c1*x - c1*c2 */
return simplify(SUB, ty, simplify(MUL, ty, l, r->kids[0]),
simplify(MUL, ty, l, r->kids[1]));
if (l->op == CNST+I && l->u.v.i > 0 && (n = ispow2(l->u.v.i)) != 0)
/* 2^n * r => r<<n */
return simplify(LSH, ty, r, cnsttree(inttype, (long)n));
identity(r,l,I,i,1);
break;
case NE+F:
cfoldcnst(F,d,!=);
commute(r,l);
break;
case NE+U:
cfoldcnst(U,u,!=);
commute(r,l);
zerofield(NE,U,u);
break;
case NEG+F:
ufoldcnst(F,cnsttree(ty, -l->u.v.d));
idempotent(NEG+F);
break;
case NEG+I:
if (l->op == CNST+I) {
if (needconst && l->u.v.i == ty->u.sym->u.limits.min.i)
warning("overflow in constant expression\n");
if (needconst || l->u.v.i != ty->u.sym->u.limits.min.i)
return cnsttree(ty, -l->u.v.i);
}
idempotent(NEG+I);
break;
case NOT+I:
op = NOT;
ufoldcnst(I,cnsttree(ty, !l->u.v.i));
break;
case RSH+I:
identity(r,l,I,i,0);
if (l->op == CNST+I && r->op == CNST+I
&& r->u.v.i >= 0 && r->u.v.i < 8*l->type->size) {
long n = l->u.v.i>>r->u.v.i;
if (l->u.v.i < 0)
n |= ~0UL<<(8*l->type->size - r->u.v.i);
return cnsttree(ty, n);
}
if (r->op == CNST+I && (r->u.v.i >= 8*ty->size || r->u.v.i < 0)) {
warning("shifting an `%t' by %d bits is undefined\n", ty, r->u.v.i);
break;
}
break;
case RSH+U:
identity(r,l,I,i,0);
sfoldcnst(>>);
if (r->op == CNST+I && (r->u.v.i >= 8*ty->size || r->u.v.i < 0)) {
warning("shifting an `%t' by %d bits is undefined\n", ty, r->u.v.i);
break;
}
break;
case SUB+F:
xfoldcnst(F,d,-,subd);
break;
case SUB+I:
xfoldcnst(I,i,-,subi);
identity(r,l,I,i,0);
break;
case SUB+U:
foldcnst(U,u,-);
identity(r,l,U,u,0);
break;
case SUB+P:
if (l->op == CNST+P && r->op == CNST+P)
return cnsttree(ty, (long)((char *)l->u.v.p - (char *)r->u.v.p));
if (r->op == CNST+I || r->op == CNST+U)
return simplify(ADD, ty, l,
cnsttree(inttype, r->op == CNST+I ? -r->u.v.i : -(long)r->u.v.u));
if (isaddrop(l->op) && r->op == ADD+I && r->kids[1]->op == CNST+I)
/* l - (x + c) => l-c - x */
return simplify(SUB, ty,
simplify(SUB, ty, l, r->kids[1]), r->kids[0]);
break;
default:assert(0);
}
return tree(op, ty, l, r);
}
/* ispow2 - if u > 1 && u == 2^n, return n, otherwise return 0 */
int ispow2(unsigned long u) {
int n;
if (u > 1 && (u&(u-1)) == 0)
for (n = 0; u; u >>= 1, n++)
if (u&1)
return n;
return 0;
}

1163
code/tools/lcc/src/sparc.md Normal file

File diff suppressed because it is too large Load diff

326
code/tools/lcc/src/stab.c Normal file
View file

@ -0,0 +1,326 @@
#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++);
{
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;
}
{
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);
}

113
code/tools/lcc/src/stab.h Normal file
View file

@ -0,0 +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

696
code/tools/lcc/src/stmt.c Normal file
View file

@ -0,0 +1,696 @@
#include "c.h"
#define SWSIZE 512
#define den(i,j) ((j-buckets[i]+1.0)/(v[j]-v[buckets[i]]+1))
struct code codehead = { Start };
Code codelist = &codehead;
float density = 0.5;
Table stmtlabs;
static int foldcond(Tree e1, Tree e2);
static void caselabel(Swtch, long, int);
static void cmp(int, Symbol, long, int);
static Tree conditional(int);
static void dostmt(int, Swtch, int);
static int equal(Symbol, Symbol);
static void forstmt(int, Swtch, int);
static void ifstmt(int, int, Swtch, int);
static Symbol localaddr(Tree);
static void stmtlabel(void);
static void swstmt(int, int, int);
static void whilestmt(int, Swtch, int);
Code code(int kind) {
Code cp;
if (!reachable(kind))
warning("unreachable code\n");
NEW(cp, FUNC);
cp->kind = kind;
cp->prev = codelist;
cp->next = NULL;
codelist->next = cp;
codelist = cp;
return cp;
}
int reachable(int kind) {
if (kind > Start) {
Code cp;
for (cp = codelist; cp->kind < Label; )
cp = cp->prev;
if (cp->kind == Jump || cp->kind == Switch)
return 0;
}
return 1;
}
void addlocal(Symbol p) {
if (!p->defined) {
code(Local)->u.var = p;
p->defined = 1;
p->scope = level;
}
}
void definept(Coordinate *p) {
Code cp = code(Defpoint);
cp->u.point.src = p ? *p : src;
cp->u.point.point = npoints;
if (ncalled > 0) {
int n = findcount(cp->u.point.src.file,
cp->u.point.src.x, cp->u.point.src.y);
if (n > 0)
refinc = (float)n/ncalled;
}
if (glevel > 2) locus(identifiers, &cp->u.point.src);
if (events.points && reachable(Gen))
{
Tree e = NULL;
apply(events.points, &cp->u.point.src, &e);
if (e)
listnodes(e, 0, 0);
}
}
void statement(int loop, Swtch swp, int lev) {
float ref = refinc;
if (Aflag >= 2 && lev == 15)
warning("more than 15 levels of nested statements\n");
switch (t) {
case IF: ifstmt(genlabel(2), loop, swp, lev + 1);
break;
case WHILE: whilestmt(genlabel(3), swp, lev + 1); break;
case DO: dostmt(genlabel(3), swp, lev + 1); expect(';');
break;
case FOR: forstmt(genlabel(4), swp, lev + 1);
break;
case BREAK: walk(NULL, 0, 0);
definept(NULL);
if (swp && swp->lab > loop)
branch(swp->lab + 1);
else if (loop)
branch(loop + 2);
else
error("illegal break statement\n");
t = gettok(); expect(';');
break;
case CONTINUE: walk(NULL, 0, 0);
definept(NULL);
if (loop)
branch(loop + 1);
else
error("illegal continue statement\n");
t = gettok(); expect(';');
break;
case SWITCH: swstmt(loop, genlabel(2), lev + 1);
break;
case CASE: {
int lab = genlabel(1);
if (swp == NULL)
error("illegal case label\n");
definelab(lab);
while (t == CASE) {
static char stop[] = { IF, ID, 0 };
Tree p;
t = gettok();
p = constexpr(0);
if (generic(p->op) == CNST && isint(p->type)) {
if (swp) {
needconst++;
p = cast(p, swp->sym->type);
if (p->type->op == UNSIGNED)
p->u.v.i = extend(p->u.v.u, p->type);
needconst--;
caselabel(swp, p->u.v.i, lab);
}
} else
error("case label must be a constant integer expression\n");
test(':', stop);
}
statement(loop, swp, lev);
} break;
case DEFAULT: if (swp == NULL)
error("illegal default label\n");
else if (swp->deflab)
error("extra default label\n");
else {
swp->deflab = findlabel(swp->lab);
definelab(swp->deflab->u.l.label);
}
t = gettok();
expect(':');
statement(loop, swp, lev); break;
case RETURN: {
Type rty = freturn(cfunc->type);
t = gettok();
definept(NULL);
if (t != ';')
if (rty == voidtype) {
error("extraneous return value\n");
expr(0);
retcode(NULL);
} else
retcode(expr(0));
else {
if (rty != voidtype)
warning("missing return value\n");
retcode(NULL);
}
branch(cfunc->u.f.label);
} expect(';');
break;
case '{': compound(loop, swp, lev + 1); break;
case ';': definept(NULL); t = gettok(); break;
case GOTO: walk(NULL, 0, 0);
definept(NULL);
t = gettok();
if (t == ID) {
Symbol p = lookup(token, stmtlabs);
if (p == NULL) {
p = install(token, &stmtlabs, 0, FUNC);
p->scope = LABELS;
p->u.l.label = genlabel(1);
p->src = src;
}
use(p, src);
branch(p->u.l.label);
t = gettok();
} else
error("missing label in goto\n"); expect(';');
break;
case ID: if (getchr() == ':') {
stmtlabel();
statement(loop, swp, lev);
break;
}
default: definept(NULL);
if (kind[t] != ID) {
error("unrecognized statement\n");
t = gettok();
} else {
Tree e = expr0(0);
listnodes(e, 0, 0);
if (nodecount == 0 || nodecount > 200)
walk(NULL, 0, 0);
else if (glevel) walk(NULL, 0, 0);
deallocate(STMT);
} expect(';');
break;
}
if (kind[t] != IF && kind[t] != ID
&& t != '}' && t != EOI) {
static char stop[] = { IF, ID, '}', 0 };
error("illegal statement termination\n");
skipto(0, stop);
}
refinc = ref;
}
static void ifstmt(int lab, int loop, Swtch swp, int lev) {
t = gettok();
expect('(');
definept(NULL);
walk(conditional(')'), 0, lab);
refinc /= 2.0;
statement(loop, swp, lev);
if (t == ELSE) {
branch(lab + 1);
t = gettok();
definelab(lab);
statement(loop, swp, lev);
if (findlabel(lab + 1)->ref)
definelab(lab + 1);
} else
definelab(lab);
}
static Tree conditional(int tok) {
Tree p = expr(tok);
if (Aflag > 1 && isfunc(p->type))
warning("%s used in a conditional expression\n",
funcname(p));
return cond(p);
}
static void stmtlabel(void) {
Symbol p = lookup(token, stmtlabs);
if (p == NULL) {
p = install(token, &stmtlabs, 0, FUNC);
p->scope = LABELS;
p->u.l.label = genlabel(1);
p->src = src;
}
if (p->defined)
error("redefinition of label `%s' previously defined at %w\n", p->name, &p->src);
p->defined = 1;
definelab(p->u.l.label);
t = gettok();
expect(':');
}
static void forstmt(int lab, Swtch swp, int lev) {
int once = 0;
Tree e1 = NULL, e2 = NULL, e3 = NULL;
Coordinate pt2, pt3;
t = gettok();
expect('(');
definept(NULL);
if (kind[t] == ID)
e1 = texpr(expr0, ';', FUNC);
else
expect(';');
walk(e1, 0, 0);
pt2 = src;
refinc *= 10.0;
if (kind[t] == ID)
e2 = texpr(conditional, ';', FUNC);
else
expect(';');
pt3 = src;
if (kind[t] == ID)
e3 = texpr(expr0, ')', FUNC);
else {
static char stop[] = { IF, ID, '}', 0 };
test(')', stop);
}
if (e2) {
once = foldcond(e1, e2);
if (!once)
branch(lab + 3);
}
definelab(lab);
statement(lab, swp, lev);
definelab(lab + 1);
definept(&pt3);
if (e3)
walk(e3, 0, 0);
if (e2) {
if (!once)
definelab(lab + 3);
definept(&pt2);
walk(e2, lab, 0);
} else {
definept(&pt2);
branch(lab);
}
if (findlabel(lab + 2)->ref)
definelab(lab + 2);
}
static void swstmt(int loop, int lab, int lev) {
Tree e;
struct swtch sw;
Code head, tail;
t = gettok();
expect('(');
definept(NULL);
e = expr(')');
if (!isint(e->type)) {
error("illegal type `%t' in switch expression\n",
e->type);
e = retype(e, inttype);
}
e = cast(e, promote(e->type));
if (generic(e->op) == INDIR && isaddrop(e->kids[0]->op)
&& e->kids[0]->u.sym->type == e->type
&& !isvolatile(e->kids[0]->u.sym->type)) {
sw.sym = e->kids[0]->u.sym;
walk(NULL, 0, 0);
} else {
sw.sym = genident(REGISTER, e->type, level);
addlocal(sw.sym);
walk(asgn(sw.sym, e), 0, 0);
}
head = code(Switch);
sw.lab = lab;
sw.deflab = NULL;
sw.ncases = 0;
sw.size = SWSIZE;
sw.values = newarray(SWSIZE, sizeof *sw.values, FUNC);
sw.labels = newarray(SWSIZE, sizeof *sw.labels, FUNC);
refinc /= 10.0;
statement(loop, &sw, lev);
if (sw.deflab == NULL) {
sw.deflab = findlabel(lab);
definelab(lab);
if (sw.ncases == 0)
warning("switch statement with no cases\n");
}
if (findlabel(lab + 1)->ref)
definelab(lab + 1);
tail = codelist;
codelist = head->prev;
codelist->next = head->prev = NULL;
if (sw.ncases > 0)
swgen(&sw);
branch(lab);
head->next->prev = codelist;
codelist->next = head->next;
codelist = tail;
}
static void caselabel(Swtch swp, long val, int lab) {
int k;
if (swp->ncases >= swp->size)
{
long *vals = swp->values;
Symbol *labs = swp->labels;
swp->size *= 2;
swp->values = newarray(swp->size, sizeof *swp->values, FUNC);
swp->labels = newarray(swp->size, sizeof *swp->labels, FUNC);
for (k = 0; k < swp->ncases; k++) {
swp->values[k] = vals[k];
swp->labels[k] = labs[k];
}
}
k = swp->ncases;
for ( ; k > 0 && swp->values[k-1] >= val; k--) {
swp->values[k] = swp->values[k-1];
swp->labels[k] = swp->labels[k-1];
}
if (k < swp->ncases && swp->values[k] == val)
error("duplicate case label `%d'\n", val);
swp->values[k] = val;
swp->labels[k] = findlabel(lab);
++swp->ncases;
if (Aflag >= 2 && swp->ncases == 258)
warning("more than 257 cases in a switch\n");
}
void swgen(Swtch swp) {
int *buckets, k, n;
long *v = swp->values;
buckets = newarray(swp->ncases + 1,
sizeof *buckets, FUNC);
for (n = k = 0; k < swp->ncases; k++, n++) {
buckets[n] = k;
while (n > 0 && den(n-1, k) >= density)
n--;
}
buckets[n] = swp->ncases;
swcode(swp, buckets, 0, n - 1);
}
void swcode(Swtch swp, int b[], int lb, int ub) {
int hilab, lolab, l, u, k = (lb + ub)/2;
long *v = swp->values;
if (k > lb && k < ub) {
lolab = genlabel(1);
hilab = genlabel(1);
} else if (k > lb) {
lolab = genlabel(1);
hilab = swp->deflab->u.l.label;
} else if (k < ub) {
lolab = swp->deflab->u.l.label;
hilab = genlabel(1);
} else
lolab = hilab = swp->deflab->u.l.label;
l = b[k];
u = b[k+1] - 1;
if (u - l + 1 <= 3)
{
int i;
for (i = l; i <= u; i++)
cmp(EQ, swp->sym, v[i], swp->labels[i]->u.l.label);
if (k > lb && k < ub)
cmp(GT, swp->sym, v[u], hilab);
else if (k > lb)
cmp(GT, swp->sym, v[u], hilab);
else if (k < ub)
cmp(LT, swp->sym, v[l], lolab);
else
assert(lolab == hilab),
branch(lolab);
walk(NULL, 0, 0);
}
else {
Tree e;
Type ty = signedint(swp->sym->type);
Symbol table = genident(STATIC,
array(voidptype, u - l + 1, 0), GLOBAL);
(*IR->defsymbol)(table);
if (!isunsigned(swp->sym->type) || v[l] != 0)
cmp(LT, swp->sym, v[l], lolab);
cmp(GT, swp->sym, v[u], hilab);
e = (*optree['-'])(SUB, cast(idtree(swp->sym), ty), cnsttree(ty, v[l]));
if (e->type->size < unsignedptr->size)
e = cast(e, unsignedlong);
walk(tree(JUMP, voidtype,
rvalue((*optree['+'])(ADD, pointer(idtree(table)), e)), NULL),
0, 0);
code(Switch);
codelist->u.swtch.table = table;
codelist->u.swtch.sym = swp->sym;
codelist->u.swtch.deflab = swp->deflab;
codelist->u.swtch.size = u - l + 1;
codelist->u.swtch.values = &v[l];
codelist->u.swtch.labels = &swp->labels[l];
if (v[u] - v[l] + 1 >= 10000)
warning("switch generates a huge table\n");
}
if (k > lb) {
assert(lolab != swp->deflab->u.l.label);
definelab(lolab);
swcode(swp, b, lb, k - 1);
}
if (k < ub) {
assert(hilab != swp->deflab->u.l.label);
definelab(hilab);
swcode(swp, b, k + 1, ub);
}
}
static void cmp(int op, Symbol p, long n, int lab) {
Type ty = signedint(p->type);
listnodes(eqtree(op,
cast(idtree(p), ty),
cnsttree(ty, n)),
lab, 0);
}
void retcode(Tree p) {
Type ty;
if (p == NULL) {
if (events.returns)
apply(events.returns, cfunc, NULL);
return;
}
p = pointer(p);
ty = assign(freturn(cfunc->type), p);
if (ty == NULL) {
error("illegal return type; found `%t' expected `%t'\n",
p->type, freturn(cfunc->type));
return;
}
p = cast(p, ty);
if (retv)
{
if (iscallb(p))
p = tree(RIGHT, p->type,
tree(CALL+B, p->type,
p->kids[0]->kids[0], idtree(retv)),
rvalue(idtree(retv)));
else
p = asgntree(ASGN, rvalue(idtree(retv)), p);
walk(p, 0, 0);
if (events.returns)
apply(events.returns, cfunc, rvalue(idtree(retv)));
return;
}
if (events.returns)
{
Symbol t1 = genident(AUTO, p->type, level);
addlocal(t1);
walk(asgn(t1, p), 0, 0);
apply(events.returns, cfunc, idtree(t1));
p = idtree(t1);
}
if (!isfloat(p->type))
p = cast(p, promote(p->type));
if (isptr(p->type))
{
Symbol q = localaddr(p);
if (q && (q->computed || q->generated))
warning("pointer to a %s is an illegal return value\n",
q->scope == PARAM ? "parameter" : "local");
else if (q)
warning("pointer to %s `%s' is an illegal return value\n",
q->scope == PARAM ? "parameter" : "local", q->name);
}
walk(tree(mkop(RET,p->type), p->type, p, NULL), 0, 0);
}
void definelab(int lab) {
Code cp;
Symbol p = findlabel(lab);
assert(lab);
walk(NULL, 0, 0);
code(Label)->u.forest = newnode(LABEL+V, NULL, NULL, p);
for (cp = codelist->prev; cp->kind <= Label; )
cp = cp->prev;
while ( cp->kind == Jump
&& cp->u.forest->kids[0]
&& specific(cp->u.forest->kids[0]->op) == ADDRG+P
&& cp->u.forest->kids[0]->syms[0] == p) {
assert(cp->u.forest->kids[0]->syms[0]->u.l.label == lab);
p->ref--;
assert(cp->next);
assert(cp->prev);
cp->prev->next = cp->next;
cp->next->prev = cp->prev;
cp = cp->prev;
while (cp->kind <= Label)
cp = cp->prev;
}
}
Node jump(int lab) {
Symbol p = findlabel(lab);
p->ref++;
return newnode(JUMP+V, newnode(ADDRG+ttob(voidptype), NULL, NULL, p),
NULL, NULL);
}
void branch(int lab) {
Code cp;
Symbol p = findlabel(lab);
assert(lab);
walk(NULL, 0, 0);
code(Label)->u.forest = jump(lab);
for (cp = codelist->prev; cp->kind < Label; )
cp = cp->prev;
while ( cp->kind == Label
&& cp->u.forest->op == LABEL+V
&& !equal(cp->u.forest->syms[0], p)) {
equatelab(cp->u.forest->syms[0], p);
assert(cp->next);
assert(cp->prev);
cp->prev->next = cp->next;
cp->next->prev = cp->prev;
cp = cp->prev;
while (cp->kind < Label)
cp = cp->prev;
}
if (cp->kind == Jump || cp->kind == Switch) {
p->ref--;
codelist->prev->next = NULL;
codelist = codelist->prev;
} else {
codelist->kind = Jump;
if (cp->kind == Label
&& cp->u.forest->op == LABEL+V
&& equal(cp->u.forest->syms[0], p))
warning("source code specifies an infinite loop");
}
}
void equatelab(Symbol old, Symbol new) {
assert(old->u.l.equatedto == NULL);
old->u.l.equatedto = new;
new->ref++;
}
static int equal(Symbol lprime, Symbol dst) {
assert(dst && lprime);
for ( ; dst; dst = dst->u.l.equatedto)
if (lprime == dst)
return 1;
return 0;
}
/* dostmt - do statement while ( expression ) */
static void dostmt(int lab, Swtch swp, int lev) {
refinc *= 10.0;
t = gettok();
definelab(lab);
statement(lab, swp, lev);
definelab(lab + 1);
expect(WHILE);
expect('(');
definept(NULL);
walk(conditional(')'), lab, 0);
if (findlabel(lab + 2)->ref)
definelab(lab + 2);
}
/* foldcond - check if initial test in for(e1;e2;e3) S is necessary */
static int foldcond(Tree e1, Tree e2) {
int op = generic(e2->op);
Symbol v;
if (e1 == 0 || e2 == 0)
return 0;
if (generic(e1->op) == ASGN && isaddrop(e1->kids[0]->op)
&& generic(e1->kids[1]->op) == CNST) {
v = e1->kids[0]->u.sym;
e1 = e1->kids[1];
} else
return 0;
if ((op==LE || op==LT || op==EQ || op==NE || op==GT || op==GE)
&& generic(e2->kids[0]->op) == INDIR
&& e2->kids[0]->kids[0]->u.sym == v
&& e2->kids[1]->op == e1->op) {
e1 = simplify(op, e2->type, e1, e2->kids[1]);
if (e1->op == CNST+I)
return e1->u.v.i;
}
return 0;
}
/* localaddr - returns q if p yields the address of local/parameter q; otherwise returns 0 */
static Symbol localaddr(Tree p) {
if (p == NULL)
return NULL;
switch (generic(p->op)) {
case INDIR: case CALL: case ARG:
return NULL;
case ADDRL: case ADDRF:
return p->u.sym;
case RIGHT: case ASGN:
if (p->kids[1])
return localaddr(p->kids[1]);
return localaddr(p->kids[0]);
case COND: {
Symbol q;
assert(p->kids[1] && p->kids[1]->op == RIGHT);
if ((q = localaddr(p->kids[1]->kids[0])) != NULL)
return q;
return localaddr(p->kids[1]->kids[1]);
}
default: {
Symbol q;
if (p->kids[0] && (q = localaddr(p->kids[0])) != NULL)
return q;
return localaddr(p->kids[1]);
}
}
}
/* whilestmt - while ( expression ) statement */
static void whilestmt(int lab, Swtch swp, int lev) {
Coordinate pt;
Tree e;
refinc *= 10.0;
t = gettok();
expect('(');
walk(NULL, 0, 0);
pt = src;
e = texpr(conditional, ')', FUNC);
branch(lab + 1);
definelab(lab);
statement(lab, swp, lev);
definelab(lab + 1);
definept(&pt);
walk(e, lab, 0);
if (findlabel(lab + 2)->ref)
definelab(lab + 2);
}

122
code/tools/lcc/src/string.c Normal file
View file

@ -0,0 +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;
}
}

314
code/tools/lcc/src/sym.c Normal file
View file

@ -0,0 +1,314 @@
#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) {
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;
}

View file

@ -0,0 +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("&amp;");
else if (*s == '<' && html)
print("&lt;");
else if (*s == '>' && html)
print("&lt;");
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)
};

133
code/tools/lcc/src/token.h Normal file
View file

@ -0,0 +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

181
code/tools/lcc/src/trace.c Normal file
View file

@ -0,0 +1,181 @@
#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;
}
}

223
code/tools/lcc/src/tree.c Normal file
View file

@ -0,0 +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);
}

748
code/tools/lcc/src/types.c Normal file
View file

@ -0,0 +1,748 @@
#include "c.h"
#include <float.h>
static Field isfield(const char *, Field);
static Type type(int, Type, int, int, void *);
static struct entry {
struct type type;
struct entry *link;
} *typetable[128];
static int maxlevel;
static Symbol pointersym;
Type chartype; /* char */
Type doubletype; /* double */
Type floattype; /* float */
Type inttype; /* signed int */
Type longdouble; /* long double */
Type longtype; /* long */
Type longlong; /* long long */
Type shorttype; /* signed short int */
Type signedchar; /* signed char */
Type unsignedchar; /* unsigned char */
Type unsignedlong; /* unsigned long int */
Type unsignedlonglong; /* unsigned long long int */
Type unsignedshort; /* unsigned short int */
Type unsignedtype; /* unsigned int */
Type funcptype; /* void (*)() */
Type charptype; /* char* */
Type voidptype; /* void* */
Type voidtype; /* basic types: void */
Type unsignedptr; /* unsigned type to hold void* */
Type signedptr; /* signed type to hold void* */
Type widechar; /* unsigned type that represents wchar_t */
static Type xxinit(int op, char *name, Metrics m) {
Symbol p = install(string(name), &types, GLOBAL, PERM);
Type ty = type(op, 0, m.size, m.align, p);
assert(ty->align == 0 || ty->size%ty->align == 0);
p->type = ty;
p->addressed = m.outofline;
switch (ty->op) {
case INT:
p->u.limits.max.i = ones(8*ty->size)>>1;
p->u.limits.min.i = -p->u.limits.max.i - 1;
break;
case UNSIGNED:
p->u.limits.max.u = ones(8*ty->size);
p->u.limits.min.u = 0;
break;
case FLOAT:
if (ty->size == sizeof (float))
p->u.limits.max.d = FLT_MAX;
else if (ty->size == sizeof (double))
p->u.limits.max.d = DBL_MAX;
else
p->u.limits.max.d = LDBL_MAX;
p->u.limits.min.d = -p->u.limits.max.d;
break;
default: assert(0);
}
return ty;
}
static Type type(int op, Type ty, int size, int align, void *sym) {
unsigned h = (op^((unsigned long)ty>>3))
&(NELEMS(typetable)-1);
struct entry *tn;
if (op != FUNCTION && (op != ARRAY || size > 0))
for (tn = typetable[h]; tn; tn = tn->link)
if (tn->type.op == op && tn->type.type == ty
&& tn->type.size == size && tn->type.align == align
&& tn->type.u.sym == sym)
return &tn->type;
NEW0(tn, PERM);
tn->type.op = op;
tn->type.type = ty;
tn->type.size = size;
tn->type.align = align;
tn->type.u.sym = sym;
tn->link = typetable[h];
typetable[h] = tn;
return &tn->type;
}
void type_init(int argc, char *argv[]) {
static int inited;
int i;
if (inited)
return;
inited = 1;
if (!IR)
return;
for (i = 1; i < argc; i++) {
int size, align, outofline;
if (strncmp(argv[i], "-unsigned_char=", 15) == 0)
IR->unsigned_char = argv[i][15] - '0';
#define xx(name) \
else if (sscanf(argv[i], "-" #name "=%d,%d,%d", &size, &align, &outofline) == 3) { \
IR->name.size = size; IR->name.align = align; \
IR->name.outofline = outofline; }
xx(charmetric)
xx(shortmetric)
xx(intmetric)
xx(longmetric)
xx(longlongmetric)
xx(floatmetric)
xx(doublemetric)
xx(longdoublemetric)
xx(ptrmetric)
xx(structmetric)
#undef xx
}
#define xx(v,name,op,metrics) v=xxinit(op,name,IR->metrics)
xx(chartype, "char", IR->unsigned_char ? UNSIGNED : INT,charmetric);
xx(doubletype, "double", FLOAT, doublemetric);
xx(floattype, "float", FLOAT, floatmetric);
xx(inttype, "int", INT, intmetric);
xx(longdouble, "long double", FLOAT, longdoublemetric);
xx(longtype, "long int", INT, longmetric);
xx(longlong, "long long int", INT, longlongmetric);
xx(shorttype, "short", INT, shortmetric);
xx(signedchar, "signed char", INT, charmetric);
xx(unsignedchar, "unsigned char", UNSIGNED,charmetric);
xx(unsignedlong, "unsigned long", UNSIGNED,longmetric);
xx(unsignedshort, "unsigned short", UNSIGNED,shortmetric);
xx(unsignedtype, "unsigned int", UNSIGNED,intmetric);
xx(unsignedlonglong,"unsigned long long",UNSIGNED,longlongmetric);
#undef xx
{
Symbol p;
p = install(string("void"), &types, GLOBAL, PERM);
voidtype = type(VOID, NULL, 0, 0, p);
p->type = voidtype;
}
pointersym = install(string("T*"), &types, GLOBAL, PERM);
pointersym->addressed = IR->ptrmetric.outofline;
pointersym->u.limits.max.p = (void*)ones(8*IR->ptrmetric.size);
pointersym->u.limits.min.p = 0;
voidptype = ptr(voidtype);
funcptype = ptr(func(voidtype, NULL, 1));
charptype = ptr(chartype);
#define xx(v,t) if (v==NULL && t->size==voidptype->size && t->align==voidptype->align) v=t
xx(unsignedptr,unsignedshort);
xx(unsignedptr,unsignedtype);
xx(unsignedptr,unsignedlong);
xx(unsignedptr,unsignedlonglong);
if (unsignedptr == NULL)
unsignedptr = type(UNSIGNED, NULL, voidptype->size, voidptype->align, voidptype->u.sym);
xx(signedptr,shorttype);
xx(signedptr,inttype);
xx(signedptr,longtype);
xx(signedptr,longlong);
if (signedptr == NULL)
signedptr = type(INT, NULL, voidptype->size, voidptype->align, voidptype->u.sym);
#undef xx
widechar = unsignedshort;
for (i = 0; i < argc; i++) {
#define xx(name,type) \
if (strcmp(argv[i], "-wchar_t=" #name) == 0) \
widechar = type;
xx(unsigned_char,unsignedchar)
xx(unsigned_int,unsignedtype)
xx(unsigned_short,unsignedshort)
}
#undef xx
}
void rmtypes(int lev) {
if (maxlevel >= lev) {
int i;
maxlevel = 0;
for (i = 0; i < NELEMS(typetable); i++) {
struct entry *tn, **tq = &typetable[i];
while ((tn = *tq) != NULL)
if (tn->type.op == FUNCTION)
tq = &tn->link;
else if (tn->type.u.sym && tn->type.u.sym->scope >= lev)
*tq = tn->link;
else {
if (tn->type.u.sym && tn->type.u.sym->scope > maxlevel)
maxlevel = tn->type.u.sym->scope;
tq = &tn->link;
}
}
}
}
Type ptr(Type ty) {
return type(POINTER, ty, IR->ptrmetric.size,
IR->ptrmetric.align, pointersym);
}
Type deref(Type ty) {
if (isptr(ty))
ty = ty->type;
else
error("type error: %s\n", "pointer expected");
return isenum(ty) ? unqual(ty)->type : ty;
}
Type array(Type ty, int n, int a) {
assert(ty);
if (isfunc(ty)) {
error("illegal type `array of %t'\n", ty);
return array(inttype, n, 0);
}
if (isarray(ty) && ty->size == 0)
error("missing array size\n");
if (ty->size == 0) {
if (unqual(ty) == voidtype)
error("illegal type `array of %t'\n", ty);
else if (Aflag >= 2)
warning("declaring type array of %t' is undefined\n", ty);
} else if (n > INT_MAX/ty->size) {
error("size of `array of %t' exceeds %d bytes\n",
ty, INT_MAX);
n = 1;
}
return type(ARRAY, ty, n*ty->size,
a ? a : ty->align, NULL);
}
Type atop(Type ty) {
if (isarray(ty))
return ptr(ty->type);
error("type error: %s\n", "array expected");
return ptr(ty);
}
Type qual(int op, Type ty) {
if (isarray(ty))
ty = type(ARRAY, qual(op, ty->type), ty->size,
ty->align, NULL);
else if (isfunc(ty))
warning("qualified function type ignored\n");
else if ((isconst(ty) && op == CONST)
|| (isvolatile(ty) && op == VOLATILE))
error("illegal type `%k %t'\n", op, ty);
else {
if (isqual(ty)) {
op += ty->op;
ty = ty->type;
}
ty = type(op, ty, ty->size, ty->align, NULL);
}
return ty;
}
Type func(Type ty, Type *proto, int style) {
if (ty && (isarray(ty) || isfunc(ty)))
error("illegal return type `%t'\n", ty);
ty = type(FUNCTION, ty, 0, 0, NULL);
ty->u.f.proto = proto;
ty->u.f.oldstyle = style;
return ty;
}
Type freturn(Type ty) {
if (isfunc(ty))
return ty->type;
error("type error: %s\n", "function expected");
return inttype;
}
int variadic(Type ty) {
if (isfunc(ty) && ty->u.f.proto) {
int i;
for (i = 0; ty->u.f.proto[i]; i++)
;
return i > 1 && ty->u.f.proto[i-1] == voidtype;
}
return 0;
}
Type newstruct(int op, char *tag) {
Symbol p;
assert(tag);
if (*tag == 0)
tag = stringd(genlabel(1));
else
if ((p = lookup(tag, types)) != NULL && (p->scope == level
|| (p->scope == PARAM && level == PARAM+1))) {
if (p->type->op == op && !p->defined)
return p->type;
error("redefinition of `%s' previously defined at %w\n",
p->name, &p->src);
}
p = install(tag, &types, level, PERM);
p->type = type(op, NULL, 0, 0, p);
if (p->scope > maxlevel)
maxlevel = p->scope;
p->src = src;
return p->type;
}
Field newfield(char *name, Type ty, Type fty) {
Field p, *q = &ty->u.sym->u.s.flist;
if (name == NULL)
name = stringd(genlabel(1));
for (p = *q; p; q = &p->link, p = *q)
if (p->name == name)
error("duplicate field name `%s' in `%t'\n",
name, ty);
NEW0(p, PERM);
*q = p;
p->name = name;
p->type = fty;
if (xref) { /* omit */
if (ty->u.sym->u.s.ftab == NULL) /* omit */
ty->u.sym->u.s.ftab = table(NULL, level); /* omit */
install(name, &ty->u.sym->u.s.ftab, 0, PERM)->src = src;/* omit */
} /* omit */
return p;
}
int eqtype(Type ty1, Type ty2, int ret) {
if (ty1 == ty2)
return 1;
if (ty1->op != ty2->op)
return 0;
switch (ty1->op) {
case ENUM: case UNION: case STRUCT:
case UNSIGNED: case INT: case FLOAT:
return 0;
case POINTER: return eqtype(ty1->type, ty2->type, 1);
case VOLATILE: case CONST+VOLATILE:
case CONST: return eqtype(ty1->type, ty2->type, 1);
case ARRAY: if (eqtype(ty1->type, ty2->type, 1)) {
if (ty1->size == ty2->size)
return 1;
if (ty1->size == 0 || ty2->size == 0)
return ret;
}
return 0;
case FUNCTION: if (eqtype(ty1->type, ty2->type, 1)) {
Type *p1 = ty1->u.f.proto, *p2 = ty2->u.f.proto;
if (p1 == p2)
return 1;
if (p1 && p2) {
for ( ; *p1 && *p2; p1++, p2++)
if (eqtype(unqual(*p1), unqual(*p2), 1) == 0)
return 0;
if (*p1 == NULL && *p2 == NULL)
return 1;
} else {
if (variadic(p1 ? ty1 : ty2))
return 0;
if (p1 == NULL)
p1 = p2;
for ( ; *p1; p1++) {
Type ty = unqual(*p1);
if (promote(ty) != (isenum(ty) ? ty->type : ty))
return 0;
}
return 1;
}
}
return 0;
}
assert(0); return 0;
}
Type promote(Type ty) {
ty = unqual(ty);
switch (ty->op) {
case ENUM:
return inttype;
case INT:
if (ty->size < inttype->size)
return inttype;
break;
case UNSIGNED:
if (ty->size < inttype->size)
return inttype;
if (ty->size < unsignedtype->size)
return unsignedtype;
break;
case FLOAT:
if (ty->size < doubletype->size)
return doubletype;
}
return ty;
}
Type signedint(Type ty) {
if (ty->op == INT)
return ty;
assert(ty->op == UNSIGNED);
#define xx(t) if (ty->size == t->size) return t
xx(inttype);
xx(longtype);
xx(longlong);
#undef xx
assert(0); return NULL;
}
Type compose(Type ty1, Type ty2) {
if (ty1 == ty2)
return ty1;
assert(ty1->op == ty2->op);
switch (ty1->op) {
case POINTER:
return ptr(compose(ty1->type, ty2->type));
case CONST+VOLATILE:
return qual(CONST, qual(VOLATILE,
compose(ty1->type, ty2->type)));
case CONST: case VOLATILE:
return qual(ty1->op, compose(ty1->type, ty2->type));
case ARRAY: { Type ty = compose(ty1->type, ty2->type);
if (ty1->size && ((ty1->type->size && ty2->size == 0) || ty1->size == ty2->size))
return array(ty, ty1->size/ty1->type->size, ty1->align);
if (ty2->size && ty2->type->size && ty1->size == 0)
return array(ty, ty2->size/ty2->type->size, ty2->align);
return array(ty, 0, 0); }
case FUNCTION: { Type *p1 = ty1->u.f.proto, *p2 = ty2->u.f.proto;
Type ty = compose(ty1->type, ty2->type);
List tlist = NULL;
if (p1 == NULL && p2 == NULL)
return func(ty, NULL, 1);
if (p1 && p2 == NULL)
return func(ty, p1, ty1->u.f.oldstyle);
if (p2 && p1 == NULL)
return func(ty, p2, ty2->u.f.oldstyle);
for ( ; *p1 && *p2; p1++, p2++) {
Type ty = compose(unqual(*p1), unqual(*p2));
if (isconst(*p1) || isconst(*p2))
ty = qual(CONST, ty);
if (isvolatile(*p1) || isvolatile(*p2))
ty = qual(VOLATILE, ty);
tlist = append(ty, tlist);
}
assert(*p1 == NULL && *p2 == NULL);
return func(ty, ltov(&tlist, PERM), 0); }
}
assert(0); return NULL;
}
int ttob(Type ty) {
switch (ty->op) {
case CONST: case VOLATILE: case CONST+VOLATILE:
return ttob(ty->type);
case VOID: case INT: case UNSIGNED: case FLOAT:
return ty->op + sizeop(ty->size);
case POINTER:
return POINTER + sizeop(voidptype->size);
case FUNCTION:
return POINTER + sizeop(funcptype->size);
case ARRAY: case STRUCT: case UNION:
return STRUCT;
case ENUM:
return INT + sizeop(inttype->size);
}
assert(0); return INT;
}
Type btot(int op, int size) {
#define xx(ty) if (size == (ty)->size) return ty;
switch (optype(op)) {
case F:
xx(floattype);
xx(doubletype);
xx(longdouble);
assert(0); return 0;
case I:
if (chartype->op == INT)
xx(chartype);
xx(signedchar);
xx(shorttype);
xx(inttype);
xx(longtype);
xx(longlong);
assert(0); return 0;
case U:
if (chartype->op == UNSIGNED)
xx(chartype);
xx(unsignedchar);
xx(unsignedshort);
xx(unsignedtype);
xx(unsignedlong);
xx(unsignedlonglong);
assert(0); return 0;
case P:
xx(voidptype);
xx(funcptype);
assert(0); return 0;
}
#undef xx
assert(0); return 0;
}
int hasproto(Type ty) {
if (ty == 0)
return 1;
switch (ty->op) {
case CONST: case VOLATILE: case CONST+VOLATILE: case POINTER:
case ARRAY:
return hasproto(ty->type);
case FUNCTION:
return hasproto(ty->type) && ty->u.f.proto;
case STRUCT: case UNION:
case VOID: case FLOAT: case ENUM: case INT: case UNSIGNED:
return 1;
}
assert(0); return 0;
}
/* fieldlist - construct a flat list of fields in type ty */
Field fieldlist(Type ty) {
return ty->u.sym->u.s.flist;
}
/* fieldref - find field name of type ty, return entry */
Field fieldref(const char *name, Type ty) {
Field p = isfield(name, unqual(ty)->u.sym->u.s.flist);
if (p && xref) {
Symbol q;
assert(unqual(ty)->u.sym->u.s.ftab);
q = lookup(name, unqual(ty)->u.sym->u.s.ftab);
assert(q);
use(q, src);
}
return p;
}
/* ftype - return a function type for rty function (ty,...)' */
Type ftype(Type rty, Type ty) {
List list = append(ty, NULL);
list = append(voidtype, list);
return func(rty, ltov(&list, PERM), 0);
}
/* isfield - if name is a field in flist, return pointer to the field structure */
static Field isfield(const char *name, Field flist) {
for ( ; flist; flist = flist->link)
if (flist->name == name)
break;
return flist;
}
/* outtype - output type ty */
void outtype(Type ty, FILE *f) {
switch (ty->op) {
case CONST+VOLATILE: case CONST: case VOLATILE:
fprint(f, "%k %t", ty->op, ty->type);
break;
case STRUCT: case UNION: case ENUM:
assert(ty->u.sym);
if (ty->size == 0)
fprint(f, "incomplete ");
assert(ty->u.sym->name);
if (*ty->u.sym->name >= '1' && *ty->u.sym->name <= '9') {
Symbol p = findtype(ty);
if (p == 0)
fprint(f, "%k defined at %w", ty->op, &ty->u.sym->src);
else
fprint(f, p->name);
} else {
fprint(f, "%k %s", ty->op, ty->u.sym->name);
if (ty->size == 0)
fprint(f, " defined at %w", &ty->u.sym->src);
}
break;
case VOID: case FLOAT: case INT: case UNSIGNED:
fprint(f, ty->u.sym->name);
break;
case POINTER:
fprint(f, "pointer to %t", ty->type);
break;
case FUNCTION:
fprint(f, "%t function", ty->type);
if (ty->u.f.proto && ty->u.f.proto[0]) {
int i;
fprint(f, "(%t", ty->u.f.proto[0]);
for (i = 1; ty->u.f.proto[i]; i++)
if (ty->u.f.proto[i] == voidtype)
fprint(f, ",...");
else
fprint(f, ",%t", ty->u.f.proto[i]);
fprint(f, ")");
} else if (ty->u.f.proto && ty->u.f.proto[0] == 0)
fprint(f, "(void)");
break;
case ARRAY:
if (ty->size > 0 && ty->type && ty->type->size > 0) {
fprint(f, "array %d", ty->size/ty->type->size);
while (ty->type && isarray(ty->type) && ty->type->type->size > 0) {
ty = ty->type;
fprint(f, ",%d", ty->size/ty->type->size);
}
} else
fprint(f, "incomplete array");
if (ty->type)
fprint(f, " of %t", ty->type);
break;
default: assert(0);
}
}
/* printdecl - output a C declaration for symbol p of type ty */
void printdecl(Symbol p, Type ty) {
switch (p->sclass) {
case AUTO:
fprint(stderr, "%s;\n", typestring(ty, p->name));
break;
case STATIC: case EXTERN:
fprint(stderr, "%k %s;\n", p->sclass, typestring(ty, p->name));
break;
case TYPEDEF: case ENUM:
break;
default: assert(0);
}
}
/* printproto - output a prototype declaration for function p */
void printproto(Symbol p, Symbol callee[]) {
if (p->type->u.f.proto)
printdecl(p, p->type);
else {
int i;
List list = 0;
if (callee[0] == 0)
list = append(voidtype, list);
else
for (i = 0; callee[i]; i++)
list = append(callee[i]->type, list);
printdecl(p, func(freturn(p->type), ltov(&list, PERM), 0));
}
}
/* prtype - print details of type ty on f with given indent */
static void prtype(Type ty, FILE *f, int indent, unsigned mark) {
switch (ty->op) {
default:
fprint(f, "(%d %d %d [%p])", ty->op, ty->size, ty->align, ty->u.sym);
break;
case FLOAT: case INT: case UNSIGNED: case VOID:
fprint(f, "(%k %d %d [\"%s\"])", ty->op, ty->size, ty->align, ty->u.sym->name);
break;
case CONST+VOLATILE: case CONST: case VOLATILE: case POINTER: case ARRAY:
fprint(f, "(%k %d %d ", ty->op, ty->size, ty->align);
prtype(ty->type, f, indent+1, mark);
fprint(f, ")");
break;
case STRUCT: case UNION:
fprint(f, "(%k %d %d [\"%s\"]", ty->op, ty->size, ty->align, ty->u.sym->name);
if (ty->x.marked != mark) {
Field p;
ty->x.marked = mark;
for (p = ty->u.sym->u.s.flist; p; p = p->link) {
fprint(f, "\n%I", indent+1);
prtype(p->type, f, indent+1, mark);
fprint(f, " %s@%d", p->name, p->offset);
if (p->lsb)
fprint(f, ":%d..%d",
fieldsize(p) + fieldright(p), fieldright(p));
}
fprint(f, "\n%I", indent);
}
fprint(f, ")");
break;
case ENUM:
fprint(f, "(%k %d %d [\"%s\"]", ty->op, ty->size, ty->align, ty->u.sym->name);
if (ty->x.marked != mark) {
int i;
Symbol *p = ty->u.sym->u.idlist;
ty->x.marked = mark;
for (i = 0; p[i] != NULL; i++)
fprint(f, "%I%s=%d\n", indent+1, p[i]->name, p[i]->u.value);
}
fprint(f, ")");
break;
case FUNCTION:
fprint(f, "(%k %d %d ", ty->op, ty->size, ty->align);
prtype(ty->type, f, indent+1, mark);
if (ty->u.f.proto) {
int i;
fprint(f, "\n%I{", indent+1);
for (i = 0; ty->u.f.proto[i]; i++) {
if (i > 0)
fprint(f, "%I", indent+2);
prtype(ty->u.f.proto[i], f, indent+2, mark);
fprint(f, "\n");
}
fprint(f, "%I}", indent+1);
}
fprint(f, ")");
break;
}
}
/* printtype - print details of type ty on fd */
void printtype(Type ty, int fd) {
static unsigned mark;
prtype(ty, fd == 1 ? stdout : stderr, 0, ++mark);
fprint(fd == 1 ? stdout : stderr, "\n");
}
/* typestring - return ty as C declaration for str, which may be "" */
char *typestring(Type ty, char *str) {
for ( ; ty; ty = ty->type) {
Symbol p;
switch (ty->op) {
case CONST+VOLATILE: case CONST: case VOLATILE:
if (isptr(ty->type))
str = stringf("%k %s", ty->op, str);
else
return stringf("%k %s", ty->op, typestring(ty->type, str));
break;
case STRUCT: case UNION: case ENUM:
assert(ty->u.sym);
if ((p = findtype(ty)) != NULL)
return *str ? stringf("%s %s", p->name, str) : p->name;
if (*ty->u.sym->name >= '1' && *ty->u.sym->name <= '9')
warning("unnamed %k in prototype\n", ty->op);
if (*str)
return stringf("%k %s %s", ty->op, ty->u.sym->name, str);
else
return stringf("%k %s", ty->op, ty->u.sym->name);
case VOID: case FLOAT: case INT: case UNSIGNED:
return *str ? stringf("%s %s", ty->u.sym->name, str) : ty->u.sym->name;
case POINTER:
if (!ischar(ty->type) && (p = findtype(ty)) != NULL)
return *str ? stringf("%s %s", p->name, str) : p->name;
str = stringf(isarray(ty->type) || isfunc(ty->type) ? "(*%s)" : "*%s", str);
break;
case FUNCTION:
if ((p = findtype(ty)) != NULL)
return *str ? stringf("%s %s", p->name, str) : p->name;
if (ty->u.f.proto == 0)
str = stringf("%s()", str);
else if (ty->u.f.proto[0]) {
int i;
str = stringf("%s(%s", str, typestring(ty->u.f.proto[0], ""));
for (i = 1; ty->u.f.proto[i]; i++)
if (ty->u.f.proto[i] == voidtype)
str = stringf("%s, ...", str);
else
str = stringf("%s, %s", str, typestring(ty->u.f.proto[i], ""));
str = stringf("%s)", str);
} else
str = stringf("%s(void)", str);
break;
case ARRAY:
if ((p = findtype(ty)) != NULL)
return *str ? stringf("%s %s", p->name, str) : p->name;
if (ty->type && ty->type->size > 0)
str = stringf("%s[%d]", str, ty->size/ty->type->size);
else
str = stringf("%s[]", str);
break;
default: assert(0);
}
}
assert(0); return 0;
}

998
code/tools/lcc/src/x86.md Normal file
View file

@ -0,0 +1,998 @@
%{
enum { EAX=0, ECX=1, EDX=2, EBX=3, ESI=6, EDI=7 };
#include "c.h"
#define NODEPTR_TYPE Node
#define OP_LABEL(p) ((p)->op)
#define LEFT_CHILD(p) ((p)->kids[0])
#define RIGHT_CHILD(p) ((p)->kids[1])
#define STATE_LABEL(p) ((p)->x.state)
static void address(Symbol, Symbol, long);
static void blkfetch(int, int, int, int);
static void blkloop(int, int, int, int, int, int[]);
static void blkstore(int, int, int, int);
static void defaddress(Symbol);
static void defconst(int, int, Value);
static void defstring(int, char *);
static void defsymbol(Symbol);
static void doarg(Node);
static void emit2(Node);
static void export(Symbol);
static void clobber(Node);
static void function(Symbol, Symbol [], Symbol [], int);
static void global(Symbol);
static void import(Symbol);
static void local(Symbol);
static void progbeg(int, char **);
static void progend(void);
static void segment(int);
static void space(int);
static void target(Node);
extern int ckstack(Node, int);
extern int memop(Node);
extern int sametree(Node, Node);
static Symbol charreg[32], shortreg[32], intreg[32];
static Symbol fltreg[32];
static Symbol charregw, shortregw, intregw, fltregw;
static int cseg;
static Symbol quo, rem;
%}
%start stmt
%term CNSTF4=4113
%term CNSTF8=8209
%term CNSTF16=16401
%term CNSTI1=1045
%term CNSTI2=2069
%term CNSTI4=4117
%term CNSTI8=8213
%term CNSTP4=4119
%term CNSTP8=8215
%term CNSTU1=1046
%term CNSTU2=2070
%term CNSTU4=4118
%term CNSTU8=8214
%term ARGB=41
%term ARGF4=4129
%term ARGF8=8225
%term ARGF16=16417
%term ARGI4=4133
%term ARGI8=8229
%term ARGP4=4135
%term ARGP8=8231
%term ARGU4=4134
%term ARGU8=8230
%term ASGNB=57
%term ASGNF4=4145
%term ASGNF8=8241
%term ASGNF16=16433
%term ASGNI1=1077
%term ASGNI2=2101
%term ASGNI4=4149
%term ASGNI8=8245
%term ASGNP4=4151
%term ASGNP8=8247
%term ASGNU1=1078
%term ASGNU2=2102
%term ASGNU4=4150
%term ASGNU8=8246
%term INDIRB=73
%term INDIRF4=4161
%term INDIRF8=8257
%term INDIRF16=16449
%term INDIRI1=1093
%term INDIRI2=2117
%term INDIRI4=4165
%term INDIRI8=8261
%term INDIRP4=4167
%term INDIRP8=8263
%term INDIRU1=1094
%term INDIRU2=2118
%term INDIRU4=4166
%term INDIRU8=8262
%term CVFF4=4209
%term CVFF8=8305
%term CVFF16=16497
%term CVFI4=4213
%term CVFI8=8309
%term CVIF4=4225
%term CVIF8=8321
%term CVIF16=16513
%term CVII1=1157
%term CVII2=2181
%term CVII4=4229
%term CVII8=8325
%term CVIU1=1158
%term CVIU2=2182
%term CVIU4=4230
%term CVIU8=8326
%term CVPP4=4247
%term CVPP8=8343
%term CVPP16=16535
%term CVPU4=4246
%term CVPU8=8342
%term CVUI1=1205
%term CVUI2=2229
%term CVUI4=4277
%term CVUI8=8373
%term CVUP4=4279
%term CVUP8=8375
%term CVUP16=16567
%term CVUU1=1206
%term CVUU2=2230
%term CVUU4=4278
%term CVUU8=8374
%term NEGF4=4289
%term NEGF8=8385
%term NEGF16=16577
%term NEGI4=4293
%term NEGI8=8389
%term CALLB=217
%term CALLF4=4305
%term CALLF8=8401
%term CALLF16=16593
%term CALLI4=4309
%term CALLI8=8405
%term CALLP4=4311
%term CALLP8=8407
%term CALLU4=4310
%term CALLU8=8406
%term CALLV=216
%term RETF4=4337
%term RETF8=8433
%term RETF16=16625
%term RETI4=4341
%term RETI8=8437
%term RETP4=4343
%term RETP8=8439
%term RETU4=4342
%term RETU8=8438
%term RETV=248
%term ADDRGP4=4359
%term ADDRGP8=8455
%term ADDRFP4=4375
%term ADDRFP8=8471
%term ADDRLP4=4391
%term ADDRLP8=8487
%term ADDF4=4401
%term ADDF8=8497
%term ADDF16=16689
%term ADDI4=4405
%term ADDI8=8501
%term ADDP4=4407
%term ADDP8=8503
%term ADDU4=4406
%term ADDU8=8502
%term SUBF4=4417
%term SUBF8=8513
%term SUBF16=16705
%term SUBI4=4421
%term SUBI8=8517
%term SUBP4=4423
%term SUBP8=8519
%term SUBU4=4422
%term SUBU8=8518
%term LSHI4=4437
%term LSHI8=8533
%term LSHU4=4438
%term LSHU8=8534
%term MODI4=4453
%term MODI8=8549
%term MODU4=4454
%term MODU8=8550
%term RSHI4=4469
%term RSHI8=8565
%term RSHU4=4470
%term RSHU8=8566
%term BANDI4=4485
%term BANDI8=8581
%term BANDU4=4486
%term BANDU8=8582
%term BCOMI4=4501
%term BCOMI8=8597
%term BCOMU4=4502
%term BCOMU8=8598
%term BORI4=4517
%term BORI8=8613
%term BORU4=4518
%term BORU8=8614
%term BXORI4=4533
%term BXORI8=8629
%term BXORU4=4534
%term BXORU8=8630
%term DIVF4=4545
%term DIVF8=8641
%term DIVF16=16833
%term DIVI4=4549
%term DIVI8=8645
%term DIVU4=4550
%term DIVU8=8646
%term MULF4=4561
%term MULF8=8657
%term MULF16=16849
%term MULI4=4565
%term MULI8=8661
%term MULU4=4566
%term MULU8=8662
%term EQF4=4577
%term EQF8=8673
%term EQF16=16865
%term EQI4=4581
%term EQI8=8677
%term EQU4=4582
%term EQU8=8678
%term GEF4=4593
%term GEF8=8689
%term GEI4=4597
%term GEI8=8693
%term GEI16=16885
%term GEU4=4598
%term GEU8=8694
%term GTF4=4609
%term GTF8=8705
%term GTF16=16897
%term GTI4=4613
%term GTI8=8709
%term GTU4=4614
%term GTU8=8710
%term LEF4=4625
%term LEF8=8721
%term LEF16=16913
%term LEI4=4629
%term LEI8=8725
%term LEU4=4630
%term LEU8=8726
%term LTF4=4641
%term LTF8=8737
%term LTF16=16929
%term LTI4=4645
%term LTI8=8741
%term LTU4=4646
%term LTU8=8742
%term NEF4=4657
%term NEF8=8753
%term NEF16=16945
%term NEI4=4661
%term NEI8=8757
%term NEU4=4662
%term NEU8=8758
%term JUMPV=584
%term LABELV=600
%term LOADB=233
%term LOADF4=4321
%term LOADF8=8417
%term LOADF16=16609
%term LOADI1=1253
%term LOADI2=2277
%term LOADI4=4325
%term LOADI8=8421
%term LOADP4=4327
%term LOADP8=8423
%term LOADU1=1254
%term LOADU2=2278
%term LOADU4=4326
%term LOADU8=8422
%term VREGP=711
%%
reg: INDIRI1(VREGP) "# read register\n"
reg: INDIRU1(VREGP) "# read register\n"
reg: INDIRI2(VREGP) "# read register\n"
reg: INDIRU2(VREGP) "# read register\n"
reg: INDIRF4(VREGP) "# read register\n"
reg: INDIRI4(VREGP) "# read register\n"
reg: INDIRP4(VREGP) "# read register\n"
reg: INDIRU4(VREGP) "# read register\n"
reg: INDIRF8(VREGP) "# read register\n"
reg: INDIRI8(VREGP) "# read register\n"
reg: INDIRP8(VREGP) "# read register\n"
reg: INDIRU8(VREGP) "# read register\n"
stmt: ASGNI1(VREGP,reg) "# write register\n"
stmt: ASGNU1(VREGP,reg) "# write register\n"
stmt: ASGNI2(VREGP,reg) "# write register\n"
stmt: ASGNU2(VREGP,reg) "# write register\n"
stmt: ASGNF4(VREGP,reg) "# write register\n"
stmt: ASGNI4(VREGP,reg) "# write register\n"
stmt: ASGNP4(VREGP,reg) "# write register\n"
stmt: ASGNU4(VREGP,reg) "# write register\n"
stmt: ASGNF8(VREGP,reg) "# write register\n"
stmt: ASGNI8(VREGP,reg) "# write register\n"
stmt: ASGNP8(VREGP,reg) "# write register\n"
stmt: ASGNU8(VREGP,reg) "# write register\n"
con: CNSTI1 "%a"
con: CNSTU1 "%a"
con: CNSTI2 "%a"
con: CNSTU2 "%a"
con: CNSTI4 "%a"
con: CNSTU4 "%a"
con: CNSTP4 "%a"
con: CNSTI8 "%a"
con: CNSTU8 "%a"
con: CNSTP8 "%a"
stmt: reg ""
acon: ADDRGP4 "(%a)"
acon: con "(%0)"
base: ADDRGP4 "(%a)"
base: reg "[%0]"
base: ADDI4(reg,acon) "%1[%0]"
base: ADDP4(reg,acon) "%1[%0]"
base: ADDU4(reg,acon) "%1[%0]"
base: ADDRFP4 "(%a)[ebp]"
base: ADDRLP4 "(%a)[ebp]"
index: reg "%0"
index: LSHI4(reg,con1) "%0*2"
index: LSHI4(reg,con2) "%0*4"
index: LSHI4(reg,con3) "%0*8"
con1: CNSTI4 "1" range(a, 1, 1)
con1: CNSTU4 "1" range(a, 1, 1)
con2: CNSTI4 "2" range(a, 2, 2)
con2: CNSTU4 "2" range(a, 2, 2)
con3: CNSTI4 "3" range(a, 3, 3)
con3: CNSTU4 "3" range(a, 3, 3)
index: LSHU4(reg,con1) "%0*2"
index: LSHU4(reg,con2) "%0*4"
index: LSHU4(reg,con3) "%0*8"
addr: base "%0"
addr: ADDI4(index,base) "%1[%0]"
addr: ADDP4(index,base) "%1[%0]"
addr: ADDU4(index,base) "%1[%0]"
addr: index "[%0]"
mem: INDIRI1(addr) "byte ptr %0"
mem: INDIRI2(addr) "word ptr %0"
mem: INDIRI4(addr) "dword ptr %0"
mem: INDIRU1(addr) "byte ptr %0"
mem: INDIRU2(addr) "word ptr %0"
mem: INDIRU4(addr) "dword ptr %0"
mem: INDIRP4(addr) "dword ptr %0"
rc: reg "%0"
rc: con "%0"
mr: reg "%0"
mr: mem "%0"
mrc0: mem "%0"
mrc0: rc "%0"
mrc1: mem "%0" 1
mrc1: rc "%0"
mrc3: mem "%0" 3
mrc3: rc "%0"
reg: addr "lea %c,%0\n" 1
reg: mrc0 "mov %c,%0\n" 1
reg: LOADI1(reg) "# move\n" 1
reg: LOADI2(reg) "# move\n" 1
reg: LOADI4(reg) "# move\n" move(a)
reg: LOADU1(reg) "# move\n" 1
reg: LOADU2(reg) "# move\n" 1
reg: LOADU4(reg) "# move\n" move(a)
reg: LOADP4(reg) "# move\n" move(a)
reg: ADDI4(reg,mrc1) "?mov %c,%0\nadd %c,%1\n" 1
reg: ADDP4(reg,mrc1) "?mov %c,%0\nadd %c,%1\n" 1
reg: ADDU4(reg,mrc1) "?mov %c,%0\nadd %c,%1\n" 1
reg: SUBI4(reg,mrc1) "?mov %c,%0\nsub %c,%1\n" 1
reg: SUBP4(reg,mrc1) "?mov %c,%0\nsub %c,%1\n" 1
reg: SUBU4(reg,mrc1) "?mov %c,%0\nsub %c,%1\n" 1
reg: BANDI4(reg,mrc1) "?mov %c,%0\nand %c,%1\n" 1
reg: BORI4(reg,mrc1) "?mov %c,%0\nor %c,%1\n" 1
reg: BXORI4(reg,mrc1) "?mov %c,%0\nxor %c,%1\n" 1
reg: BANDU4(reg,mrc1) "?mov %c,%0\nand %c,%1\n" 1
reg: BORU4(reg,mrc1) "?mov %c,%0\nor %c,%1\n" 1
reg: BXORU4(reg,mrc1) "?mov %c,%0\nxor %c,%1\n" 1
stmt: ASGNI4(addr,ADDI4(mem,con1)) "inc %1\n" memop(a)
stmt: ASGNI4(addr,ADDU4(mem,con1)) "inc %1\n" memop(a)
stmt: ASGNP4(addr,ADDP4(mem,con1)) "inc %1\n" memop(a)
stmt: ASGNI4(addr,SUBI4(mem,con1)) "dec %1\n" memop(a)
stmt: ASGNI4(addr,SUBU4(mem,con1)) "dec %1\n" memop(a)
stmt: ASGNP4(addr,SUBP4(mem,con1)) "dec %1\n" memop(a)
stmt: ASGNI4(addr,ADDI4(mem,rc)) "add %1,%2\n" memop(a)
stmt: ASGNI4(addr,SUBI4(mem,rc)) "sub %1,%2\n" memop(a)
stmt: ASGNU4(addr,ADDU4(mem,rc)) "add %1,%2\n" memop(a)
stmt: ASGNU4(addr,SUBU4(mem,rc)) "sub %1,%2\n" memop(a)
stmt: ASGNI4(addr,BANDI4(mem,rc)) "and %1,%2\n" memop(a)
stmt: ASGNI4(addr,BORI4(mem,rc)) "or %1,%2\n" memop(a)
stmt: ASGNI4(addr,BXORI4(mem,rc)) "xor %1,%2\n" memop(a)
stmt: ASGNU4(addr,BANDU4(mem,rc)) "and %1,%2\n" memop(a)
stmt: ASGNU4(addr,BORU4(mem,rc)) "or %1,%2\n" memop(a)
stmt: ASGNU4(addr,BXORU4(mem,rc)) "xor %1,%2\n" memop(a)
reg: BCOMI4(reg) "?mov %c,%0\nnot %c\n" 2
reg: BCOMU4(reg) "?mov %c,%0\nnot %c\n" 2
reg: NEGI4(reg) "?mov %c,%0\nneg %c\n" 2
stmt: ASGNI4(addr,BCOMI4(mem)) "not %1\n" memop(a)
stmt: ASGNU4(addr,BCOMU4(mem)) "not %1\n" memop(a)
stmt: ASGNI4(addr,NEGI4(mem)) "neg %1\n" memop(a)
reg: LSHI4(reg,con5) "?mov %c,%0\nsal %c,%1\n" 2
reg: LSHU4(reg,con5) "?mov %c,%0\nshl %c,%1\n" 2
reg: RSHI4(reg,con5) "?mov %c,%0\nsar %c,%1\n" 2
reg: RSHU4(reg,con5) "?mov %c,%0\nshr %c,%1\n" 2
stmt: ASGNI4(addr,LSHI4(mem,con5)) "sal %1,%2\n" memop(a)
stmt: ASGNI4(addr,LSHU4(mem,con5)) "shl %1,%2\n" memop(a)
stmt: ASGNI4(addr,RSHI4(mem,con5)) "sar %1,%2\n" memop(a)
stmt: ASGNI4(addr,RSHU4(mem,con5)) "shr %1,%2\n" memop(a)
con5: CNSTI4 "%a" range(a, 0, 31)
reg: LSHI4(reg,reg) "?mov %c,%0\nmov ecx,%1\nsal %c,cl\n" 3
reg: LSHU4(reg,reg) "?mov %c,%0\nmov ecx,%1\nshl %c,cl\n" 2
reg: RSHI4(reg,reg) "?mov %c,%0\nmov ecx,%1\nsar %c,cl\n" 2
reg: RSHU4(reg,reg) "?mov %c,%0\nmov ecx,%1\nshr %c,cl\n" 2
reg: MULI4(reg,mrc3) "?mov %c,%0\nimul %c,%1\n" 14
reg: MULI4(con,mr) "imul %c,%1,%0\n" 13
reg: MULU4(reg,mr) "mul %1\n" 13
reg: DIVU4(reg,reg) "xor edx,edx\ndiv %1\n"
reg: MODU4(reg,reg) "xor edx,edx\ndiv %1\n"
reg: DIVI4(reg,reg) "cdq\nidiv %1\n"
reg: MODI4(reg,reg) "cdq\nidiv %1\n"
reg: CVPU4(reg) "mov %c,%0\n" move(a)
reg: CVUP4(reg) "mov %c,%0\n" move(a)
reg: CVII4(INDIRI1(addr)) "movsx %c,byte ptr %0\n" 3
reg: CVII4(INDIRI2(addr)) "movsx %c,word ptr %0\n" 3
reg: CVUU4(INDIRU1(addr)) "movzx %c,byte ptr %0\n" 3
reg: CVUU4(INDIRU2(addr)) "movzx %c,word ptr %0\n" 3
reg: CVII4(reg) "# extend\n" 3
reg: CVIU4(reg) "# extend\n" 3
reg: CVUI4(reg) "# extend\n" 3
reg: CVUU4(reg) "# extend\n" 3
reg: CVII1(reg) "# truncate\n" 1
reg: CVII2(reg) "# truncate\n" 1
reg: CVUU1(reg) "# truncate\n" 1
reg: CVUU2(reg) "# truncate\n" 1
stmt: ASGNI1(addr,rc) "mov byte ptr %0,%1\n" 1
stmt: ASGNI2(addr,rc) "mov word ptr %0,%1\n" 1
stmt: ASGNI4(addr,rc) "mov dword ptr %0,%1\n" 1
stmt: ASGNU1(addr,rc) "mov byte ptr %0,%1\n" 1
stmt: ASGNU2(addr,rc) "mov word ptr %0,%1\n" 1
stmt: ASGNU4(addr,rc) "mov dword ptr %0,%1\n" 1
stmt: ASGNP4(addr,rc) "mov dword ptr %0,%1\n" 1
stmt: ARGI4(mrc3) "push %0\n" 1
stmt: ARGU4(mrc3) "push %0\n" 1
stmt: ARGP4(mrc3) "push %0\n" 1
stmt: ASGNB(reg,INDIRB(reg)) "mov ecx,%a\nrep movsb\n"
stmt: ARGB(INDIRB(reg)) "sub esp,%a\nmov edi,esp\nmov ecx,%a\nrep movsb\n"
memf: INDIRF8(addr) "qword ptr %0"
memf: INDIRF4(addr) "dword ptr %0"
memf: CVFF8(INDIRF4(addr)) "dword ptr %0"
reg: memf "fld %0\n" 3
stmt: ASGNF8(addr,reg) "fstp qword ptr %0\n" 7
stmt: ASGNF4(addr,reg) "fstp dword ptr %0\n" 7
stmt: ASGNF4(addr,CVFF4(reg)) "fstp dword ptr %0\n" 7
stmt: ARGF8(reg) "sub esp,8\nfstp qword ptr [esp]\n"
stmt: ARGF4(reg) "sub esp,4\nfstp dword ptr [esp]\n"
reg: NEGF8(reg) "fchs\n"
reg: NEGF4(reg) "fchs\n"
flt: memf " %0"
flt: reg "p st(1),st"
reg: ADDF8(reg,flt) "fadd%1\n"
reg: ADDF4(reg,flt) "fadd%1\n"
reg: DIVF8(reg,flt) "fdiv%1\n"
reg: DIVF4(reg,flt) "fdiv%1\n"
reg: MULF8(reg,flt) "fmul%1\n"
reg: MULF4(reg,flt) "fmul%1\n"
reg: SUBF8(reg,flt) "fsub%1\n"
reg: SUBF4(reg,flt) "fsub%1\n"
reg: CVFF8(reg) "# CVFF8\n"
reg: CVFF4(reg) "sub esp,4\nfstp dword ptr 0[esp]\nfld dword ptr 0[esp]\nadd esp,4\n" 12
reg: CVFI4(reg) "call __ftol\n" 31
reg: CVIF8(INDIRI4(addr)) "fild dword ptr %0\n" 10
reg: CVIF4(reg) "push %0\nfild dword ptr 0[esp]\nadd esp,4\n" 12
reg: CVIF8(reg) "push %0\nfild dword ptr 0[esp]\nadd esp,4\n" 12
addrj: ADDRGP4 "%a"
addrj: reg "%0" 2
addrj: mem "%0" 2
stmt: JUMPV(addrj) "jmp %0\n" 3
stmt: LABELV "%a:\n"
stmt: EQI4(mem,rc) "cmp %0,%1\nje %a\n" 5
stmt: GEI4(mem,rc) "cmp %0,%1\njge %a\n" 5
stmt: GTI4(mem,rc) "cmp %0,%1\njg %a\n" 5
stmt: LEI4(mem,rc) "cmp %0,%1\njle %a\n" 5
stmt: LTI4(mem,rc) "cmp %0,%1\njl %a\n" 5
stmt: NEI4(mem,rc) "cmp %0,%1\njne %a\n" 5
stmt: GEU4(mem,rc) "cmp %0,%1\njae %a\n" 5
stmt: GTU4(mem,rc) "cmp %0,%1\nja %a\n" 5
stmt: LEU4(mem,rc) "cmp %0,%1\njbe %a\n" 5
stmt: LTU4(mem,rc) "cmp %0,%1\njb %a\n" 5
stmt: EQI4(reg,mrc1) "cmp %0,%1\nje %a\n" 4
stmt: GEI4(reg,mrc1) "cmp %0,%1\njge %a\n" 4
stmt: GTI4(reg,mrc1) "cmp %0,%1\njg %a\n" 4
stmt: LEI4(reg,mrc1) "cmp %0,%1\njle %a\n" 4
stmt: LTI4(reg,mrc1) "cmp %0,%1\njl %a\n" 4
stmt: NEI4(reg,mrc1) "cmp %0,%1\njne %a\n" 4
stmt: EQU4(reg,mrc1) "cmp %0,%1\nje %a\n" 4
stmt: GEU4(reg,mrc1) "cmp %0,%1\njae %a\n" 4
stmt: GTU4(reg,mrc1) "cmp %0,%1\nja %a\n" 4
stmt: LEU4(reg,mrc1) "cmp %0,%1\njbe %a\n" 4
stmt: LTU4(reg,mrc1) "cmp %0,%1\njb %a\n" 4
stmt: NEU4(reg,mrc1) "cmp %0,%1\njne %a\n" 4
cmpf: memf " %0"
cmpf: reg "p"
stmt: EQF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\nje %a\n"
stmt: GEF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njbe %a\n"
stmt: GTF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njb %a\n"
stmt: LEF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njae %a\n"
stmt: LTF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\nja %a\n"
stmt: NEF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njne %a\n"
stmt: EQF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\nje %a\n"
stmt: GEF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njbe %a\n"
stmt: GTF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njb %a\n"
stmt: LEF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njae %a\n"
stmt: LTF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\nja %a\n"
stmt: NEF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njne %a\n"
reg: CALLI4(addrj) "call %0\nadd esp,%a\n"
reg: CALLU4(addrj) "call %0\nadd esp,%a\n"
reg: CALLP4(addrj) "call %0\nadd esp,%a\n"
stmt: CALLV(addrj) "call %0\nadd esp,%a\n"
reg: CALLF4(addrj) "call %0\nadd esp,%a\n"
reg: CALLF8(addrj) "call %0\nadd esp,%a\n"
stmt: CALLF4(addrj) "call %0\nadd esp,%a\nfstp\n"
stmt: CALLF8(addrj) "call %0\nadd esp,%a\nfstp\n"
stmt: RETI4(reg) "# ret\n"
stmt: RETU4(reg) "# ret\n"
stmt: RETP4(reg) "# ret\n"
stmt: RETF4(reg) "# ret\n"
stmt: RETF8(reg) "# ret\n"
%%
static void progbeg(int argc, char *argv[]) {
int i;
{
union {
char c;
int i;
} u;
u.i = 0;
u.c = 1;
swap = ((int)(u.i == 1)) != IR->little_endian;
}
parseflags(argc, argv);
intreg[EAX] = mkreg("eax", EAX, 1, IREG);
intreg[EDX] = mkreg("edx", EDX, 1, IREG);
intreg[ECX] = mkreg("ecx", ECX, 1, IREG);
intreg[EBX] = mkreg("ebx", EBX, 1, IREG);
intreg[ESI] = mkreg("esi", ESI, 1, IREG);
intreg[EDI] = mkreg("edi", EDI, 1, IREG);
shortreg[EAX] = mkreg("ax", EAX, 1, IREG);
shortreg[ECX] = mkreg("cx", ECX, 1, IREG);
shortreg[EDX] = mkreg("dx", EDX, 1, IREG);
shortreg[EBX] = mkreg("bx", EBX, 1, IREG);
shortreg[ESI] = mkreg("si", ESI, 1, IREG);
shortreg[EDI] = mkreg("di", EDI, 1, IREG);
charreg[EAX] = mkreg("al", EAX, 1, IREG);
charreg[ECX] = mkreg("cl", ECX, 1, IREG);
charreg[EDX] = mkreg("dl", EDX, 1, IREG);
charreg[EBX] = mkreg("bl", EBX, 1, IREG);
for (i = 0; i < 8; i++)
fltreg[i] = mkreg("%d", i, 0, FREG);
charregw = mkwildcard(charreg);
shortregw = mkwildcard(shortreg);
intregw = mkwildcard(intreg);
fltregw = mkwildcard(fltreg);
tmask[IREG] = (1<<EDI) | (1<<ESI) | (1<<EBX)
| (1<<EDX) | (1<<ECX) | (1<<EAX);
vmask[IREG] = 0;
tmask[FREG] = 0xff;
vmask[FREG] = 0;
print(".486\n");
print(".model flat\n");
print("extrn __fltused:near\n");
print("extrn __ftol:near\n");
cseg = 0;
quo = mkreg("eax", EAX, 1, IREG);
quo->x.regnode->mask |= 1<<EDX;
rem = mkreg("edx", EDX, 1, IREG);
rem->x.regnode->mask |= 1<<EAX;
}
static Symbol rmap(int opk) {
switch (optype(opk)) {
case B: case P:
return intregw;
case I: case U:
if (opsize(opk) == 1)
return charregw;
else if (opsize(opk) == 2)
return shortregw;
else
return intregw;
case F:
return fltregw;
default:
return 0;
}
}
static void segment(int n) {
if (n == cseg)
return;
if (cseg == CODE || cseg == LIT)
print("_TEXT ends\n");
else if (cseg == DATA || cseg == BSS)
print("_DATA ends\n");
cseg = n;
if (cseg == CODE || cseg == LIT)
print("_TEXT segment\n");
else if (cseg == DATA || cseg == BSS)
print("_DATA segment\n");
}
static void progend(void) {
segment(0);
print("end\n");
}
static void target(Node p) {
assert(p);
switch (specific(p->op)) {
case MUL+U:
setreg(p, quo);
rtarget(p, 0, intreg[EAX]);
break;
case DIV+I: case DIV+U:
setreg(p, quo);
rtarget(p, 0, quo);
break;
case MOD+I: case MOD+U:
setreg(p, rem);
rtarget(p, 0, quo);
break;
case ASGN+B:
rtarget(p, 0, intreg[EDI]);
rtarget(p->kids[1], 0, intreg[ESI]);
break;
case ARG+B:
rtarget(p->kids[0], 0, intreg[ESI]);
break;
case CVF+I:
setreg(p, intreg[EAX]);
break;
case CALL+I: case CALL+U: case CALL+P: case CALL+V:
setreg(p, intreg[EAX]);
break;
case RET+I: case RET+U: case RET+P:
rtarget(p, 0, intreg[EAX]);
break;
}
}
static void clobber(Node p) {
static int nstack = 0;
assert(p);
nstack = ckstack(p, nstack);
switch (specific(p->op)) {
case RSH+I: case RSH+U: case LSH+I: case LSH+U:
if (generic(p->kids[1]->op) != CNST
&& !( generic(p->kids[1]->op) == INDIR
&& specific(p->kids[1]->kids[0]->op) == VREG+P
&& p->kids[1]->syms[RX]->u.t.cse
&& generic(p->kids[1]->syms[RX]->u.t.cse->op) == CNST
)) {
spill(1<<ECX, 1, p);
}
break;
case ASGN+B: case ARG+B:
spill(1<<ECX | 1<<ESI | 1<<EDI, IREG, p);
break;
case EQ+F: case LE+F: case GE+F: case LT+F: case GT+F: case NE+F:
spill(1<<EAX, IREG, p);
break;
case CALL+F:
spill(1<<EDX | 1<<EAX | 1<<ECX, IREG, p);
break;
case CALL+I: case CALL+U: case CALL+P: case CALL+V:
spill(1<<EDX | 1<<ECX, IREG, p);
break;
}
}
#define isfp(p) (optype((p)->op)==F)
int ckstack(Node p, int n) {
int i;
for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
if (isfp(p->x.kids[i]))
n--;
if (isfp(p) && p->count > 0)
n++;
if (n > 8)
error("expression too complicated\n");
debug(fprint(stderr, "(ckstack(%x)=%d)\n", p, n));
assert(n >= 0);
return n;
}
int memop(Node p) {
assert(p);
assert(generic(p->op) == ASGN);
assert(p->kids[0]);
assert(p->kids[1]);
if (generic(p->kids[1]->kids[0]->op) == INDIR
&& sametree(p->kids[0], p->kids[1]->kids[0]->kids[0]))
return 3;
else
return LBURG_MAX;
}
int sametree(Node p, Node q) {
return p == NULL && q == NULL
|| p && q && p->op == q->op && p->syms[0] == q->syms[0]
&& sametree(p->kids[0], q->kids[0])
&& sametree(p->kids[1], q->kids[1]);
}
static void emit2(Node p) {
int op = specific(p->op);
#define preg(f) ((f)[getregnum(p->x.kids[0])]->x.name)
if (op == CVI+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1)
print("movsx %s,%s\n", p->syms[RX]->x.name
, preg(charreg));
else if (op == CVI+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1)
print("movsx %s,%s\n", p->syms[RX]->x.name
, preg(charreg));
else if (op == CVI+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2)
print("movsx %s,%s\n", p->syms[RX]->x.name
, preg(shortreg));
else if (op == CVI+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2)
print("movsx %s,%s\n", p->syms[RX]->x.name
, preg(shortreg));
else if (op == CVU+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1)
print("movzx %s,%s\n", p->syms[RX]->x.name
, preg(charreg));
else if (op == CVU+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1)
print("movzx %s,%s\n", p->syms[RX]->x.name
, preg(charreg));
else if (op == CVU+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2)
print("movzx %s,%s\n", p->syms[RX]->x.name
, preg(shortreg));
else if (op == CVU+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2)
print("movzx %s,%s\n", p->syms[RX]->x.name
, preg(shortreg));
else if (generic(op) == CVI || generic(op) == CVU || generic(op) == LOAD) {
char *dst = intreg[getregnum(p)]->x.name;
char *src = preg(intreg);
assert(opsize(p->op) <= opsize(p->x.kids[0]->op));
if (dst != src)
print("mov %s,%s\n", dst, src);
}
}
static void doarg(Node p) {
assert(p && p->syms[0]);
mkactual(4, p->syms[0]->u.c.v.i);
}
static void blkfetch(int k, int off, int reg, int tmp) {}
static void blkstore(int k, int off, int reg, int tmp) {}
static void blkloop(int dreg, int doff, int sreg, int soff,
int size, int tmps[]) {}
static void local(Symbol p) {
if (isfloat(p->type))
p->sclass = AUTO;
if (askregvar(p, (*IR->x.rmap)(ttob(p->type))) == 0)
mkauto(p);
}
static void function(Symbol f, Symbol caller[], Symbol callee[], int n) {
int i;
print("%s:\n", f->x.name);
print("push ebx\n");
print("push esi\n");
print("push edi\n");
print("push ebp\n");
print("mov ebp,esp\n");
usedmask[0] = usedmask[1] = 0;
freemask[0] = freemask[1] = ~(unsigned)0;
offset = 16 + 4;
for (i = 0; callee[i]; i++) {
Symbol p = callee[i];
Symbol q = caller[i];
assert(q);
p->x.offset = q->x.offset = offset;
p->x.name = q->x.name = stringf("%d", p->x.offset);
p->sclass = q->sclass = AUTO;
offset += roundup(q->type->size, 4);
}
assert(caller[i] == 0);
offset = maxoffset = 0;
gencode(caller, callee);
framesize = roundup(maxoffset, 4);
if (framesize > 0)
print("sub esp,%d\n", framesize);
emitcode();
print("mov esp,ebp\n");
print("pop ebp\n");
print("pop edi\n");
print("pop esi\n");
print("pop ebx\n");
print("ret\n");
}
static void defsymbol(Symbol p) {
if (p->scope >= LOCAL && p->sclass == STATIC)
p->x.name = stringf("L%d", genlabel(1));
else if (p->generated)
p->x.name = stringf("L%s", p->name);
else if (p->scope == GLOBAL || p->sclass == EXTERN)
p->x.name = stringf("_%s", p->name);
else if (p->scope == CONSTANTS
&& (isint(p->type) || isptr(p->type))
&& p->name[0] == '0' && p->name[1] == 'x')
p->x.name = stringf("0%sH", &p->name[2]);
else
p->x.name = p->name;
}
static void address(Symbol q, Symbol p, long n) {
if (p->scope == GLOBAL
|| p->sclass == STATIC || p->sclass == EXTERN)
q->x.name = stringf("%s%s%D",
p->x.name, n >= 0 ? "+" : "", n);
else {
assert(n <= INT_MAX && n >= INT_MIN);
q->x.offset = p->x.offset + n;
q->x.name = stringd(q->x.offset);
}
}
static void defconst(int suffix, int size, Value v) {
if (suffix == I && size == 1)
print("db %d\n", v.u);
else if (suffix == I && size == 2)
print("dw %d\n", v.i);
else if (suffix == I && size == 4)
print("dd %d\n", v.i);
else if (suffix == U && size == 1)
print("db 0%xH\n", v.u);
else if (suffix == U && size == 2)
print("dw 0%xH\n", v.u);
else if (suffix == U && size == 4)
print("dd 0%xH\n", v.u);
else if (suffix == P && size == 4)
print("dd 0%xH\n", v.p);
else if (suffix == F && size == 4) {
float f = v.d;
print("dd 0%xH\n", *(unsigned *)&f);
}
else if (suffix == F && size == 8) {
double d = v.d;
unsigned *p = (unsigned *)&d;
print("dd 0%xH\ndd 0%xH\n", p[swap], p[!swap]);
}
else assert(0);
}
static void defaddress(Symbol p) {
print("dd %s\n", p->x.name);
}
static void defstring(int n, char *str) {
char *s;
for (s = str; s < str + n; s++)
print("db %d\n", (*s)&0377);
}
static void export(Symbol p) {
print("public %s\n", p->x.name);
}
static void import(Symbol p) {
int oldseg = cseg;
if (p->ref > 0) {
segment(0);
print("extrn %s:near\n", p->x.name);
segment(oldseg);
}
}
static void global(Symbol p) {
print("align %d\n",
p->type->align > 4 ? 4 : p->type->align);
print("%s label byte\n", p->x.name);
if (p->u.seg == BSS)
print("db %d dup (0)\n", p->type->size);
}
static void space(int n) {
if (cseg != BSS)
print("db %d dup (0)\n", n);
}
Interface x86IR = {
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, 4, 1, /* double */
8, 4, 1, /* long double */
4, 4, 0, /* T * */
0, 4, 0, /* struct; so that ARGB keeps stack aligned */
1, /* little_endian */
0, /* mulops_calls */
0, /* wants_callb */
1, /* wants_argb */
0, /* left_to_right */
0, /* wants_dag */
0, /* unsigned_char */
address,
blockbeg,
blockend,
defaddress,
defconst,
defstring,
defsymbol,
emit,
export,
function,
gen,
global,
import,
local,
progbeg,
progend,
segment,
space,
0, 0, 0, 0, 0, 0, 0,
{1, rmap,
blkfetch, blkstore, blkloop,
_label,
_rule,
_nts,
_kids,
_string,
_templates,
_isinstruction,
_ntname,
emit2,
doarg,
target,
clobber,
}
};
static char rcsid[] = "$Id: x86.md 145 2001-10-17 21:53:10Z timo $";

File diff suppressed because it is too large Load diff