diff options
Diffstat (limited to 'lcc/src')
44 files changed, 19269 insertions, 19269 deletions
diff --git a/lcc/src/2html.c b/lcc/src/2html.c index 3c9b146..8a0be3a 100755 --- a/lcc/src/2html.c +++ b/lcc/src/2html.c @@ -1,555 +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;
-}
+#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; +} diff --git a/lcc/src/alloc.c b/lcc/src/alloc.c index 698da4f..e0566df 100755 --- a/lcc/src/alloc.c +++ b/lcc/src/alloc.c @@ -1,94 +1,94 @@ -#include "c.h"
-struct block {
- struct block *next;
- char *limit;
- char *avail;
-};
-union align {
- long l;
- char *p;
- double d;
- int (*f)(void);
-};
-union header {
- struct block b;
- union align a;
-};
-#ifdef PURIFY
-union header *arena[3];
-
-void *allocate(unsigned long n, unsigned a) {
- union header *new = malloc(sizeof *new + n);
-
- assert(a < NELEMS(arena));
- if (new == NULL) {
- error("insufficient memory\n");
- exit(1);
- }
- new->b.next = (void *)arena[a];
- arena[a] = new;
- return new + 1;
-}
-
-void deallocate(unsigned a) {
- union header *p, *q;
-
- assert(a < NELEMS(arena));
- for (p = arena[a]; p; p = q) {
- q = (void *)p->b.next;
- free(p);
- }
- arena[a] = NULL;
-}
-
-void *newarray(unsigned long m, unsigned long n, unsigned a) {
- return allocate(m*n, a);
-}
-#else
-static struct block
- first[] = { { NULL }, { NULL }, { NULL } },
- *arena[] = { &first[0], &first[1], &first[2] };
-static struct block *freeblocks;
-
-void *allocate(unsigned long n, unsigned a) {
- struct block *ap;
-
- assert(a < NELEMS(arena));
- assert(n > 0);
- ap = arena[a];
- n = roundup(n, sizeof (union align));
- while (n > ap->limit - ap->avail) {
- if ((ap->next = freeblocks) != NULL) {
- freeblocks = freeblocks->next;
- ap = ap->next;
- } else
- {
- unsigned m = sizeof (union header) + n + roundup(10*1024, sizeof (union align));
- ap->next = malloc(m);
- ap = ap->next;
- if (ap == NULL) {
- error("insufficient memory\n");
- exit(1);
- }
- ap->limit = (char *)ap + m;
- }
- ap->avail = (char *)((union header *)ap + 1);
- ap->next = NULL;
- arena[a] = ap;
-
- }
- ap->avail += n;
- return ap->avail - n;
-}
-
-void *newarray(unsigned long m, unsigned long n, unsigned a) {
- return allocate(m*n, a);
-}
-void deallocate(unsigned a) {
- assert(a < NELEMS(arena));
- arena[a]->next = freeblocks;
- freeblocks = first[a].next;
- first[a].next = NULL;
- arena[a] = &first[a];
-}
-#endif
+#include "c.h" +struct block { + struct block *next; + char *limit; + char *avail; +}; +union align { + long l; + char *p; + double d; + int (*f)(void); +}; +union header { + struct block b; + union align a; +}; +#ifdef PURIFY +union header *arena[3]; + +void *allocate(unsigned long n, unsigned a) { + union header *new = malloc(sizeof *new + n); + + assert(a < NELEMS(arena)); + if (new == NULL) { + error("insufficient memory\n"); + exit(1); + } + new->b.next = (void *)arena[a]; + arena[a] = new; + return new + 1; +} + +void deallocate(unsigned a) { + union header *p, *q; + + assert(a < NELEMS(arena)); + for (p = arena[a]; p; p = q) { + q = (void *)p->b.next; + free(p); + } + arena[a] = NULL; +} + +void *newarray(unsigned long m, unsigned long n, unsigned a) { + return allocate(m*n, a); +} +#else +static struct block + first[] = { { NULL }, { NULL }, { NULL } }, + *arena[] = { &first[0], &first[1], &first[2] }; +static struct block *freeblocks; + +void *allocate(unsigned long n, unsigned a) { + struct block *ap; + + assert(a < NELEMS(arena)); + assert(n > 0); + ap = arena[a]; + n = roundup(n, sizeof (union align)); + while (n > ap->limit - ap->avail) { + if ((ap->next = freeblocks) != NULL) { + freeblocks = freeblocks->next; + ap = ap->next; + } else + { + unsigned m = sizeof (union header) + n + roundup(10*1024, sizeof (union align)); + ap->next = malloc(m); + ap = ap->next; + if (ap == NULL) { + error("insufficient memory\n"); + exit(1); + } + ap->limit = (char *)ap + m; + } + ap->avail = (char *)((union header *)ap + 1); + ap->next = NULL; + arena[a] = ap; + + } + ap->avail += n; + return ap->avail - n; +} + +void *newarray(unsigned long m, unsigned long n, unsigned a) { + return allocate(m*n, a); +} +void deallocate(unsigned a) { + assert(a < NELEMS(arena)); + arena[a]->next = freeblocks; + freeblocks = first[a].next; + first[a].next = NULL; + arena[a] = &first[a]; +} +#endif diff --git a/lcc/src/alpha.md b/lcc/src/alpha.md index fe7140a..450dfd3 100755 --- a/lcc/src/alpha.md +++ b/lcc/src/alpha.md @@ -1,1192 +1,1192 @@ -%{
-#define INTTMP ((0xff<<1)|(1<<22)|(1<<25)|(1<<27))
-#define INTVAR (0x3f<<9)
-#define FLTTMP ((0x3f<<10)|(0x1ff<<22))
-#define FLTVAR (0xff<<2)
-
-#define INTRET 0x00000001
-#define FLTRET 0x00000003
-
-#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))
-
-#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);
-static Symbol ireg[32], freg[32];
-static Symbol iregw, fregw;
-
-static int tmpregs[] = {4, 2, 3};
-static Symbol blkreg;
-
-static int cseg;
-
-static char *currentfile;
-
-%}
-%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: con "%0"
-acon: ADDRGP8 "%a"
-
-addr: ADDI4(reg,acon) "%1($%0)"
-addr: ADDI8(reg,acon) "%1($%0)"
-addr: ADDU8(reg,acon) "%1($%0)"
-addr: ADDP8(reg,acon) "%1($%0)"
-
-addr: acon "%0"
-addr: reg "($%0)"
-
-addr: ADDRFP8 "%a+%F($sp)"
-addr: ADDRLP8 "%a+%F($sp)"
-
-reg: addr "lda $%c,%0\n" 1
-
-reg: CNSTI1 "# reg\n" range(a, 0, 0)
-reg: CNSTI2 "# reg\n" range(a, 0, 0)
-reg: CNSTI4 "# reg\n" range(a, 0, 0)
-reg: CNSTI8 "# reg\n" range(a, 0, 0)
-reg: CNSTU1 "# reg\n" range(a, 0, 0)
-reg: CNSTU2 "# reg\n" range(a, 0, 0)
-reg: CNSTU4 "# reg\n" range(a, 0, 0)
-reg: CNSTU8 "# reg\n" range(a, 0, 0)
-reg: CNSTP8 "# reg\n" range(a, 0, 0)
-
-stmt: ASGNI1(addr,reg) "stb $%1,%0\n" 1
-stmt: ASGNU1(addr,reg) "stb $%1,%0\n" 1
-stmt: ASGNI2(addr,reg) "stw $%1,%0\n" 1
-stmt: ASGNU2(addr,reg) "stw $%1,%0\n" 1
-
-stmt: ASGNI4(addr,reg) "stl $%1,%0\n" 1
-stmt: ASGNU4(addr,reg) "stl $%1,%0\n" 1
-stmt: ASGNI8(addr,reg) "stq $%1,%0\n" 1
-stmt: ASGNU8(addr,reg) "stq $%1,%0\n" 1
-stmt: ASGNP8(addr,reg) "stq $%1,%0\n" 1
-
-reg: INDIRI1(reg) "ldb $%c,($%0)\n" 1
-reg: INDIRI2(reg) "ldw $%c,($%0)\n" 1
-reg: INDIRI4(addr) "ldl $%c,%0\n" 1
-reg: INDIRI8(addr) "ldq $%c,%0\n" 1
-reg: INDIRP8(addr) "ldq $%c,%0\n" 1
-reg: INDIRU1(reg) "ldbu $%c,($%0)\n" 1
-reg: INDIRU2(reg) "ldwu $%c,($%0)\n" 1
-reg: INDIRU4(addr) "ldl $%c,%0\nzap $%c,240,$%c\n" 2
-reg: INDIRU8(addr) "ldq $%c,%0\n" 1
-
-reg: CVII4(INDIRI1(reg)) "ldb $%c,($%0)\n" 1
-reg: CVII8(INDIRI1(reg)) "ldb $%c,($%0)\n" 1
-reg: CVII4(INDIRI2(reg)) "ldw $%c,($%0)\n" 1
-reg: CVII8(INDIRI2(reg)) "ldw $%c,($%0)\n" 1
-reg: CVII8(INDIRI4(addr)) "ldl $%c,%0\n" 1
-
-reg: CVUU4(INDIRU1(reg)) "ldbu $%c,($%0)\n" 1
-reg: CVUU8(INDIRU1(reg)) "ldbu $%c,($%0)\n" 1
-reg: CVUU4(INDIRU2(reg)) "ldwu $%c,($%0)\n" 1
-reg: CVUU8(INDIRU2(reg)) "ldwu $%c,($%0)\n" 1
-reg: CVUU8(INDIRU4(addr)) "ldl $%c,%0\nzap $%c,240,$%c\n" 2
-
-reg: CVUI4(INDIRU1(reg)) "ldbu $%c,($%0)\n" 1
-reg: CVUI8(INDIRU1(reg)) "ldbu $%c,($%0)\n" 1
-reg: CVUI4(INDIRU2(reg)) "ldwu $%c,($%0)\n" 1
-reg: CVUI8(INDIRU2(reg)) "ldwu $%c,($%0)\n" 1
-reg: CVUI8(INDIRU4(addr)) "ldl $%c,%0\nzap $%c,240,$%c\n" 2
-
-reg: CVIU8(reg) "mov $%0,$%c\n" move(a)
-
-reg: INDIRF4(addr) "lds $f%c,%0\n" 1
-reg: INDIRF8(addr) "ldt $f%c,%0\n" 1
-stmt: ASGNF4(addr,reg) "sts $f%1,%0\n" 1
-stmt: ASGNF8(addr,reg) "stt $f%1,%0\n" 1
-
-reg: MULI4(reg,rc) "mull $%0,%1,$%c\n" 1
-reg: MULI8(reg,rc) "mulq $%0,%1,$%c\n" 1
-reg: MULU4(reg,rc) "mull $%0,%1,$%c\nzap $%c,240,$%c\n" 2
-reg: MULU8(reg,rc) "mulq $%0,%1,$%c\n" 1
-
-reg: DIVI4(reg,rc) "divl $%0,%1,$%c\n" 1
-reg: DIVI8(reg,rc) "divq $%0,%1,$%c\n" 1
-reg: DIVU4(reg,rc) "divlu $%0,%1,$%c\n" 1
-reg: DIVU8(reg,rc) "divqu $%0,%1,$%c\n" 1
-reg: MODI4(reg,rc) "reml $%0,%1,$%c\n" 1
-reg: MODI8(reg,rc) "remq $%0,%1,$%c\n" 1
-reg: MODU4(reg,rc) "remlu $%0,%1,$%c\n" 1
-reg: MODU8(reg,rc) "remqu $%0,%1,$%c\n" 1
-
-rc: con "%0"
-rc: reg "$%0"
-
-reg: ADDI4(reg,rc) "addl $%0,%1,$%c\n" 1
-reg: ADDI8(reg,rc) "addq $%0,%1,$%c\n" 1
-reg: ADDP8(reg,rc) "addq $%0,%1,$%c\n" 1
-reg: ADDU4(reg,rc) "addl $%0,%1,$%c\nzap $%c,240,$%c\n" 2
-reg: ADDU8(reg,rc) "addq $%0,%1,$%c\n" 1
-reg: SUBI4(reg,rc) "subl $%0,%1,$%c\n" 1
-reg: SUBI8(reg,rc) "subq $%0,%1,$%c\n" 1
-reg: SUBP8(reg,rc) "subq $%0,%1,$%c\n" 1
-reg: SUBU4(reg,rc) "subl $%0,%1,$%c\nzap $%c,240,$%c\n" 2
-reg: SUBU8(reg,rc) "subq $%0,%1,$%c\n" 1
-
-reg: BANDI4(reg,rc) "and $%0,%1,$%c\naddl $%c,0,$%c\n" 2
-reg: BANDI8(reg,rc) "and $%0,%1,$%c\n" 1
-reg: BANDU4(reg,rc) "and $%0,%1,$%c\n" 1
-reg: BANDU8(reg,rc) "and $%0,%1,$%c\n" 1
-reg: BORI4(reg,rc) "or $%0,%1,$%c\naddl $%c,0,$%c\n" 2
-reg: BORI8(reg,rc) "or $%0,%1,$%c\n" 1
-reg: BORU4(reg,rc) "or $%0,%1,$%c\n" 1
-reg: BORU8(reg,rc) "or $%0,%1,$%c\n" 1
-reg: BXORI4(reg,rc) "xor $%0,%1,$%c\naddl $%c,0,$%c\n" 2
-reg: BXORI8(reg,rc) "xor $%0,%1,$%c\n" 1
-reg: BXORU4(reg,rc) "xor $%0,%1,$%c\n" 1
-reg: BXORU8(reg,rc) "xor $%0,%1,$%c\n" 1
-
-rc6: CNSTI4 "%a" range(a,0,63)
-rc6: CNSTI8 "%a" range(a,0,63)
-rc6: reg "$%0"
-
-reg: LSHI4(reg,rc6) "sll $%0,%1,$%c\naddl $%c,0,$%c\n" 2
-reg: LSHI8(reg,rc6) "sll $%0,%1,$%c\n" 1
-reg: LSHU4(reg,rc6) "sll $%0,%1,$%c\nzap $%c,240,$%c\n" 2
-reg: LSHU8(reg,rc6) "sll $%0,%1,$%c\n" 1
-reg: RSHI4(reg,rc6) "sra $%0,%1,$%c\naddl $%c,0,$%c\n" 2
-reg: RSHI8(reg,rc6) "sra $%0,%1,$%c\n" 1
-reg: RSHU4(reg,rc6) "srl $%0,%1,$%c\n" 1
-reg: RSHU8(reg,rc6) "srl $%0,%1,$%c\n" 1
-
-reg: BCOMI4(reg) "not $%0,$%c\naddl $%c,0,$%c\n" 2
-reg: BCOMU4(reg) "not $%0,$%c\nzap $%c,240,$%c\n" 2
-reg: BCOMI8(reg) "not $%0,$%c\n" 1
-reg: BCOMU8(reg) "not $%0,$%c\n" 1
-reg: NEGI4(reg) "negl $%0,$%c\n" 1
-reg: NEGI8(reg) "negq $%0,$%c\n" 1
-reg: LOADI1(reg) "mov $%0,$%c\n" move(a)
-reg: LOADI2(reg) "mov $%0,$%c\n" move(a)
-reg: LOADI4(reg) "mov $%0,$%c\n" move(a)
-reg: LOADI8(reg) "mov $%0,$%c\n" move(a)
-reg: LOADP8(reg) "mov $%0,$%c\n" move(a)
-reg: LOADU1(reg) "mov $%0,$%c\n" move(a)
-reg: LOADU2(reg) "mov $%0,$%c\n" move(a)
-reg: LOADU4(reg) "mov $%0,$%c\n" move(a)
-reg: LOADU8(reg) "mov $%0,$%c\n" move(a)
-
-reg: ADDF4(reg,reg) "adds $f%0,$f%1,$f%c\n" 1
-reg: ADDF8(reg,reg) "addt $f%0,$f%1,$f%c\n" 1
-reg: DIVF4(reg,reg) "divs $f%0,$f%1,$f%c\n" 1
-reg: DIVF8(reg,reg) "divt $f%0,$f%1,$f%c\n" 1
-reg: MULF4(reg,reg) "muls $f%0,$f%1,$f%c\n" 1
-reg: MULF8(reg,reg) "mult $f%0,$f%1,$f%c\n" 1
-reg: SUBF4(reg,reg) "subs $f%0,$f%1,$f%c\n" 1
-reg: SUBF8(reg,reg) "subt $f%0,$f%1,$f%c\n" 1
-reg: LOADF4(reg) "fmov $f%0,$f%c\n" move(a)
-reg: LOADF8(reg) "fmov $f%0,$f%c\n" move(a)
-reg: NEGF4(reg) "negs $f%0,$f%c\n" 1
-reg: NEGF8(reg) "negt $f%0,$f%c\n" 1
-reg: CVII4(reg) "sll $%0,8*(8-%a),$%c\nsra $%c,8*(8-%a),$%c\n" 2
-reg: CVII8(reg) "sll $%0,8*(8-%a),$%c\nsra $%c,8*(8-%a),$%c\n" 2
-reg: CVUI4(reg) "and $%0,(1<<(8*%a))-1,$%c\n" 1
-reg: CVUI8(reg) "and $%0,(1<<(8*%a))-1,$%c\n" 1
-reg: CVUU4(reg) "and $%0,(1<<(8*%a))-1,$%c\n" 1
-reg: CVUU8(reg) "and $%0,(1<<(8*%a))-1,$%c\n" 1
-
-reg: CVUP8(reg) "and $%0,(1<<(8*%a))-1,$%c\n" 1
-
-reg: CVFF4(reg) "cvtts $f%0,$f%c\n" 1
-reg: CVFF8(reg) "cvtst $f%0,$f%c\n" 1
-
-reg: CVIF4(reg) "stq $%0,-56+%F($sp)\nldt $%f%c,-56+%F($sp)\ncvtqs $f%c,$f%c\n" 3
-reg: CVIF8(reg) "stq $%0,-56+%F($sp)\nldt $%f%c,-56+%F($sp)\ncvtqt $f%c,$f%c\n" 3
-reg: CVIF4(INDIRI4(addr)) "lds $f%c,%0\ncvtlq $f%c,$f%c\ncvtqs $f%c,$f%c\n" 3
-reg: CVIF4(INDIRI8(addr)) "ldt $f%c,%0\ncvtqs $f%c,$f%c\n" 2
-reg: CVIF8(INDIRI4(addr)) "lds $f%c,%0\ncvtlq $f%c,$f%c\ncvtqt $f%c,$f%c\n" 3
-reg: CVIF8(INDIRI8(addr)) "ldt $f%c,%0\ncvtqt $f%c,$f%c\n" 2
-
-reg: CVFI4(reg) "cvttqc $f%0,$f1\ncvtql $f1,$f1\nsts $f1,-56+%F($sp)\nldl $%c,-56+%F($sp)\n" 4
-reg: CVFI8(reg) "cvttqc $f%0,$f1\nstt $f1,-56+%F($sp)\nldq $%c,-56+%F($sp)\n" 3
-
-stmt: LABELV "%a:\n"
-
-stmt: JUMPV(acon) "br %0\n" 1
-stmt: JUMPV(reg) "jmp ($%0)\n" 1
-
-stmt: EQI4(reg,rc6) "cmpeq $%0,%1,$23\nbne $23,%a\n" 2
-stmt: EQU4(reg,rc6) "cmpeq $%0,%1,$23\nbne $23,%a\n" 2
-stmt: EQI8(reg,rc6) "cmpeq $%0,%1,$23\nbne $23,%a\n" 2
-stmt: EQU8(reg,rc6) "cmpeq $%0,%1,$23\nbne $23,%a\n" 2
-stmt: NEI4(reg,rc6) "cmpeq $%0,%1,$23\nbeq $23,%a\n" 2
-stmt: NEU4(reg,rc6) "cmpeq $%0,%1,$23\nbeq $23,%a\n" 2
-stmt: NEI8(reg,rc6) "cmpeq $%0,%1,$23\nbeq $23,%a\n" 2
-stmt: NEU8(reg,rc6) "cmpeq $%0,%1,$23\nbeq $23,%a\n" 2
-stmt: GEI4(reg,rc6) "cmplt $%0,%1,$23\nbeq $23,%a\n" 2
-stmt: GEI8(reg,rc6) "cmplt $%0,%1,$23\nbeq $23,%a\n" 2
-stmt: GEU4(reg,rc6) "cmpult $%0,%1,$23\nbeq $23,%a\n" 1
-stmt: GEU8(reg,rc6) "cmpult $%0,%1,$23\nbeq $23,%a\n" 1
-stmt: GTI4(reg,rc6) "cmple $%0,%1,$23\nbeq $23,%a\n" 2
-stmt: GTI8(reg,rc6) "cmple $%0,%1,$23\nbeq $23,%a\n" 2
-stmt: GTU4(reg,rc6) "cmpule $%0,%1,$23\nbeq $23,%a\n" 1
-stmt: GTU8(reg,rc6) "cmpule $%0,%1,$23\nbeq $23,%a\n" 1
-stmt: LEI4(reg,rc6) "cmple $%0,%1,$23\nbne $23,%a\n" 2
-stmt: LEI8(reg,rc6) "cmple $%0,%1,$23\nbne $23,%a\n" 2
-stmt: LEU4(reg,rc6) "cmpule $%0,%1,$23\nbne $23,%a\n" 2
-stmt: LEU8(reg,rc6) "cmpule $%0,%1,$23\nbne $23,%a\n" 2
-stmt: LTI4(reg,rc6) "cmplt $%0,%1,$23\nbne $23,%a\n" 2
-stmt: LTI8(reg,rc6) "cmplt $%0,%1,$23\nbne $23,%a\n" 2
-stmt: LTU4(reg,rc6) "cmpult $%0,%1,$23\nbne $23,%a\n" 2
-stmt: LTU8(reg,rc6) "cmpult $%0,%1,$23\nbne $23,%a\n" 2
-
-stmt: EQF4(reg,reg) "cmpteq $f%0,$f%1,$f1\nfbne $f1,%a\n" 2
-stmt: EQF8(reg,reg) "cmpteq $f%0,$f%1,$f1\nfbne $f1,%a\n" 2
-stmt: LEF4(reg,reg) "cmptle $f%0,$f%1,$f1\nfbne $f1,%a\n" 2
-stmt: LEF8(reg,reg) "cmptle $f%0,$f%1,$f1\nfbne $f1,%a\n" 2
-stmt: LTF4(reg,reg) "cmptlt $f%0,$f%1,$f1\nfbne $f1,%a\n" 2
-stmt: LTF8(reg,reg) "cmptlt $f%0,$f%1,$f1\nfbne $f1,%a\n" 2
-
-stmt: NEF4(reg,reg) "cmpteq $f%0,$f%1,$f1\nfbeq $f1,%a\n" 2
-stmt: NEF8(reg,reg) "cmpteq $f%0,$f%1,$f1\nfbeq $f1,%a\n" 2
-stmt: GEF4(reg,reg) "cmptlt $f%0,$f%1,$f1\nfbeq $f1,%a\n" 2
-stmt: GEF8(reg,reg) "cmptlt $f%0,$f%1,$f1\nfbeq $f1,%a\n" 2
-stmt: GTF4(reg,reg) "cmptle $f%0,$f%1,$f1\nfbeq $f1,%a\n" 2
-stmt: GTF8(reg,reg) "cmptle $f%0,$f%1,$f1\nfbeq $f1,%a\n" 2
-
-ar: ADDRGP8 "%a"
-ar: reg "($%0)"
-
-reg: CALLF4(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2
-reg: CALLF8(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2
-reg: CALLI4(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2
-reg: CALLI8(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2
-reg: CALLP8(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2
-reg: CALLU4(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2
-reg: CALLU8(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2
-stmt: CALLV(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2
-
-stmt: RETF4(reg) "# ret\n" 1
-stmt: RETF8(reg) "# ret\n" 1
-stmt: RETI4(reg) "# ret\n" 1
-stmt: RETU4(reg) "# ret\n" 1
-stmt: RETI8(reg) "# ret\n" 1
-stmt: RETU8(reg) "# ret\n" 1
-stmt: RETP8(reg) "# ret\n" 1
-stmt: RETV(reg) "# ret\n" 1
-
-stmt: ARGF4(reg) "# arg\n" 1
-stmt: ARGF8(reg) "# arg\n" 1
-stmt: ARGI4(reg) "# arg\n" 1
-stmt: ARGI8(reg) "# arg\n" 1
-stmt: ARGP8(reg) "# arg\n" 1
-stmt: ARGU4(reg) "# arg\n" 1
-stmt: ARGU8(reg) "# arg\n" 1
-
-stmt: ARGB(INDIRB(reg)) "# argb %0\n" 1
-stmt: ASGNB(reg,INDIRB(reg)) "# asgnb %0 %1\n" 1
-
-%%
-static void progend(void){}
-
-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);
-
- for (i = 0; i < 32; i++)
- freg[i] = mkreg("%d", i, 1, FREG);
- for (i = 0; i < 32; i++)
- ireg[i] = mkreg("%d", i, 1, IREG);
- ireg[29]->x.name = "gp";
- ireg[30]->x.name = "sp";
- fregw = mkwildcard(freg);
- iregw = mkwildcard(ireg);
-
- tmask[IREG] = INTTMP; tmask[FREG] = FLTTMP;
- vmask[IREG] = INTVAR; vmask[FREG] = FLTVAR;
-
- blkreg = mkreg("1", 1, 0xf, IREG);
-
-}
-
-static Symbol rmap(int opk) {
- switch (optype(opk)) {
- case I: case U: case P: case B:
- return iregw;
- case F:
- return fregw;
- default:
- return 0;
- }
-}
-
-static Symbol argreg(int offset, int ty) {
- if (offset >= 48)
- return NULL;
- else if (ty == F)
- return freg[(offset/8) + 16];
- else
- return ireg[(offset/8) + 16];
-}
-
-static void target(Node p) {
- assert(p);
- switch (specific(p->op)) {
- case CNST+I: case CNST+U: case CNST+P:
- if (range(p, 0, 0) == 0) {
- setreg(p, ireg[31]);
- p->x.registered = 1;
- }
- break;
- case CNST+F:
- if (p->syms[0]->u.c.v.d == 0) {
- setreg(p, freg[31]);
- p->x.registered = 1;
- }
- break;
-
- case CALL+V:
- rtarget(p, 0, ireg[27]);
- break;
- case CALL+F:
- rtarget(p, 0, ireg[27]);
- setreg(p, freg[0]);
- break;
- case CALL+I: case CALL+P: case CALL+U:
- rtarget(p, 0, ireg[27]);
- setreg(p, ireg[0]);
- break;
- case RET+F:
- rtarget(p, 0, freg[0]);
- break;
- case RET+I: case RET+U: case RET+P:
- rtarget(p, 0, ireg[0]);
- break;
-
- case ARG+F: case ARG+I: case ARG+P: case ARG+U: {
- Symbol q = argreg(p->syms[2]->u.c.v.i, optype(p->op));
- if (q)
- rtarget(p, 0, q);
- break;
- }
-
-
- case ASGN+B: rtarget(p->kids[1], 0, blkreg); break;
- case ARG+B: rtarget(p->kids[0], 0, blkreg); break;
-
- }
-}
-
-static void clobber(Node p) {
- assert(p);
- switch (specific(p->op)) {
- case ASGN+I: case ASGN+U:
- if (opsize(p->op) <= 2)
- spill(1<<24, IREG, p);
- break;
-
- case DIV+I: case DIV+U: case MOD+I: case MOD+U:
- spill(((1<<27)|(3<<24))&~p->syms[RX]->x.regnode->mask, IREG, p);
- break;
-
- case CALL+F:
- spill(INTTMP | INTRET, IREG, p);
- spill(FLTTMP, FREG, p);
- break;
- case CALL+I: case CALL+P: case CALL+U:
- spill(INTTMP, IREG, p);
- spill(FLTTMP | FLTRET, FREG, p);
- break;
- case CALL+V:
- spill(INTTMP | INTRET, IREG, p);
- spill(FLTTMP | FLTRET, FREG, p);
- break;
-
- }
-}
-
-static void emit2(Node p) {
- int dst, n, src, sz, ty;
- static int ty0;
- Symbol q;
-
- switch (specific(p->op)) {
- case ARG+F: case ARG+I: case ARG+P: case ARG+U:
- ty = optype(p->op);
- sz = opsize(p->op);
- q = argreg(p->syms[2]->u.c.v.i, ty);
- src = getregnum(p->x.kids[0]);
- if (q)
- break;
- else if (ty == F && sz == 4)
- print("sts $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i - 48);
- else if (ty == F && sz == 8)
- print("stt $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i - 48);
- else if (sz == 4)
- print("stq $%d,%d($sp)\n", src, p->syms[2]->u.c.v.i - 48);
- else if (sz == 8)
- print("stq $%d,%d($sp)\n", src, p->syms[2]->u.c.v.i - 48);
- else
- assert(0);
- break;
-
- case ASGN+B:
- dalign = salign = p->syms[1]->u.c.v.i;
- blkcopy(getregnum(p->x.kids[0]), 0,
- getregnum(p->x.kids[1]), 0,
- p->syms[0]->u.c.v.i, tmpregs);
- break;
-
-
- case ARG+B: {
- int doff = p->syms[2]->u.c.v.i, soff = 0, sreg = getregnum(p->x.kids[0]);
- dalign = 8;
- salign = p->syms[1]->u.c.v.i;
- n = p->syms[0]->u.c.v.i;
- for ( ; doff <= 40 && n > 0; doff += 8) {
- print("uldq $%d,%d($%d)\n", (doff/8)+16, soff, sreg);
- soff += 8;
- n -= 8;
- }
- if (n > 0)
- blkcopy(30, doff - 48, sreg, soff, n, tmpregs);
- break;
- }
-
- }
-}
-
-static void doarg(Node p) {
- p->syms[2] = intconst(mkactual(8, roundup(p->syms[0]->u.c.v.i,8)));
-}
-
-static void local(Symbol p) {
- if (askregvar(p, rmap(ttob(p->type))) == 0)
- mkauto(p);
-}
-
-static int bitcount(unsigned mask) {
- unsigned i, n = 0;
-
- for (i = 1; i; i <<= 1)
- if (mask&i)
- n++;
- return n;
-}
-
-static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
- int i, sizeargs, saved, sizefsave, sizeisave, varargs;
- Symbol r, argregs[6];
-
- usedmask[0] = usedmask[1] = 0;
- freemask[0] = freemask[1] = ~(unsigned)0;
- maxargoffset = offset = maxoffset = 0;
-
- for (i = 0; callee[i]; i++)
- ;
- varargs = variadic(f->type)
- || i > 0 && strcmp(callee[i-1]->name, "va_alist") == 0;
- if (varargs)
- sizeargs = 2*48;
- else
- sizeargs = 48;
-
- for (i = 0; callee[i]; i++) {
- Symbol p = callee[i];
- Symbol q = caller[i];
- assert(q);
- if (isfloat(p->type) && varargs) {
- p->x.offset = q->x.offset = offset - 2*48;
- p->x.name = q->x.name = stringd(offset - 2*48);
- } else {
- p->x.offset = q->x.offset = offset - 48;
- p->x.name = q->x.name = stringd(offset - 48);
- }
- offset = roundup(offset, q->type->align);
- r = argreg(offset, optype(ttob(q->type)));
- if (i < 6)
- argregs[i] = r;
- offset = roundup(offset + q->type->size, 8);
- if (varargs)
- p->sclass = AUTO;
- else if (r && ncalls == 0 && !isstruct(q->type) && !p->addressed
-) {
- p->sclass = q->sclass = REGISTER;
- askregvar(p, r);
- assert(p->x.regnode && p->x.regnode->vbl == p);
- q->x = p->x;
- q->type = p->type;
- } else if (askregvar(p, rmap(ttob(p->type)))
- && r != NULL /*
- && (isint(p->type) || p->type == q->type) */
-) {
- assert(q->sclass != REGISTER);
- p->sclass = q->sclass = REGISTER;
- q->type = p->type;
- }
-
- }
- assert(!caller[i]);
-
- offset = sizeargs + 8;
- gencode(caller, callee);
- usedmask[IREG] &= ~(INTTMP|(0x3f<<16)|INTRET);
- usedmask[FREG] &= ~(FLTTMP|(0x3f<<16)|FLTRET);
- if (ncalls || usedmask[IREG] || usedmask[FREG])
- usedmask[IREG] |= 1<<26;
- sizefsave = 8*bitcount(usedmask[FREG]);
- sizeisave = 8*bitcount(usedmask[IREG]);
- if (maxargoffset > 48)
- maxargoffset -= 48;
- else
- maxargoffset = 0;
- if (maxoffset < sizeargs)
- maxoffset = sizeargs;
- framesize = roundup(maxargoffset + sizefsave + sizeisave + maxoffset, 16);
- segment(CODE);
- print(".ent %s\n", f->x.name);
- print("%s:\n", f->x.name);
- print("ldgp $gp,0($27)\n");
- i = maxargoffset + sizefsave - framesize;
- if (framesize > 0)
- print("lda $sp,%d($sp)\n", -framesize);
- if (usedmask[FREG])
- print(".fmask 0x%x,%d\n", usedmask[FREG], i - 8);
- if (usedmask[IREG])
- print(".mask 0x%x,%d\n", usedmask[IREG], i + sizeisave - 8);
- print(".frame $sp,%d,$26,%d\n", framesize, sizeargs);
-
- saved = maxargoffset;
- for (i = 2; i <= 9; i++)
- if (usedmask[FREG]&(1<<i)) {
- print("stt $f%d,%d($sp)\n", i, saved);
- saved += 8;
- }
-
- for (i = 9; i <= 26; i++)
- if (usedmask[IREG]&(1<<i)) {
- print("stq $%d,%d($sp)\n", i, saved);
- saved += 8;
- }
- for (i = 0; i < 6 && callee[i]; i++) {
- r = argregs[i];
- if (r && r->x.regnode != callee[i]->x.regnode) {
- Symbol out = callee[i];
- Symbol in = caller[i];
- int rn = r->x.regnode->number;
- int rs = r->x.regnode->set;
- int tyin = ttob(in->type);
-
- assert(out && in && r && r->x.regnode);
- assert(out->sclass != REGISTER || out->x.regnode);
- if (out->sclass == REGISTER) {
- if (rs == FREG)
- print("fmov $f%d,$f%d\n", rn, out->x.regnode->number);
- else
- print("mov $%d,$%d\n", rn, out->x.regnode->number);
-
- } else {
- int off = in->x.offset + framesize;
- if (rs == FREG && tyin == F+sizeop(8))
- print("stt $f%d,%d($sp)\n", rn, off);
- else if (rs == FREG && tyin == F+sizeop(4))
- print("sts $f%d,%d($sp)\n", rn, off);
- else {
- int i, n = (in->type->size + 7)/8;
- for (i = rn; i < rn+n && i <= 21; i++)
- print("stq $%d,%d($sp)\n", i, off + (i-rn)*8);
- }
-
- }
-
- }
- }
- if (varargs && callee[i-1]) {
- i = callee[i-1]->x.offset + roundup(callee[i-1]->type->size, 8);
- for (i = (48+i)/8; i < 6; i++) {
- print("stq $%d,%d($sp)\n", i + 16, framesize - 48 + 8*i);
- print("stt $f%d,%d($sp)\n", i + 16, framesize - 2*48 + 8*i);
- }
- }
- print(".prologue 1\n");
-
- emitcode();
- saved = maxargoffset;
- for (i = 2; i <= 9; i++)
- if (usedmask[FREG]&(1<<i)) {
- print("ldt $f%d,%d($sp)\n", i, saved);
- saved += 8;
- }
- for (i = 9; i <= 26; i++)
- if (usedmask[IREG]&(1<<i)) {
- print("ldq $%d,%d($sp)\n", i, saved);
- saved += 8;
- }
- if (framesize > 0)
- print("lda $sp,%d($sp)\n", framesize);
- print("ret\n");
- print(".end %s\n", f->x.name);
-
-}
-
-static void defconst(int suffix, int size, Value v) {
- if (suffix == F && size == 4) {
- float f = v.d;
- print(".long 0x%x\n", *(unsigned *)&f);
- } else if (suffix == F && size == 8) {
- double d = v.d;
- unsigned *p = (unsigned *)&d;
- print(".long 0x%x\n.long 0x%x\n", p[swap], p[!swap]);
- } else if (suffix == P)
- print(".quad 0x%X\n", v.p);
- else if (size == 1)
- print(".byte 0x%x\n", suffix == I ? v.i : v.u);
- else if (size == 2)
- print(".word 0x%x\n", suffix == I ? v.i&0xFFFF : v.u&0xFFFF);
- else if (size == 4)
- print(".long 0x%x\n", suffix == I ? v.i : v.u);
- else if (size == 8)
- print(".quad 0x%X\n", suffix == I ? v.i : v.u);
-
-}
-
-static void defaddress(Symbol p) {
- print(".quad %s\n", p->x.name);
-}
-
-static void defstring(int n, char *str) {
- char *s;
-
- for (s = str; s < str + n; s++)
- print(".byte %d\n", (*s)&0377);
-}
-
-static void export(Symbol p) {
- print(".globl %s\n", p->x.name);
-}
-
-static void import(Symbol p) {
- if (!isfunc(p->type))
- print(".extern %s %d\n", p->name, p->type->size);
-}
-
-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
- assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)),
- 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 global(Symbol p) {
- if (p->u.seg == DATA || p->u.seg == LIT) {
- assert(p->type->align <= 8);
- print(".align %c\n", ".01.2...3"[p->type->align]);
- print("%s:\n", p->x.name);
- } else if (p->sclass == STATIC || Aflag >= 2)
- print(".lcomm %s,%d\n", p->x.name, p->type->size);
- else
- print( ".comm %s,%d\n", p->x.name, p->type->size);
-}
-
-static void segment(int n) {
- cseg = n;
- switch (n) {
- case DATA: print(".sdata\n"); break;
- case CODE: print(".text\n"); break;
- case LIT: print(".rdata\n"); break;
- }
-}
-
-static void space(int n) {
- if (cseg != BSS)
- print(".space %d\n", n);
-}
-
-static void blkloop(int dreg, int doff, int sreg, int soff, int size, int tmps[]) {
- int lab = genlabel(1);
-
- print("addq $%d,%d,$%d\n", sreg, size&~7, sreg);
- print("addq $%d,%d,$%d\n", dreg, size&~7, tmps[2]);
- blkcopy(tmps[2], doff, sreg, soff, size&7, tmps);
- print("L.%d:\n", lab);
- print("addq $%d,%d,$%d\n", sreg, -8, sreg);
- print("addq $%d,%d,$%d\n", tmps[2], -8, tmps[2]);
- blkcopy(tmps[2], doff, sreg, soff, 8, tmps);
- print("cmpult $%d,$%d,$23\nbne $23,L.%d\n", dreg, tmps[2], lab);
-}
-
-static void blkfetch(int size, int off, int reg, int tmp) {
- assert(size == 1 || size == 2 || size == 4 || size == 8);
- if (size == 1)
- print("ldb $%d,%d($%d)\n", tmp, off, reg);
- else if (size == 2)
- print("ldw $%d,%d($%d)\n", tmp, off, reg);
- else if (salign >= size && size == 4)
- print("ldl $%d,%d($%d)\n", tmp, off, reg);
- else if (salign >= size && size == 8)
- print("ldq $%d,%d($%d)\n", tmp, off, reg);
- else if (size == 4)
- print("uldl $%d,%d($%d)\n", tmp, off, reg);
- else
- print("uldq $%d,%d($%d)\n", tmp, off, reg);
-}
-
-static void blkstore(int size, int off, int reg, int tmp) {
- assert(size == 1 || size == 2 || size == 4 || size == 8);
- if (size == 1)
- print("stb $%d,%d($%d)\n", tmp, off, reg);
- else if (size == 2)
- print("stw $%d,%d($%d)\n", tmp, off, reg);
- else if (dalign >= size && size == 4)
- print("stl $%d,%d($%d)\n", tmp, off, reg);
- else if (dalign >= size && size == 8)
- print("stq $%d,%d($%d)\n", tmp, off, reg);
- else if (size == 4)
- print("ustl $%d,%d($%d)\n", tmp, off, reg);
- else
- print("ustq $%d,%d($%d)\n", tmp, off, reg);
-}
-
-/* stabinit - initialize stab output */
-static void stabinit(char *file, int argc, char *argv[]) {
- if (file) {
- print(".file 2,\"%s\"\n", file);
- currentfile = file;
- }
-}
-
-/* stabline - emit stab entry for source coordinate *cp */
-static void stabline(Coordinate *cp) {
- if (cp->file && cp->file != currentfile) {
- print(".file 2,\"%s\"\n", cp->file);
- currentfile = cp->file;
- }
- print(".loc 2,%d\n", cp->y);
-}
-
-/* stabsym - output a stab entry for symbol p */
-static void stabsym(Symbol p) {
- if (p == cfunc && IR->stabline)
- (*IR->stabline)(&p->src);
-}
-Interface alphaIR = {
- 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 */
- 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, stabinit, stabline, stabsym, 0,
- {
- 1, /* max_unaligned_load */
- rmap,
- blkfetch, blkstore, blkloop,
- _label,
- _rule,
- _nts,
- _kids,
- _string,
- _templates,
- _isinstruction,
- _ntname,
- emit2,
- doarg,
- target,
- clobber,
-
- }
-
-};
-
-
-static char rcsid[] = "$Id: alpha.md 145 2001-10-17 21:53:10Z timo $";
-
+%{ +#define INTTMP ((0xff<<1)|(1<<22)|(1<<25)|(1<<27)) +#define INTVAR (0x3f<<9) +#define FLTTMP ((0x3f<<10)|(0x1ff<<22)) +#define FLTVAR (0xff<<2) + +#define INTRET 0x00000001 +#define FLTRET 0x00000003 + +#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)) + +#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); +static Symbol ireg[32], freg[32]; +static Symbol iregw, fregw; + +static int tmpregs[] = {4, 2, 3}; +static Symbol blkreg; + +static int cseg; + +static char *currentfile; + +%} +%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: con "%0" +acon: ADDRGP8 "%a" + +addr: ADDI4(reg,acon) "%1($%0)" +addr: ADDI8(reg,acon) "%1($%0)" +addr: ADDU8(reg,acon) "%1($%0)" +addr: ADDP8(reg,acon) "%1($%0)" + +addr: acon "%0" +addr: reg "($%0)" + +addr: ADDRFP8 "%a+%F($sp)" +addr: ADDRLP8 "%a+%F($sp)" + +reg: addr "lda $%c,%0\n" 1 + +reg: CNSTI1 "# reg\n" range(a, 0, 0) +reg: CNSTI2 "# reg\n" range(a, 0, 0) +reg: CNSTI4 "# reg\n" range(a, 0, 0) +reg: CNSTI8 "# reg\n" range(a, 0, 0) +reg: CNSTU1 "# reg\n" range(a, 0, 0) +reg: CNSTU2 "# reg\n" range(a, 0, 0) +reg: CNSTU4 "# reg\n" range(a, 0, 0) +reg: CNSTU8 "# reg\n" range(a, 0, 0) +reg: CNSTP8 "# reg\n" range(a, 0, 0) + +stmt: ASGNI1(addr,reg) "stb $%1,%0\n" 1 +stmt: ASGNU1(addr,reg) "stb $%1,%0\n" 1 +stmt: ASGNI2(addr,reg) "stw $%1,%0\n" 1 +stmt: ASGNU2(addr,reg) "stw $%1,%0\n" 1 + +stmt: ASGNI4(addr,reg) "stl $%1,%0\n" 1 +stmt: ASGNU4(addr,reg) "stl $%1,%0\n" 1 +stmt: ASGNI8(addr,reg) "stq $%1,%0\n" 1 +stmt: ASGNU8(addr,reg) "stq $%1,%0\n" 1 +stmt: ASGNP8(addr,reg) "stq $%1,%0\n" 1 + +reg: INDIRI1(reg) "ldb $%c,($%0)\n" 1 +reg: INDIRI2(reg) "ldw $%c,($%0)\n" 1 +reg: INDIRI4(addr) "ldl $%c,%0\n" 1 +reg: INDIRI8(addr) "ldq $%c,%0\n" 1 +reg: INDIRP8(addr) "ldq $%c,%0\n" 1 +reg: INDIRU1(reg) "ldbu $%c,($%0)\n" 1 +reg: INDIRU2(reg) "ldwu $%c,($%0)\n" 1 +reg: INDIRU4(addr) "ldl $%c,%0\nzap $%c,240,$%c\n" 2 +reg: INDIRU8(addr) "ldq $%c,%0\n" 1 + +reg: CVII4(INDIRI1(reg)) "ldb $%c,($%0)\n" 1 +reg: CVII8(INDIRI1(reg)) "ldb $%c,($%0)\n" 1 +reg: CVII4(INDIRI2(reg)) "ldw $%c,($%0)\n" 1 +reg: CVII8(INDIRI2(reg)) "ldw $%c,($%0)\n" 1 +reg: CVII8(INDIRI4(addr)) "ldl $%c,%0\n" 1 + +reg: CVUU4(INDIRU1(reg)) "ldbu $%c,($%0)\n" 1 +reg: CVUU8(INDIRU1(reg)) "ldbu $%c,($%0)\n" 1 +reg: CVUU4(INDIRU2(reg)) "ldwu $%c,($%0)\n" 1 +reg: CVUU8(INDIRU2(reg)) "ldwu $%c,($%0)\n" 1 +reg: CVUU8(INDIRU4(addr)) "ldl $%c,%0\nzap $%c,240,$%c\n" 2 + +reg: CVUI4(INDIRU1(reg)) "ldbu $%c,($%0)\n" 1 +reg: CVUI8(INDIRU1(reg)) "ldbu $%c,($%0)\n" 1 +reg: CVUI4(INDIRU2(reg)) "ldwu $%c,($%0)\n" 1 +reg: CVUI8(INDIRU2(reg)) "ldwu $%c,($%0)\n" 1 +reg: CVUI8(INDIRU4(addr)) "ldl $%c,%0\nzap $%c,240,$%c\n" 2 + +reg: CVIU8(reg) "mov $%0,$%c\n" move(a) + +reg: INDIRF4(addr) "lds $f%c,%0\n" 1 +reg: INDIRF8(addr) "ldt $f%c,%0\n" 1 +stmt: ASGNF4(addr,reg) "sts $f%1,%0\n" 1 +stmt: ASGNF8(addr,reg) "stt $f%1,%0\n" 1 + +reg: MULI4(reg,rc) "mull $%0,%1,$%c\n" 1 +reg: MULI8(reg,rc) "mulq $%0,%1,$%c\n" 1 +reg: MULU4(reg,rc) "mull $%0,%1,$%c\nzap $%c,240,$%c\n" 2 +reg: MULU8(reg,rc) "mulq $%0,%1,$%c\n" 1 + +reg: DIVI4(reg,rc) "divl $%0,%1,$%c\n" 1 +reg: DIVI8(reg,rc) "divq $%0,%1,$%c\n" 1 +reg: DIVU4(reg,rc) "divlu $%0,%1,$%c\n" 1 +reg: DIVU8(reg,rc) "divqu $%0,%1,$%c\n" 1 +reg: MODI4(reg,rc) "reml $%0,%1,$%c\n" 1 +reg: MODI8(reg,rc) "remq $%0,%1,$%c\n" 1 +reg: MODU4(reg,rc) "remlu $%0,%1,$%c\n" 1 +reg: MODU8(reg,rc) "remqu $%0,%1,$%c\n" 1 + +rc: con "%0" +rc: reg "$%0" + +reg: ADDI4(reg,rc) "addl $%0,%1,$%c\n" 1 +reg: ADDI8(reg,rc) "addq $%0,%1,$%c\n" 1 +reg: ADDP8(reg,rc) "addq $%0,%1,$%c\n" 1 +reg: ADDU4(reg,rc) "addl $%0,%1,$%c\nzap $%c,240,$%c\n" 2 +reg: ADDU8(reg,rc) "addq $%0,%1,$%c\n" 1 +reg: SUBI4(reg,rc) "subl $%0,%1,$%c\n" 1 +reg: SUBI8(reg,rc) "subq $%0,%1,$%c\n" 1 +reg: SUBP8(reg,rc) "subq $%0,%1,$%c\n" 1 +reg: SUBU4(reg,rc) "subl $%0,%1,$%c\nzap $%c,240,$%c\n" 2 +reg: SUBU8(reg,rc) "subq $%0,%1,$%c\n" 1 + +reg: BANDI4(reg,rc) "and $%0,%1,$%c\naddl $%c,0,$%c\n" 2 +reg: BANDI8(reg,rc) "and $%0,%1,$%c\n" 1 +reg: BANDU4(reg,rc) "and $%0,%1,$%c\n" 1 +reg: BANDU8(reg,rc) "and $%0,%1,$%c\n" 1 +reg: BORI4(reg,rc) "or $%0,%1,$%c\naddl $%c,0,$%c\n" 2 +reg: BORI8(reg,rc) "or $%0,%1,$%c\n" 1 +reg: BORU4(reg,rc) "or $%0,%1,$%c\n" 1 +reg: BORU8(reg,rc) "or $%0,%1,$%c\n" 1 +reg: BXORI4(reg,rc) "xor $%0,%1,$%c\naddl $%c,0,$%c\n" 2 +reg: BXORI8(reg,rc) "xor $%0,%1,$%c\n" 1 +reg: BXORU4(reg,rc) "xor $%0,%1,$%c\n" 1 +reg: BXORU8(reg,rc) "xor $%0,%1,$%c\n" 1 + +rc6: CNSTI4 "%a" range(a,0,63) +rc6: CNSTI8 "%a" range(a,0,63) +rc6: reg "$%0" + +reg: LSHI4(reg,rc6) "sll $%0,%1,$%c\naddl $%c,0,$%c\n" 2 +reg: LSHI8(reg,rc6) "sll $%0,%1,$%c\n" 1 +reg: LSHU4(reg,rc6) "sll $%0,%1,$%c\nzap $%c,240,$%c\n" 2 +reg: LSHU8(reg,rc6) "sll $%0,%1,$%c\n" 1 +reg: RSHI4(reg,rc6) "sra $%0,%1,$%c\naddl $%c,0,$%c\n" 2 +reg: RSHI8(reg,rc6) "sra $%0,%1,$%c\n" 1 +reg: RSHU4(reg,rc6) "srl $%0,%1,$%c\n" 1 +reg: RSHU8(reg,rc6) "srl $%0,%1,$%c\n" 1 + +reg: BCOMI4(reg) "not $%0,$%c\naddl $%c,0,$%c\n" 2 +reg: BCOMU4(reg) "not $%0,$%c\nzap $%c,240,$%c\n" 2 +reg: BCOMI8(reg) "not $%0,$%c\n" 1 +reg: BCOMU8(reg) "not $%0,$%c\n" 1 +reg: NEGI4(reg) "negl $%0,$%c\n" 1 +reg: NEGI8(reg) "negq $%0,$%c\n" 1 +reg: LOADI1(reg) "mov $%0,$%c\n" move(a) +reg: LOADI2(reg) "mov $%0,$%c\n" move(a) +reg: LOADI4(reg) "mov $%0,$%c\n" move(a) +reg: LOADI8(reg) "mov $%0,$%c\n" move(a) +reg: LOADP8(reg) "mov $%0,$%c\n" move(a) +reg: LOADU1(reg) "mov $%0,$%c\n" move(a) +reg: LOADU2(reg) "mov $%0,$%c\n" move(a) +reg: LOADU4(reg) "mov $%0,$%c\n" move(a) +reg: LOADU8(reg) "mov $%0,$%c\n" move(a) + +reg: ADDF4(reg,reg) "adds $f%0,$f%1,$f%c\n" 1 +reg: ADDF8(reg,reg) "addt $f%0,$f%1,$f%c\n" 1 +reg: DIVF4(reg,reg) "divs $f%0,$f%1,$f%c\n" 1 +reg: DIVF8(reg,reg) "divt $f%0,$f%1,$f%c\n" 1 +reg: MULF4(reg,reg) "muls $f%0,$f%1,$f%c\n" 1 +reg: MULF8(reg,reg) "mult $f%0,$f%1,$f%c\n" 1 +reg: SUBF4(reg,reg) "subs $f%0,$f%1,$f%c\n" 1 +reg: SUBF8(reg,reg) "subt $f%0,$f%1,$f%c\n" 1 +reg: LOADF4(reg) "fmov $f%0,$f%c\n" move(a) +reg: LOADF8(reg) "fmov $f%0,$f%c\n" move(a) +reg: NEGF4(reg) "negs $f%0,$f%c\n" 1 +reg: NEGF8(reg) "negt $f%0,$f%c\n" 1 +reg: CVII4(reg) "sll $%0,8*(8-%a),$%c\nsra $%c,8*(8-%a),$%c\n" 2 +reg: CVII8(reg) "sll $%0,8*(8-%a),$%c\nsra $%c,8*(8-%a),$%c\n" 2 +reg: CVUI4(reg) "and $%0,(1<<(8*%a))-1,$%c\n" 1 +reg: CVUI8(reg) "and $%0,(1<<(8*%a))-1,$%c\n" 1 +reg: CVUU4(reg) "and $%0,(1<<(8*%a))-1,$%c\n" 1 +reg: CVUU8(reg) "and $%0,(1<<(8*%a))-1,$%c\n" 1 + +reg: CVUP8(reg) "and $%0,(1<<(8*%a))-1,$%c\n" 1 + +reg: CVFF4(reg) "cvtts $f%0,$f%c\n" 1 +reg: CVFF8(reg) "cvtst $f%0,$f%c\n" 1 + +reg: CVIF4(reg) "stq $%0,-56+%F($sp)\nldt $%f%c,-56+%F($sp)\ncvtqs $f%c,$f%c\n" 3 +reg: CVIF8(reg) "stq $%0,-56+%F($sp)\nldt $%f%c,-56+%F($sp)\ncvtqt $f%c,$f%c\n" 3 +reg: CVIF4(INDIRI4(addr)) "lds $f%c,%0\ncvtlq $f%c,$f%c\ncvtqs $f%c,$f%c\n" 3 +reg: CVIF4(INDIRI8(addr)) "ldt $f%c,%0\ncvtqs $f%c,$f%c\n" 2 +reg: CVIF8(INDIRI4(addr)) "lds $f%c,%0\ncvtlq $f%c,$f%c\ncvtqt $f%c,$f%c\n" 3 +reg: CVIF8(INDIRI8(addr)) "ldt $f%c,%0\ncvtqt $f%c,$f%c\n" 2 + +reg: CVFI4(reg) "cvttqc $f%0,$f1\ncvtql $f1,$f1\nsts $f1,-56+%F($sp)\nldl $%c,-56+%F($sp)\n" 4 +reg: CVFI8(reg) "cvttqc $f%0,$f1\nstt $f1,-56+%F($sp)\nldq $%c,-56+%F($sp)\n" 3 + +stmt: LABELV "%a:\n" + +stmt: JUMPV(acon) "br %0\n" 1 +stmt: JUMPV(reg) "jmp ($%0)\n" 1 + +stmt: EQI4(reg,rc6) "cmpeq $%0,%1,$23\nbne $23,%a\n" 2 +stmt: EQU4(reg,rc6) "cmpeq $%0,%1,$23\nbne $23,%a\n" 2 +stmt: EQI8(reg,rc6) "cmpeq $%0,%1,$23\nbne $23,%a\n" 2 +stmt: EQU8(reg,rc6) "cmpeq $%0,%1,$23\nbne $23,%a\n" 2 +stmt: NEI4(reg,rc6) "cmpeq $%0,%1,$23\nbeq $23,%a\n" 2 +stmt: NEU4(reg,rc6) "cmpeq $%0,%1,$23\nbeq $23,%a\n" 2 +stmt: NEI8(reg,rc6) "cmpeq $%0,%1,$23\nbeq $23,%a\n" 2 +stmt: NEU8(reg,rc6) "cmpeq $%0,%1,$23\nbeq $23,%a\n" 2 +stmt: GEI4(reg,rc6) "cmplt $%0,%1,$23\nbeq $23,%a\n" 2 +stmt: GEI8(reg,rc6) "cmplt $%0,%1,$23\nbeq $23,%a\n" 2 +stmt: GEU4(reg,rc6) "cmpult $%0,%1,$23\nbeq $23,%a\n" 1 +stmt: GEU8(reg,rc6) "cmpult $%0,%1,$23\nbeq $23,%a\n" 1 +stmt: GTI4(reg,rc6) "cmple $%0,%1,$23\nbeq $23,%a\n" 2 +stmt: GTI8(reg,rc6) "cmple $%0,%1,$23\nbeq $23,%a\n" 2 +stmt: GTU4(reg,rc6) "cmpule $%0,%1,$23\nbeq $23,%a\n" 1 +stmt: GTU8(reg,rc6) "cmpule $%0,%1,$23\nbeq $23,%a\n" 1 +stmt: LEI4(reg,rc6) "cmple $%0,%1,$23\nbne $23,%a\n" 2 +stmt: LEI8(reg,rc6) "cmple $%0,%1,$23\nbne $23,%a\n" 2 +stmt: LEU4(reg,rc6) "cmpule $%0,%1,$23\nbne $23,%a\n" 2 +stmt: LEU8(reg,rc6) "cmpule $%0,%1,$23\nbne $23,%a\n" 2 +stmt: LTI4(reg,rc6) "cmplt $%0,%1,$23\nbne $23,%a\n" 2 +stmt: LTI8(reg,rc6) "cmplt $%0,%1,$23\nbne $23,%a\n" 2 +stmt: LTU4(reg,rc6) "cmpult $%0,%1,$23\nbne $23,%a\n" 2 +stmt: LTU8(reg,rc6) "cmpult $%0,%1,$23\nbne $23,%a\n" 2 + +stmt: EQF4(reg,reg) "cmpteq $f%0,$f%1,$f1\nfbne $f1,%a\n" 2 +stmt: EQF8(reg,reg) "cmpteq $f%0,$f%1,$f1\nfbne $f1,%a\n" 2 +stmt: LEF4(reg,reg) "cmptle $f%0,$f%1,$f1\nfbne $f1,%a\n" 2 +stmt: LEF8(reg,reg) "cmptle $f%0,$f%1,$f1\nfbne $f1,%a\n" 2 +stmt: LTF4(reg,reg) "cmptlt $f%0,$f%1,$f1\nfbne $f1,%a\n" 2 +stmt: LTF8(reg,reg) "cmptlt $f%0,$f%1,$f1\nfbne $f1,%a\n" 2 + +stmt: NEF4(reg,reg) "cmpteq $f%0,$f%1,$f1\nfbeq $f1,%a\n" 2 +stmt: NEF8(reg,reg) "cmpteq $f%0,$f%1,$f1\nfbeq $f1,%a\n" 2 +stmt: GEF4(reg,reg) "cmptlt $f%0,$f%1,$f1\nfbeq $f1,%a\n" 2 +stmt: GEF8(reg,reg) "cmptlt $f%0,$f%1,$f1\nfbeq $f1,%a\n" 2 +stmt: GTF4(reg,reg) "cmptle $f%0,$f%1,$f1\nfbeq $f1,%a\n" 2 +stmt: GTF8(reg,reg) "cmptle $f%0,$f%1,$f1\nfbeq $f1,%a\n" 2 + +ar: ADDRGP8 "%a" +ar: reg "($%0)" + +reg: CALLF4(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2 +reg: CALLF8(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2 +reg: CALLI4(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2 +reg: CALLI8(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2 +reg: CALLP8(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2 +reg: CALLU4(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2 +reg: CALLU8(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2 +stmt: CALLV(ar) "jsr $26,%0\nldgp $gp,0($26)\n" 2 + +stmt: RETF4(reg) "# ret\n" 1 +stmt: RETF8(reg) "# ret\n" 1 +stmt: RETI4(reg) "# ret\n" 1 +stmt: RETU4(reg) "# ret\n" 1 +stmt: RETI8(reg) "# ret\n" 1 +stmt: RETU8(reg) "# ret\n" 1 +stmt: RETP8(reg) "# ret\n" 1 +stmt: RETV(reg) "# ret\n" 1 + +stmt: ARGF4(reg) "# arg\n" 1 +stmt: ARGF8(reg) "# arg\n" 1 +stmt: ARGI4(reg) "# arg\n" 1 +stmt: ARGI8(reg) "# arg\n" 1 +stmt: ARGP8(reg) "# arg\n" 1 +stmt: ARGU4(reg) "# arg\n" 1 +stmt: ARGU8(reg) "# arg\n" 1 + +stmt: ARGB(INDIRB(reg)) "# argb %0\n" 1 +stmt: ASGNB(reg,INDIRB(reg)) "# asgnb %0 %1\n" 1 + +%% +static void progend(void){} + +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); + + for (i = 0; i < 32; i++) + freg[i] = mkreg("%d", i, 1, FREG); + for (i = 0; i < 32; i++) + ireg[i] = mkreg("%d", i, 1, IREG); + ireg[29]->x.name = "gp"; + ireg[30]->x.name = "sp"; + fregw = mkwildcard(freg); + iregw = mkwildcard(ireg); + + tmask[IREG] = INTTMP; tmask[FREG] = FLTTMP; + vmask[IREG] = INTVAR; vmask[FREG] = FLTVAR; + + blkreg = mkreg("1", 1, 0xf, IREG); + +} + +static Symbol rmap(int opk) { + switch (optype(opk)) { + case I: case U: case P: case B: + return iregw; + case F: + return fregw; + default: + return 0; + } +} + +static Symbol argreg(int offset, int ty) { + if (offset >= 48) + return NULL; + else if (ty == F) + return freg[(offset/8) + 16]; + else + return ireg[(offset/8) + 16]; +} + +static void target(Node p) { + assert(p); + switch (specific(p->op)) { + case CNST+I: case CNST+U: case CNST+P: + if (range(p, 0, 0) == 0) { + setreg(p, ireg[31]); + p->x.registered = 1; + } + break; + case CNST+F: + if (p->syms[0]->u.c.v.d == 0) { + setreg(p, freg[31]); + p->x.registered = 1; + } + break; + + case CALL+V: + rtarget(p, 0, ireg[27]); + break; + case CALL+F: + rtarget(p, 0, ireg[27]); + setreg(p, freg[0]); + break; + case CALL+I: case CALL+P: case CALL+U: + rtarget(p, 0, ireg[27]); + setreg(p, ireg[0]); + break; + case RET+F: + rtarget(p, 0, freg[0]); + break; + case RET+I: case RET+U: case RET+P: + rtarget(p, 0, ireg[0]); + break; + + case ARG+F: case ARG+I: case ARG+P: case ARG+U: { + Symbol q = argreg(p->syms[2]->u.c.v.i, optype(p->op)); + if (q) + rtarget(p, 0, q); + break; + } + + + case ASGN+B: rtarget(p->kids[1], 0, blkreg); break; + case ARG+B: rtarget(p->kids[0], 0, blkreg); break; + + } +} + +static void clobber(Node p) { + assert(p); + switch (specific(p->op)) { + case ASGN+I: case ASGN+U: + if (opsize(p->op) <= 2) + spill(1<<24, IREG, p); + break; + + case DIV+I: case DIV+U: case MOD+I: case MOD+U: + spill(((1<<27)|(3<<24))&~p->syms[RX]->x.regnode->mask, IREG, p); + break; + + case CALL+F: + spill(INTTMP | INTRET, IREG, p); + spill(FLTTMP, FREG, p); + break; + case CALL+I: case CALL+P: case CALL+U: + spill(INTTMP, IREG, p); + spill(FLTTMP | FLTRET, FREG, p); + break; + case CALL+V: + spill(INTTMP | INTRET, IREG, p); + spill(FLTTMP | FLTRET, FREG, p); + break; + + } +} + +static void emit2(Node p) { + int dst, n, src, sz, ty; + static int ty0; + Symbol q; + + switch (specific(p->op)) { + case ARG+F: case ARG+I: case ARG+P: case ARG+U: + ty = optype(p->op); + sz = opsize(p->op); + q = argreg(p->syms[2]->u.c.v.i, ty); + src = getregnum(p->x.kids[0]); + if (q) + break; + else if (ty == F && sz == 4) + print("sts $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i - 48); + else if (ty == F && sz == 8) + print("stt $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i - 48); + else if (sz == 4) + print("stq $%d,%d($sp)\n", src, p->syms[2]->u.c.v.i - 48); + else if (sz == 8) + print("stq $%d,%d($sp)\n", src, p->syms[2]->u.c.v.i - 48); + else + assert(0); + break; + + case ASGN+B: + dalign = salign = p->syms[1]->u.c.v.i; + blkcopy(getregnum(p->x.kids[0]), 0, + getregnum(p->x.kids[1]), 0, + p->syms[0]->u.c.v.i, tmpregs); + break; + + + case ARG+B: { + int doff = p->syms[2]->u.c.v.i, soff = 0, sreg = getregnum(p->x.kids[0]); + dalign = 8; + salign = p->syms[1]->u.c.v.i; + n = p->syms[0]->u.c.v.i; + for ( ; doff <= 40 && n > 0; doff += 8) { + print("uldq $%d,%d($%d)\n", (doff/8)+16, soff, sreg); + soff += 8; + n -= 8; + } + if (n > 0) + blkcopy(30, doff - 48, sreg, soff, n, tmpregs); + break; + } + + } +} + +static void doarg(Node p) { + p->syms[2] = intconst(mkactual(8, roundup(p->syms[0]->u.c.v.i,8))); +} + +static void local(Symbol p) { + if (askregvar(p, rmap(ttob(p->type))) == 0) + mkauto(p); +} + +static int bitcount(unsigned mask) { + unsigned i, n = 0; + + for (i = 1; i; i <<= 1) + if (mask&i) + n++; + return n; +} + +static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { + int i, sizeargs, saved, sizefsave, sizeisave, varargs; + Symbol r, argregs[6]; + + usedmask[0] = usedmask[1] = 0; + freemask[0] = freemask[1] = ~(unsigned)0; + maxargoffset = offset = maxoffset = 0; + + for (i = 0; callee[i]; i++) + ; + varargs = variadic(f->type) + || i > 0 && strcmp(callee[i-1]->name, "va_alist") == 0; + if (varargs) + sizeargs = 2*48; + else + sizeargs = 48; + + for (i = 0; callee[i]; i++) { + Symbol p = callee[i]; + Symbol q = caller[i]; + assert(q); + if (isfloat(p->type) && varargs) { + p->x.offset = q->x.offset = offset - 2*48; + p->x.name = q->x.name = stringd(offset - 2*48); + } else { + p->x.offset = q->x.offset = offset - 48; + p->x.name = q->x.name = stringd(offset - 48); + } + offset = roundup(offset, q->type->align); + r = argreg(offset, optype(ttob(q->type))); + if (i < 6) + argregs[i] = r; + offset = roundup(offset + q->type->size, 8); + if (varargs) + p->sclass = AUTO; + else if (r && ncalls == 0 && !isstruct(q->type) && !p->addressed +) { + p->sclass = q->sclass = REGISTER; + askregvar(p, r); + assert(p->x.regnode && p->x.regnode->vbl == p); + q->x = p->x; + q->type = p->type; + } else if (askregvar(p, rmap(ttob(p->type))) + && r != NULL /* + && (isint(p->type) || p->type == q->type) */ +) { + assert(q->sclass != REGISTER); + p->sclass = q->sclass = REGISTER; + q->type = p->type; + } + + } + assert(!caller[i]); + + offset = sizeargs + 8; + gencode(caller, callee); + usedmask[IREG] &= ~(INTTMP|(0x3f<<16)|INTRET); + usedmask[FREG] &= ~(FLTTMP|(0x3f<<16)|FLTRET); + if (ncalls || usedmask[IREG] || usedmask[FREG]) + usedmask[IREG] |= 1<<26; + sizefsave = 8*bitcount(usedmask[FREG]); + sizeisave = 8*bitcount(usedmask[IREG]); + if (maxargoffset > 48) + maxargoffset -= 48; + else + maxargoffset = 0; + if (maxoffset < sizeargs) + maxoffset = sizeargs; + framesize = roundup(maxargoffset + sizefsave + sizeisave + maxoffset, 16); + segment(CODE); + print(".ent %s\n", f->x.name); + print("%s:\n", f->x.name); + print("ldgp $gp,0($27)\n"); + i = maxargoffset + sizefsave - framesize; + if (framesize > 0) + print("lda $sp,%d($sp)\n", -framesize); + if (usedmask[FREG]) + print(".fmask 0x%x,%d\n", usedmask[FREG], i - 8); + if (usedmask[IREG]) + print(".mask 0x%x,%d\n", usedmask[IREG], i + sizeisave - 8); + print(".frame $sp,%d,$26,%d\n", framesize, sizeargs); + + saved = maxargoffset; + for (i = 2; i <= 9; i++) + if (usedmask[FREG]&(1<<i)) { + print("stt $f%d,%d($sp)\n", i, saved); + saved += 8; + } + + for (i = 9; i <= 26; i++) + if (usedmask[IREG]&(1<<i)) { + print("stq $%d,%d($sp)\n", i, saved); + saved += 8; + } + for (i = 0; i < 6 && callee[i]; i++) { + r = argregs[i]; + if (r && r->x.regnode != callee[i]->x.regnode) { + Symbol out = callee[i]; + Symbol in = caller[i]; + int rn = r->x.regnode->number; + int rs = r->x.regnode->set; + int tyin = ttob(in->type); + + assert(out && in && r && r->x.regnode); + assert(out->sclass != REGISTER || out->x.regnode); + if (out->sclass == REGISTER) { + if (rs == FREG) + print("fmov $f%d,$f%d\n", rn, out->x.regnode->number); + else + print("mov $%d,$%d\n", rn, out->x.regnode->number); + + } else { + int off = in->x.offset + framesize; + if (rs == FREG && tyin == F+sizeop(8)) + print("stt $f%d,%d($sp)\n", rn, off); + else if (rs == FREG && tyin == F+sizeop(4)) + print("sts $f%d,%d($sp)\n", rn, off); + else { + int i, n = (in->type->size + 7)/8; + for (i = rn; i < rn+n && i <= 21; i++) + print("stq $%d,%d($sp)\n", i, off + (i-rn)*8); + } + + } + + } + } + if (varargs && callee[i-1]) { + i = callee[i-1]->x.offset + roundup(callee[i-1]->type->size, 8); + for (i = (48+i)/8; i < 6; i++) { + print("stq $%d,%d($sp)\n", i + 16, framesize - 48 + 8*i); + print("stt $f%d,%d($sp)\n", i + 16, framesize - 2*48 + 8*i); + } + } + print(".prologue 1\n"); + + emitcode(); + saved = maxargoffset; + for (i = 2; i <= 9; i++) + if (usedmask[FREG]&(1<<i)) { + print("ldt $f%d,%d($sp)\n", i, saved); + saved += 8; + } + for (i = 9; i <= 26; i++) + if (usedmask[IREG]&(1<<i)) { + print("ldq $%d,%d($sp)\n", i, saved); + saved += 8; + } + if (framesize > 0) + print("lda $sp,%d($sp)\n", framesize); + print("ret\n"); + print(".end %s\n", f->x.name); + +} + +static void defconst(int suffix, int size, Value v) { + if (suffix == F && size == 4) { + float f = v.d; + print(".long 0x%x\n", *(unsigned *)&f); + } else if (suffix == F && size == 8) { + double d = v.d; + unsigned *p = (unsigned *)&d; + print(".long 0x%x\n.long 0x%x\n", p[swap], p[!swap]); + } else if (suffix == P) + print(".quad 0x%X\n", v.p); + else if (size == 1) + print(".byte 0x%x\n", suffix == I ? v.i : v.u); + else if (size == 2) + print(".word 0x%x\n", suffix == I ? v.i&0xFFFF : v.u&0xFFFF); + else if (size == 4) + print(".long 0x%x\n", suffix == I ? v.i : v.u); + else if (size == 8) + print(".quad 0x%X\n", suffix == I ? v.i : v.u); + +} + +static void defaddress(Symbol p) { + print(".quad %s\n", p->x.name); +} + +static void defstring(int n, char *str) { + char *s; + + for (s = str; s < str + n; s++) + print(".byte %d\n", (*s)&0377); +} + +static void export(Symbol p) { + print(".globl %s\n", p->x.name); +} + +static void import(Symbol p) { + if (!isfunc(p->type)) + print(".extern %s %d\n", p->name, p->type->size); +} + +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 + assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)), + 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 global(Symbol p) { + if (p->u.seg == DATA || p->u.seg == LIT) { + assert(p->type->align <= 8); + print(".align %c\n", ".01.2...3"[p->type->align]); + print("%s:\n", p->x.name); + } else if (p->sclass == STATIC || Aflag >= 2) + print(".lcomm %s,%d\n", p->x.name, p->type->size); + else + print( ".comm %s,%d\n", p->x.name, p->type->size); +} + +static void segment(int n) { + cseg = n; + switch (n) { + case DATA: print(".sdata\n"); break; + case CODE: print(".text\n"); break; + case LIT: print(".rdata\n"); break; + } +} + +static void space(int n) { + if (cseg != BSS) + print(".space %d\n", n); +} + +static void blkloop(int dreg, int doff, int sreg, int soff, int size, int tmps[]) { + int lab = genlabel(1); + + print("addq $%d,%d,$%d\n", sreg, size&~7, sreg); + print("addq $%d,%d,$%d\n", dreg, size&~7, tmps[2]); + blkcopy(tmps[2], doff, sreg, soff, size&7, tmps); + print("L.%d:\n", lab); + print("addq $%d,%d,$%d\n", sreg, -8, sreg); + print("addq $%d,%d,$%d\n", tmps[2], -8, tmps[2]); + blkcopy(tmps[2], doff, sreg, soff, 8, tmps); + print("cmpult $%d,$%d,$23\nbne $23,L.%d\n", dreg, tmps[2], lab); +} + +static void blkfetch(int size, int off, int reg, int tmp) { + assert(size == 1 || size == 2 || size == 4 || size == 8); + if (size == 1) + print("ldb $%d,%d($%d)\n", tmp, off, reg); + else if (size == 2) + print("ldw $%d,%d($%d)\n", tmp, off, reg); + else if (salign >= size && size == 4) + print("ldl $%d,%d($%d)\n", tmp, off, reg); + else if (salign >= size && size == 8) + print("ldq $%d,%d($%d)\n", tmp, off, reg); + else if (size == 4) + print("uldl $%d,%d($%d)\n", tmp, off, reg); + else + print("uldq $%d,%d($%d)\n", tmp, off, reg); +} + +static void blkstore(int size, int off, int reg, int tmp) { + assert(size == 1 || size == 2 || size == 4 || size == 8); + if (size == 1) + print("stb $%d,%d($%d)\n", tmp, off, reg); + else if (size == 2) + print("stw $%d,%d($%d)\n", tmp, off, reg); + else if (dalign >= size && size == 4) + print("stl $%d,%d($%d)\n", tmp, off, reg); + else if (dalign >= size && size == 8) + print("stq $%d,%d($%d)\n", tmp, off, reg); + else if (size == 4) + print("ustl $%d,%d($%d)\n", tmp, off, reg); + else + print("ustq $%d,%d($%d)\n", tmp, off, reg); +} + +/* stabinit - initialize stab output */ +static void stabinit(char *file, int argc, char *argv[]) { + if (file) { + print(".file 2,\"%s\"\n", file); + currentfile = file; + } +} + +/* stabline - emit stab entry for source coordinate *cp */ +static void stabline(Coordinate *cp) { + if (cp->file && cp->file != currentfile) { + print(".file 2,\"%s\"\n", cp->file); + currentfile = cp->file; + } + print(".loc 2,%d\n", cp->y); +} + +/* stabsym - output a stab entry for symbol p */ +static void stabsym(Symbol p) { + if (p == cfunc && IR->stabline) + (*IR->stabline)(&p->src); +} +Interface alphaIR = { + 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 */ + 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, stabinit, stabline, stabsym, 0, + { + 1, /* max_unaligned_load */ + rmap, + blkfetch, blkstore, blkloop, + _label, + _rule, + _nts, + _kids, + _string, + _templates, + _isinstruction, + _ntname, + emit2, + doarg, + target, + clobber, + + } + +}; + + +static char rcsid[] = "$Id: alpha.md 145 2001-10-17 21:53:10Z timo $"; + diff --git a/lcc/src/asdl.c b/lcc/src/asdl.c index 1c01c0c..bb22c89 100755 --- a/lcc/src/asdl.c +++ b/lcc/src/asdl.c @@ -1,399 +1,399 @@ -#include "c.h"
-#include "rcc.h"
-#if WIN32
-#include <fcntl.h>
-#include <io.h>
-#endif
-
-
-static list_ty interfaces;
-static rcc_program_ty pickle;
-
-char *string(const char *str) {
- return (char *)Atom_string(str);
-}
-
-char *stringd(long n) {
- return (char *)Atom_int(n);
-}
-
-char *stringn(const char *str, int len) {
- return (char *)Atom_new(str, len);
-}
-
-static void put(rcc_interface_ty node) {
- Seq_addhi(interfaces, node);
-}
-
-static int typeuid(Type ty) {
- rcc_type_ty type;
-
- assert(ty);
- if (ty->x.typeno != 0)
- return ty->x.typeno;
- ty->x.typeno = pickle->nuids++;
- switch (ty->op) {
-#define xx(op) case op: type = rcc_##op(ty->size, ty->align); break
- xx(INT);
- xx(UNSIGNED);
- xx(FLOAT);
- xx(VOID);
-#undef xx
-#define xx(op) case op: type = rcc_##op(ty->size, ty->align, typeuid(ty->type)); break
- xx(POINTER);
- xx(ARRAY);
- xx(CONST);
- xx(VOLATILE);
-#undef xx
- case CONST+VOLATILE:
- type = rcc_CONST(ty->size, ty->align, typeuid(ty->type));
- break;
- case ENUM: {
- list_ty ids = Seq_new(0);
- int i;
- for (i = 0; ty->u.sym->u.idlist[i] != NULL; i++)
- Seq_addhi(ids, rcc_enum_(ty->u.sym->u.idlist[i]->name,
- ty->u.sym->u.idlist[i]->u.value));
- assert(i > 0);
- type = rcc_ENUM(ty->size, ty->align, ty->u.sym->name, ids);
- break;
- }
- case STRUCT: case UNION: {
- list_ty fields = Seq_new(0);
- Field p = fieldlist(ty);
- for ( ; p != NULL; p = p->link)
- Seq_addhi(fields, rcc_field(p->name, typeuid(p->type), p->offset, p->bitsize, p->lsb));
- if (ty->op == STRUCT)
- type = rcc_STRUCT(ty->size, ty->align, ty->u.sym->name, fields);
- else
- type = rcc_UNION (ty->size, ty->align, ty->u.sym->name, fields);
- break;
- }
- case FUNCTION: {
- list_ty formals = Seq_new(0);
- if (ty->u.f.proto != NULL && ty->u.f.proto[0] != NULL) {
- int i;
- for (i = 0; ty->u.f.proto[i] != NULL; i++)
- Seq_addhi(formals, to_generic_int(typeuid(ty->u.f.proto[i])));
- } else if (ty->u.f.proto != NULL && ty->u.f.proto[0] == NULL)
- Seq_addhi(formals, to_generic_int(typeuid(voidtype)));
- type = rcc_FUNCTION(ty->size, ty->align, typeuid(ty->type), formals);
- break;
- }
- default: assert(0);
- }
- Seq_addhi(pickle->items, rcc_Type(ty->x.typeno, type));
- return ty->x.typeno;
-}
-
-static int symboluid(Symbol p) {
- assert(p);
- assert(p->scope != CONSTANTS && p->scope != LABELS);
- if (p->x.offset == 0)
- p->x.offset = pickle->nuids++;
- return p->x.offset;
-}
-
-static rcc_symbol_ty mk_symbol(Symbol p) {
- int flags = 0, ref = 10000*p->ref;
-
- if (p->ref > 0 && ref == 0)
- ref++;
-#define xx(f,n) flags |= p->f<<n;
- xx(structarg,0)
- xx(addressed,1)
- xx(computed,2)
- xx(temporary,3)
- xx(generated,4)
-#undef xx
- return rcc_symbol(p->name, typeuid(p->type), p->scope, p->sclass, ref, flags);
-}
-
-static rcc_real_ty mk_real(int size, Value v) {
- unsigned *p = (unsigned *)&v.d;
- return rcc_real(p[swap], p[1-swap]);
-}
-
-static void asdl_segment(int n) {
- static int cseg;
-
- if (cseg != n)
- put(rcc_Segment(cseg = n));
-}
-
-static void asdl_address(Symbol q, Symbol p, long n) {
- assert(q->x.offset == 0);
- put(rcc_Address(symboluid(q), mk_symbol(q), symboluid(p), n));
-}
-
-static void asdl_blockbeg(Env *e) {
- put(rcc_Blockbeg());
-}
-
-static void asdl_blockend(Env *e) {
- put(rcc_Blockend());
-}
-
-static void asdl_defaddress(Symbol p) {
- if (p->scope == LABELS)
- put(rcc_Deflabel(p->u.l.label));
- else
- put(rcc_Defaddress(symboluid(p)));
-}
-
-static void asdl_defconst(int suffix, int size, Value v) {
- switch (suffix) {
- case I: put(rcc_Defconst(suffix, size, v.i)); return;
- case U: put(rcc_Defconst(suffix, size, v.u)); return;
- case P: put(rcc_Defconst(suffix, size, (unsigned long)v.p)); return; /* FIXME */
- case F: put(rcc_Defconstf(size, mk_real(size, v))); return;
- assert(0);
- }
-}
-
-static void asdl_defstring(int len, char *str) {
- put(rcc_Defstring(Text_box(stringn(str, len), len)));
-}
-
-static void asdl_defsymbol(Symbol p) {
- if (p->scope >= GLOBAL)
- symboluid(p);
-}
-
-static Symbol temps;
-
-static rcc_node_ty visit(Node p) {
- Symbol q;
- rcc_node_ty left = NULL, right = NULL;
- int suffix = optype(p->op), size = opsize(p->op);
-
- assert(p);
- for (q = temps; q; q = q->u.t.next)
- if (q->u.t.cse == p) {
- q->u.t.cse = NULL;
- return rcc_CSE(0, 0, symboluid(q), visit(p));
- }
- if (p->kids[0] != NULL)
- left = visit(p->kids[0]);
- if (p->kids[1] != NULL)
- right = visit(p->kids[1]);
- switch (specific(p->op)) {
- case CNST+F:
- assert(p->syms[0]);
- return rcc_CNSTF(suffix, size, mk_real(size, p->syms[0]->u.c.v));
- case CALL+B:
- assert(p->syms[0]);
- assert(p->syms[0]->type);
- return rcc_CALLB(suffix, size, left, right, typeuid(p->syms[0]->type));
- case RET+V:
- return rcc_RET(suffix, size);
- case LABEL+V:
- assert(p->syms[0]);
- return rcc_LABEL(suffix, size, p->syms[0]->u.l.label);
- }
- switch (generic(p->op)) {
- case CNST:
- assert(p->syms[0]);
- return rcc_CNST(suffix, size, p->syms[0]->u.c.v.i); /* FIXME */
- case ARG:
- assert(p->syms[0]);
- return rcc_ARG(suffix, size, left, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i);
- case ASGN:
- assert(p->syms[0]);
- assert(p->syms[1]);
- return rcc_ASGN(suffix, size, left, right, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i);
- case CVF: case CVI: case CVP: case CVU:
- assert(p->syms[0]);
- return rcc_CVT(suffix, size, generic(p->op), left, p->syms[0]->u.c.v.i);
- case CALL:
- assert(p->syms[0]);
- assert(p->syms[0]->type);
- return rcc_CALL(suffix, size, left, typeuid(p->syms[0]->type));
-#define xx(op) case op: return rcc_##op(suffix, size, symboluid(p->syms[0]))
- xx(ADDRG);
- xx(ADDRF);
-#undef xx
- case ADDRL:
- if (!p->syms[0]->defined)
- (*IR->local)(p->syms[0]);
- p->syms[0]->defined = 1;
- return rcc_ADDRL(suffix, size, symboluid(p->syms[0]));
- case JUMP:
- if (p->syms[0] != NULL)
- return rcc_BRANCH(suffix, size, p->syms[0]->u.l.label);
- return rcc_Unary(suffix, size, generic(p->op), left);
- case INDIR: case RET: case NEG: case BCOM:
- return rcc_Unary(suffix, size, generic(p->op), left);
- case BOR: case BAND: case BXOR: case RSH: case LSH:
- case ADD: case SUB: case DIV: case MUL: case MOD:
- return rcc_Binary(suffix, size, generic(p->op), left, right);
- case EQ: case NE: case GT: case GE: case LE: case LT:
- assert(p->syms[0]);
- return rcc_Compare(suffix, size, generic(p->op), left, right, p->syms[0]->u.l.label);
- }
- assert(0);
- return NULL;
-}
-
-static void asdl_emit(Node p) {}
-
-static void asdl_local(Symbol p) {
- assert(p->x.offset == 0);
- put(rcc_Local(symboluid(p), mk_symbol(p)));
- if (p->temporary && p->u.t.cse) {
- p->u.t.next = temps;
- temps = p;
- }
-}
-
-static Symbol pending = NULL;
-
-static void dopending(Symbol p) {
- if (pending != NULL) {
- int uid = symboluid(pending);
- rcc_symbol_ty symbol = mk_symbol(pending);
- Seq_addhi(pickle->items, rcc_Symbol(uid, symbol));
- }
- pending = p;
-}
-
-
-static void asdl_export(Symbol p) {
- put(rcc_Export(symboluid(p)));
-}
-
-static void asdl_function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
- list_ty codelist = Seq_new(0), save, calleelist = Seq_new(0), callerlist = Seq_new(0);
- int i;
-
- dopending(f);
- for (i = 0; caller[i] != NULL; i++) {
- asdl_local(caller[i]);
- Seq_addhi(callerlist, to_generic_int(symboluid(caller[i])));
- }
- for (i = 0; callee[i] != NULL; i++) {
- asdl_local(callee[i]);
- Seq_addhi(calleelist, to_generic_int(symboluid(callee[i])));
- }
- save = interfaces;
- interfaces = codelist;
- gencode(caller, callee);
- asdl_segment(CODE);
- emitcode();
- interfaces = save;
- put(rcc_Function(symboluid(f), callerlist, calleelist, ncalls, codelist));
-}
-
-static Node asdl_gen(Node p) {
- Node q;
- list_ty forest = Seq_new(0);
-
- for (q = p; p != NULL; p = p->link)
- if (specific(p->op) == JUMP+V && specific(p->kids[0]->op) == ADDRG+P
- && p->kids[0]->syms[0]->scope == LABELS) {
- p->syms[0] = p->kids[0]->syms[0];
- p->kids[0] = NULL;
- }
- for (p = q; p != NULL; p = p->link)
- Seq_addhi(forest, visit(p));
- put(rcc_Forest(forest));
- temps = NULL;
- return q;
-}
-
-static void asdl_global(Symbol p) {
- dopending(p);
- put(rcc_Global(symboluid(p), p->u.seg));
-}
-
-static void asdl_import(Symbol p) {
- dopending(p);
- put(rcc_Import(symboluid(p)));
-}
-
-static void asdl_progbeg(int argc, char *argv[]) {
- int i;
-
-#if WIN32
- _setmode(_fileno(stdout), _O_BINARY);
-#endif
- pickle = rcc_program(1, 0, Seq_new(0), Seq_new(0), argc, Seq_new(0));
- for (i = 0; i < argc; i++)
- Seq_addhi(pickle->argv, to_generic_string(Text_box(argv[i], strlen(argv[i]) + 1)));
- interfaces = pickle->interfaces;
-}
-
-static int checkuid(list_ty list) {
- int i, n = 0, count = Seq_length(list);
-
- for (i = 0; i < count; i++) {
- rcc_interface_ty in = Seq_get(list, i);
- if (in->kind == rcc_Local_enum
- || in->kind == rcc_Address_enum)
- n++;
- else if (in->kind == rcc_Function_enum)
- n += checkuid(in->v.rcc_Function.codelist);
- }
- return n;
-}
-
-static void asdl_progend(void) {
- dopending(NULL);
- {
- int n = checkuid(pickle->interfaces) + Seq_length(pickle->items);
- if (n != pickle->nuids - 1)
- fprintf(stderr, "?bogus uid count: have %d should have %d\n",
- n, pickle->nuids-1);
- }
- pickle->nlabels = genlabel(0);
- write_int((int)(100*(assert(strstr(rcsid, ",v")), strtod(strstr(rcsid, ",v")+2, NULL))
-), stdout);
- rcc_write_program(pickle, stdout);
-}
-static void asdl_space(int n) {
- put(rcc_Space(n));
-}
-
-void asdl_init(int argc, char *argv[]) {
- int i;
- static int inited;
-
- if (inited)
- return;
- inited = 1;
- for (i = 1; i < argc; i++)
- if (strcmp(argv[i], "-asdl") == 0) {
-#define xx(f) IR->f = asdl_##f
- xx(address);
- xx(blockbeg);
- xx(blockend);
- xx(defaddress);
- xx(defconst);
- xx(defstring);
- xx(defsymbol);
- xx(emit);
- xx(export);
- xx(function);
- xx(gen);
- xx(global);
- xx(import);
- xx(local);
- xx(progbeg);
- xx(progend);
- xx(segment);
- xx(space);
-#undef xx
-#define xx(f) IR->f = 0
- xx(stabblock);
- xx(stabend);
- xx(stabfend);
- xx(stabinit);
- xx(stabline);
- xx(stabsym);
- xx(stabtype);
-#undef xx
- IR->wants_dag = 0;
- prunetemps = 0; /* pass2 prunes useless temps */
- assignargs = 0; /* pass2 generates caller to callee assignments */
- }
-}
+#include "c.h" +#include "rcc.h" +#if WIN32 +#include <fcntl.h> +#include <io.h> +#endif + + +static list_ty interfaces; +static rcc_program_ty pickle; + +char *string(const char *str) { + return (char *)Atom_string(str); +} + +char *stringd(long n) { + return (char *)Atom_int(n); +} + +char *stringn(const char *str, int len) { + return (char *)Atom_new(str, len); +} + +static void put(rcc_interface_ty node) { + Seq_addhi(interfaces, node); +} + +static int typeuid(Type ty) { + rcc_type_ty type; + + assert(ty); + if (ty->x.typeno != 0) + return ty->x.typeno; + ty->x.typeno = pickle->nuids++; + switch (ty->op) { +#define xx(op) case op: type = rcc_##op(ty->size, ty->align); break + xx(INT); + xx(UNSIGNED); + xx(FLOAT); + xx(VOID); +#undef xx +#define xx(op) case op: type = rcc_##op(ty->size, ty->align, typeuid(ty->type)); break + xx(POINTER); + xx(ARRAY); + xx(CONST); + xx(VOLATILE); +#undef xx + case CONST+VOLATILE: + type = rcc_CONST(ty->size, ty->align, typeuid(ty->type)); + break; + case ENUM: { + list_ty ids = Seq_new(0); + int i; + for (i = 0; ty->u.sym->u.idlist[i] != NULL; i++) + Seq_addhi(ids, rcc_enum_(ty->u.sym->u.idlist[i]->name, + ty->u.sym->u.idlist[i]->u.value)); + assert(i > 0); + type = rcc_ENUM(ty->size, ty->align, ty->u.sym->name, ids); + break; + } + case STRUCT: case UNION: { + list_ty fields = Seq_new(0); + Field p = fieldlist(ty); + for ( ; p != NULL; p = p->link) + Seq_addhi(fields, rcc_field(p->name, typeuid(p->type), p->offset, p->bitsize, p->lsb)); + if (ty->op == STRUCT) + type = rcc_STRUCT(ty->size, ty->align, ty->u.sym->name, fields); + else + type = rcc_UNION (ty->size, ty->align, ty->u.sym->name, fields); + break; + } + case FUNCTION: { + list_ty formals = Seq_new(0); + if (ty->u.f.proto != NULL && ty->u.f.proto[0] != NULL) { + int i; + for (i = 0; ty->u.f.proto[i] != NULL; i++) + Seq_addhi(formals, to_generic_int(typeuid(ty->u.f.proto[i]))); + } else if (ty->u.f.proto != NULL && ty->u.f.proto[0] == NULL) + Seq_addhi(formals, to_generic_int(typeuid(voidtype))); + type = rcc_FUNCTION(ty->size, ty->align, typeuid(ty->type), formals); + break; + } + default: assert(0); + } + Seq_addhi(pickle->items, rcc_Type(ty->x.typeno, type)); + return ty->x.typeno; +} + +static int symboluid(Symbol p) { + assert(p); + assert(p->scope != CONSTANTS && p->scope != LABELS); + if (p->x.offset == 0) + p->x.offset = pickle->nuids++; + return p->x.offset; +} + +static rcc_symbol_ty mk_symbol(Symbol p) { + int flags = 0, ref = 10000*p->ref; + + if (p->ref > 0 && ref == 0) + ref++; +#define xx(f,n) flags |= p->f<<n; + xx(structarg,0) + xx(addressed,1) + xx(computed,2) + xx(temporary,3) + xx(generated,4) +#undef xx + return rcc_symbol(p->name, typeuid(p->type), p->scope, p->sclass, ref, flags); +} + +static rcc_real_ty mk_real(int size, Value v) { + unsigned *p = (unsigned *)&v.d; + return rcc_real(p[swap], p[1-swap]); +} + +static void asdl_segment(int n) { + static int cseg; + + if (cseg != n) + put(rcc_Segment(cseg = n)); +} + +static void asdl_address(Symbol q, Symbol p, long n) { + assert(q->x.offset == 0); + put(rcc_Address(symboluid(q), mk_symbol(q), symboluid(p), n)); +} + +static void asdl_blockbeg(Env *e) { + put(rcc_Blockbeg()); +} + +static void asdl_blockend(Env *e) { + put(rcc_Blockend()); +} + +static void asdl_defaddress(Symbol p) { + if (p->scope == LABELS) + put(rcc_Deflabel(p->u.l.label)); + else + put(rcc_Defaddress(symboluid(p))); +} + +static void asdl_defconst(int suffix, int size, Value v) { + switch (suffix) { + case I: put(rcc_Defconst(suffix, size, v.i)); return; + case U: put(rcc_Defconst(suffix, size, v.u)); return; + case P: put(rcc_Defconst(suffix, size, (unsigned long)v.p)); return; /* FIXME */ + case F: put(rcc_Defconstf(size, mk_real(size, v))); return; + assert(0); + } +} + +static void asdl_defstring(int len, char *str) { + put(rcc_Defstring(Text_box(stringn(str, len), len))); +} + +static void asdl_defsymbol(Symbol p) { + if (p->scope >= GLOBAL) + symboluid(p); +} + +static Symbol temps; + +static rcc_node_ty visit(Node p) { + Symbol q; + rcc_node_ty left = NULL, right = NULL; + int suffix = optype(p->op), size = opsize(p->op); + + assert(p); + for (q = temps; q; q = q->u.t.next) + if (q->u.t.cse == p) { + q->u.t.cse = NULL; + return rcc_CSE(0, 0, symboluid(q), visit(p)); + } + if (p->kids[0] != NULL) + left = visit(p->kids[0]); + if (p->kids[1] != NULL) + right = visit(p->kids[1]); + switch (specific(p->op)) { + case CNST+F: + assert(p->syms[0]); + return rcc_CNSTF(suffix, size, mk_real(size, p->syms[0]->u.c.v)); + case CALL+B: + assert(p->syms[0]); + assert(p->syms[0]->type); + return rcc_CALLB(suffix, size, left, right, typeuid(p->syms[0]->type)); + case RET+V: + return rcc_RET(suffix, size); + case LABEL+V: + assert(p->syms[0]); + return rcc_LABEL(suffix, size, p->syms[0]->u.l.label); + } + switch (generic(p->op)) { + case CNST: + assert(p->syms[0]); + return rcc_CNST(suffix, size, p->syms[0]->u.c.v.i); /* FIXME */ + case ARG: + assert(p->syms[0]); + return rcc_ARG(suffix, size, left, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i); + case ASGN: + assert(p->syms[0]); + assert(p->syms[1]); + return rcc_ASGN(suffix, size, left, right, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i); + case CVF: case CVI: case CVP: case CVU: + assert(p->syms[0]); + return rcc_CVT(suffix, size, generic(p->op), left, p->syms[0]->u.c.v.i); + case CALL: + assert(p->syms[0]); + assert(p->syms[0]->type); + return rcc_CALL(suffix, size, left, typeuid(p->syms[0]->type)); +#define xx(op) case op: return rcc_##op(suffix, size, symboluid(p->syms[0])) + xx(ADDRG); + xx(ADDRF); +#undef xx + case ADDRL: + if (!p->syms[0]->defined) + (*IR->local)(p->syms[0]); + p->syms[0]->defined = 1; + return rcc_ADDRL(suffix, size, symboluid(p->syms[0])); + case JUMP: + if (p->syms[0] != NULL) + return rcc_BRANCH(suffix, size, p->syms[0]->u.l.label); + return rcc_Unary(suffix, size, generic(p->op), left); + case INDIR: case RET: case NEG: case BCOM: + return rcc_Unary(suffix, size, generic(p->op), left); + case BOR: case BAND: case BXOR: case RSH: case LSH: + case ADD: case SUB: case DIV: case MUL: case MOD: + return rcc_Binary(suffix, size, generic(p->op), left, right); + case EQ: case NE: case GT: case GE: case LE: case LT: + assert(p->syms[0]); + return rcc_Compare(suffix, size, generic(p->op), left, right, p->syms[0]->u.l.label); + } + assert(0); + return NULL; +} + +static void asdl_emit(Node p) {} + +static void asdl_local(Symbol p) { + assert(p->x.offset == 0); + put(rcc_Local(symboluid(p), mk_symbol(p))); + if (p->temporary && p->u.t.cse) { + p->u.t.next = temps; + temps = p; + } +} + +static Symbol pending = NULL; + +static void dopending(Symbol p) { + if (pending != NULL) { + int uid = symboluid(pending); + rcc_symbol_ty symbol = mk_symbol(pending); + Seq_addhi(pickle->items, rcc_Symbol(uid, symbol)); + } + pending = p; +} + + +static void asdl_export(Symbol p) { + put(rcc_Export(symboluid(p))); +} + +static void asdl_function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { + list_ty codelist = Seq_new(0), save, calleelist = Seq_new(0), callerlist = Seq_new(0); + int i; + + dopending(f); + for (i = 0; caller[i] != NULL; i++) { + asdl_local(caller[i]); + Seq_addhi(callerlist, to_generic_int(symboluid(caller[i]))); + } + for (i = 0; callee[i] != NULL; i++) { + asdl_local(callee[i]); + Seq_addhi(calleelist, to_generic_int(symboluid(callee[i]))); + } + save = interfaces; + interfaces = codelist; + gencode(caller, callee); + asdl_segment(CODE); + emitcode(); + interfaces = save; + put(rcc_Function(symboluid(f), callerlist, calleelist, ncalls, codelist)); +} + +static Node asdl_gen(Node p) { + Node q; + list_ty forest = Seq_new(0); + + for (q = p; p != NULL; p = p->link) + if (specific(p->op) == JUMP+V && specific(p->kids[0]->op) == ADDRG+P + && p->kids[0]->syms[0]->scope == LABELS) { + p->syms[0] = p->kids[0]->syms[0]; + p->kids[0] = NULL; + } + for (p = q; p != NULL; p = p->link) + Seq_addhi(forest, visit(p)); + put(rcc_Forest(forest)); + temps = NULL; + return q; +} + +static void asdl_global(Symbol p) { + dopending(p); + put(rcc_Global(symboluid(p), p->u.seg)); +} + +static void asdl_import(Symbol p) { + dopending(p); + put(rcc_Import(symboluid(p))); +} + +static void asdl_progbeg(int argc, char *argv[]) { + int i; + +#if WIN32 + _setmode(_fileno(stdout), _O_BINARY); +#endif + pickle = rcc_program(1, 0, Seq_new(0), Seq_new(0), argc, Seq_new(0)); + for (i = 0; i < argc; i++) + Seq_addhi(pickle->argv, to_generic_string(Text_box(argv[i], strlen(argv[i]) + 1))); + interfaces = pickle->interfaces; +} + +static int checkuid(list_ty list) { + int i, n = 0, count = Seq_length(list); + + for (i = 0; i < count; i++) { + rcc_interface_ty in = Seq_get(list, i); + if (in->kind == rcc_Local_enum + || in->kind == rcc_Address_enum) + n++; + else if (in->kind == rcc_Function_enum) + n += checkuid(in->v.rcc_Function.codelist); + } + return n; +} + +static void asdl_progend(void) { + dopending(NULL); + { + int n = checkuid(pickle->interfaces) + Seq_length(pickle->items); + if (n != pickle->nuids - 1) + fprintf(stderr, "?bogus uid count: have %d should have %d\n", + n, pickle->nuids-1); + } + pickle->nlabels = genlabel(0); + write_int((int)(100*(assert(strstr(rcsid, ",v")), strtod(strstr(rcsid, ",v")+2, NULL)) +), stdout); + rcc_write_program(pickle, stdout); +} +static void asdl_space(int n) { + put(rcc_Space(n)); +} + +void asdl_init(int argc, char *argv[]) { + int i; + static int inited; + + if (inited) + return; + inited = 1; + for (i = 1; i < argc; i++) + if (strcmp(argv[i], "-asdl") == 0) { +#define xx(f) IR->f = asdl_##f + xx(address); + xx(blockbeg); + xx(blockend); + xx(defaddress); + xx(defconst); + xx(defstring); + xx(defsymbol); + xx(emit); + xx(export); + xx(function); + xx(gen); + xx(global); + xx(import); + xx(local); + xx(progbeg); + xx(progend); + xx(segment); + xx(space); +#undef xx +#define xx(f) IR->f = 0 + xx(stabblock); + xx(stabend); + xx(stabfend); + xx(stabinit); + xx(stabline); + xx(stabsym); + xx(stabtype); +#undef xx + IR->wants_dag = 0; + prunetemps = 0; /* pass2 prunes useless temps */ + assignargs = 0; /* pass2 generates caller to callee assignments */ + } +} diff --git a/lcc/src/bind.c b/lcc/src/bind.c index 3723e37..562ffda 100755 --- a/lcc/src/bind.c +++ b/lcc/src/bind.c @@ -1,23 +1,23 @@ -#include "c.h"
-extern Interface alphaIR;
-extern Interface mipsebIR, mipselIR;
-extern Interface sparcIR, solarisIR;
-extern Interface x86IR, x86linuxIR;
-extern Interface symbolicIR, symbolic64IR;
-extern Interface nullIR;
-extern Interface bytecodeIR;
-Binding bindings[] = {
- "alpha/osf", &alphaIR,
- "mips/irix", &mipsebIR,
- "mips/ultrix", &mipselIR,
- "sparc/sun", &sparcIR,
- "sparc/solaris", &solarisIR,
- "x86/win32", &x86IR,
- "x86/linux", &x86linuxIR,
- "symbolic/osf", &symbolic64IR,
- "symbolic/irix", &symbolicIR,
- "symbolic", &symbolicIR,
- "null", &nullIR,
- "bytecode", &bytecodeIR,
- NULL, NULL
-};
+#include "c.h" +extern Interface alphaIR; +extern Interface mipsebIR, mipselIR; +extern Interface sparcIR, solarisIR; +extern Interface x86IR, x86linuxIR; +extern Interface symbolicIR, symbolic64IR; +extern Interface nullIR; +extern Interface bytecodeIR; +Binding bindings[] = { + "alpha/osf", &alphaIR, + "mips/irix", &mipsebIR, + "mips/ultrix", &mipselIR, + "sparc/sun", &sparcIR, + "sparc/solaris", &solarisIR, + "x86/win32", &x86IR, + "x86/linux", &x86linuxIR, + "symbolic/osf", &symbolic64IR, + "symbolic/irix", &symbolicIR, + "symbolic", &symbolicIR, + "null", &nullIR, + "bytecode", &bytecodeIR, + NULL, NULL +}; diff --git a/lcc/src/bytecode.c b/lcc/src/bytecode.c index f32a04f..8b8a6b6 100755 --- a/lcc/src/bytecode.c +++ b/lcc/src/bytecode.c @@ -1,365 +1,365 @@ -#include "c.h"
-#define I(f) b_##f
-
-
-static void I(segment)(int n) {
- static int cseg;
-
- if (cseg != n)
- switch (cseg = n) {
- case CODE: print("code\n"); return;
- case DATA: print("data\n"); return;
- case BSS: print("bss\n"); return;
- case LIT: print("lit\n"); return;
- default: assert(0);
- }
-}
-
-static void I(address)(Symbol q, Symbol p, long n) {
- q->x.name = stringf("%s%s%D", p->x.name, n > 0 ? "+" : "", n);
-}
-
-static void I(defaddress)(Symbol p) {
- print("address %s\n", p->x.name);
-}
-
-static void I(defconst)(int suffix, int size, Value v) {
- switch (suffix) {
- case I:
- if (size > sizeof (int))
- print("byte %d %D\n", size, v.i);
- else
- print("byte %d %d\n", size, v.i);
- return;
- case U:
- if (size > sizeof (unsigned))
- print("byte %d %U\n", size, v.u);
- else
- print("byte %d %u\n", size, v.u);
- return;
- case P: print("byte %d %U\n", size, (unsigned long)v.p); return;
- case F:
- if (size == 4) {
- float f = v.d;
- print("byte 4 %u\n", *(unsigned *)&f);
- } else {
- unsigned *p = (unsigned *)&v.d;
- print("byte 4 %u\n", p[swap]);
- print("byte 4 %u\n", p[1 - swap]);
- }
- return;
- }
- assert(0);
-}
-
-static void I(defstring)(int len, char *str) {
- char *s;
-
- for (s = str; s < str + len; s++)
- print("byte 1 %d\n", (*s)&0377);
-}
-
-static void I(defsymbol)(Symbol p) {
- if (p->scope == CONSTANTS)
- switch (optype(ttob(p->type))) {
- case I: p->x.name = stringf("%D", p->u.c.v.i); break;
- case U: p->x.name = stringf("%U", p->u.c.v.u); break;
- case P: p->x.name = stringf("%U", p->u.c.v.p); break;
- case F:
- { // JDC: added this to get inline floats
- unsigned temp;
-
- *(float *)&temp = p->u.c.v.d;
- p->x.name = stringf("%U", temp );
- }
- break;// JDC: added this
- default: assert(0);
- }
- else if (p->scope >= LOCAL && p->sclass == STATIC)
- p->x.name = stringf("$%d", genlabel(1));
- else if (p->scope == LABELS || p->generated)
- p->x.name = stringf("$%s", p->name);
- else
- p->x.name = p->name;
-}
-
-static void dumptree(Node p) {
- switch (specific(p->op)) {
- case ASGN+B:
- assert(p->kids[0]);
- assert(p->kids[1]);
- assert(p->syms[0]);
- dumptree(p->kids[0]);
- dumptree(p->kids[1]);
- print("%s %d\n", opname(p->op), p->syms[0]->u.c.v.u);
- return;
- case RET+V:
- assert(!p->kids[0]);
- assert(!p->kids[1]);
- print("%s\n", opname(p->op));
- return;
- }
- switch (generic(p->op)) {
- case CNST: case ADDRG: case ADDRF: case ADDRL: case LABEL:
- assert(!p->kids[0]);
- assert(!p->kids[1]);
- assert(p->syms[0] && p->syms[0]->x.name);
- print("%s %s\n", opname(p->op), p->syms[0]->x.name);
- return;
- case CVF: case CVI: case CVP: case CVU:
- assert(p->kids[0]);
- assert(!p->kids[1]);
- assert(p->syms[0]);
- dumptree(p->kids[0]);
- print("%s %d\n", opname(p->op), p->syms[0]->u.c.v.i);
- return;
- case ARG: case BCOM: case NEG: case INDIR: case JUMP: case RET:
- assert(p->kids[0]);
- assert(!p->kids[1]);
- dumptree(p->kids[0]);
- print("%s\n", opname(p->op));
- return;
- case CALL:
- assert(p->kids[0]);
- assert(!p->kids[1]);
- assert(optype(p->op) != B);
- dumptree(p->kids[0]);
- print("%s\n", opname(p->op));
- if ( !p->count ) { printf("pop\n"); }; // JDC
- return;
- case ASGN: case BOR: case BAND: case BXOR: case RSH: case LSH:
- case ADD: case SUB: case DIV: case MUL: case MOD:
- assert(p->kids[0]);
- assert(p->kids[1]);
- dumptree(p->kids[0]);
- dumptree(p->kids[1]);
- print("%s\n", opname(p->op));
- return;
- case EQ: case NE: case GT: case GE: case LE: case LT:
- assert(p->kids[0]);
- assert(p->kids[1]);
- assert(p->syms[0]);
- assert(p->syms[0]->x.name);
- dumptree(p->kids[0]);
- dumptree(p->kids[1]);
- print("%s %s\n", opname(p->op), p->syms[0]->x.name);
- return;
- }
- assert(0);
-}
-
-static void I(emit)(Node p) {
- for (; p; p = p->link)
- dumptree(p);
-}
-
-static void I(export)(Symbol p) {
- print("export %s\n", p->x.name);
-}
-
-static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
- int i;
-
- (*IR->segment)(CODE);
- offset = 0;
- for (i = 0; caller[i] && callee[i]; i++) {
- offset = roundup(offset, caller[i]->type->align);
- caller[i]->x.name = callee[i]->x.name = stringf("%d", offset);
- caller[i]->x.offset = callee[i]->x.offset = offset;
- offset += caller[i]->type->size;
- }
- maxargoffset = maxoffset = argoffset = offset = 0;
- gencode(caller, callee);
- print("proc %s %d %d\n", f->x.name, maxoffset, maxargoffset);
- emitcode();
- print("endproc %s %d %d\n", f->x.name, maxoffset, maxargoffset);
-
-}
-
-static void gen02(Node p) {
- assert(p);
- if (generic(p->op) == ARG) {
- assert(p->syms[0]);
- argoffset += (p->syms[0]->u.c.v.i < 4 ? 4 : p->syms[0]->u.c.v.i);
- } else if (generic(p->op) == CALL) {
- maxargoffset = (argoffset > maxargoffset ? argoffset : maxargoffset);
- argoffset = 0;
- }
-}
-
-static void gen01(Node p) {
- if (p) {
- gen01(p->kids[0]);
- gen01(p->kids[1]);
- gen02(p);
- }
-}
-
-static Node I(gen)(Node p) {
- Node q;
-
- assert(p);
- for (q = p; q; q = q->link)
- gen01(q);
- return p;
-}
-
-static void I(global)(Symbol p) {
- print("align %d\n", p->type->align > 4 ? 4 : p->type->align);
- print("LABELV %s\n", p->x.name);
-}
-
-static void I(import)(Symbol p) {
- print("import %s\n", p->x.name);
-}
-
-static void I(local)(Symbol p) {
- offset = roundup(offset, p->type->align);
- p->x.name = stringf("%d", offset);
- p->x.offset = offset;
- offset += p->type->size;
-}
-
-static void I(progbeg)(int argc, char *argv[]) {}
-
-static void I(progend)(void) {}
-
-static void I(space)(int n) {
- print("skip %d\n", n);
-}
-
-//========================================================
-
-// JDC: hacked up to get interleaved source lines in asm code
-static char *sourceFile;
-static char *sourcePtr;
-static int sourceLine;
-
-static int filelength( FILE *f ) {
- int pos;
- int end;
-
- pos = ftell (f);
- fseek (f, 0, SEEK_END);
- end = ftell (f);
- fseek (f, pos, SEEK_SET);
-
- return end;
-}
-
-static void LoadSourceFile( const char *filename ) {
- FILE *f;
- int length;
-
- f = fopen( filename, "r" );
- if ( !f ) {
- print( ";couldn't open %s\n", filename );
- sourceFile = NULL;
- return;
- }
- length = filelength( f );
- sourceFile = malloc( length + 1 );
- if ( sourceFile ) {
- fread( sourceFile, length, 1, f );
- sourceFile[length] = 0;
- }
-
- fclose( f );
- sourceLine = 1;
- sourcePtr = sourceFile;
-}
-
-static void PrintToSourceLine( int line ) {
- int c;
-
- if ( !sourceFile ) {
- return;
- }
- while ( sourceLine <= line ) {
- int i;
-
- for ( i = 0 ; sourcePtr[i] && sourcePtr[i] != '\n' ; i++ ) {
- }
- c = sourcePtr[i];
- if ( c == '\n' ) {
- sourcePtr[i] = 0;
- }
- print( ";%d:%s\n", sourceLine, sourcePtr );
- if ( c == 0 ) {
- sourcePtr += i; // end of file
- } else {
- sourcePtr += i+1;
- }
- sourceLine++;
- }
-}
-
-static void I(stabline)(Coordinate *cp) {
- static char *prevfile;
- static int prevline;
-
- if (cp->file && (prevfile == NULL || strcmp(prevfile, cp->file) != 0)) {
- print("file \"%s\"\n", prevfile = cp->file);
- prevline = 0;
- if ( sourceFile ) {
- free( sourceFile );
- sourceFile = NULL;
- }
- // load the new source file
- LoadSourceFile( cp->file );
- }
- if (cp->y != prevline) {
- print("line %d\n", prevline = cp->y);
- PrintToSourceLine( cp->y );
- }
-}
-
-//========================================================
-
-#define b_blockbeg blockbeg
-#define b_blockend blockend
-
-Interface bytecodeIR = {
- 1, 1, 0, /* char */
- 2, 2, 0, /* short */
- 4, 4, 0, /* int */
- 4, 4, 0, /* long */
- 4, 4, 0, /* long long */
- 4, 4, 0, /* float */ // JDC: use inline floats
- 4, 4, 0, /* double */ // JDC: don't ever emit 8 byte double code
- 4, 4, 0, /* long double */ // JDC: don't ever emit 8 byte double code
- 4, 4, 0, /* T* */
- 0, 4, 0, /* struct */
- 0, /* little_endian */
- 0, /* mulops_calls */
- 0, /* wants_callb */
- 0, /* wants_argb */
- 1, /* left_to_right */
- 0, /* wants_dag */
- 0, /* unsigned_char */
- I(address),
- I(blockbeg),
- I(blockend),
- I(defaddress),
- I(defconst),
- I(defstring),
- I(defsymbol),
- I(emit),
- I(export),
- I(function),
- I(gen),
- I(global),
- I(import),
- I(local),
- I(progbeg),
- I(progend),
- I(segment),
- I(space),
- 0, /* I(stabblock) */
- 0, /* I(stabend) */
- 0, /* I(stabfend) */
- 0, /* I(stabinit) */
- I(stabline),
- 0, /* I(stabsym) */
- 0, /* I(stabtype) */
-};
+#include "c.h" +#define I(f) b_##f + + +static void I(segment)(int n) { + static int cseg; + + if (cseg != n) + switch (cseg = n) { + case CODE: print("code\n"); return; + case DATA: print("data\n"); return; + case BSS: print("bss\n"); return; + case LIT: print("lit\n"); return; + default: assert(0); + } +} + +static void I(address)(Symbol q, Symbol p, long n) { + q->x.name = stringf("%s%s%D", p->x.name, n > 0 ? "+" : "", n); +} + +static void I(defaddress)(Symbol p) { + print("address %s\n", p->x.name); +} + +static void I(defconst)(int suffix, int size, Value v) { + switch (suffix) { + case I: + if (size > sizeof (int)) + print("byte %d %D\n", size, v.i); + else + print("byte %d %d\n", size, v.i); + return; + case U: + if (size > sizeof (unsigned)) + print("byte %d %U\n", size, v.u); + else + print("byte %d %u\n", size, v.u); + return; + case P: print("byte %d %U\n", size, (unsigned long)v.p); return; + case F: + if (size == 4) { + float f = v.d; + print("byte 4 %u\n", *(unsigned *)&f); + } else { + unsigned *p = (unsigned *)&v.d; + print("byte 4 %u\n", p[swap]); + print("byte 4 %u\n", p[1 - swap]); + } + return; + } + assert(0); +} + +static void I(defstring)(int len, char *str) { + char *s; + + for (s = str; s < str + len; s++) + print("byte 1 %d\n", (*s)&0377); +} + +static void I(defsymbol)(Symbol p) { + if (p->scope == CONSTANTS) + switch (optype(ttob(p->type))) { + case I: p->x.name = stringf("%D", p->u.c.v.i); break; + case U: p->x.name = stringf("%U", p->u.c.v.u); break; + case P: p->x.name = stringf("%U", p->u.c.v.p); break; + case F: + { // JDC: added this to get inline floats + unsigned temp; + + *(float *)&temp = p->u.c.v.d; + p->x.name = stringf("%U", temp ); + } + break;// JDC: added this + default: assert(0); + } + else if (p->scope >= LOCAL && p->sclass == STATIC) + p->x.name = stringf("$%d", genlabel(1)); + else if (p->scope == LABELS || p->generated) + p->x.name = stringf("$%s", p->name); + else + p->x.name = p->name; +} + +static void dumptree(Node p) { + switch (specific(p->op)) { + case ASGN+B: + assert(p->kids[0]); + assert(p->kids[1]); + assert(p->syms[0]); + dumptree(p->kids[0]); + dumptree(p->kids[1]); + print("%s %d\n", opname(p->op), p->syms[0]->u.c.v.u); + return; + case RET+V: + assert(!p->kids[0]); + assert(!p->kids[1]); + print("%s\n", opname(p->op)); + return; + } + switch (generic(p->op)) { + case CNST: case ADDRG: case ADDRF: case ADDRL: case LABEL: + assert(!p->kids[0]); + assert(!p->kids[1]); + assert(p->syms[0] && p->syms[0]->x.name); + print("%s %s\n", opname(p->op), p->syms[0]->x.name); + return; + case CVF: case CVI: case CVP: case CVU: + assert(p->kids[0]); + assert(!p->kids[1]); + assert(p->syms[0]); + dumptree(p->kids[0]); + print("%s %d\n", opname(p->op), p->syms[0]->u.c.v.i); + return; + case ARG: case BCOM: case NEG: case INDIR: case JUMP: case RET: + assert(p->kids[0]); + assert(!p->kids[1]); + dumptree(p->kids[0]); + print("%s\n", opname(p->op)); + return; + case CALL: + assert(p->kids[0]); + assert(!p->kids[1]); + assert(optype(p->op) != B); + dumptree(p->kids[0]); + print("%s\n", opname(p->op)); + if ( !p->count ) { printf("pop\n"); }; // JDC + return; + case ASGN: case BOR: case BAND: case BXOR: case RSH: case LSH: + case ADD: case SUB: case DIV: case MUL: case MOD: + assert(p->kids[0]); + assert(p->kids[1]); + dumptree(p->kids[0]); + dumptree(p->kids[1]); + print("%s\n", opname(p->op)); + return; + case EQ: case NE: case GT: case GE: case LE: case LT: + assert(p->kids[0]); + assert(p->kids[1]); + assert(p->syms[0]); + assert(p->syms[0]->x.name); + dumptree(p->kids[0]); + dumptree(p->kids[1]); + print("%s %s\n", opname(p->op), p->syms[0]->x.name); + return; + } + assert(0); +} + +static void I(emit)(Node p) { + for (; p; p = p->link) + dumptree(p); +} + +static void I(export)(Symbol p) { + print("export %s\n", p->x.name); +} + +static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { + int i; + + (*IR->segment)(CODE); + offset = 0; + for (i = 0; caller[i] && callee[i]; i++) { + offset = roundup(offset, caller[i]->type->align); + caller[i]->x.name = callee[i]->x.name = stringf("%d", offset); + caller[i]->x.offset = callee[i]->x.offset = offset; + offset += caller[i]->type->size; + } + maxargoffset = maxoffset = argoffset = offset = 0; + gencode(caller, callee); + print("proc %s %d %d\n", f->x.name, maxoffset, maxargoffset); + emitcode(); + print("endproc %s %d %d\n", f->x.name, maxoffset, maxargoffset); + +} + +static void gen02(Node p) { + assert(p); + if (generic(p->op) == ARG) { + assert(p->syms[0]); + argoffset += (p->syms[0]->u.c.v.i < 4 ? 4 : p->syms[0]->u.c.v.i); + } else if (generic(p->op) == CALL) { + maxargoffset = (argoffset > maxargoffset ? argoffset : maxargoffset); + argoffset = 0; + } +} + +static void gen01(Node p) { + if (p) { + gen01(p->kids[0]); + gen01(p->kids[1]); + gen02(p); + } +} + +static Node I(gen)(Node p) { + Node q; + + assert(p); + for (q = p; q; q = q->link) + gen01(q); + return p; +} + +static void I(global)(Symbol p) { + print("align %d\n", p->type->align > 4 ? 4 : p->type->align); + print("LABELV %s\n", p->x.name); +} + +static void I(import)(Symbol p) { + print("import %s\n", p->x.name); +} + +static void I(local)(Symbol p) { + offset = roundup(offset, p->type->align); + p->x.name = stringf("%d", offset); + p->x.offset = offset; + offset += p->type->size; +} + +static void I(progbeg)(int argc, char *argv[]) {} + +static void I(progend)(void) {} + +static void I(space)(int n) { + print("skip %d\n", n); +} + +//======================================================== + +// JDC: hacked up to get interleaved source lines in asm code +static char *sourceFile; +static char *sourcePtr; +static int sourceLine; + +static int filelength( FILE *f ) { + int pos; + int end; + + pos = ftell (f); + fseek (f, 0, SEEK_END); + end = ftell (f); + fseek (f, pos, SEEK_SET); + + return end; +} + +static void LoadSourceFile( const char *filename ) { + FILE *f; + int length; + + f = fopen( filename, "r" ); + if ( !f ) { + print( ";couldn't open %s\n", filename ); + sourceFile = NULL; + return; + } + length = filelength( f ); + sourceFile = malloc( length + 1 ); + if ( sourceFile ) { + fread( sourceFile, length, 1, f ); + sourceFile[length] = 0; + } + + fclose( f ); + sourceLine = 1; + sourcePtr = sourceFile; +} + +static void PrintToSourceLine( int line ) { + int c; + + if ( !sourceFile ) { + return; + } + while ( sourceLine <= line ) { + int i; + + for ( i = 0 ; sourcePtr[i] && sourcePtr[i] != '\n' ; i++ ) { + } + c = sourcePtr[i]; + if ( c == '\n' ) { + sourcePtr[i] = 0; + } + print( ";%d:%s\n", sourceLine, sourcePtr ); + if ( c == 0 ) { + sourcePtr += i; // end of file + } else { + sourcePtr += i+1; + } + sourceLine++; + } +} + +static void I(stabline)(Coordinate *cp) { + static char *prevfile; + static int prevline; + + if (cp->file && (prevfile == NULL || strcmp(prevfile, cp->file) != 0)) { + print("file \"%s\"\n", prevfile = cp->file); + prevline = 0; + if ( sourceFile ) { + free( sourceFile ); + sourceFile = NULL; + } + // load the new source file + LoadSourceFile( cp->file ); + } + if (cp->y != prevline) { + print("line %d\n", prevline = cp->y); + PrintToSourceLine( cp->y ); + } +} + +//======================================================== + +#define b_blockbeg blockbeg +#define b_blockend blockend + +Interface bytecodeIR = { + 1, 1, 0, /* char */ + 2, 2, 0, /* short */ + 4, 4, 0, /* int */ + 4, 4, 0, /* long */ + 4, 4, 0, /* long long */ + 4, 4, 0, /* float */ // JDC: use inline floats + 4, 4, 0, /* double */ // JDC: don't ever emit 8 byte double code + 4, 4, 0, /* long double */ // JDC: don't ever emit 8 byte double code + 4, 4, 0, /* T* */ + 0, 4, 0, /* struct */ + 0, /* little_endian */ + 0, /* mulops_calls */ + 0, /* wants_callb */ + 0, /* wants_argb */ + 1, /* left_to_right */ + 0, /* wants_dag */ + 0, /* unsigned_char */ + I(address), + I(blockbeg), + I(blockend), + I(defaddress), + I(defconst), + I(defstring), + I(defsymbol), + I(emit), + I(export), + I(function), + I(gen), + I(global), + I(import), + I(local), + I(progbeg), + I(progend), + I(segment), + I(space), + 0, /* I(stabblock) */ + 0, /* I(stabend) */ + 0, /* I(stabfend) */ + 0, /* I(stabinit) */ + I(stabline), + 0, /* I(stabsym) */ + 0, /* I(stabtype) */ +}; diff --git a/lcc/src/c.h b/lcc/src/c.h index e21419d..a0e45b0 100755 --- a/lcc/src/c.h +++ b/lcc/src/c.h @@ -1,723 +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);
-
+#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); + diff --git a/lcc/src/config.h b/lcc/src/config.h index 20d115c..6f0d5a6 100755 --- a/lcc/src/config.h +++ b/lcc/src/config.h @@ -1,102 +1,102 @@ -typedef struct {
- unsigned char max_unaligned_load;
- Symbol (*rmap)(int);
-
- void (*blkfetch)(int size, int off, int reg, int tmp);
- void (*blkstore)(int size, int off, int reg, int tmp);
- void (*blkloop)(int dreg, int doff,
- int sreg, int soff,
- int size, int tmps[]);
- void (*_label)(Node);
- int (*_rule)(void*, int);
- short **_nts;
- void (*_kids)(Node, int, Node*);
- char **_string;
- char **_templates;
- char *_isinstruction;
- char **_ntname;
- void (*emit2)(Node);
- void (*doarg)(Node);
- void (*target)(Node);
- void (*clobber)(Node);
-} Xinterface;
-extern int askregvar(Symbol, Symbol);
-extern void blkcopy(int, int, int, int, int, int[]);
-extern int getregnum(Node);
-extern int mayrecalc(Node);
-extern int mkactual(int, int);
-extern void mkauto(Symbol);
-extern Symbol mkreg(char *, int, int, int);
-extern Symbol mkwildcard(Symbol *);
-extern int move(Node);
-extern int notarget(Node);
-extern void parseflags(int, char **);
-extern int range(Node, int, int);
-extern unsigned regloc(Symbol); /* omit */
-extern void rtarget(Node, int, Symbol);
-extern void setreg(Node, Symbol);
-extern void spill(unsigned, int, Node);
-extern int widens(Node);
-
-extern int argoffset, maxargoffset;
-extern int bflag, dflag;
-extern int dalign, salign;
-extern int framesize;
-extern unsigned freemask[], usedmask[];
-extern int offset, maxoffset;
-extern int swap;
-extern unsigned tmask[], vmask[];
-typedef struct {
- unsigned listed:1;
- unsigned registered:1;
- unsigned emitted:1;
- unsigned copy:1;
- unsigned equatable:1;
- unsigned spills:1;
- unsigned mayrecalc:1;
- void *state;
- short inst;
- Node kids[3];
- Node prev, next;
- Node prevuse;
- short argno;
-} Xnode;
-typedef struct {
- Symbol vbl;
- short set;
- short number;
- unsigned mask;
-} *Regnode;
-enum { IREG=0, FREG=1 };
-typedef struct {
- char *name;
- unsigned int eaddr; /* omit */
- int offset;
- Node lastuse;
- int usecount;
- Regnode regnode;
- Symbol *wildcard;
-} Xsymbol;
-enum { RX=2 };
-typedef struct {
- int offset;
- unsigned freemask[2];
-} Env;
-
-#define LBURG_MAX SHRT_MAX
-
-enum { VREG=(44<<4) };
-
-/* Exported for the front end */
-extern void blockbeg(Env *);
-extern void blockend(Env *);
-extern void emit(Node);
-extern Node gen(Node);
-
-extern unsigned emitbin(Node, int);
-
-#ifdef NDEBUG
-#define debug(x) (void)0
-#else
-#define debug(x) (void)(dflag&&((x),0))
-#endif
+typedef struct { + unsigned char max_unaligned_load; + Symbol (*rmap)(int); + + void (*blkfetch)(int size, int off, int reg, int tmp); + void (*blkstore)(int size, int off, int reg, int tmp); + void (*blkloop)(int dreg, int doff, + int sreg, int soff, + int size, int tmps[]); + void (*_label)(Node); + int (*_rule)(void*, int); + short **_nts; + void (*_kids)(Node, int, Node*); + char **_string; + char **_templates; + char *_isinstruction; + char **_ntname; + void (*emit2)(Node); + void (*doarg)(Node); + void (*target)(Node); + void (*clobber)(Node); +} Xinterface; +extern int askregvar(Symbol, Symbol); +extern void blkcopy(int, int, int, int, int, int[]); +extern int getregnum(Node); +extern int mayrecalc(Node); +extern int mkactual(int, int); +extern void mkauto(Symbol); +extern Symbol mkreg(char *, int, int, int); +extern Symbol mkwildcard(Symbol *); +extern int move(Node); +extern int notarget(Node); +extern void parseflags(int, char **); +extern int range(Node, int, int); +extern unsigned regloc(Symbol); /* omit */ +extern void rtarget(Node, int, Symbol); +extern void setreg(Node, Symbol); +extern void spill(unsigned, int, Node); +extern int widens(Node); + +extern int argoffset, maxargoffset; +extern int bflag, dflag; +extern int dalign, salign; +extern int framesize; +extern unsigned freemask[], usedmask[]; +extern int offset, maxoffset; +extern int swap; +extern unsigned tmask[], vmask[]; +typedef struct { + unsigned listed:1; + unsigned registered:1; + unsigned emitted:1; + unsigned copy:1; + unsigned equatable:1; + unsigned spills:1; + unsigned mayrecalc:1; + void *state; + short inst; + Node kids[3]; + Node prev, next; + Node prevuse; + short argno; +} Xnode; +typedef struct { + Symbol vbl; + short set; + short number; + unsigned mask; +} *Regnode; +enum { IREG=0, FREG=1 }; +typedef struct { + char *name; + unsigned int eaddr; /* omit */ + int offset; + Node lastuse; + int usecount; + Regnode regnode; + Symbol *wildcard; +} Xsymbol; +enum { RX=2 }; +typedef struct { + int offset; + unsigned freemask[2]; +} Env; + +#define LBURG_MAX SHRT_MAX + +enum { VREG=(44<<4) }; + +/* Exported for the front end */ +extern void blockbeg(Env *); +extern void blockend(Env *); +extern void emit(Node); +extern Node gen(Node); + +extern unsigned emitbin(Node, int); + +#ifdef NDEBUG +#define debug(x) (void)0 +#else +#define debug(x) (void)(dflag&&((x),0)) +#endif diff --git a/lcc/src/dag.c b/lcc/src/dag.c index 6e931ae..8e0ddea 100755 --- a/lcc/src/dag.c +++ b/lcc/src/dag.c @@ -1,735 +1,735 @@ -#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);
-}
-
+#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); +} + diff --git a/lcc/src/dagcheck.md b/lcc/src/dagcheck.md index 5deec0d..292dbee 100755 --- a/lcc/src/dagcheck.md +++ b/lcc/src/dagcheck.md @@ -1,210 +1,210 @@ -%{
-#include "c.h"
-typedef Node NODEPTR_TYPE;
-#define OP_LABEL(p) (specific((p)->op))
-#define LEFT_CHILD(p) ((p)->kids[0])
-#define RIGHT_CHILD(p) ((p)->kids[1])
-#define STATE_LABEL(p) ((p)->x.state)
-#define PANIC error
-%}
-%term CNSTF=17 CNSTI=21 CNSTP=23 CNSTU=22
-%term ARGB=41 ARGF=33 ARGI=37 ARGP=39 ARGU=38
-%term ASGNB=57 ASGNF=49 ASGNI=53 ASGNP=55 ASGNU=54
-%term INDIRB=73 INDIRF=65 INDIRI=69 INDIRP=71 INDIRU=70
-%term CVFF=113 CVFI=117
-%term CVIF=129 CVII=133 CVIU=134
-%term CVPP=151 CVPU=150
-%term CVUI=181 CVUP=183 CVUU=182
-%term NEGF=193 NEGI=197
-%term CALLB=217 CALLF=209 CALLI=213 CALLP=215 CALLU=214 CALLV=216
-%term RETF=241 RETI=245 RETP=247 RETU=246 RETV=248
-%term ADDRGP=263
-%term ADDRFP=279
-%term ADDRLP=295
-%term ADDF=305 ADDI=309 ADDP=311 ADDU=310
-%term SUBF=321 SUBI=325 SUBP=327 SUBU=326
-%term LSHI=341 LSHU=342
-%term MODI=357 MODU=358
-%term RSHI=373 RSHU=374
-%term BANDI=389 BANDU=390
-%term BCOMI=405 BCOMU=406
-%term BORI=421 BORU=422
-%term BXORI=437 BXORU=438
-%term DIVF=449 DIVI=453 DIVU=454
-%term MULF=465 MULI=469 MULU=470
-%term EQF=481 EQI=485 EQU=486
-%term GEF=497 GEI=501 GEU=502
-%term GTF=513 GTI=517 GTU=518
-%term LEF=529 LEI=533 LEU=534
-%term LTF=545 LTI=549 LTU=550
-%term NEF=561 NEI=565 NEU=566
-%term JUMPV=584
-%term LABELV=600
-%%
-stmt: INDIRB(P) ""
-stmt: INDIRF(P) ""
-stmt: INDIRI(P) ""
-stmt: INDIRU(P) ""
-stmt: INDIRP(P) ""
-stmt: CALLF(P) ""
-stmt: CALLI(P) ""
-stmt: CALLU(P) ""
-stmt: CALLP(P) ""
-stmt: V ""
-bogus: I "" 1
-bogus: U "" 1
-bogus: P "" 1
-bogus: F "" 1
-bogus: B "" 1
-bogus: V "" 1
-I: bogus "" 1
-U: bogus "" 1
-P: bogus "" 1
-F: bogus "" 1
-B: bogus "" 1
-V: bogus "" 1
-F: CNSTF ""
-I: CNSTI ""
-P: CNSTP ""
-U: CNSTU ""
-V: ARGB(B) ""
-V: ARGF(F) ""
-V: ARGI(I) ""
-V: ARGU(U) ""
-V: ARGP(P) ""
-V: ASGNB(P,B) ""
-V: ASGNF(P,F) ""
-V: ASGNI(P,I) ""
-V: ASGNU(P,U) ""
-V: ASGNP(P,P) ""
-B: INDIRB(P) ""
-F: INDIRF(P) ""
-I: INDIRI(P) ""
-U: INDIRU(P) ""
-P: INDIRP(P) ""
-I: CVII(I) ""
-I: CVUI(U) ""
-I: CVFI(F) ""
-U: CVIU(I) ""
-U: CVUU(U) ""
-U: CVPU(P) ""
-F: CVIF(I) ""
-F: CVFF(F) ""
-P: CVUP(U) ""
-P: CVPP(P) ""
-F: NEGF(F) ""
-I: NEGI(I) ""
-V: CALLB(P,P) ""
-F: CALLF(P) ""
-I: CALLI(P) ""
-U: CALLU(P) ""
-P: CALLP(P) ""
-V: CALLV(P) ""
-V: RETF(F) ""
-V: RETI(I) ""
-V: RETU(U) ""
-V: RETP(P) ""
-V: RETV ""
-P: ADDRGP ""
-P: ADDRFP ""
-P: ADDRLP ""
-F: ADDF(F,F) ""
-I: ADDI(I,I) ""
-P: ADDP(P,I) ""
-P: ADDP(I,P) ""
-P: ADDP(U,P) ""
-P: ADDP(P,U) ""
-U: ADDU(U,U) ""
-F: SUBF(F,F) ""
-I: SUBI(I,I) ""
-P: SUBP(P,I) ""
-P: SUBP(P,U) ""
-U: SUBU(U,U) ""
-I: LSHI(I,I) ""
-U: LSHU(U,I) ""
-I: MODI(I,I) ""
-U: MODU(U,U) ""
-I: RSHI(I,I) ""
-U: RSHU(U,I) ""
-U: BANDU(U,U) ""
-I: BANDI(I,I) ""
-U: BCOMU(U) ""
-I: BCOMI(I) ""
-I: BORI(I,I) ""
-U: BORU(U,U) ""
-U: BXORU(U,U) ""
-I: BXORI(I,I) ""
-F: DIVF(F,F) ""
-I: DIVI(I,I) ""
-U: DIVU(U,U) ""
-F: MULF(F,F) ""
-I: MULI(I,I) ""
-U: MULU(U,U) ""
-V: EQF(F,F) ""
-V: EQI(I,I) ""
-V: EQU(U,U) ""
-V: GEF(F,F) ""
-V: GEI(I,I) ""
-V: GEU(U,U) ""
-V: GTF(F,F) ""
-V: GTI(I,I) ""
-V: GTU(U,U) ""
-V: LEF(F,F) ""
-V: LEI(I,I) ""
-V: LEU(U,U) ""
-V: LTF(F,F) ""
-V: LTI(I,I) ""
-V: LTU(U,U) ""
-V: NEF(F,F) ""
-V: NEI(I,I) ""
-V: NEU(U,U) ""
-V: JUMPV(P) ""
-V: LABELV ""
-%%
-
-static void reduce(NODEPTR_TYPE p, int goalnt) {
- int i, sz = opsize(p->op), rulenumber = _rule(p->x.state, goalnt);
- short *nts = _nts[rulenumber];
- NODEPTR_TYPE kids[10];
-
- assert(rulenumber);
- _kids(p, rulenumber, kids);
- for (i = 0; nts[i]; i++)
- reduce(kids[i], nts[i]);
- switch (optype(p->op)) {
-#define xx(ty) if (sz == ty->size) return
- case I:
- case U:
- xx(chartype);
- xx(shorttype);
- xx(inttype);
- xx(longtype);
- xx(longlong);
- break;
- case F:
- xx(floattype);
- xx(doubletype);
- xx(longdouble);
- break;
- case P:
- xx(voidptype);
- xx(funcptype);
- break;
- case V:
- case B: if (sz == 0) return;
-#undef xx
- }
- printdag(p, 2);
- assert(0);
-}
-
-void check(Node p) {
- struct _state { short cost[1]; };
-
- _label(p);
- if (((struct _state *)p->x.state)->cost[1] > 0) {
- printdag(p, 2);
- assert(0);
- }
- reduce(p, 1);
-}
+%{ +#include "c.h" +typedef Node NODEPTR_TYPE; +#define OP_LABEL(p) (specific((p)->op)) +#define LEFT_CHILD(p) ((p)->kids[0]) +#define RIGHT_CHILD(p) ((p)->kids[1]) +#define STATE_LABEL(p) ((p)->x.state) +#define PANIC error +%} +%term CNSTF=17 CNSTI=21 CNSTP=23 CNSTU=22 +%term ARGB=41 ARGF=33 ARGI=37 ARGP=39 ARGU=38 +%term ASGNB=57 ASGNF=49 ASGNI=53 ASGNP=55 ASGNU=54 +%term INDIRB=73 INDIRF=65 INDIRI=69 INDIRP=71 INDIRU=70 +%term CVFF=113 CVFI=117 +%term CVIF=129 CVII=133 CVIU=134 +%term CVPP=151 CVPU=150 +%term CVUI=181 CVUP=183 CVUU=182 +%term NEGF=193 NEGI=197 +%term CALLB=217 CALLF=209 CALLI=213 CALLP=215 CALLU=214 CALLV=216 +%term RETF=241 RETI=245 RETP=247 RETU=246 RETV=248 +%term ADDRGP=263 +%term ADDRFP=279 +%term ADDRLP=295 +%term ADDF=305 ADDI=309 ADDP=311 ADDU=310 +%term SUBF=321 SUBI=325 SUBP=327 SUBU=326 +%term LSHI=341 LSHU=342 +%term MODI=357 MODU=358 +%term RSHI=373 RSHU=374 +%term BANDI=389 BANDU=390 +%term BCOMI=405 BCOMU=406 +%term BORI=421 BORU=422 +%term BXORI=437 BXORU=438 +%term DIVF=449 DIVI=453 DIVU=454 +%term MULF=465 MULI=469 MULU=470 +%term EQF=481 EQI=485 EQU=486 +%term GEF=497 GEI=501 GEU=502 +%term GTF=513 GTI=517 GTU=518 +%term LEF=529 LEI=533 LEU=534 +%term LTF=545 LTI=549 LTU=550 +%term NEF=561 NEI=565 NEU=566 +%term JUMPV=584 +%term LABELV=600 +%% +stmt: INDIRB(P) "" +stmt: INDIRF(P) "" +stmt: INDIRI(P) "" +stmt: INDIRU(P) "" +stmt: INDIRP(P) "" +stmt: CALLF(P) "" +stmt: CALLI(P) "" +stmt: CALLU(P) "" +stmt: CALLP(P) "" +stmt: V "" +bogus: I "" 1 +bogus: U "" 1 +bogus: P "" 1 +bogus: F "" 1 +bogus: B "" 1 +bogus: V "" 1 +I: bogus "" 1 +U: bogus "" 1 +P: bogus "" 1 +F: bogus "" 1 +B: bogus "" 1 +V: bogus "" 1 +F: CNSTF "" +I: CNSTI "" +P: CNSTP "" +U: CNSTU "" +V: ARGB(B) "" +V: ARGF(F) "" +V: ARGI(I) "" +V: ARGU(U) "" +V: ARGP(P) "" +V: ASGNB(P,B) "" +V: ASGNF(P,F) "" +V: ASGNI(P,I) "" +V: ASGNU(P,U) "" +V: ASGNP(P,P) "" +B: INDIRB(P) "" +F: INDIRF(P) "" +I: INDIRI(P) "" +U: INDIRU(P) "" +P: INDIRP(P) "" +I: CVII(I) "" +I: CVUI(U) "" +I: CVFI(F) "" +U: CVIU(I) "" +U: CVUU(U) "" +U: CVPU(P) "" +F: CVIF(I) "" +F: CVFF(F) "" +P: CVUP(U) "" +P: CVPP(P) "" +F: NEGF(F) "" +I: NEGI(I) "" +V: CALLB(P,P) "" +F: CALLF(P) "" +I: CALLI(P) "" +U: CALLU(P) "" +P: CALLP(P) "" +V: CALLV(P) "" +V: RETF(F) "" +V: RETI(I) "" +V: RETU(U) "" +V: RETP(P) "" +V: RETV "" +P: ADDRGP "" +P: ADDRFP "" +P: ADDRLP "" +F: ADDF(F,F) "" +I: ADDI(I,I) "" +P: ADDP(P,I) "" +P: ADDP(I,P) "" +P: ADDP(U,P) "" +P: ADDP(P,U) "" +U: ADDU(U,U) "" +F: SUBF(F,F) "" +I: SUBI(I,I) "" +P: SUBP(P,I) "" +P: SUBP(P,U) "" +U: SUBU(U,U) "" +I: LSHI(I,I) "" +U: LSHU(U,I) "" +I: MODI(I,I) "" +U: MODU(U,U) "" +I: RSHI(I,I) "" +U: RSHU(U,I) "" +U: BANDU(U,U) "" +I: BANDI(I,I) "" +U: BCOMU(U) "" +I: BCOMI(I) "" +I: BORI(I,I) "" +U: BORU(U,U) "" +U: BXORU(U,U) "" +I: BXORI(I,I) "" +F: DIVF(F,F) "" +I: DIVI(I,I) "" +U: DIVU(U,U) "" +F: MULF(F,F) "" +I: MULI(I,I) "" +U: MULU(U,U) "" +V: EQF(F,F) "" +V: EQI(I,I) "" +V: EQU(U,U) "" +V: GEF(F,F) "" +V: GEI(I,I) "" +V: GEU(U,U) "" +V: GTF(F,F) "" +V: GTI(I,I) "" +V: GTU(U,U) "" +V: LEF(F,F) "" +V: LEI(I,I) "" +V: LEU(U,U) "" +V: LTF(F,F) "" +V: LTI(I,I) "" +V: LTU(U,U) "" +V: NEF(F,F) "" +V: NEI(I,I) "" +V: NEU(U,U) "" +V: JUMPV(P) "" +V: LABELV "" +%% + +static void reduce(NODEPTR_TYPE p, int goalnt) { + int i, sz = opsize(p->op), rulenumber = _rule(p->x.state, goalnt); + short *nts = _nts[rulenumber]; + NODEPTR_TYPE kids[10]; + + assert(rulenumber); + _kids(p, rulenumber, kids); + for (i = 0; nts[i]; i++) + reduce(kids[i], nts[i]); + switch (optype(p->op)) { +#define xx(ty) if (sz == ty->size) return + case I: + case U: + xx(chartype); + xx(shorttype); + xx(inttype); + xx(longtype); + xx(longlong); + break; + case F: + xx(floattype); + xx(doubletype); + xx(longdouble); + break; + case P: + xx(voidptype); + xx(funcptype); + break; + case V: + case B: if (sz == 0) return; +#undef xx + } + printdag(p, 2); + assert(0); +} + +void check(Node p) { + struct _state { short cost[1]; }; + + _label(p); + if (((struct _state *)p->x.state)->cost[1] > 0) { + printdag(p, 2); + assert(0); + } + reduce(p, 1); +} diff --git a/lcc/src/decl.c b/lcc/src/decl.c index 59e0850..fc1d6bc 100755 --- a/lcc/src/decl.c +++ b/lcc/src/decl.c @@ -1,1160 +1,1160 @@ -#include "c.h"
-
-
-#define add(x,n) (x > inttype->u.sym->u.limits.max.i-(n) ? (overflow=1,x) : x+(n))
-#define chkoverflow(x,n) ((void)add(x,n))
-#define bits2bytes(n) (((n) + 7)/8)
-static int regcount;
-
-static List autos, registers;
-Symbol cfunc; /* current function */
-Symbol retv; /* return value location for structs */
-
-static void checkref(Symbol, void *);
-static Symbol dclglobal(int, char *, Type, Coordinate *);
-static Symbol dcllocal(int, char *, Type, Coordinate *);
-static Symbol dclparam(int, char *, Type, Coordinate *);
-static Type dclr(Type, char **, Symbol **, int);
-static Type dclr1(char **, Symbol **, int);
-static void decl(Symbol (*)(int, char *, Type, Coordinate *));
-extern void doconst(Symbol, void *);
-static void doglobal(Symbol, void *);
-static void doextern(Symbol, void *);
-static void exitparams(Symbol []);
-static void fields(Type);
-static void funcdefn(int, char *, Type, Symbol [], Coordinate);
-static void initglobal(Symbol, int);
-static void oldparam(Symbol, void *);
-static Symbol *parameters(Type);
-static Type specifier(int *);
-static Type structdcl(int);
-static Type tnode(int, Type);
-void program(void) {
- int n;
-
- level = GLOBAL;
- for (n = 0; t != EOI; n++)
- if (kind[t] == CHAR || kind[t] == STATIC
- || t == ID || t == '*' || t == '(') {
- decl(dclglobal);
- deallocate(STMT);
- if (!(glevel >= 3 || xref))
- deallocate(FUNC);
- } else if (t == ';') {
- warning("empty declaration\n");
- t = gettok();
- } else {
- error("unrecognized declaration\n");
- t = gettok();
- }
- if (n == 0)
- warning("empty input file\n");
-}
-static Type specifier(int *sclass) {
- int cls, cons, sign, size, type, vol;
- Type ty = NULL;
-
- cls = vol = cons = sign = size = type = 0;
- if (sclass == NULL)
- cls = AUTO;
- for (;;) {
- int *p, tt = t;
- switch (t) {
- case AUTO:
- case REGISTER: if (level <= GLOBAL && cls == 0)
- error("invalid use of `%k'\n", t);
- p = &cls; t = gettok(); break;
- case STATIC: case EXTERN:
- case TYPEDEF: p = &cls; t = gettok(); break;
- case CONST: p = &cons; t = gettok(); break;
- case VOLATILE: p = &vol; t = gettok(); break;
- case SIGNED:
- case UNSIGNED: p = &sign; t = gettok(); break;
- case LONG: if (size == LONG) {
- size = 0;
- tt = LONG+LONG;
- }
- p = &size; t = gettok(); break;
- case SHORT: p = &size; t = gettok(); break;
- case VOID: case CHAR: case INT: case FLOAT:
- case DOUBLE: p = &type; ty = tsym->type;
- t = gettok(); break;
- case ENUM: p = &type; ty = enumdcl(); break;
- case STRUCT:
- case UNION: p = &type; ty = structdcl(t); break;
- case ID:
- if (istypename(t, tsym) && type == 0
- && sign == 0 && size == 0) {
- use(tsym, src);
- ty = tsym->type;
- if (isqual(ty)
- && ty->size != ty->type->size) {
- ty = unqual(ty);
- if (isconst(tsym->type))
- ty = qual(CONST, ty);
- if (isvolatile(tsym->type))
- ty = qual(VOLATILE, ty);
- tsym->type = ty;
- }
- p = &type;
- t = gettok();
- } else
- p = NULL;
- break;
- default: p = NULL;
- }
- if (p == NULL)
- break;
- if (*p)
- error("invalid use of `%k'\n", tt);
- *p = tt;
- }
- if (sclass)
- *sclass = cls;
- if (type == 0) {
- type = INT;
- ty = inttype;
- }
- if (size == SHORT && type != INT
- || size == LONG+LONG && type != INT
- || size == LONG && type != INT && type != DOUBLE
- || sign && type != INT && type != CHAR)
- error("invalid type specification\n");
- if (type == CHAR && sign)
- ty = sign == UNSIGNED ? unsignedchar : signedchar;
- else if (size == SHORT)
- ty = sign == UNSIGNED ? unsignedshort : shorttype;
- else if (size == LONG && type == DOUBLE)
- ty = longdouble;
- else if (size == LONG+LONG) {
- ty = sign == UNSIGNED ? unsignedlonglong : longlong;
- if (Aflag >= 1)
- warning("`%t' is a non-ANSI type\n", ty);
- } else if (size == LONG)
- ty = sign == UNSIGNED ? unsignedlong : longtype;
- else if (sign == UNSIGNED && type == INT)
- ty = unsignedtype;
- if (cons == CONST)
- ty = qual(CONST, ty);
- if (vol == VOLATILE)
- ty = qual(VOLATILE, ty);
- return ty;
-}
-static void decl(Symbol (*dcl)(int, char *, Type, Coordinate *)) {
- int sclass;
- Type ty, ty1;
- static char stop[] = { CHAR, STATIC, ID, 0 };
-
- ty = specifier(&sclass);
- if (t == ID || t == '*' || t == '(' || t == '[') {
- char *id;
- Coordinate pos;
- id = NULL;
- pos = src;
- if (level == GLOBAL) {
- Symbol *params = NULL;
- ty1 = dclr(ty, &id, ¶ms, 0);
- if (params && id && isfunc(ty1)
- && (t == '{' || istypename(t, tsym)
- || (kind[t] == STATIC && t != TYPEDEF))) {
- if (sclass == TYPEDEF) {
- error("invalid use of `typedef'\n");
- sclass = EXTERN;
- }
- if (ty1->u.f.oldstyle)
- exitscope();
- funcdefn(sclass, id, ty1, params, pos);
- return;
- } else if (params)
- exitparams(params);
- } else
- ty1 = dclr(ty, &id, NULL, 0);
- for (;;) {
- if (Aflag >= 1 && !hasproto(ty1))
- warning("missing prototype\n");
- if (id == NULL)
- error("missing identifier\n");
- else if (sclass == TYPEDEF)
- {
- Symbol p = lookup(id, identifiers);
- if (p && p->scope == level)
- error("redeclaration of `%s'\n", id);
- p = install(id, &identifiers, level,
- level < LOCAL ? PERM : FUNC);
- p->type = ty1;
- p->sclass = TYPEDEF;
- p->src = pos;
- }
- else
- (void)(*dcl)(sclass, id, ty1, &pos);
- if (t != ',')
- break;
- t = gettok();
- id = NULL;
- pos = src;
- ty1 = dclr(ty, &id, NULL, 0);
- }
- } else if (ty == NULL
- || !(isenum(ty) ||
- isstruct(ty) && (*unqual(ty)->u.sym->name < '1' || *unqual(ty)->u.sym->name > '9')))
- error("empty declaration\n");
- test(';', stop);
-}
-static Symbol dclglobal(int sclass, char *id, Type ty, Coordinate *pos) {
- Symbol p;
-
- if (sclass == 0)
- sclass = AUTO;
- else if (sclass != EXTERN && sclass != STATIC) {
- error("invalid storage class `%k' for `%t %s'\n",
- sclass, ty, id);
- sclass = AUTO;
- }
- p = lookup(id, identifiers);
- if (p && p->scope == GLOBAL) {
- if (p->sclass != TYPEDEF && eqtype(ty, p->type, 1))
- ty = compose(ty, p->type);
- else
- error("redeclaration of `%s' previously declared at %w\n", p->name, &p->src);
-
- if (!isfunc(ty) && p->defined && t == '=')
- error("redefinition of `%s' previously defined at %w\n", p->name, &p->src);
-
- if (p->sclass == EXTERN && sclass == STATIC
- || p->sclass == STATIC && sclass == AUTO
- || p->sclass == AUTO && sclass == STATIC)
- warning("inconsistent linkage for `%s' previously declared at %w\n", p->name, &p->src);
-
- }
- if (p == NULL || p->scope != GLOBAL) {
- Symbol q = lookup(id, externals);
- if (q) {
- if (sclass == STATIC || !eqtype(ty, q->type, 1))
- warning("declaration of `%s' does not match previous declaration at %w\n", id, &q->src);
-
- p = relocate(id, externals, globals);
- p->sclass = sclass;
- } else {
- p = install(id, &globals, GLOBAL, PERM);
- p->sclass = sclass;
- (*IR->defsymbol)(p);
- }
- if (p->sclass != STATIC) {
- static int nglobals;
- nglobals++;
- if (Aflag >= 2 && nglobals == 512)
- warning("more than 511 external identifiers\n");
- }
- } else if (p->sclass == EXTERN)
- p->sclass = sclass;
- p->type = ty;
- p->src = *pos;
- if (t == '=' && isfunc(p->type)) {
- error("illegal initialization for `%s'\n", p->name);
- t = gettok();
- initializer(p->type, 0);
- } else if (t == '=') {
- initglobal(p, 0);
- if (glevel > 0 && IR->stabsym) {
- (*IR->stabsym)(p); swtoseg(p->u.seg); }
- } else if (p->sclass == STATIC && !isfunc(p->type)
- && p->type->size == 0)
- error("undefined size for `%t %s'\n", p->type, p->name);
- return p;
-}
-static void initglobal(Symbol p, int flag) {
- Type ty;
-
- if (t == '=' || flag) {
- if (p->sclass == STATIC) {
- for (ty = p->type; isarray(ty); ty = ty->type)
- ;
- defglobal(p, isconst(ty) ? LIT : DATA);
- } else
- defglobal(p, DATA);
- if (t == '=')
- t = gettok();
- ty = initializer(p->type, 0);
- if (isarray(p->type) && p->type->size == 0)
- p->type = ty;
- if (p->sclass == EXTERN)
- p->sclass = AUTO;
- }
-}
-void defglobal(Symbol p, int seg) {
- p->u.seg = seg;
- swtoseg(p->u.seg);
- if (p->sclass != STATIC)
- (*IR->export)(p);
- (*IR->global)(p);
- p->defined = 1;
-}
-
-static Type dclr(Type basety, char **id, Symbol **params, int abstract) {
- Type ty = dclr1(id, params, abstract);
-
- for ( ; ty; ty = ty->type)
- switch (ty->op) {
- case POINTER:
- basety = ptr(basety);
- break;
- case FUNCTION:
- basety = func(basety, ty->u.f.proto,
- ty->u.f.oldstyle);
- break;
- case ARRAY:
- basety = array(basety, ty->size, 0);
- break;
- case CONST: case VOLATILE:
- basety = qual(ty->op, basety);
- break;
- default: assert(0);
- }
- if (Aflag >= 2 && basety->size > 32767)
- warning("more than 32767 bytes in `%t'\n", basety);
- return basety;
-}
-static Type tnode(int op, Type type) {
- Type ty;
-
- NEW0(ty, STMT);
- ty->op = op;
- ty->type = type;
- return ty;
-}
-static Type dclr1(char **id, Symbol **params, int abstract) {
- Type ty = NULL;
-
- switch (t) {
- case ID: if (id)
- *id = token;
- else
- error("extraneous identifier `%s'\n", token);
- t = gettok(); break;
- case '*': t = gettok(); if (t == CONST || t == VOLATILE) {
- Type ty1;
- ty1 = ty = tnode(t, NULL);
- while ((t = gettok()) == CONST || t == VOLATILE)
- ty1 = tnode(t, ty1);
- ty->type = dclr1(id, params, abstract);
- ty = ty1;
- } else
- ty = dclr1(id, params, abstract);
- ty = tnode(POINTER, ty); break;
- case '(': t = gettok(); if (abstract
- && (t == REGISTER || istypename(t, tsym) || t == ')')) {
- Symbol *args;
- ty = tnode(FUNCTION, ty);
- enterscope();
- if (level > PARAM)
- enterscope();
- args = parameters(ty);
- exitparams(args);
- } else {
- ty = dclr1(id, params, abstract);
- expect(')');
- if (abstract && ty == NULL
- && (id == NULL || *id == NULL))
- return tnode(FUNCTION, NULL);
- } break;
- case '[': break;
- default: return ty;
- }
- while (t == '(' || t == '[')
- switch (t) {
- case '(': t = gettok(); { Symbol *args;
- ty = tnode(FUNCTION, ty);
- enterscope();
- if (level > PARAM)
- enterscope();
- args = parameters(ty);
- if (params && *params == NULL)
- *params = args;
- else
- exitparams(args);
- }
- break;
- case '[': t = gettok(); { int n = 0;
- if (kind[t] == ID) {
- n = intexpr(']', 1);
- if (n <= 0) {
- error("`%d' is an illegal array size\n", n);
- n = 1;
- }
- } else
- expect(']');
- ty = tnode(ARRAY, ty);
- ty->size = n; } break;
- default: assert(0);
- }
- return ty;
-}
-static Symbol *parameters(Type fty) {
- List list = NULL;
- Symbol *params;
-
- if (kind[t] == STATIC || istypename(t, tsym)) {
- int n = 0;
- Type ty1 = NULL;
- for (;;) {
- Type ty;
- int sclass = 0;
- char *id = NULL;
- if (ty1 && t == ELLIPSIS) {
- static struct symbol sentinel;
- if (sentinel.type == NULL) {
- sentinel.type = voidtype;
- sentinel.defined = 1;
- }
- if (ty1 == voidtype)
- error("illegal formal parameter types\n");
- list = append(&sentinel, list);
- t = gettok();
- break;
- }
- if (!istypename(t, tsym) && t != REGISTER)
- error("missing parameter type\n");
- n++;
- ty = dclr(specifier(&sclass), &id, NULL, 1);
- if ( ty == voidtype && (ty1 || id)
- || ty1 == voidtype)
- error("illegal formal parameter types\n");
- if (id == NULL)
- id = stringd(n);
- if (ty != voidtype)
- list = append(dclparam(sclass, id, ty, &src), list);
- if (Aflag >= 1 && !hasproto(ty))
- warning("missing prototype\n");
- if (ty1 == NULL)
- ty1 = ty;
- if (t != ',')
- break;
- t = gettok();
- }
- fty->u.f.proto = newarray(length(list) + 1,
- sizeof (Type *), PERM);
- params = ltov(&list, FUNC);
- for (n = 0; params[n]; n++)
- fty->u.f.proto[n] = params[n]->type;
- fty->u.f.proto[n] = NULL;
- fty->u.f.oldstyle = 0;
- } else {
- if (t == ID)
- for (;;) {
- Symbol p;
- if (t != ID) {
- error("expecting an identifier\n");
- break;
- }
- p = dclparam(0, token, inttype, &src);
- p->defined = 0;
- list = append(p, list);
- t = gettok();
- if (t != ',')
- break;
- t = gettok();
- }
- params = ltov(&list, FUNC);
- fty->u.f.proto = NULL;
- fty->u.f.oldstyle = 1;
- }
- if (t != ')') {
- static char stop[] = { CHAR, STATIC, IF, ')', 0 };
- expect(')');
- skipto('{', stop);
- }
- if (t == ')')
- t = gettok();
- return params;
-}
-static void exitparams(Symbol params[]) {
- assert(params);
- if (params[0] && !params[0]->defined)
- error("extraneous old-style parameter list\n");
- if (level > PARAM)
- exitscope();
- exitscope();
-}
-
-static Symbol dclparam(int sclass, char *id, Type ty, Coordinate *pos) {
- Symbol p;
-
- if (isfunc(ty))
- ty = ptr(ty);
- else if (isarray(ty))
- ty = atop(ty);
- if (sclass == 0)
- sclass = AUTO;
- else if (sclass != REGISTER) {
- error("invalid storage class `%k' for `%t%s\n",
- sclass, ty, stringf(id ? " %s'" : "' parameter", id));
- sclass = AUTO;
- } else if (isvolatile(ty) || isstruct(ty)) {
- warning("register declaration ignored for `%t%s\n",
- ty, stringf(id ? " %s'" : "' parameter", id));
- sclass = AUTO;
- }
-
- p = lookup(id, identifiers);
- if (p && p->scope == level)
- error("duplicate declaration for `%s' previously declared at %w\n", id, &p->src);
-
- else
- p = install(id, &identifiers, level, FUNC);
- p->sclass = sclass;
- p->src = *pos;
- p->type = ty;
- p->defined = 1;
- if (t == '=') {
- error("illegal initialization for parameter `%s'\n", id);
- t = gettok();
- (void)expr1(0);
- }
- return p;
-}
-static Type structdcl(int op) {
- char *tag;
- Type ty;
- Symbol p;
- Coordinate pos;
-
- t = gettok();
- pos = src;
- if (t == ID) {
- tag = token;
- t = gettok();
- } else
- tag = "";
- if (t == '{') {
- static char stop[] = { IF, ',', 0 };
- ty = newstruct(op, tag);
- ty->u.sym->src = pos;
- ty->u.sym->defined = 1;
- t = gettok();
- if (istypename(t, tsym))
- fields(ty);
- else
- error("invalid %k field declarations\n", op);
- test('}', stop);
- }
- else if (*tag && (p = lookup(tag, types)) != NULL
- && p->type->op == op) {
- ty = p->type;
- if (t == ';' && p->scope < level)
- ty = newstruct(op, tag);
- }
- else {
- if (*tag == 0)
- error("missing %k tag\n", op);
- ty = newstruct(op, tag);
- }
- if (*tag && xref)
- use(ty->u.sym, pos);
- return ty;
-}
-static void fields(Type ty) {
- { int n = 0;
- while (istypename(t, tsym)) {
- static char stop[] = { IF, CHAR, '}', 0 };
- Type ty1 = specifier(NULL);
- for (;;) {
- Field p;
- char *id = NULL;
- Type fty = dclr(ty1, &id, NULL, 0);
- p = newfield(id, ty, fty);
- if (Aflag >= 1 && !hasproto(p->type))
- warning("missing prototype\n");
- if (t == ':') {
- if (unqual(p->type) != inttype
- && unqual(p->type) != unsignedtype) {
- error("`%t' is an illegal bit-field type\n",
- p->type);
- p->type = inttype;
- }
- t = gettok();
- p->bitsize = intexpr(0, 0);
- if (p->bitsize > 8*inttype->size || p->bitsize < 0) {
- error("`%d' is an illegal bit-field size\n",
- p->bitsize);
- p->bitsize = 8*inttype->size;
- } else if (p->bitsize == 0 && id) {
- warning("extraneous 0-width bit field `%t %s' ignored\n", p->type, id);
-
- p->name = stringd(genlabel(1));
- }
- p->lsb = 1;
- }
- else {
- if (id == NULL)
- error("field name missing\n");
- else if (isfunc(p->type))
- error("`%t' is an illegal field type\n", p->type);
- else if (p->type->size == 0)
- error("undefined size for field `%t %s'\n",
- p->type, id);
- }
- if (isconst(p->type))
- ty->u.sym->u.s.cfields = 1;
- if (isvolatile(p->type))
- ty->u.sym->u.s.vfields = 1;
- n++;
- if (Aflag >= 2 && n == 128)
- warning("more than 127 fields in `%t'\n", ty);
- if (t != ',')
- break;
- t = gettok();
- }
- test(';', stop);
- } }
- { int bits = 0, off = 0, overflow = 0;
- Field p, *q = &ty->u.sym->u.s.flist;
- ty->align = IR->structmetric.align;
- for (p = *q; p; p = p->link) {
- int a = p->type->align ? p->type->align : 1;
- if (p->lsb)
- a = unsignedtype->align;
- if (ty->op == UNION)
- off = bits = 0;
- else if (p->bitsize == 0 || bits == 0
- || bits - 1 + p->bitsize > 8*unsignedtype->size) {
- off = add(off, bits2bytes(bits-1));
- bits = 0;
- chkoverflow(off, a - 1);
- off = roundup(off, a);
- }
- if (a > ty->align)
- ty->align = a;
- p->offset = off;
-
- if (p->lsb) {
- if (bits == 0)
- bits = 1;
- if (IR->little_endian)
- p->lsb = bits;
- else
- p->lsb = 8*unsignedtype->size - bits + 1
- - p->bitsize + 1;
- bits += p->bitsize;
- } else
- off = add(off, p->type->size);
- if (off + bits2bytes(bits-1) > ty->size)
- ty->size = off + bits2bytes(bits-1);
- if (p->name == NULL
- || !('1' <= *p->name && *p->name <= '9')) {
- *q = p;
- q = &p->link;
- }
- }
- *q = NULL;
- chkoverflow(ty->size, ty->align - 1);
- ty->size = roundup(ty->size, ty->align);
- if (overflow) {
- error("size of `%t' exceeds %d bytes\n", ty, inttype->u.sym->u.limits.max.i);
- ty->size = inttype->u.sym->u.limits.max.i&(~(ty->align - 1));
- } }
-}
-static void funcdefn(int sclass, char *id, Type ty, Symbol params[], Coordinate pt) {
- int i, n;
- Symbol *callee, *caller, p;
- Type rty = freturn(ty);
-
- if (isstruct(rty) && rty->size == 0)
- error("illegal use of incomplete type `%t'\n", rty);
- for (n = 0; params[n]; n++)
- ;
- if (n > 0 && params[n-1]->name == NULL)
- params[--n] = NULL;
- if (Aflag >= 2 && n > 31)
- warning("more than 31 parameters in function `%s'\n", id);
- if (ty->u.f.oldstyle) {
- if (Aflag >= 1)
- warning("old-style function definition for `%s'\n", id);
- caller = params;
- callee = newarray(n + 1, sizeof *callee, FUNC);
- memcpy(callee, caller, (n+1)*sizeof *callee);
- enterscope();
- assert(level == PARAM);
- while (kind[t] == STATIC || istypename(t, tsym))
- decl(dclparam);
- foreach(identifiers, PARAM, oldparam, callee);
-
- for (i = 0; (p = callee[i]) != NULL; i++) {
- if (!p->defined)
- callee[i] = dclparam(0, p->name, inttype, &p->src);
- *caller[i] = *p;
- caller[i]->sclass = AUTO;
- caller[i]->type = promote(p->type);
- }
- p = lookup(id, identifiers);
- if (p && p->scope == GLOBAL && isfunc(p->type)
- && p->type->u.f.proto) {
- Type *proto = p->type->u.f.proto;
- for (i = 0; caller[i] && proto[i]; i++) {
- Type ty = unqual(proto[i]);
- if (eqtype(isenum(ty) ? ty->type : ty,
- unqual(caller[i]->type), 1) == 0)
- break;
- else if (isenum(ty) && !isenum(unqual(caller[i]->type)))
- warning("compatibility of `%t' and `%t' is compiler dependent\n",
- proto[i], caller[i]->type);
- }
- if (proto[i] || caller[i])
- error("conflicting argument declarations for function `%s'\n", id);
-
- }
- else {
- Type *proto = newarray(n + 1, sizeof *proto, PERM);
- if (Aflag >= 1)
- warning("missing prototype for `%s'\n", id);
- for (i = 0; i < n; i++)
- proto[i] = caller[i]->type;
- proto[i] = NULL;
- ty = func(rty, proto, 1);
- }
- } else {
- callee = params;
- caller = newarray(n + 1, sizeof *caller, FUNC);
- for (i = 0; (p = callee[i]) != NULL && p->name; i++) {
- NEW(caller[i], FUNC);
- *caller[i] = *p;
- if (isint(p->type))
- caller[i]->type = promote(p->type);
- caller[i]->sclass = AUTO;
- if ('1' <= *p->name && *p->name <= '9')
- error("missing name for parameter %d to function `%s'\n", i + 1, id);
-
- }
- caller[i] = NULL;
- }
- for (i = 0; (p = callee[i]) != NULL; i++)
- if (p->type->size == 0) {
- error("undefined size for parameter `%t %s'\n",
- p->type, p->name);
- caller[i]->type = p->type = inttype;
- }
- if (Aflag >= 2 && sclass != STATIC && strcmp(id, "main") == 0) {
- if (ty->u.f.oldstyle)
- warning("`%t %s()' is a non-ANSI definition\n", rty, id);
- else if (!(rty == inttype
- && (n == 0 && callee[0] == NULL
- || n == 2 && callee[0]->type == inttype
- && isptr(callee[1]->type) && callee[1]->type->type == charptype
- && !variadic(ty))))
- warning("`%s' is a non-ANSI definition\n", typestring(ty, id));
- }
- p = lookup(id, identifiers);
- if (p && isfunc(p->type) && p->defined)
- error("redefinition of `%s' previously defined at %w\n",
- p->name, &p->src);
- cfunc = dclglobal(sclass, id, ty, &pt);
- cfunc->u.f.label = genlabel(1);
- cfunc->u.f.callee = callee;
- cfunc->u.f.pt = src;
- cfunc->defined = 1;
- if (xref)
- use(cfunc, cfunc->src);
- if (Pflag)
- printproto(cfunc, cfunc->u.f.callee);
- if (ncalled >= 0)
- ncalled = findfunc(cfunc->name, pt.file);
- labels = table(NULL, LABELS);
- stmtlabs = table(NULL, LABELS);
- refinc = 1.0;
- regcount = 0;
- codelist = &codehead;
- codelist->next = NULL;
- if (!IR->wants_callb && isstruct(rty))
- retv = genident(AUTO, ptr(rty), PARAM);
- compound(0, NULL, 0);
-
- {
- Code cp;
- for (cp = codelist; cp->kind < Label; cp = cp->prev)
- ;
- if (cp->kind != Jump) {
- if (rty != voidtype) {
- warning("missing return value\n");
- retcode(cnsttree(inttype, 0L));
- } else
- retcode(NULL);
- }
- }
- definelab(cfunc->u.f.label);
- if (events.exit)
- apply(events.exit, cfunc, NULL);
- walk(NULL, 0, 0);
- exitscope();
- assert(level == PARAM);
- foreach(identifiers, level, checkref, NULL);
- if (!IR->wants_callb && isstruct(rty)) {
- Symbol *a;
- a = newarray(n + 2, sizeof *a, FUNC);
- a[0] = retv;
- memcpy(&a[1], callee, (n+1)*sizeof *callee);
- callee = a;
- a = newarray(n + 2, sizeof *a, FUNC);
- NEW(a[0], FUNC);
- *a[0] = *retv;
- memcpy(&a[1], caller, (n+1)*sizeof *callee);
- caller = a;
- }
- if (!IR->wants_argb)
- for (i = 0; caller[i]; i++)
- if (isstruct(caller[i]->type)) {
- caller[i]->type = ptr(caller[i]->type);
- callee[i]->type = ptr(callee[i]->type);
- caller[i]->structarg = callee[i]->structarg = 1;
- }
- if (glevel > 1) for (i = 0; callee[i]; i++) callee[i]->sclass = AUTO;
- if (cfunc->sclass != STATIC)
- (*IR->export)(cfunc);
- if (glevel && IR->stabsym) {
- swtoseg(CODE); (*IR->stabsym)(cfunc); }
- swtoseg(CODE);
- (*IR->function)(cfunc, caller, callee, cfunc->u.f.ncalls);
- if (glevel && IR->stabfend)
- (*IR->stabfend)(cfunc, lineno);
- foreach(stmtlabs, LABELS, checklab, NULL);
- exitscope();
- expect('}');
- labels = stmtlabs = NULL;
- retv = NULL;
- cfunc = NULL;
-}
-static void oldparam(Symbol p, void *cl) {
- int i;
- Symbol *callee = cl;
-
- for (i = 0; callee[i]; i++)
- if (p->name == callee[i]->name) {
- callee[i] = p;
- return;
- }
- error("declared parameter `%s' is missing\n", p->name);
-}
-void compound(int loop, struct swtch *swp, int lev) {
- Code cp;
- int nregs;
-
- walk(NULL, 0, 0);
- cp = code(Blockbeg);
- enterscope();
- assert(level >= LOCAL);
- if (level == LOCAL && events.entry)
- apply(events.entry, cfunc, NULL);
- definept(NULL);
- expect('{');
- autos = registers = NULL;
- if (level == LOCAL && IR->wants_callb
- && isstruct(freturn(cfunc->type))) {
- retv = genident(AUTO, ptr(freturn(cfunc->type)), level);
- retv->defined = 1;
- retv->ref = 1;
- registers = append(retv, registers);
- }
- while (kind[t] == CHAR || kind[t] == STATIC
- || istypename(t, tsym) && getchr() != ':')
- decl(dcllocal);
- {
- int i;
- Symbol *a = ltov(&autos, STMT);
- nregs = length(registers);
- for (i = 0; a[i]; i++)
- registers = append(a[i], registers);
- cp->u.block.locals = ltov(®isters, FUNC);
- }
- if (events.blockentry)
- apply(events.blockentry, cp->u.block.locals, NULL);
- while (kind[t] == IF || kind[t] == ID)
- statement(loop, swp, lev);
- walk(NULL, 0, 0);
- foreach(identifiers, level, checkref, NULL);
- {
- int i = nregs, j;
- Symbol p;
- for ( ; (p = cp->u.block.locals[i]) != NULL; i++) {
- for (j = i; j > nregs
- && cp->u.block.locals[j-1]->ref < p->ref; j--)
- cp->u.block.locals[j] = cp->u.block.locals[j-1];
- cp->u.block.locals[j] = p;
- }
- }
- if (events.blockexit)
- apply(events.blockexit, cp->u.block.locals, NULL);
- cp->u.block.level = level;
- cp->u.block.identifiers = identifiers;
- cp->u.block.types = types;
- code(Blockend)->u.begin = cp;
- if (reachable(Gen))
- definept(NULL);
- if (level > LOCAL) {
- exitscope();
- expect('}');
- }
-}
-static void checkref(Symbol p, void *cl) {
- if (p->scope >= PARAM
- && (isvolatile(p->type) || isfunc(p->type)))
- p->addressed = 1;
- if (Aflag >= 2 && p->defined && p->ref == 0) {
- if (p->sclass == STATIC)
- warning("static `%t %s' is not referenced\n",
- p->type, p->name);
- else if (p->scope == PARAM)
- warning("parameter `%t %s' is not referenced\n",
- p->type, p->name);
- else if (p->scope >= LOCAL && p->sclass != EXTERN)
- warning("local `%t %s' is not referenced\n",
- p->type, p->name);
- }
- if (p->sclass == AUTO
- && (p->scope == PARAM && regcount == 0
- || p->scope >= LOCAL)
- && !p->addressed && isscalar(p->type) && p->ref >= 3.0)
- p->sclass = REGISTER;
- if (level == GLOBAL && p->sclass == STATIC && !p->defined
- && isfunc(p->type) && p->ref)
- error("undefined static `%t %s'\n", p->type, p->name);
- assert(!(level == GLOBAL && p->sclass == STATIC && !p->defined && !isfunc(p->type)));
-}
-static Symbol dcllocal(int sclass, char *id, Type ty, Coordinate *pos) {
- Symbol p, q;
-
- if (sclass == 0)
- sclass = isfunc(ty) ? EXTERN : AUTO;
- else if (isfunc(ty) && sclass != EXTERN) {
- error("invalid storage class `%k' for `%t %s'\n",
- sclass, ty, id);
- sclass = EXTERN;
- } else if (sclass == REGISTER
- && (isvolatile(ty) || isstruct(ty) || isarray(ty))) {
- warning("register declaration ignored for `%t %s'\n",
- ty, id);
- sclass = AUTO;
- }
- q = lookup(id, identifiers);
- if (q && q->scope >= level
- || q && q->scope == PARAM && level == LOCAL)
- if (sclass == EXTERN && q->sclass == EXTERN
- && eqtype(q->type, ty, 1))
- ty = compose(ty, q->type);
- else
- error("redeclaration of `%s' previously declared at %w\n", q->name, &q->src);
-
- assert(level >= LOCAL);
- p = install(id, &identifiers, level, sclass == STATIC || sclass == EXTERN ? PERM : FUNC);
- p->type = ty;
- p->sclass = sclass;
- p->src = *pos;
- switch (sclass) {
- case EXTERN: q = lookup(id, globals);
- if (q == NULL || q->sclass == TYPEDEF || q->sclass == ENUM) {
- q = lookup(id, externals);
- if (q == NULL) {
- q = install(p->name, &externals, GLOBAL, PERM);
- q->type = p->type;
- q->sclass = EXTERN;
- q->src = src;
- (*IR->defsymbol)(q);
- }
- }
- if (!eqtype(p->type, q->type, 1))
- warning("declaration of `%s' does not match previous declaration at %w\n", q->name, &q->src);
-
- p->u.alias = q; break;
- case STATIC: (*IR->defsymbol)(p);
- initglobal(p, 0);
- if (!p->defined)
- if (p->type->size > 0) {
- defglobal(p, BSS);
- (*IR->space)(p->type->size);
- } else
- error("undefined size for `%t %s'\n",
- p->type, p->name);
- p->defined = 1; break;
- case REGISTER: registers = append(p, registers);
- regcount++;
- p->defined = 1;
- break;
- case AUTO: autos = append(p, autos);
- p->defined = 1; break;
- default: assert(0);
- }
- if (t == '=') {
- Tree e;
- if (sclass == EXTERN)
- error("illegal initialization of `extern %s'\n", id);
- t = gettok();
- definept(NULL);
- if (isscalar(p->type)
- || isstruct(p->type) && t != '{') {
- if (t == '{') {
- t = gettok();
- e = expr1(0);
- expect('}');
- } else
- e = expr1(0);
- } else {
- Symbol t1;
- Type ty = p->type, ty1 = ty;
- while (isarray(ty1))
- ty1 = ty1->type;
- if (!isconst(ty) && (!isarray(ty) || !isconst(ty1)))
- ty = qual(CONST, ty);
- t1 = genident(STATIC, ty, GLOBAL);
- initglobal(t1, 1);
- if (isarray(p->type) && p->type->size == 0
- && t1->type->size > 0)
- p->type = array(p->type->type,
- t1->type->size/t1->type->type->size, 0);
- e = idtree(t1);
- }
- walk(root(asgn(p, e)), 0, 0);
- p->ref = 1;
- }
- if (!isfunc(p->type) && p->defined && p->type->size <= 0)
- error("undefined size for `%t %s'\n", p->type, id);
- return p;
-}
-void finalize(void) {
- foreach(externals, GLOBAL, doextern, NULL);
- foreach(identifiers, GLOBAL, doglobal, NULL);
- foreach(identifiers, GLOBAL, checkref, NULL);
- foreach(constants, CONSTANTS, doconst, NULL);
-}
-static void doextern(Symbol p, void *cl) {
- (*IR->import)(p);
-}
-static void doglobal(Symbol p, void *cl) {
- if (!p->defined && (p->sclass == EXTERN
- || isfunc(p->type) && p->sclass == AUTO))
- (*IR->import)(p);
- else if (!p->defined && !isfunc(p->type)
- && (p->sclass == AUTO || p->sclass == STATIC)) {
- if (isarray(p->type)
- && p->type->size == 0 && p->type->type->size > 0)
- p->type = array(p->type->type, 1, 0);
- if (p->type->size > 0) {
- defglobal(p, BSS);
- (*IR->space)(p->type->size);
- if (glevel > 0 && IR->stabsym)
- (*IR->stabsym)(p);
- } else
- error("undefined size for `%t %s'\n",
- p->type, p->name);
- p->defined = 1;
- }
- if (Pflag
- && !isfunc(p->type)
- && !p->generated && p->sclass != EXTERN)
- printdecl(p, p->type);
-}
-void doconst(Symbol p, void *cl) {
- if (p->u.c.loc) {
- assert(p->u.c.loc->u.seg == 0);
- defglobal(p->u.c.loc, LIT);
- if (isarray(p->type) && p->type->type == widechar) {
- unsigned int *s = p->u.c.v.p;
- int n = p->type->size/widechar->size;
- while (n-- > 0) {
- Value v;
- v.u = *s++;
- (*IR->defconst)(widechar->op, widechar->size, v);
- }
- } else if (isarray(p->type))
- (*IR->defstring)(p->type->size, p->u.c.v.p);
- else
- (*IR->defconst)(p->type->op, p->type->size, p->u.c.v);
- p->u.c.loc = NULL;
- }
-}
-void checklab(Symbol p, void *cl) {
- if (!p->defined)
- error("undefined label `%s'\n", p->name);
- p->defined = 1;
-}
-
-Type enumdcl(void) {
- char *tag;
- Type ty;
- Symbol p;
- Coordinate pos;
-
- t = gettok();
- pos = src;
- if (t == ID) {
- tag = token;
- t = gettok();
- } else
- tag = "";
- if (t == '{') {
- static char follow[] = { IF, 0 };
- int n = 0;
- long k = -1;
- List idlist = 0;
- ty = newstruct(ENUM, tag);
- t = gettok();
- if (t != ID)
- error("expecting an enumerator identifier\n");
- while (t == ID) {
- char *id = token;
- Coordinate s;
- if (tsym && tsym->scope == level)
- error("redeclaration of `%s' previously declared at %w\n",
- token, &tsym->src);
- s = src;
- t = gettok();
- if (t == '=') {
- t = gettok();
- k = intexpr(0, 0);
- } else {
- if (k == inttype->u.sym->u.limits.max.i)
- error("overflow in value for enumeration constant `%s'\n", id);
- k++;
- }
- p = install(id, &identifiers, level, level < LOCAL ? PERM : FUNC);
- p->src = s;
- p->type = ty;
- p->sclass = ENUM;
- p->u.value = k;
- idlist = append(p, idlist);
- n++;
- if (Aflag >= 2 && n == 128)
- warning("more than 127 enumeration constants in `%t'\n", ty);
- if (t != ',')
- break;
- t = gettok();
- if (Aflag >= 2 && t == '}')
- warning("non-ANSI trailing comma in enumerator list\n");
- }
- test('}', follow);
- ty->type = inttype;
- ty->size = ty->type->size;
- ty->align = ty->type->align;
- ty->u.sym->u.idlist = ltov(&idlist, PERM);
- ty->u.sym->defined = 1;
- } else if ((p = lookup(tag, types)) != NULL && p->type->op == ENUM) {
- ty = p->type;
- if (t == ';')
- error("empty declaration\n");
- } else {
- error("unknown enumeration `%s'\n", tag);
- ty = newstruct(ENUM, tag);
- ty->type = inttype;
- }
- if (*tag && xref)
- use(p, pos);
- return ty;
-}
-
-Type typename(void) {
- Type ty = specifier(NULL);
-
- if (t == '*' || t == '(' || t == '[') {
- ty = dclr(ty, NULL, NULL, 1);
- if (Aflag >= 1 && !hasproto(ty))
- warning("missing prototype\n");
- }
- return ty;
-}
-
+#include "c.h" + + +#define add(x,n) (x > inttype->u.sym->u.limits.max.i-(n) ? (overflow=1,x) : x+(n)) +#define chkoverflow(x,n) ((void)add(x,n)) +#define bits2bytes(n) (((n) + 7)/8) +static int regcount; + +static List autos, registers; +Symbol cfunc; /* current function */ +Symbol retv; /* return value location for structs */ + +static void checkref(Symbol, void *); +static Symbol dclglobal(int, char *, Type, Coordinate *); +static Symbol dcllocal(int, char *, Type, Coordinate *); +static Symbol dclparam(int, char *, Type, Coordinate *); +static Type dclr(Type, char **, Symbol **, int); +static Type dclr1(char **, Symbol **, int); +static void decl(Symbol (*)(int, char *, Type, Coordinate *)); +extern void doconst(Symbol, void *); +static void doglobal(Symbol, void *); +static void doextern(Symbol, void *); +static void exitparams(Symbol []); +static void fields(Type); +static void funcdefn(int, char *, Type, Symbol [], Coordinate); +static void initglobal(Symbol, int); +static void oldparam(Symbol, void *); +static Symbol *parameters(Type); +static Type specifier(int *); +static Type structdcl(int); +static Type tnode(int, Type); +void program(void) { + int n; + + level = GLOBAL; + for (n = 0; t != EOI; n++) + if (kind[t] == CHAR || kind[t] == STATIC + || t == ID || t == '*' || t == '(') { + decl(dclglobal); + deallocate(STMT); + if (!(glevel >= 3 || xref)) + deallocate(FUNC); + } else if (t == ';') { + warning("empty declaration\n"); + t = gettok(); + } else { + error("unrecognized declaration\n"); + t = gettok(); + } + if (n == 0) + warning("empty input file\n"); +} +static Type specifier(int *sclass) { + int cls, cons, sign, size, type, vol; + Type ty = NULL; + + cls = vol = cons = sign = size = type = 0; + if (sclass == NULL) + cls = AUTO; + for (;;) { + int *p, tt = t; + switch (t) { + case AUTO: + case REGISTER: if (level <= GLOBAL && cls == 0) + error("invalid use of `%k'\n", t); + p = &cls; t = gettok(); break; + case STATIC: case EXTERN: + case TYPEDEF: p = &cls; t = gettok(); break; + case CONST: p = &cons; t = gettok(); break; + case VOLATILE: p = &vol; t = gettok(); break; + case SIGNED: + case UNSIGNED: p = &sign; t = gettok(); break; + case LONG: if (size == LONG) { + size = 0; + tt = LONG+LONG; + } + p = &size; t = gettok(); break; + case SHORT: p = &size; t = gettok(); break; + case VOID: case CHAR: case INT: case FLOAT: + case DOUBLE: p = &type; ty = tsym->type; + t = gettok(); break; + case ENUM: p = &type; ty = enumdcl(); break; + case STRUCT: + case UNION: p = &type; ty = structdcl(t); break; + case ID: + if (istypename(t, tsym) && type == 0 + && sign == 0 && size == 0) { + use(tsym, src); + ty = tsym->type; + if (isqual(ty) + && ty->size != ty->type->size) { + ty = unqual(ty); + if (isconst(tsym->type)) + ty = qual(CONST, ty); + if (isvolatile(tsym->type)) + ty = qual(VOLATILE, ty); + tsym->type = ty; + } + p = &type; + t = gettok(); + } else + p = NULL; + break; + default: p = NULL; + } + if (p == NULL) + break; + if (*p) + error("invalid use of `%k'\n", tt); + *p = tt; + } + if (sclass) + *sclass = cls; + if (type == 0) { + type = INT; + ty = inttype; + } + if (size == SHORT && type != INT + || size == LONG+LONG && type != INT + || size == LONG && type != INT && type != DOUBLE + || sign && type != INT && type != CHAR) + error("invalid type specification\n"); + if (type == CHAR && sign) + ty = sign == UNSIGNED ? unsignedchar : signedchar; + else if (size == SHORT) + ty = sign == UNSIGNED ? unsignedshort : shorttype; + else if (size == LONG && type == DOUBLE) + ty = longdouble; + else if (size == LONG+LONG) { + ty = sign == UNSIGNED ? unsignedlonglong : longlong; + if (Aflag >= 1) + warning("`%t' is a non-ANSI type\n", ty); + } else if (size == LONG) + ty = sign == UNSIGNED ? unsignedlong : longtype; + else if (sign == UNSIGNED && type == INT) + ty = unsignedtype; + if (cons == CONST) + ty = qual(CONST, ty); + if (vol == VOLATILE) + ty = qual(VOLATILE, ty); + return ty; +} +static void decl(Symbol (*dcl)(int, char *, Type, Coordinate *)) { + int sclass; + Type ty, ty1; + static char stop[] = { CHAR, STATIC, ID, 0 }; + + ty = specifier(&sclass); + if (t == ID || t == '*' || t == '(' || t == '[') { + char *id; + Coordinate pos; + id = NULL; + pos = src; + if (level == GLOBAL) { + Symbol *params = NULL; + ty1 = dclr(ty, &id, ¶ms, 0); + if (params && id && isfunc(ty1) + && (t == '{' || istypename(t, tsym) + || (kind[t] == STATIC && t != TYPEDEF))) { + if (sclass == TYPEDEF) { + error("invalid use of `typedef'\n"); + sclass = EXTERN; + } + if (ty1->u.f.oldstyle) + exitscope(); + funcdefn(sclass, id, ty1, params, pos); + return; + } else if (params) + exitparams(params); + } else + ty1 = dclr(ty, &id, NULL, 0); + for (;;) { + if (Aflag >= 1 && !hasproto(ty1)) + warning("missing prototype\n"); + if (id == NULL) + error("missing identifier\n"); + else if (sclass == TYPEDEF) + { + Symbol p = lookup(id, identifiers); + if (p && p->scope == level) + error("redeclaration of `%s'\n", id); + p = install(id, &identifiers, level, + level < LOCAL ? PERM : FUNC); + p->type = ty1; + p->sclass = TYPEDEF; + p->src = pos; + } + else + (void)(*dcl)(sclass, id, ty1, &pos); + if (t != ',') + break; + t = gettok(); + id = NULL; + pos = src; + ty1 = dclr(ty, &id, NULL, 0); + } + } else if (ty == NULL + || !(isenum(ty) || + isstruct(ty) && (*unqual(ty)->u.sym->name < '1' || *unqual(ty)->u.sym->name > '9'))) + error("empty declaration\n"); + test(';', stop); +} +static Symbol dclglobal(int sclass, char *id, Type ty, Coordinate *pos) { + Symbol p; + + if (sclass == 0) + sclass = AUTO; + else if (sclass != EXTERN && sclass != STATIC) { + error("invalid storage class `%k' for `%t %s'\n", + sclass, ty, id); + sclass = AUTO; + } + p = lookup(id, identifiers); + if (p && p->scope == GLOBAL) { + if (p->sclass != TYPEDEF && eqtype(ty, p->type, 1)) + ty = compose(ty, p->type); + else + error("redeclaration of `%s' previously declared at %w\n", p->name, &p->src); + + if (!isfunc(ty) && p->defined && t == '=') + error("redefinition of `%s' previously defined at %w\n", p->name, &p->src); + + if (p->sclass == EXTERN && sclass == STATIC + || p->sclass == STATIC && sclass == AUTO + || p->sclass == AUTO && sclass == STATIC) + warning("inconsistent linkage for `%s' previously declared at %w\n", p->name, &p->src); + + } + if (p == NULL || p->scope != GLOBAL) { + Symbol q = lookup(id, externals); + if (q) { + if (sclass == STATIC || !eqtype(ty, q->type, 1)) + warning("declaration of `%s' does not match previous declaration at %w\n", id, &q->src); + + p = relocate(id, externals, globals); + p->sclass = sclass; + } else { + p = install(id, &globals, GLOBAL, PERM); + p->sclass = sclass; + (*IR->defsymbol)(p); + } + if (p->sclass != STATIC) { + static int nglobals; + nglobals++; + if (Aflag >= 2 && nglobals == 512) + warning("more than 511 external identifiers\n"); + } + } else if (p->sclass == EXTERN) + p->sclass = sclass; + p->type = ty; + p->src = *pos; + if (t == '=' && isfunc(p->type)) { + error("illegal initialization for `%s'\n", p->name); + t = gettok(); + initializer(p->type, 0); + } else if (t == '=') { + initglobal(p, 0); + if (glevel > 0 && IR->stabsym) { + (*IR->stabsym)(p); swtoseg(p->u.seg); } + } else if (p->sclass == STATIC && !isfunc(p->type) + && p->type->size == 0) + error("undefined size for `%t %s'\n", p->type, p->name); + return p; +} +static void initglobal(Symbol p, int flag) { + Type ty; + + if (t == '=' || flag) { + if (p->sclass == STATIC) { + for (ty = p->type; isarray(ty); ty = ty->type) + ; + defglobal(p, isconst(ty) ? LIT : DATA); + } else + defglobal(p, DATA); + if (t == '=') + t = gettok(); + ty = initializer(p->type, 0); + if (isarray(p->type) && p->type->size == 0) + p->type = ty; + if (p->sclass == EXTERN) + p->sclass = AUTO; + } +} +void defglobal(Symbol p, int seg) { + p->u.seg = seg; + swtoseg(p->u.seg); + if (p->sclass != STATIC) + (*IR->export)(p); + (*IR->global)(p); + p->defined = 1; +} + +static Type dclr(Type basety, char **id, Symbol **params, int abstract) { + Type ty = dclr1(id, params, abstract); + + for ( ; ty; ty = ty->type) + switch (ty->op) { + case POINTER: + basety = ptr(basety); + break; + case FUNCTION: + basety = func(basety, ty->u.f.proto, + ty->u.f.oldstyle); + break; + case ARRAY: + basety = array(basety, ty->size, 0); + break; + case CONST: case VOLATILE: + basety = qual(ty->op, basety); + break; + default: assert(0); + } + if (Aflag >= 2 && basety->size > 32767) + warning("more than 32767 bytes in `%t'\n", basety); + return basety; +} +static Type tnode(int op, Type type) { + Type ty; + + NEW0(ty, STMT); + ty->op = op; + ty->type = type; + return ty; +} +static Type dclr1(char **id, Symbol **params, int abstract) { + Type ty = NULL; + + switch (t) { + case ID: if (id) + *id = token; + else + error("extraneous identifier `%s'\n", token); + t = gettok(); break; + case '*': t = gettok(); if (t == CONST || t == VOLATILE) { + Type ty1; + ty1 = ty = tnode(t, NULL); + while ((t = gettok()) == CONST || t == VOLATILE) + ty1 = tnode(t, ty1); + ty->type = dclr1(id, params, abstract); + ty = ty1; + } else + ty = dclr1(id, params, abstract); + ty = tnode(POINTER, ty); break; + case '(': t = gettok(); if (abstract + && (t == REGISTER || istypename(t, tsym) || t == ')')) { + Symbol *args; + ty = tnode(FUNCTION, ty); + enterscope(); + if (level > PARAM) + enterscope(); + args = parameters(ty); + exitparams(args); + } else { + ty = dclr1(id, params, abstract); + expect(')'); + if (abstract && ty == NULL + && (id == NULL || *id == NULL)) + return tnode(FUNCTION, NULL); + } break; + case '[': break; + default: return ty; + } + while (t == '(' || t == '[') + switch (t) { + case '(': t = gettok(); { Symbol *args; + ty = tnode(FUNCTION, ty); + enterscope(); + if (level > PARAM) + enterscope(); + args = parameters(ty); + if (params && *params == NULL) + *params = args; + else + exitparams(args); + } + break; + case '[': t = gettok(); { int n = 0; + if (kind[t] == ID) { + n = intexpr(']', 1); + if (n <= 0) { + error("`%d' is an illegal array size\n", n); + n = 1; + } + } else + expect(']'); + ty = tnode(ARRAY, ty); + ty->size = n; } break; + default: assert(0); + } + return ty; +} +static Symbol *parameters(Type fty) { + List list = NULL; + Symbol *params; + + if (kind[t] == STATIC || istypename(t, tsym)) { + int n = 0; + Type ty1 = NULL; + for (;;) { + Type ty; + int sclass = 0; + char *id = NULL; + if (ty1 && t == ELLIPSIS) { + static struct symbol sentinel; + if (sentinel.type == NULL) { + sentinel.type = voidtype; + sentinel.defined = 1; + } + if (ty1 == voidtype) + error("illegal formal parameter types\n"); + list = append(&sentinel, list); + t = gettok(); + break; + } + if (!istypename(t, tsym) && t != REGISTER) + error("missing parameter type\n"); + n++; + ty = dclr(specifier(&sclass), &id, NULL, 1); + if ( ty == voidtype && (ty1 || id) + || ty1 == voidtype) + error("illegal formal parameter types\n"); + if (id == NULL) + id = stringd(n); + if (ty != voidtype) + list = append(dclparam(sclass, id, ty, &src), list); + if (Aflag >= 1 && !hasproto(ty)) + warning("missing prototype\n"); + if (ty1 == NULL) + ty1 = ty; + if (t != ',') + break; + t = gettok(); + } + fty->u.f.proto = newarray(length(list) + 1, + sizeof (Type *), PERM); + params = ltov(&list, FUNC); + for (n = 0; params[n]; n++) + fty->u.f.proto[n] = params[n]->type; + fty->u.f.proto[n] = NULL; + fty->u.f.oldstyle = 0; + } else { + if (t == ID) + for (;;) { + Symbol p; + if (t != ID) { + error("expecting an identifier\n"); + break; + } + p = dclparam(0, token, inttype, &src); + p->defined = 0; + list = append(p, list); + t = gettok(); + if (t != ',') + break; + t = gettok(); + } + params = ltov(&list, FUNC); + fty->u.f.proto = NULL; + fty->u.f.oldstyle = 1; + } + if (t != ')') { + static char stop[] = { CHAR, STATIC, IF, ')', 0 }; + expect(')'); + skipto('{', stop); + } + if (t == ')') + t = gettok(); + return params; +} +static void exitparams(Symbol params[]) { + assert(params); + if (params[0] && !params[0]->defined) + error("extraneous old-style parameter list\n"); + if (level > PARAM) + exitscope(); + exitscope(); +} + +static Symbol dclparam(int sclass, char *id, Type ty, Coordinate *pos) { + Symbol p; + + if (isfunc(ty)) + ty = ptr(ty); + else if (isarray(ty)) + ty = atop(ty); + if (sclass == 0) + sclass = AUTO; + else if (sclass != REGISTER) { + error("invalid storage class `%k' for `%t%s\n", + sclass, ty, stringf(id ? " %s'" : "' parameter", id)); + sclass = AUTO; + } else if (isvolatile(ty) || isstruct(ty)) { + warning("register declaration ignored for `%t%s\n", + ty, stringf(id ? " %s'" : "' parameter", id)); + sclass = AUTO; + } + + p = lookup(id, identifiers); + if (p && p->scope == level) + error("duplicate declaration for `%s' previously declared at %w\n", id, &p->src); + + else + p = install(id, &identifiers, level, FUNC); + p->sclass = sclass; + p->src = *pos; + p->type = ty; + p->defined = 1; + if (t == '=') { + error("illegal initialization for parameter `%s'\n", id); + t = gettok(); + (void)expr1(0); + } + return p; +} +static Type structdcl(int op) { + char *tag; + Type ty; + Symbol p; + Coordinate pos; + + t = gettok(); + pos = src; + if (t == ID) { + tag = token; + t = gettok(); + } else + tag = ""; + if (t == '{') { + static char stop[] = { IF, ',', 0 }; + ty = newstruct(op, tag); + ty->u.sym->src = pos; + ty->u.sym->defined = 1; + t = gettok(); + if (istypename(t, tsym)) + fields(ty); + else + error("invalid %k field declarations\n", op); + test('}', stop); + } + else if (*tag && (p = lookup(tag, types)) != NULL + && p->type->op == op) { + ty = p->type; + if (t == ';' && p->scope < level) + ty = newstruct(op, tag); + } + else { + if (*tag == 0) + error("missing %k tag\n", op); + ty = newstruct(op, tag); + } + if (*tag && xref) + use(ty->u.sym, pos); + return ty; +} +static void fields(Type ty) { + { int n = 0; + while (istypename(t, tsym)) { + static char stop[] = { IF, CHAR, '}', 0 }; + Type ty1 = specifier(NULL); + for (;;) { + Field p; + char *id = NULL; + Type fty = dclr(ty1, &id, NULL, 0); + p = newfield(id, ty, fty); + if (Aflag >= 1 && !hasproto(p->type)) + warning("missing prototype\n"); + if (t == ':') { + if (unqual(p->type) != inttype + && unqual(p->type) != unsignedtype) { + error("`%t' is an illegal bit-field type\n", + p->type); + p->type = inttype; + } + t = gettok(); + p->bitsize = intexpr(0, 0); + if (p->bitsize > 8*inttype->size || p->bitsize < 0) { + error("`%d' is an illegal bit-field size\n", + p->bitsize); + p->bitsize = 8*inttype->size; + } else if (p->bitsize == 0 && id) { + warning("extraneous 0-width bit field `%t %s' ignored\n", p->type, id); + + p->name = stringd(genlabel(1)); + } + p->lsb = 1; + } + else { + if (id == NULL) + error("field name missing\n"); + else if (isfunc(p->type)) + error("`%t' is an illegal field type\n", p->type); + else if (p->type->size == 0) + error("undefined size for field `%t %s'\n", + p->type, id); + } + if (isconst(p->type)) + ty->u.sym->u.s.cfields = 1; + if (isvolatile(p->type)) + ty->u.sym->u.s.vfields = 1; + n++; + if (Aflag >= 2 && n == 128) + warning("more than 127 fields in `%t'\n", ty); + if (t != ',') + break; + t = gettok(); + } + test(';', stop); + } } + { int bits = 0, off = 0, overflow = 0; + Field p, *q = &ty->u.sym->u.s.flist; + ty->align = IR->structmetric.align; + for (p = *q; p; p = p->link) { + int a = p->type->align ? p->type->align : 1; + if (p->lsb) + a = unsignedtype->align; + if (ty->op == UNION) + off = bits = 0; + else if (p->bitsize == 0 || bits == 0 + || bits - 1 + p->bitsize > 8*unsignedtype->size) { + off = add(off, bits2bytes(bits-1)); + bits = 0; + chkoverflow(off, a - 1); + off = roundup(off, a); + } + if (a > ty->align) + ty->align = a; + p->offset = off; + + if (p->lsb) { + if (bits == 0) + bits = 1; + if (IR->little_endian) + p->lsb = bits; + else + p->lsb = 8*unsignedtype->size - bits + 1 + - p->bitsize + 1; + bits += p->bitsize; + } else + off = add(off, p->type->size); + if (off + bits2bytes(bits-1) > ty->size) + ty->size = off + bits2bytes(bits-1); + if (p->name == NULL + || !('1' <= *p->name && *p->name <= '9')) { + *q = p; + q = &p->link; + } + } + *q = NULL; + chkoverflow(ty->size, ty->align - 1); + ty->size = roundup(ty->size, ty->align); + if (overflow) { + error("size of `%t' exceeds %d bytes\n", ty, inttype->u.sym->u.limits.max.i); + ty->size = inttype->u.sym->u.limits.max.i&(~(ty->align - 1)); + } } +} +static void funcdefn(int sclass, char *id, Type ty, Symbol params[], Coordinate pt) { + int i, n; + Symbol *callee, *caller, p; + Type rty = freturn(ty); + + if (isstruct(rty) && rty->size == 0) + error("illegal use of incomplete type `%t'\n", rty); + for (n = 0; params[n]; n++) + ; + if (n > 0 && params[n-1]->name == NULL) + params[--n] = NULL; + if (Aflag >= 2 && n > 31) + warning("more than 31 parameters in function `%s'\n", id); + if (ty->u.f.oldstyle) { + if (Aflag >= 1) + warning("old-style function definition for `%s'\n", id); + caller = params; + callee = newarray(n + 1, sizeof *callee, FUNC); + memcpy(callee, caller, (n+1)*sizeof *callee); + enterscope(); + assert(level == PARAM); + while (kind[t] == STATIC || istypename(t, tsym)) + decl(dclparam); + foreach(identifiers, PARAM, oldparam, callee); + + for (i = 0; (p = callee[i]) != NULL; i++) { + if (!p->defined) + callee[i] = dclparam(0, p->name, inttype, &p->src); + *caller[i] = *p; + caller[i]->sclass = AUTO; + caller[i]->type = promote(p->type); + } + p = lookup(id, identifiers); + if (p && p->scope == GLOBAL && isfunc(p->type) + && p->type->u.f.proto) { + Type *proto = p->type->u.f.proto; + for (i = 0; caller[i] && proto[i]; i++) { + Type ty = unqual(proto[i]); + if (eqtype(isenum(ty) ? ty->type : ty, + unqual(caller[i]->type), 1) == 0) + break; + else if (isenum(ty) && !isenum(unqual(caller[i]->type))) + warning("compatibility of `%t' and `%t' is compiler dependent\n", + proto[i], caller[i]->type); + } + if (proto[i] || caller[i]) + error("conflicting argument declarations for function `%s'\n", id); + + } + else { + Type *proto = newarray(n + 1, sizeof *proto, PERM); + if (Aflag >= 1) + warning("missing prototype for `%s'\n", id); + for (i = 0; i < n; i++) + proto[i] = caller[i]->type; + proto[i] = NULL; + ty = func(rty, proto, 1); + } + } else { + callee = params; + caller = newarray(n + 1, sizeof *caller, FUNC); + for (i = 0; (p = callee[i]) != NULL && p->name; i++) { + NEW(caller[i], FUNC); + *caller[i] = *p; + if (isint(p->type)) + caller[i]->type = promote(p->type); + caller[i]->sclass = AUTO; + if ('1' <= *p->name && *p->name <= '9') + error("missing name for parameter %d to function `%s'\n", i + 1, id); + + } + caller[i] = NULL; + } + for (i = 0; (p = callee[i]) != NULL; i++) + if (p->type->size == 0) { + error("undefined size for parameter `%t %s'\n", + p->type, p->name); + caller[i]->type = p->type = inttype; + } + if (Aflag >= 2 && sclass != STATIC && strcmp(id, "main") == 0) { + if (ty->u.f.oldstyle) + warning("`%t %s()' is a non-ANSI definition\n", rty, id); + else if (!(rty == inttype + && (n == 0 && callee[0] == NULL + || n == 2 && callee[0]->type == inttype + && isptr(callee[1]->type) && callee[1]->type->type == charptype + && !variadic(ty)))) + warning("`%s' is a non-ANSI definition\n", typestring(ty, id)); + } + p = lookup(id, identifiers); + if (p && isfunc(p->type) && p->defined) + error("redefinition of `%s' previously defined at %w\n", + p->name, &p->src); + cfunc = dclglobal(sclass, id, ty, &pt); + cfunc->u.f.label = genlabel(1); + cfunc->u.f.callee = callee; + cfunc->u.f.pt = src; + cfunc->defined = 1; + if (xref) + use(cfunc, cfunc->src); + if (Pflag) + printproto(cfunc, cfunc->u.f.callee); + if (ncalled >= 0) + ncalled = findfunc(cfunc->name, pt.file); + labels = table(NULL, LABELS); + stmtlabs = table(NULL, LABELS); + refinc = 1.0; + regcount = 0; + codelist = &codehead; + codelist->next = NULL; + if (!IR->wants_callb && isstruct(rty)) + retv = genident(AUTO, ptr(rty), PARAM); + compound(0, NULL, 0); + + { + Code cp; + for (cp = codelist; cp->kind < Label; cp = cp->prev) + ; + if (cp->kind != Jump) { + if (rty != voidtype) { + warning("missing return value\n"); + retcode(cnsttree(inttype, 0L)); + } else + retcode(NULL); + } + } + definelab(cfunc->u.f.label); + if (events.exit) + apply(events.exit, cfunc, NULL); + walk(NULL, 0, 0); + exitscope(); + assert(level == PARAM); + foreach(identifiers, level, checkref, NULL); + if (!IR->wants_callb && isstruct(rty)) { + Symbol *a; + a = newarray(n + 2, sizeof *a, FUNC); + a[0] = retv; + memcpy(&a[1], callee, (n+1)*sizeof *callee); + callee = a; + a = newarray(n + 2, sizeof *a, FUNC); + NEW(a[0], FUNC); + *a[0] = *retv; + memcpy(&a[1], caller, (n+1)*sizeof *callee); + caller = a; + } + if (!IR->wants_argb) + for (i = 0; caller[i]; i++) + if (isstruct(caller[i]->type)) { + caller[i]->type = ptr(caller[i]->type); + callee[i]->type = ptr(callee[i]->type); + caller[i]->structarg = callee[i]->structarg = 1; + } + if (glevel > 1) for (i = 0; callee[i]; i++) callee[i]->sclass = AUTO; + if (cfunc->sclass != STATIC) + (*IR->export)(cfunc); + if (glevel && IR->stabsym) { + swtoseg(CODE); (*IR->stabsym)(cfunc); } + swtoseg(CODE); + (*IR->function)(cfunc, caller, callee, cfunc->u.f.ncalls); + if (glevel && IR->stabfend) + (*IR->stabfend)(cfunc, lineno); + foreach(stmtlabs, LABELS, checklab, NULL); + exitscope(); + expect('}'); + labels = stmtlabs = NULL; + retv = NULL; + cfunc = NULL; +} +static void oldparam(Symbol p, void *cl) { + int i; + Symbol *callee = cl; + + for (i = 0; callee[i]; i++) + if (p->name == callee[i]->name) { + callee[i] = p; + return; + } + error("declared parameter `%s' is missing\n", p->name); +} +void compound(int loop, struct swtch *swp, int lev) { + Code cp; + int nregs; + + walk(NULL, 0, 0); + cp = code(Blockbeg); + enterscope(); + assert(level >= LOCAL); + if (level == LOCAL && events.entry) + apply(events.entry, cfunc, NULL); + definept(NULL); + expect('{'); + autos = registers = NULL; + if (level == LOCAL && IR->wants_callb + && isstruct(freturn(cfunc->type))) { + retv = genident(AUTO, ptr(freturn(cfunc->type)), level); + retv->defined = 1; + retv->ref = 1; + registers = append(retv, registers); + } + while (kind[t] == CHAR || kind[t] == STATIC + || istypename(t, tsym) && getchr() != ':') + decl(dcllocal); + { + int i; + Symbol *a = ltov(&autos, STMT); + nregs = length(registers); + for (i = 0; a[i]; i++) + registers = append(a[i], registers); + cp->u.block.locals = ltov(®isters, FUNC); + } + if (events.blockentry) + apply(events.blockentry, cp->u.block.locals, NULL); + while (kind[t] == IF || kind[t] == ID) + statement(loop, swp, lev); + walk(NULL, 0, 0); + foreach(identifiers, level, checkref, NULL); + { + int i = nregs, j; + Symbol p; + for ( ; (p = cp->u.block.locals[i]) != NULL; i++) { + for (j = i; j > nregs + && cp->u.block.locals[j-1]->ref < p->ref; j--) + cp->u.block.locals[j] = cp->u.block.locals[j-1]; + cp->u.block.locals[j] = p; + } + } + if (events.blockexit) + apply(events.blockexit, cp->u.block.locals, NULL); + cp->u.block.level = level; + cp->u.block.identifiers = identifiers; + cp->u.block.types = types; + code(Blockend)->u.begin = cp; + if (reachable(Gen)) + definept(NULL); + if (level > LOCAL) { + exitscope(); + expect('}'); + } +} +static void checkref(Symbol p, void *cl) { + if (p->scope >= PARAM + && (isvolatile(p->type) || isfunc(p->type))) + p->addressed = 1; + if (Aflag >= 2 && p->defined && p->ref == 0) { + if (p->sclass == STATIC) + warning("static `%t %s' is not referenced\n", + p->type, p->name); + else if (p->scope == PARAM) + warning("parameter `%t %s' is not referenced\n", + p->type, p->name); + else if (p->scope >= LOCAL && p->sclass != EXTERN) + warning("local `%t %s' is not referenced\n", + p->type, p->name); + } + if (p->sclass == AUTO + && (p->scope == PARAM && regcount == 0 + || p->scope >= LOCAL) + && !p->addressed && isscalar(p->type) && p->ref >= 3.0) + p->sclass = REGISTER; + if (level == GLOBAL && p->sclass == STATIC && !p->defined + && isfunc(p->type) && p->ref) + error("undefined static `%t %s'\n", p->type, p->name); + assert(!(level == GLOBAL && p->sclass == STATIC && !p->defined && !isfunc(p->type))); +} +static Symbol dcllocal(int sclass, char *id, Type ty, Coordinate *pos) { + Symbol p, q; + + if (sclass == 0) + sclass = isfunc(ty) ? EXTERN : AUTO; + else if (isfunc(ty) && sclass != EXTERN) { + error("invalid storage class `%k' for `%t %s'\n", + sclass, ty, id); + sclass = EXTERN; + } else if (sclass == REGISTER + && (isvolatile(ty) || isstruct(ty) || isarray(ty))) { + warning("register declaration ignored for `%t %s'\n", + ty, id); + sclass = AUTO; + } + q = lookup(id, identifiers); + if (q && q->scope >= level + || q && q->scope == PARAM && level == LOCAL) + if (sclass == EXTERN && q->sclass == EXTERN + && eqtype(q->type, ty, 1)) + ty = compose(ty, q->type); + else + error("redeclaration of `%s' previously declared at %w\n", q->name, &q->src); + + assert(level >= LOCAL); + p = install(id, &identifiers, level, sclass == STATIC || sclass == EXTERN ? PERM : FUNC); + p->type = ty; + p->sclass = sclass; + p->src = *pos; + switch (sclass) { + case EXTERN: q = lookup(id, globals); + if (q == NULL || q->sclass == TYPEDEF || q->sclass == ENUM) { + q = lookup(id, externals); + if (q == NULL) { + q = install(p->name, &externals, GLOBAL, PERM); + q->type = p->type; + q->sclass = EXTERN; + q->src = src; + (*IR->defsymbol)(q); + } + } + if (!eqtype(p->type, q->type, 1)) + warning("declaration of `%s' does not match previous declaration at %w\n", q->name, &q->src); + + p->u.alias = q; break; + case STATIC: (*IR->defsymbol)(p); + initglobal(p, 0); + if (!p->defined) + if (p->type->size > 0) { + defglobal(p, BSS); + (*IR->space)(p->type->size); + } else + error("undefined size for `%t %s'\n", + p->type, p->name); + p->defined = 1; break; + case REGISTER: registers = append(p, registers); + regcount++; + p->defined = 1; + break; + case AUTO: autos = append(p, autos); + p->defined = 1; break; + default: assert(0); + } + if (t == '=') { + Tree e; + if (sclass == EXTERN) + error("illegal initialization of `extern %s'\n", id); + t = gettok(); + definept(NULL); + if (isscalar(p->type) + || isstruct(p->type) && t != '{') { + if (t == '{') { + t = gettok(); + e = expr1(0); + expect('}'); + } else + e = expr1(0); + } else { + Symbol t1; + Type ty = p->type, ty1 = ty; + while (isarray(ty1)) + ty1 = ty1->type; + if (!isconst(ty) && (!isarray(ty) || !isconst(ty1))) + ty = qual(CONST, ty); + t1 = genident(STATIC, ty, GLOBAL); + initglobal(t1, 1); + if (isarray(p->type) && p->type->size == 0 + && t1->type->size > 0) + p->type = array(p->type->type, + t1->type->size/t1->type->type->size, 0); + e = idtree(t1); + } + walk(root(asgn(p, e)), 0, 0); + p->ref = 1; + } + if (!isfunc(p->type) && p->defined && p->type->size <= 0) + error("undefined size for `%t %s'\n", p->type, id); + return p; +} +void finalize(void) { + foreach(externals, GLOBAL, doextern, NULL); + foreach(identifiers, GLOBAL, doglobal, NULL); + foreach(identifiers, GLOBAL, checkref, NULL); + foreach(constants, CONSTANTS, doconst, NULL); +} +static void doextern(Symbol p, void *cl) { + (*IR->import)(p); +} +static void doglobal(Symbol p, void *cl) { + if (!p->defined && (p->sclass == EXTERN + || isfunc(p->type) && p->sclass == AUTO)) + (*IR->import)(p); + else if (!p->defined && !isfunc(p->type) + && (p->sclass == AUTO || p->sclass == STATIC)) { + if (isarray(p->type) + && p->type->size == 0 && p->type->type->size > 0) + p->type = array(p->type->type, 1, 0); + if (p->type->size > 0) { + defglobal(p, BSS); + (*IR->space)(p->type->size); + if (glevel > 0 && IR->stabsym) + (*IR->stabsym)(p); + } else + error("undefined size for `%t %s'\n", + p->type, p->name); + p->defined = 1; + } + if (Pflag + && !isfunc(p->type) + && !p->generated && p->sclass != EXTERN) + printdecl(p, p->type); +} +void doconst(Symbol p, void *cl) { + if (p->u.c.loc) { + assert(p->u.c.loc->u.seg == 0); + defglobal(p->u.c.loc, LIT); + if (isarray(p->type) && p->type->type == widechar) { + unsigned int *s = p->u.c.v.p; + int n = p->type->size/widechar->size; + while (n-- > 0) { + Value v; + v.u = *s++; + (*IR->defconst)(widechar->op, widechar->size, v); + } + } else if (isarray(p->type)) + (*IR->defstring)(p->type->size, p->u.c.v.p); + else + (*IR->defconst)(p->type->op, p->type->size, p->u.c.v); + p->u.c.loc = NULL; + } +} +void checklab(Symbol p, void *cl) { + if (!p->defined) + error("undefined label `%s'\n", p->name); + p->defined = 1; +} + +Type enumdcl(void) { + char *tag; + Type ty; + Symbol p; + Coordinate pos; + + t = gettok(); + pos = src; + if (t == ID) { + tag = token; + t = gettok(); + } else + tag = ""; + if (t == '{') { + static char follow[] = { IF, 0 }; + int n = 0; + long k = -1; + List idlist = 0; + ty = newstruct(ENUM, tag); + t = gettok(); + if (t != ID) + error("expecting an enumerator identifier\n"); + while (t == ID) { + char *id = token; + Coordinate s; + if (tsym && tsym->scope == level) + error("redeclaration of `%s' previously declared at %w\n", + token, &tsym->src); + s = src; + t = gettok(); + if (t == '=') { + t = gettok(); + k = intexpr(0, 0); + } else { + if (k == inttype->u.sym->u.limits.max.i) + error("overflow in value for enumeration constant `%s'\n", id); + k++; + } + p = install(id, &identifiers, level, level < LOCAL ? PERM : FUNC); + p->src = s; + p->type = ty; + p->sclass = ENUM; + p->u.value = k; + idlist = append(p, idlist); + n++; + if (Aflag >= 2 && n == 128) + warning("more than 127 enumeration constants in `%t'\n", ty); + if (t != ',') + break; + t = gettok(); + if (Aflag >= 2 && t == '}') + warning("non-ANSI trailing comma in enumerator list\n"); + } + test('}', follow); + ty->type = inttype; + ty->size = ty->type->size; + ty->align = ty->type->align; + ty->u.sym->u.idlist = ltov(&idlist, PERM); + ty->u.sym->defined = 1; + } else if ((p = lookup(tag, types)) != NULL && p->type->op == ENUM) { + ty = p->type; + if (t == ';') + error("empty declaration\n"); + } else { + error("unknown enumeration `%s'\n", tag); + ty = newstruct(ENUM, tag); + ty->type = inttype; + } + if (*tag && xref) + use(p, pos); + return ty; +} + +Type typename(void) { + Type ty = specifier(NULL); + + if (t == '*' || t == '(' || t == '[') { + ty = dclr(ty, NULL, NULL, 1); + if (Aflag >= 1 && !hasproto(ty)) + warning("missing prototype\n"); + } + return ty; +} + diff --git a/lcc/src/enode.c b/lcc/src/enode.c index a81c632..0503cc3 100755 --- a/lcc/src/enode.c +++ b/lcc/src/enode.c @@ -1,543 +1,543 @@ -#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);
-}
+#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); +} diff --git a/lcc/src/error.c b/lcc/src/error.c index 56d164c..2187c10 100755 --- a/lcc/src/error.c +++ b/lcc/src/error.c @@ -1,137 +1,137 @@ -#include "c.h"
-
-
-static void printtoken(void);
-int errcnt = 0;
-int errlimit = 20;
-char kind[] = {
-#define xx(a,b,c,d,e,f,g) f,
-#define yy(a,b,c,d,e,f,g) f,
-#include "token.h"
-};
-int wflag; /* != 0 to suppress warning messages */
-
-void test(int tok, char set[]) {
- if (t == tok)
- t = gettok();
- else {
- expect(tok);
- skipto(tok, set);
- if (t == tok)
- t = gettok();
- }
-}
-void expect(int tok) {
- if (t == tok)
- t = gettok();
- else {
- error("syntax error; found");
- printtoken();
- fprint(stderr, " expecting `%k'\n", tok);
- }
-}
-void error(const char *fmt, ...) {
- va_list ap;
-
- if (errcnt++ >= errlimit) {
- errcnt = -1;
- error("too many errors\n");
- exit(1);
- }
- va_start(ap, fmt);
- if (firstfile != file && firstfile && *firstfile)
- fprint(stderr, "%s: ", firstfile);
- fprint(stderr, "%w: ", &src);
- vfprint(stderr, NULL, fmt, ap);
- va_end(ap);
-}
-
-void skipto(int tok, char set[]) {
- int n;
- char *s;
-
- assert(set);
- for (n = 0; t != EOI && t != tok; t = gettok()) {
- for (s = set; *s && kind[t] != *s; s++)
- ;
- if (kind[t] == *s)
- break;
- if (n++ == 0)
- error("skipping");
- if (n <= 8)
- printtoken();
- else if (n == 9)
- fprint(stderr, " ...");
- }
- if (n > 8) {
- fprint(stderr, " up to");
- printtoken();
- }
- if (n > 0)
- fprint(stderr, "\n");
-}
-/* fatal - issue fatal error message and exit */
-int fatal(const char *name, const char *fmt, int n) {
- print("\n");
- errcnt = -1;
- error("compiler error in %s--", name);
- fprint(stderr, fmt, n);
- exit(EXIT_FAILURE);
- return 0;
-}
-
-/* printtoken - print current token preceeded by a space */
-static void printtoken(void) {
- switch (t) {
- case ID: fprint(stderr, " `%s'", token); break;
- case ICON:
- fprint(stderr, " `%s'", vtoa(tsym->type, tsym->u.c.v));
- break;
- case SCON: {
- int i, n;
- if (ischar(tsym->type->type)) {
- char *s = tsym->u.c.v.p;
- n = tsym->type->size;
- fprint(stderr, " \"");
- for (i = 0; i < 20 && i < n && *s; s++, i++)
- if (*s < ' ' || *s >= 0177)
- fprint(stderr, "\\%o", *s);
- else
- fprint(stderr, "%c", *s);
- } else { /* wchar_t string */
- unsigned int *s = tsym->u.c.v.p;
- assert(tsym->type->type->size == widechar->size);
- n = tsym->type->size/widechar->size;
- fprint(stderr, " L\"");
- for (i = 0; i < 20 && i < n && *s; s++, i++)
- if (*s < ' ' || *s >= 0177)
- fprint(stderr, "\\x%x", *s);
- else
- fprint(stderr, "%c", *s);
- }
- if (i < n)
- fprint(stderr, " ...");
- else
- fprint(stderr, "\"");
- break;
- }
- case FCON:
- fprint(stderr, " `%S'", token, (char*)cp - token);
- break;
- case '`': case '\'': fprint(stderr, " \"%k\"", t); break;
- default: fprint(stderr, " `%k'", t);
- }
-}
-
-/* warning - issue warning error message */
-void warning(const char *fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
- if (wflag == 0) {
- errcnt--;
- error("warning: ");
- vfprint(stderr, NULL, fmt, ap);
- }
- va_end(ap);
-}
+#include "c.h" + + +static void printtoken(void); +int errcnt = 0; +int errlimit = 20; +char kind[] = { +#define xx(a,b,c,d,e,f,g) f, +#define yy(a,b,c,d,e,f,g) f, +#include "token.h" +}; +int wflag; /* != 0 to suppress warning messages */ + +void test(int tok, char set[]) { + if (t == tok) + t = gettok(); + else { + expect(tok); + skipto(tok, set); + if (t == tok) + t = gettok(); + } +} +void expect(int tok) { + if (t == tok) + t = gettok(); + else { + error("syntax error; found"); + printtoken(); + fprint(stderr, " expecting `%k'\n", tok); + } +} +void error(const char *fmt, ...) { + va_list ap; + + if (errcnt++ >= errlimit) { + errcnt = -1; + error("too many errors\n"); + exit(1); + } + va_start(ap, fmt); + if (firstfile != file && firstfile && *firstfile) + fprint(stderr, "%s: ", firstfile); + fprint(stderr, "%w: ", &src); + vfprint(stderr, NULL, fmt, ap); + va_end(ap); +} + +void skipto(int tok, char set[]) { + int n; + char *s; + + assert(set); + for (n = 0; t != EOI && t != tok; t = gettok()) { + for (s = set; *s && kind[t] != *s; s++) + ; + if (kind[t] == *s) + break; + if (n++ == 0) + error("skipping"); + if (n <= 8) + printtoken(); + else if (n == 9) + fprint(stderr, " ..."); + } + if (n > 8) { + fprint(stderr, " up to"); + printtoken(); + } + if (n > 0) + fprint(stderr, "\n"); +} +/* fatal - issue fatal error message and exit */ +int fatal(const char *name, const char *fmt, int n) { + print("\n"); + errcnt = -1; + error("compiler error in %s--", name); + fprint(stderr, fmt, n); + exit(EXIT_FAILURE); + return 0; +} + +/* printtoken - print current token preceeded by a space */ +static void printtoken(void) { + switch (t) { + case ID: fprint(stderr, " `%s'", token); break; + case ICON: + fprint(stderr, " `%s'", vtoa(tsym->type, tsym->u.c.v)); + break; + case SCON: { + int i, n; + if (ischar(tsym->type->type)) { + char *s = tsym->u.c.v.p; + n = tsym->type->size; + fprint(stderr, " \""); + for (i = 0; i < 20 && i < n && *s; s++, i++) + if (*s < ' ' || *s >= 0177) + fprint(stderr, "\\%o", *s); + else + fprint(stderr, "%c", *s); + } else { /* wchar_t string */ + unsigned int *s = tsym->u.c.v.p; + assert(tsym->type->type->size == widechar->size); + n = tsym->type->size/widechar->size; + fprint(stderr, " L\""); + for (i = 0; i < 20 && i < n && *s; s++, i++) + if (*s < ' ' || *s >= 0177) + fprint(stderr, "\\x%x", *s); + else + fprint(stderr, "%c", *s); + } + if (i < n) + fprint(stderr, " ..."); + else + fprint(stderr, "\""); + break; + } + case FCON: + fprint(stderr, " `%S'", token, (char*)cp - token); + break; + case '`': case '\'': fprint(stderr, " \"%k\"", t); break; + default: fprint(stderr, " `%k'", t); + } +} + +/* warning - issue warning error message */ +void warning(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + if (wflag == 0) { + errcnt--; + error("warning: "); + vfprint(stderr, NULL, fmt, ap); + } + va_end(ap); +} diff --git a/lcc/src/event.c b/lcc/src/event.c index 12f409f..4549e3f 100755 --- a/lcc/src/event.c +++ b/lcc/src/event.c @@ -1,28 +1,28 @@ -#include "c.h"
-
-
-struct entry {
- Apply func;
- void *cl;
-};
-
-Events events;
-void attach(Apply func, void *cl, List *list) {
- struct entry *p;
-
- NEW(p, PERM);
- p->func = func;
- p->cl = cl;
- *list = append(p, *list);
-}
-void apply(List event, void *arg1, void *arg2) {
- if (event) {
- List lp = event;
- do {
- struct entry *p = lp->x;
- (*p->func)(p->cl, arg1, arg2);
- lp = lp->link;
- } while (lp != event);
- }
-}
-
+#include "c.h" + + +struct entry { + Apply func; + void *cl; +}; + +Events events; +void attach(Apply func, void *cl, List *list) { + struct entry *p; + + NEW(p, PERM); + p->func = func; + p->cl = cl; + *list = append(p, *list); +} +void apply(List event, void *arg1, void *arg2) { + if (event) { + List lp = event; + do { + struct entry *p = lp->x; + (*p->func)(p->cl, arg1, arg2); + lp = lp->link; + } while (lp != event); + } +} + diff --git a/lcc/src/expr.c b/lcc/src/expr.c index 30b79cc..79f8f40 100755 --- a/lcc/src/expr.c +++ b/lcc/src/expr.c @@ -1,709 +1,709 @@ -#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);
-}
+#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); +} diff --git a/lcc/src/gen.c b/lcc/src/gen.c index ab8506a..7202c45 100755 --- a/lcc/src/gen.c +++ b/lcc/src/gen.c @@ -1,830 +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;
-}
-
+#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; +} + diff --git a/lcc/src/init.c b/lcc/src/init.c index 67bcc69..27bbc51 100755 --- a/lcc/src/init.c +++ b/lcc/src/init.c @@ -1,318 +1,318 @@ -#include "c.h"
-
-
-static int curseg; /* current segment */
-
-/* defpointer - initialize a pointer to p or to 0 if p==0 */
-void defpointer(Symbol p) {
- if (p) {
- (*IR->defaddress)(p);
- p->ref++;
- } else {
- static Value v;
- (*IR->defconst)(P, voidptype->size, v);
- }
-}
-
-/* genconst - generate/check constant expression e; return size */
-static int genconst(Tree e, int def) {
- for (;;)
- switch (generic(e->op)) {
- case ADDRG:
- if (def)
- (*IR->defaddress)(e->u.sym);
- return e->type->size;
- case CNST:
- if (e->op == CNST+P && isarray(e->type)) {
- e = cvtconst(e);
- continue;
- }
- if (def)
- (*IR->defconst)(e->type->op, e->type->size, e->u.v);
- return e->type->size;
- case RIGHT:
- assert(e->kids[0] || e->kids[1]);
- if (e->kids[1] && e->kids[0])
- error("initializer must be constant\n");
- e = e->kids[1] ? e->kids[1] : e->kids[0];
- continue;
- case CVP:
- if (isarith(e->type))
- error("cast from `%t' to `%t' is illegal in constant expressions\n",
- e->kids[0]->type, e->type);
- /* fall thru */
- case CVI: case CVU: case CVF:
- e = e->kids[0];
- continue;
- default:
- error("initializer must be constant\n");
- if (def)
- genconst(consttree(0, inttype), def);
- return inttype->size;
- }
-}
-
-/* initvalue - evaluate a constant expression for a value of integer type ty */
-static Tree initvalue(Type ty) {
- Type aty;
- Tree e;
-
- needconst++;
- e = expr1(0);
- if ((aty = assign(ty, e)) != NULL)
- e = cast(e, aty);
- else {
- error("invalid initialization type; found `%t' expected `%t'\n",
- e->type, ty);
- e = retype(consttree(0, inttype), ty);
- }
- needconst--;
- if (generic(e->op) != CNST) {
- error("initializer must be constant\n");
- e = retype(consttree(0, inttype), ty);
- }
- return e;
-}
-
-/* initarray - initialize array of ty of <= len bytes; if len == 0, go to } */
-static int initarray(int len, Type ty, int lev) {
- int n = 0;
-
- do {
- initializer(ty, lev);
- n += ty->size;
- if (len > 0 && n >= len || t != ',')
- break;
- t = gettok();
- } while (t != '}');
- return n;
-}
-
-/* initchar - initialize array of <= len ty characters; if len == 0, go to } */
-static int initchar(int len, Type ty) {
- int n = 0;
- char buf[16], *s = buf;
-
- do {
- *s++ = initvalue(ty)->u.v.i;
- if (++n%inttype->size == 0) {
- (*IR->defstring)(inttype->size, buf);
- s = buf;
- }
- if (len > 0 && n >= len || t != ',')
- break;
- t = gettok();
- } while (t != '}');
- if (s > buf)
- (*IR->defstring)(s - buf, buf);
- return n;
-}
-
-/* initend - finish off an initialization at level lev; accepts trailing comma */
-static void initend(int lev, char follow[]) {
- if (lev == 0 && t == ',')
- t = gettok();
- test('}', follow);
-}
-
-/* initfields - initialize <= an unsigned's worth of bit fields in fields p to q */
-static int initfields(Field p, Field q) {
- unsigned int bits = 0;
- int i, n = 0;
-
- do {
- i = initvalue(inttype)->u.v.i;
- if (fieldsize(p) < 8*p->type->size) {
- if (p->type == inttype &&
- (i < -(int)(fieldmask(p)>>1)-1 || i > (int)(fieldmask(p)>>1))
- || p->type == unsignedtype && (i&~fieldmask(p)) != 0)
- warning("initializer exceeds bit-field width\n");
- i &= fieldmask(p);
- }
- bits |= i<<fieldright(p);
- if (IR->little_endian) {
- if (fieldsize(p) + fieldright(p) > n)
- n = fieldsize(p) + fieldright(p);
- } else {
- if (fieldsize(p) + fieldleft(p) > n)
- n = fieldsize(p) + fieldleft(p);
- }
- if (p->link == q)
- break;
- p = p->link;
- } while (t == ',' && (t = gettok()) != 0);
- n = (n + 7)/8;
- for (i = 0; i < n; i++) {
- Value v;
- if (IR->little_endian) {
- v.u = (unsigned char)bits;
- bits >>= 8;
- } else { /* a big endian */
- v.u = (unsigned char)(bits>>(8*(unsignedtype->size - 1)));
- bits <<= 8;
- }
- (*IR->defconst)(U, unsignedchar->size, v);
- }
- return n;
-}
-
-/* initstruct - initialize a struct ty of <= len bytes; if len == 0, go to } */
-static int initstruct(int len, Type ty, int lev) {
- int a, n = 0;
- Field p = ty->u.sym->u.s.flist;
-
- do {
- if (p->offset > n) {
- (*IR->space)(p->offset - n);
- n += p->offset - n;
- }
- if (p->lsb) {
- Field q = p;
- while (q->link && q->link->offset == p->offset)
- q = q->link;
- n += initfields(p, q->link);
- p = q;
- } else {
- initializer(p->type, lev);
- n += p->type->size;
- }
- if (p->link) {
- p = p->link;
- a = p->type->align;
- } else
- a = ty->align;
- if (a && n%a) {
- (*IR->space)(a - n%a);
- n = roundup(n, a);
- }
- if (len > 0 && n >= len || t != ',')
- break;
- t = gettok();
- } while (t != '}');
- return n;
-}
-
-/* initializer - constexpr | { constexpr ( , constexpr )* [ , ] } */
-Type initializer(Type ty, int lev) {
- int n = 0;
- Tree e;
- Type aty = NULL;
- static char follow[] = { IF, CHAR, STATIC, 0 };
-
- ty = unqual(ty);
- if (isscalar(ty)) {
- needconst++;
- if (t == '{') {
- t = gettok();
- e = expr1(0);
- initend(lev, follow);
- } else
- e = expr1(0);
- e = pointer(e);
- if ((aty = assign(ty, e)) != NULL)
- e = cast(e, aty);
- else
- error("invalid initialization type; found `%t' expected `%t'\n",
- e->type, ty);
- n = genconst(e, 1);
- deallocate(STMT);
- needconst--;
- }
- if ((isunion(ty) || isstruct(ty)) && ty->size == 0) {
- static char follow[] = { CHAR, STATIC, 0 };
- error("cannot initialize undefined `%t'\n", ty);
- skipto(';', follow);
- return ty;
- } else if (isunion(ty)) {
- if (t == '{') {
- t = gettok();
- n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
- initend(lev, follow);
- } else {
- if (lev == 0)
- error("missing { in initialization of `%t'\n", ty);
- n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
- }
- } else if (isstruct(ty)) {
- if (t == '{') {
- t = gettok();
- n = initstruct(0, ty, lev + 1);
- test('}', follow);
- } else if (lev > 0)
- n = initstruct(ty->size, ty, lev + 1);
- else {
- error("missing { in initialization of `%t'\n", ty);
- n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
- }
- }
- if (isarray(ty))
- aty = unqual(ty->type);
- if (isarray(ty) && ischar(aty)) {
- if (t == SCON) {
- if (ty->size > 0 && ty->size == tsym->type->size - 1)
- tsym->type = array(chartype, ty->size, 0);
- n = tsym->type->size;
- (*IR->defstring)(tsym->type->size, tsym->u.c.v.p);
- t = gettok();
- } else if (t == '{') {
- t = gettok();
- if (t == SCON) {
- ty = initializer(ty, lev + 1);
- initend(lev, follow);
- return ty;
- }
- n = initchar(0, aty);
- test('}', follow);
- } else if (lev > 0 && ty->size > 0)
- n = initchar(ty->size, aty);
- else { /* eg, char c[] = 0; */
- error("missing { in initialization of `%t'\n", ty);
- n = initchar(1, aty);
- }
- } else if (isarray(ty)) {
- if (t == SCON && aty == widechar) {
- int i;
- unsigned int *s = tsym->u.c.v.p;
- if (ty->size > 0 && ty->size == tsym->type->size - widechar->size)
- tsym->type = array(widechar, ty->size/widechar->size, 0);
- n = tsym->type->size;
- for (i = 0; i < n; i += widechar->size) {
- Value v;
- v.u = *s++;
- (*IR->defconst)(widechar->op, widechar->size, v);
- }
- t = gettok();
- } else if (t == '{') {
- t = gettok();
- if (t == SCON && aty == widechar) {
- ty = initializer(ty, lev + 1);
- initend(lev, follow);
- return ty;
- }
- n = initarray(0, aty, lev + 1);
- test('}', follow);
- } else if (lev > 0 && ty->size > 0)
- n = initarray(ty->size, aty, lev + 1);
- else {
- error("missing { in initialization of `%t'\n", ty);
- n = initarray(aty->size, aty, lev + 1);
- }
- }
- if (ty->size) {
- if (n > ty->size)
- error("too many initializers\n");
- else if (n < ty->size)
- (*IR->space)(ty->size - n);
- } else if (isarray(ty) && ty->type->size > 0)
- ty = array(ty->type, n/ty->type->size, 0);
- else
- ty->size = n;
- return ty;
-}
-
-/* swtoseg - switch to segment seg, if necessary */
-void swtoseg(int seg) {
- if (curseg != seg)
- (*IR->segment)(seg);
- curseg = seg;
-}
+#include "c.h" + + +static int curseg; /* current segment */ + +/* defpointer - initialize a pointer to p or to 0 if p==0 */ +void defpointer(Symbol p) { + if (p) { + (*IR->defaddress)(p); + p->ref++; + } else { + static Value v; + (*IR->defconst)(P, voidptype->size, v); + } +} + +/* genconst - generate/check constant expression e; return size */ +static int genconst(Tree e, int def) { + for (;;) + switch (generic(e->op)) { + case ADDRG: + if (def) + (*IR->defaddress)(e->u.sym); + return e->type->size; + case CNST: + if (e->op == CNST+P && isarray(e->type)) { + e = cvtconst(e); + continue; + } + if (def) + (*IR->defconst)(e->type->op, e->type->size, e->u.v); + return e->type->size; + case RIGHT: + assert(e->kids[0] || e->kids[1]); + if (e->kids[1] && e->kids[0]) + error("initializer must be constant\n"); + e = e->kids[1] ? e->kids[1] : e->kids[0]; + continue; + case CVP: + if (isarith(e->type)) + error("cast from `%t' to `%t' is illegal in constant expressions\n", + e->kids[0]->type, e->type); + /* fall thru */ + case CVI: case CVU: case CVF: + e = e->kids[0]; + continue; + default: + error("initializer must be constant\n"); + if (def) + genconst(consttree(0, inttype), def); + return inttype->size; + } +} + +/* initvalue - evaluate a constant expression for a value of integer type ty */ +static Tree initvalue(Type ty) { + Type aty; + Tree e; + + needconst++; + e = expr1(0); + if ((aty = assign(ty, e)) != NULL) + e = cast(e, aty); + else { + error("invalid initialization type; found `%t' expected `%t'\n", + e->type, ty); + e = retype(consttree(0, inttype), ty); + } + needconst--; + if (generic(e->op) != CNST) { + error("initializer must be constant\n"); + e = retype(consttree(0, inttype), ty); + } + return e; +} + +/* initarray - initialize array of ty of <= len bytes; if len == 0, go to } */ +static int initarray(int len, Type ty, int lev) { + int n = 0; + + do { + initializer(ty, lev); + n += ty->size; + if (len > 0 && n >= len || t != ',') + break; + t = gettok(); + } while (t != '}'); + return n; +} + +/* initchar - initialize array of <= len ty characters; if len == 0, go to } */ +static int initchar(int len, Type ty) { + int n = 0; + char buf[16], *s = buf; + + do { + *s++ = initvalue(ty)->u.v.i; + if (++n%inttype->size == 0) { + (*IR->defstring)(inttype->size, buf); + s = buf; + } + if (len > 0 && n >= len || t != ',') + break; + t = gettok(); + } while (t != '}'); + if (s > buf) + (*IR->defstring)(s - buf, buf); + return n; +} + +/* initend - finish off an initialization at level lev; accepts trailing comma */ +static void initend(int lev, char follow[]) { + if (lev == 0 && t == ',') + t = gettok(); + test('}', follow); +} + +/* initfields - initialize <= an unsigned's worth of bit fields in fields p to q */ +static int initfields(Field p, Field q) { + unsigned int bits = 0; + int i, n = 0; + + do { + i = initvalue(inttype)->u.v.i; + if (fieldsize(p) < 8*p->type->size) { + if (p->type == inttype && + (i < -(int)(fieldmask(p)>>1)-1 || i > (int)(fieldmask(p)>>1)) + || p->type == unsignedtype && (i&~fieldmask(p)) != 0) + warning("initializer exceeds bit-field width\n"); + i &= fieldmask(p); + } + bits |= i<<fieldright(p); + if (IR->little_endian) { + if (fieldsize(p) + fieldright(p) > n) + n = fieldsize(p) + fieldright(p); + } else { + if (fieldsize(p) + fieldleft(p) > n) + n = fieldsize(p) + fieldleft(p); + } + if (p->link == q) + break; + p = p->link; + } while (t == ',' && (t = gettok()) != 0); + n = (n + 7)/8; + for (i = 0; i < n; i++) { + Value v; + if (IR->little_endian) { + v.u = (unsigned char)bits; + bits >>= 8; + } else { /* a big endian */ + v.u = (unsigned char)(bits>>(8*(unsignedtype->size - 1))); + bits <<= 8; + } + (*IR->defconst)(U, unsignedchar->size, v); + } + return n; +} + +/* initstruct - initialize a struct ty of <= len bytes; if len == 0, go to } */ +static int initstruct(int len, Type ty, int lev) { + int a, n = 0; + Field p = ty->u.sym->u.s.flist; + + do { + if (p->offset > n) { + (*IR->space)(p->offset - n); + n += p->offset - n; + } + if (p->lsb) { + Field q = p; + while (q->link && q->link->offset == p->offset) + q = q->link; + n += initfields(p, q->link); + p = q; + } else { + initializer(p->type, lev); + n += p->type->size; + } + if (p->link) { + p = p->link; + a = p->type->align; + } else + a = ty->align; + if (a && n%a) { + (*IR->space)(a - n%a); + n = roundup(n, a); + } + if (len > 0 && n >= len || t != ',') + break; + t = gettok(); + } while (t != '}'); + return n; +} + +/* initializer - constexpr | { constexpr ( , constexpr )* [ , ] } */ +Type initializer(Type ty, int lev) { + int n = 0; + Tree e; + Type aty = NULL; + static char follow[] = { IF, CHAR, STATIC, 0 }; + + ty = unqual(ty); + if (isscalar(ty)) { + needconst++; + if (t == '{') { + t = gettok(); + e = expr1(0); + initend(lev, follow); + } else + e = expr1(0); + e = pointer(e); + if ((aty = assign(ty, e)) != NULL) + e = cast(e, aty); + else + error("invalid initialization type; found `%t' expected `%t'\n", + e->type, ty); + n = genconst(e, 1); + deallocate(STMT); + needconst--; + } + if ((isunion(ty) || isstruct(ty)) && ty->size == 0) { + static char follow[] = { CHAR, STATIC, 0 }; + error("cannot initialize undefined `%t'\n", ty); + skipto(';', follow); + return ty; + } else if (isunion(ty)) { + if (t == '{') { + t = gettok(); + n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1); + initend(lev, follow); + } else { + if (lev == 0) + error("missing { in initialization of `%t'\n", ty); + n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1); + } + } else if (isstruct(ty)) { + if (t == '{') { + t = gettok(); + n = initstruct(0, ty, lev + 1); + test('}', follow); + } else if (lev > 0) + n = initstruct(ty->size, ty, lev + 1); + else { + error("missing { in initialization of `%t'\n", ty); + n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1); + } + } + if (isarray(ty)) + aty = unqual(ty->type); + if (isarray(ty) && ischar(aty)) { + if (t == SCON) { + if (ty->size > 0 && ty->size == tsym->type->size - 1) + tsym->type = array(chartype, ty->size, 0); + n = tsym->type->size; + (*IR->defstring)(tsym->type->size, tsym->u.c.v.p); + t = gettok(); + } else if (t == '{') { + t = gettok(); + if (t == SCON) { + ty = initializer(ty, lev + 1); + initend(lev, follow); + return ty; + } + n = initchar(0, aty); + test('}', follow); + } else if (lev > 0 && ty->size > 0) + n = initchar(ty->size, aty); + else { /* eg, char c[] = 0; */ + error("missing { in initialization of `%t'\n", ty); + n = initchar(1, aty); + } + } else if (isarray(ty)) { + if (t == SCON && aty == widechar) { + int i; + unsigned int *s = tsym->u.c.v.p; + if (ty->size > 0 && ty->size == tsym->type->size - widechar->size) + tsym->type = array(widechar, ty->size/widechar->size, 0); + n = tsym->type->size; + for (i = 0; i < n; i += widechar->size) { + Value v; + v.u = *s++; + (*IR->defconst)(widechar->op, widechar->size, v); + } + t = gettok(); + } else if (t == '{') { + t = gettok(); + if (t == SCON && aty == widechar) { + ty = initializer(ty, lev + 1); + initend(lev, follow); + return ty; + } + n = initarray(0, aty, lev + 1); + test('}', follow); + } else if (lev > 0 && ty->size > 0) + n = initarray(ty->size, aty, lev + 1); + else { + error("missing { in initialization of `%t'\n", ty); + n = initarray(aty->size, aty, lev + 1); + } + } + if (ty->size) { + if (n > ty->size) + error("too many initializers\n"); + else if (n < ty->size) + (*IR->space)(ty->size - n); + } else if (isarray(ty) && ty->type->size > 0) + ty = array(ty->type, n/ty->type->size, 0); + else + ty->size = n; + return ty; +} + +/* swtoseg - switch to segment seg, if necessary */ +void swtoseg(int seg) { + if (curseg != seg) + (*IR->segment)(seg); + curseg = seg; +} diff --git a/lcc/src/inits.c b/lcc/src/inits.c index d4d49df..449724a 100755 --- a/lcc/src/inits.c +++ b/lcc/src/inits.c @@ -1,8 +1,8 @@ -void init(int argc, char *argv[]) {
- {extern void input_init(int, char *[]); input_init(argc, argv);}
- {extern void main_init(int, char *[]); main_init(argc, argv);}
- {extern void prof_init(int, char *[]); prof_init(argc, argv);}
- {extern void trace_init(int, char *[]); trace_init(argc, argv);}
- {extern void type_init(int, char *[]); type_init(argc, argv);}
- {extern void x86linux_init(int, char *[]); x86linux_init(argc, argv);}
-}
+void init(int argc, char *argv[]) { + {extern void input_init(int, char *[]); input_init(argc, argv);} + {extern void main_init(int, char *[]); main_init(argc, argv);} + {extern void prof_init(int, char *[]); prof_init(argc, argv);} + {extern void trace_init(int, char *[]); trace_init(argc, argv);} + {extern void type_init(int, char *[]); type_init(argc, argv);} + {extern void x86linux_init(int, char *[]); x86linux_init(argc, argv);} +} diff --git a/lcc/src/input.c b/lcc/src/input.c index 2f34420..4f0afc8 100755 --- a/lcc/src/input.c +++ b/lcc/src/input.c @@ -1,134 +1,134 @@ -#include "c.h"
-
-
-static void pragma(void);
-static void resynch(void);
-
-static int bsize;
-static unsigned char buffer[MAXLINE+1 + BUFSIZE+1];
-unsigned char *cp; /* current input character */
-char *file; /* current input file name */
-char *firstfile; /* first input file */
-unsigned char *limit; /* points to last character + 1 */
-char *line; /* current line */
-int lineno; /* line number of current line */
-
-void nextline(void) {
- do {
- if (cp >= limit) {
- fillbuf();
- if (cp >= limit)
- cp = limit;
- if (cp == limit)
- return;
- } else {
- lineno++;
- for (line = (char *)cp; *cp==' ' || *cp=='\t'; cp++)
- ;
- if (*cp == '#') {
- resynch();
- nextline();
- }
- }
- } while (*cp == '\n' && cp == limit);
-}
-void fillbuf(void) {
- if (bsize == 0)
- return;
- if (cp >= limit)
- cp = &buffer[MAXLINE+1];
- else
- {
- int n = limit - cp;
- unsigned char *s = &buffer[MAXLINE+1] - n;
- assert(s >= buffer);
- line = (char *)s - ((char *)cp - line);
- while (cp < limit)
- *s++ = *cp++;
- cp = &buffer[MAXLINE+1] - n;
- }
- if (feof(stdin))
- bsize = 0;
- else
- bsize = fread(&buffer[MAXLINE+1], 1, BUFSIZE, stdin);
- if (bsize < 0) {
- error("read error\n");
- exit(EXIT_FAILURE);
- }
- limit = &buffer[MAXLINE+1+bsize];
- *limit = '\n';
-}
-void input_init(int argc, char *argv[]) {
- static int inited;
-
- if (inited)
- return;
- inited = 1;
- main_init(argc, argv);
- limit = cp = &buffer[MAXLINE+1];
- bsize = -1;
- lineno = 0;
- file = NULL;
- fillbuf();
- if (cp >= limit)
- cp = limit;
- nextline();
-}
-
-/* pragma - handle #pragma ref id... */
-static void pragma(void) {
- if ((t = gettok()) == ID && strcmp(token, "ref") == 0)
- for (;;) {
- while (*cp == ' ' || *cp == '\t')
- cp++;
- if (*cp == '\n' || *cp == 0)
- break;
- if ((t = gettok()) == ID && tsym) {
- tsym->ref++;
- use(tsym, src);
- }
- }
-}
-
-/* resynch - set line number/file name in # n [ "file" ] and #pragma ... */
-static void resynch(void) {
- for (cp++; *cp == ' ' || *cp == '\t'; )
- cp++;
- if (limit - cp < MAXLINE)
- fillbuf();
- if (strncmp((char *)cp, "pragma", 6) == 0) {
- cp += 6;
- pragma();
- } else if (*cp >= '0' && *cp <= '9') {
- line: for (lineno = 0; *cp >= '0' && *cp <= '9'; )
- lineno = 10*lineno + *cp++ - '0';
- lineno--;
- while (*cp == ' ' || *cp == '\t')
- cp++;
- if (*cp == '"') {
- file = (char *)++cp;
- while (*cp && *cp != '"' && *cp != '\n')
- cp++;
- file = stringn(file, (char *)cp - file);
- if (*cp == '\n')
- warning("missing \" in preprocessor line\n");
- if (firstfile == 0)
- firstfile = file;
- }
- } else if (strncmp((char *)cp, "line", 4) == 0) {
- for (cp += 4; *cp == ' ' || *cp == '\t'; )
- cp++;
- if (*cp >= '0' && *cp <= '9')
- goto line;
- if (Aflag >= 2)
- warning("unrecognized control line\n");
- } else if (Aflag >= 2 && *cp != '\n')
- warning("unrecognized control line\n");
- while (*cp)
- if (*cp++ == '\n')
- if (cp == limit + 1)
- nextline();
- else
- break;
-}
-
+#include "c.h" + + +static void pragma(void); +static void resynch(void); + +static int bsize; +static unsigned char buffer[MAXLINE+1 + BUFSIZE+1]; +unsigned char *cp; /* current input character */ +char *file; /* current input file name */ +char *firstfile; /* first input file */ +unsigned char *limit; /* points to last character + 1 */ +char *line; /* current line */ +int lineno; /* line number of current line */ + +void nextline(void) { + do { + if (cp >= limit) { + fillbuf(); + if (cp >= limit) + cp = limit; + if (cp == limit) + return; + } else { + lineno++; + for (line = (char *)cp; *cp==' ' || *cp=='\t'; cp++) + ; + if (*cp == '#') { + resynch(); + nextline(); + } + } + } while (*cp == '\n' && cp == limit); +} +void fillbuf(void) { + if (bsize == 0) + return; + if (cp >= limit) + cp = &buffer[MAXLINE+1]; + else + { + int n = limit - cp; + unsigned char *s = &buffer[MAXLINE+1] - n; + assert(s >= buffer); + line = (char *)s - ((char *)cp - line); + while (cp < limit) + *s++ = *cp++; + cp = &buffer[MAXLINE+1] - n; + } + if (feof(stdin)) + bsize = 0; + else + bsize = fread(&buffer[MAXLINE+1], 1, BUFSIZE, stdin); + if (bsize < 0) { + error("read error\n"); + exit(EXIT_FAILURE); + } + limit = &buffer[MAXLINE+1+bsize]; + *limit = '\n'; +} +void input_init(int argc, char *argv[]) { + static int inited; + + if (inited) + return; + inited = 1; + main_init(argc, argv); + limit = cp = &buffer[MAXLINE+1]; + bsize = -1; + lineno = 0; + file = NULL; + fillbuf(); + if (cp >= limit) + cp = limit; + nextline(); +} + +/* pragma - handle #pragma ref id... */ +static void pragma(void) { + if ((t = gettok()) == ID && strcmp(token, "ref") == 0) + for (;;) { + while (*cp == ' ' || *cp == '\t') + cp++; + if (*cp == '\n' || *cp == 0) + break; + if ((t = gettok()) == ID && tsym) { + tsym->ref++; + use(tsym, src); + } + } +} + +/* resynch - set line number/file name in # n [ "file" ] and #pragma ... */ +static void resynch(void) { + for (cp++; *cp == ' ' || *cp == '\t'; ) + cp++; + if (limit - cp < MAXLINE) + fillbuf(); + if (strncmp((char *)cp, "pragma", 6) == 0) { + cp += 6; + pragma(); + } else if (*cp >= '0' && *cp <= '9') { + line: for (lineno = 0; *cp >= '0' && *cp <= '9'; ) + lineno = 10*lineno + *cp++ - '0'; + lineno--; + while (*cp == ' ' || *cp == '\t') + cp++; + if (*cp == '"') { + file = (char *)++cp; + while (*cp && *cp != '"' && *cp != '\n') + cp++; + file = stringn(file, (char *)cp - file); + if (*cp == '\n') + warning("missing \" in preprocessor line\n"); + if (firstfile == 0) + firstfile = file; + } + } else if (strncmp((char *)cp, "line", 4) == 0) { + for (cp += 4; *cp == ' ' || *cp == '\t'; ) + cp++; + if (*cp >= '0' && *cp <= '9') + goto line; + if (Aflag >= 2) + warning("unrecognized control line\n"); + } else if (Aflag >= 2 && *cp != '\n') + warning("unrecognized control line\n"); + while (*cp) + if (*cp++ == '\n') + if (cp == limit + 1) + nextline(); + else + break; +} + diff --git a/lcc/src/lex.c b/lcc/src/lex.c index 09c50f3..6643172 100755 --- a/lcc/src/lex.c +++ b/lcc/src/lex.c @@ -1,922 +1,922 @@ -#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];
-}
+#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]; +} diff --git a/lcc/src/list.c b/lcc/src/list.c index dbd63ed..29e660a 100755 --- a/lcc/src/list.c +++ b/lcc/src/list.c @@ -1,56 +1,56 @@ -#include "c.h"
-
-
-static List freenodes; /* free list nodes */
-
-/* append - append x to list, return new list */
-List append(void *x, List list) {
- List new;
-
- if ((new = freenodes) != NULL)
- freenodes = freenodes->link;
- else
- NEW(new, PERM);
- if (list) {
- new->link = list->link;
- list->link = new;
- } else
- new->link = new;
- new->x = x;
- return new;
-}
-
-/* length - # elements in list */
-int length(List list) {
- int n = 0;
-
- if (list) {
- List lp = list;
- do
- n++;
- while ((lp = lp->link) != list);
- }
- return n;
-}
-
-/* ltov - convert list to an NULL-terminated vector allocated in arena */
-void *ltov(List *list, unsigned arena) {
- int i = 0;
- void **array = newarray(length(*list) + 1, sizeof array[0], arena);
-
- if (*list) {
- List lp = *list;
- do {
- lp = lp->link;
- array[i++] = lp->x;
- } while (lp != *list);
-#ifndef PURIFY
- lp = (*list)->link;
- (*list)->link = freenodes;
- freenodes = lp;
-#endif
- }
- *list = NULL;
- array[i] = NULL;
- return array;
-}
+#include "c.h" + + +static List freenodes; /* free list nodes */ + +/* append - append x to list, return new list */ +List append(void *x, List list) { + List new; + + if ((new = freenodes) != NULL) + freenodes = freenodes->link; + else + NEW(new, PERM); + if (list) { + new->link = list->link; + list->link = new; + } else + new->link = new; + new->x = x; + return new; +} + +/* length - # elements in list */ +int length(List list) { + int n = 0; + + if (list) { + List lp = list; + do + n++; + while ((lp = lp->link) != list); + } + return n; +} + +/* ltov - convert list to an NULL-terminated vector allocated in arena */ +void *ltov(List *list, unsigned arena) { + int i = 0; + void **array = newarray(length(*list) + 1, sizeof array[0], arena); + + if (*list) { + List lp = *list; + do { + lp = lp->link; + array[i++] = lp->x; + } while (lp != *list); +#ifndef PURIFY + lp = (*list)->link; + (*list)->link = freenodes; + freenodes = lp; +#endif + } + *list = NULL; + array[i] = NULL; + return array; +} diff --git a/lcc/src/main.c b/lcc/src/main.c index 1367fa0..63b85f2 100755 --- a/lcc/src/main.c +++ b/lcc/src/main.c @@ -1,225 +1,225 @@ -#include "c.h"
-
-static char rcsid[] = "main.c - faked rcsid";
-
-static void typestab(Symbol, void *);
-
-static void stabline(Coordinate *);
-static void stabend(Coordinate *, Symbol, Coordinate **, Symbol *, Symbol *);
-Interface *IR = NULL;
-
-int Aflag; /* >= 0 if -A specified */
-int Pflag; /* != 0 if -P specified */
-int glevel; /* == [0-9] if -g[0-9] specified */
-int xref; /* != 0 for cross-reference data */
-Symbol YYnull; /* _YYnull symbol if -n or -nvalidate specified */
-Symbol YYcheck; /* _YYcheck symbol if -nvalidate,check specified */
-
-static char *comment;
-static Interface stabIR;
-static char *currentfile; /* current file name */
-static int currentline; /* current line number */
-static FILE *srcfp; /* stream for current file, if non-NULL */
-static int srcpos; /* position of srcfp, if srcfp is non-NULL */
-int main(int argc, char *argv[]) {
- int i, j;
- for (i = argc - 1; i > 0; i--)
- if (strncmp(argv[i], "-target=", 8) == 0)
- break;
- if (i > 0) {
- char *s = strchr(argv[i], '\\');
- if (s != NULL)
- *s = '/';
- for (j = 0; bindings[j].name && bindings[j].ir; j++)
- if (strcmp(&argv[i][8], bindings[j].name) == 0) {
- IR = bindings[j].ir;
- break;
- }
- if (s != NULL)
- *s = '\\';
- }
- if (!IR) {
- fprint(stderr, "%s: unknown target", argv[0]);
- if (i > 0)
- fprint(stderr, " `%s'", &argv[i][8]);
- fprint(stderr, "; must specify one of\n");
- for (i = 0; bindings[i].name; i++)
- fprint(stderr, "\t-target=%s\n", bindings[i].name);
- exit(EXIT_FAILURE);
- }
- init(argc, argv);
- t = gettok();
- (*IR->progbeg)(argc, argv);
- if (glevel && IR->stabinit)
- (*IR->stabinit)(firstfile, argc, argv);
- program();
- if (events.end)
- apply(events.end, NULL, NULL);
- memset(&events, 0, sizeof events);
- if (glevel || xref) {
- Symbol symroot = NULL;
- Coordinate src;
- foreach(types, GLOBAL, typestab, &symroot);
- foreach(identifiers, GLOBAL, typestab, &symroot);
- src.file = firstfile;
- src.x = 0;
- src.y = lineno;
- if ((glevel > 2 || xref) && IR->stabend)
- (*IR->stabend)(&src, symroot,
- ltov(&loci, PERM),
- ltov(&symbols, PERM), NULL);
- else if (IR->stabend)
- (*IR->stabend)(&src, NULL, NULL, NULL, NULL);
- }
- finalize();
- (*IR->progend)();
- deallocate(PERM);
- return errcnt > 0;
-}
-/* main_init - process program arguments */
-void main_init(int argc, char *argv[]) {
- char *infile = NULL, *outfile = NULL;
- int i;
- static int inited;
-
- if (inited)
- return;
- inited = 1;
- type_init(argc, argv);
- for (i = 1; i < argc; i++)
- if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "-g2") == 0)
- glevel = 2;
- else if (strncmp(argv[i], "-g", 2) == 0) { /* -gn[,x] */
- char *p = strchr(argv[i], ',');
- glevel = atoi(argv[i]+2);
- if (p) {
- comment = p + 1;
- if (glevel == 0)
- glevel = 1;
- if (stabIR.stabline == NULL) {
- stabIR.stabline = IR->stabline;
- stabIR.stabend = IR->stabend;
- IR->stabline = stabline;
- IR->stabend = stabend;
- }
- }
- } else if (strcmp(argv[i], "-x") == 0)
- xref++;
- else if (strcmp(argv[i], "-A") == 0) {
- ++Aflag;
- } else if (strcmp(argv[i], "-P") == 0)
- Pflag++;
- else if (strcmp(argv[i], "-w") == 0)
- wflag++;
- else if (strcmp(argv[i], "-n") == 0) {
- if (!YYnull) {
- YYnull = install(string("_YYnull"), &globals, GLOBAL, PERM);
- YYnull->type = func(voidptype, NULL, 1);
- YYnull->sclass = EXTERN;
- (*IR->defsymbol)(YYnull);
- }
- } else if (strncmp(argv[i], "-n", 2) == 0) { /* -nvalid[,check] */
- char *p = strchr(argv[i], ',');
- if (p) {
- YYcheck = install(string(p+1), &globals, GLOBAL, PERM);
- YYcheck->type = func(voidptype, NULL, 1);
- YYcheck->sclass = EXTERN;
- (*IR->defsymbol)(YYcheck);
- p = stringn(argv[i]+2, p - (argv[i]+2));
- } else
- p = string(argv[i]+2);
- YYnull = install(p, &globals, GLOBAL, PERM);
- YYnull->type = func(voidptype, NULL, 1);
- YYnull->sclass = EXTERN;
- (*IR->defsymbol)(YYnull);
- } else if (strcmp(argv[i], "-v") == 0)
- fprint(stderr, "%s %s\n", argv[0], rcsid);
- else if (strncmp(argv[i], "-s", 2) == 0)
- density = strtod(&argv[i][2], NULL);
- else if (strncmp(argv[i], "-errout=", 8) == 0) {
- FILE *f = fopen(argv[i]+8, "w");
- if (f == NULL) {
- fprint(stderr, "%s: can't write errors to `%s'\n", argv[0], argv[i]+8);
- exit(EXIT_FAILURE);
- }
- fclose(f);
- f = freopen(argv[i]+8, "w", stderr);
- assert(f);
- } else if (strncmp(argv[i], "-e", 2) == 0) {
- int x;
- if ((x = strtol(&argv[i][2], NULL, 0)) > 0)
- errlimit = x;
- } else if (strncmp(argv[i], "-little_endian=", 15) == 0)
- IR->little_endian = argv[i][15] - '0';
- else if (strncmp(argv[i], "-mulops_calls=", 18) == 0)
- IR->mulops_calls = argv[i][18] - '0';
- else if (strncmp(argv[i], "-wants_callb=", 13) == 0)
- IR->wants_callb = argv[i][13] - '0';
- else if (strncmp(argv[i], "-wants_argb=", 12) == 0)
- IR->wants_argb = argv[i][12] - '0';
- else if (strncmp(argv[i], "-left_to_right=", 15) == 0)
- IR->left_to_right = argv[i][15] - '0';
- else if (strncmp(argv[i], "-wants_dag=", 11) == 0)
- IR->wants_dag = argv[i][11] - '0';
- else if (*argv[i] != '-' || strcmp(argv[i], "-") == 0) {
- if (infile == NULL)
- infile = argv[i];
- else if (outfile == NULL)
- outfile = argv[i];
- }
-
- if (infile != NULL && strcmp(infile, "-") != 0
- && freopen(infile, "r", stdin) == NULL) {
- fprint(stderr, "%s: can't read `%s'\n", argv[0], infile);
- exit(EXIT_FAILURE);
- }
- if (outfile != NULL && strcmp(outfile, "-") != 0
- && freopen(outfile, "w", stdout) == NULL) {
- fprint(stderr, "%s: can't write `%s'\n", argv[0], outfile);
- exit(EXIT_FAILURE);
- }
-}
-/* typestab - emit stab entries for p */
-static void typestab(Symbol p, void *cl) {
- if (*(Symbol *)cl == 0 && p->sclass && p->sclass != TYPEDEF)
- *(Symbol *)cl = p;
- if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype)
- (*IR->stabtype)(p);
-}
-
-/* stabline - emit source code for source coordinate *cp */
-static void stabline(Coordinate *cp) {
- if (cp->file && cp->file != currentfile) {
- if (srcfp)
- fclose(srcfp);
- currentfile = cp->file;
- srcfp = fopen(currentfile, "r");
- srcpos = 0;
- currentline = 0;
- }
- if (currentline != cp->y && srcfp) {
- char buf[512];
- if (srcpos > cp->y) {
- rewind(srcfp);
- srcpos = 0;
- }
- for ( ; srcpos < cp->y; srcpos++)
- if (fgets(buf, sizeof buf, srcfp) == NULL) {
- fclose(srcfp);
- srcfp = NULL;
- break;
- }
- if (srcfp && srcpos == cp->y)
- print("%s%s", comment, buf);
- }
- currentline = cp->y;
- if (stabIR.stabline)
- (*stabIR.stabline)(cp);
-}
-
-static void stabend(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {
- if (stabIR.stabend)
- (*stabIR.stabend)(cp, p, cpp, sp, stab);
- if (srcfp)
- fclose(srcfp);
-}
+#include "c.h" + +static char rcsid[] = "main.c - faked rcsid"; + +static void typestab(Symbol, void *); + +static void stabline(Coordinate *); +static void stabend(Coordinate *, Symbol, Coordinate **, Symbol *, Symbol *); +Interface *IR = NULL; + +int Aflag; /* >= 0 if -A specified */ +int Pflag; /* != 0 if -P specified */ +int glevel; /* == [0-9] if -g[0-9] specified */ +int xref; /* != 0 for cross-reference data */ +Symbol YYnull; /* _YYnull symbol if -n or -nvalidate specified */ +Symbol YYcheck; /* _YYcheck symbol if -nvalidate,check specified */ + +static char *comment; +static Interface stabIR; +static char *currentfile; /* current file name */ +static int currentline; /* current line number */ +static FILE *srcfp; /* stream for current file, if non-NULL */ +static int srcpos; /* position of srcfp, if srcfp is non-NULL */ +int main(int argc, char *argv[]) { + int i, j; + for (i = argc - 1; i > 0; i--) + if (strncmp(argv[i], "-target=", 8) == 0) + break; + if (i > 0) { + char *s = strchr(argv[i], '\\'); + if (s != NULL) + *s = '/'; + for (j = 0; bindings[j].name && bindings[j].ir; j++) + if (strcmp(&argv[i][8], bindings[j].name) == 0) { + IR = bindings[j].ir; + break; + } + if (s != NULL) + *s = '\\'; + } + if (!IR) { + fprint(stderr, "%s: unknown target", argv[0]); + if (i > 0) + fprint(stderr, " `%s'", &argv[i][8]); + fprint(stderr, "; must specify one of\n"); + for (i = 0; bindings[i].name; i++) + fprint(stderr, "\t-target=%s\n", bindings[i].name); + exit(EXIT_FAILURE); + } + init(argc, argv); + t = gettok(); + (*IR->progbeg)(argc, argv); + if (glevel && IR->stabinit) + (*IR->stabinit)(firstfile, argc, argv); + program(); + if (events.end) + apply(events.end, NULL, NULL); + memset(&events, 0, sizeof events); + if (glevel || xref) { + Symbol symroot = NULL; + Coordinate src; + foreach(types, GLOBAL, typestab, &symroot); + foreach(identifiers, GLOBAL, typestab, &symroot); + src.file = firstfile; + src.x = 0; + src.y = lineno; + if ((glevel > 2 || xref) && IR->stabend) + (*IR->stabend)(&src, symroot, + ltov(&loci, PERM), + ltov(&symbols, PERM), NULL); + else if (IR->stabend) + (*IR->stabend)(&src, NULL, NULL, NULL, NULL); + } + finalize(); + (*IR->progend)(); + deallocate(PERM); + return errcnt > 0; +} +/* main_init - process program arguments */ +void main_init(int argc, char *argv[]) { + char *infile = NULL, *outfile = NULL; + int i; + static int inited; + + if (inited) + return; + inited = 1; + type_init(argc, argv); + for (i = 1; i < argc; i++) + if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "-g2") == 0) + glevel = 2; + else if (strncmp(argv[i], "-g", 2) == 0) { /* -gn[,x] */ + char *p = strchr(argv[i], ','); + glevel = atoi(argv[i]+2); + if (p) { + comment = p + 1; + if (glevel == 0) + glevel = 1; + if (stabIR.stabline == NULL) { + stabIR.stabline = IR->stabline; + stabIR.stabend = IR->stabend; + IR->stabline = stabline; + IR->stabend = stabend; + } + } + } else if (strcmp(argv[i], "-x") == 0) + xref++; + else if (strcmp(argv[i], "-A") == 0) { + ++Aflag; + } else if (strcmp(argv[i], "-P") == 0) + Pflag++; + else if (strcmp(argv[i], "-w") == 0) + wflag++; + else if (strcmp(argv[i], "-n") == 0) { + if (!YYnull) { + YYnull = install(string("_YYnull"), &globals, GLOBAL, PERM); + YYnull->type = func(voidptype, NULL, 1); + YYnull->sclass = EXTERN; + (*IR->defsymbol)(YYnull); + } + } else if (strncmp(argv[i], "-n", 2) == 0) { /* -nvalid[,check] */ + char *p = strchr(argv[i], ','); + if (p) { + YYcheck = install(string(p+1), &globals, GLOBAL, PERM); + YYcheck->type = func(voidptype, NULL, 1); + YYcheck->sclass = EXTERN; + (*IR->defsymbol)(YYcheck); + p = stringn(argv[i]+2, p - (argv[i]+2)); + } else + p = string(argv[i]+2); + YYnull = install(p, &globals, GLOBAL, PERM); + YYnull->type = func(voidptype, NULL, 1); + YYnull->sclass = EXTERN; + (*IR->defsymbol)(YYnull); + } else if (strcmp(argv[i], "-v") == 0) + fprint(stderr, "%s %s\n", argv[0], rcsid); + else if (strncmp(argv[i], "-s", 2) == 0) + density = strtod(&argv[i][2], NULL); + else if (strncmp(argv[i], "-errout=", 8) == 0) { + FILE *f = fopen(argv[i]+8, "w"); + if (f == NULL) { + fprint(stderr, "%s: can't write errors to `%s'\n", argv[0], argv[i]+8); + exit(EXIT_FAILURE); + } + fclose(f); + f = freopen(argv[i]+8, "w", stderr); + assert(f); + } else if (strncmp(argv[i], "-e", 2) == 0) { + int x; + if ((x = strtol(&argv[i][2], NULL, 0)) > 0) + errlimit = x; + } else if (strncmp(argv[i], "-little_endian=", 15) == 0) + IR->little_endian = argv[i][15] - '0'; + else if (strncmp(argv[i], "-mulops_calls=", 18) == 0) + IR->mulops_calls = argv[i][18] - '0'; + else if (strncmp(argv[i], "-wants_callb=", 13) == 0) + IR->wants_callb = argv[i][13] - '0'; + else if (strncmp(argv[i], "-wants_argb=", 12) == 0) + IR->wants_argb = argv[i][12] - '0'; + else if (strncmp(argv[i], "-left_to_right=", 15) == 0) + IR->left_to_right = argv[i][15] - '0'; + else if (strncmp(argv[i], "-wants_dag=", 11) == 0) + IR->wants_dag = argv[i][11] - '0'; + else if (*argv[i] != '-' || strcmp(argv[i], "-") == 0) { + if (infile == NULL) + infile = argv[i]; + else if (outfile == NULL) + outfile = argv[i]; + } + + if (infile != NULL && strcmp(infile, "-") != 0 + && freopen(infile, "r", stdin) == NULL) { + fprint(stderr, "%s: can't read `%s'\n", argv[0], infile); + exit(EXIT_FAILURE); + } + if (outfile != NULL && strcmp(outfile, "-") != 0 + && freopen(outfile, "w", stdout) == NULL) { + fprint(stderr, "%s: can't write `%s'\n", argv[0], outfile); + exit(EXIT_FAILURE); + } +} +/* typestab - emit stab entries for p */ +static void typestab(Symbol p, void *cl) { + if (*(Symbol *)cl == 0 && p->sclass && p->sclass != TYPEDEF) + *(Symbol *)cl = p; + if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype) + (*IR->stabtype)(p); +} + +/* stabline - emit source code for source coordinate *cp */ +static void stabline(Coordinate *cp) { + if (cp->file && cp->file != currentfile) { + if (srcfp) + fclose(srcfp); + currentfile = cp->file; + srcfp = fopen(currentfile, "r"); + srcpos = 0; + currentline = 0; + } + if (currentline != cp->y && srcfp) { + char buf[512]; + if (srcpos > cp->y) { + rewind(srcfp); + srcpos = 0; + } + for ( ; srcpos < cp->y; srcpos++) + if (fgets(buf, sizeof buf, srcfp) == NULL) { + fclose(srcfp); + srcfp = NULL; + break; + } + if (srcfp && srcpos == cp->y) + print("%s%s", comment, buf); + } + currentline = cp->y; + if (stabIR.stabline) + (*stabIR.stabline)(cp); +} + +static void stabend(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) { + if (stabIR.stabend) + (*stabIR.stabend)(cp, p, cpp, sp, stab); + if (srcfp) + fclose(srcfp); +} diff --git a/lcc/src/mips.md b/lcc/src/mips.md index 7e643fb..41f6d8c 100755 --- a/lcc/src/mips.md +++ b/lcc/src/mips.md @@ -1,1120 +1,1120 @@ -%{
-#define INTTMP 0x0100ff00
-#define INTVAR 0x40ff0000
-#define FLTTMP 0x000f0ff0
-#define FLTVAR 0xfff00000
-
-#define INTRET 0x00000004
-#define FLTRET 0x00000003
-
-#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))
-
-#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);
-static int bitcount (unsigned);
-static Symbol argreg (int, int, int, int, int);
-
-static Symbol ireg[32], freg2[32], d6;
-static Symbol iregw, freg2w;
-static int tmpregs[] = {3, 9, 10};
-static Symbol blkreg;
-
-static int gnum = 8;
-static int pic;
-
-static int cseg;
-%}
-%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: con "%0"
-acon: ADDRGP4 "%a"
-addr: ADDI4(reg,acon) "%1($%0)"
-addr: ADDU4(reg,acon) "%1($%0)"
-addr: ADDP4(reg,acon) "%1($%0)"
-addr: acon "%0"
-addr: reg "($%0)"
-addr: ADDRFP4 "%a+%F($sp)"
-addr: ADDRLP4 "%a+%F($sp)"
-reg: addr "la $%c,%0\n" 1
-reg: CNSTI1 "# reg\n" range(a, 0, 0)
-reg: CNSTI2 "# reg\n" range(a, 0, 0)
-reg: CNSTI4 "# reg\n" range(a, 0, 0)
-reg: CNSTU1 "# reg\n" range(a, 0, 0)
-reg: CNSTU2 "# reg\n" range(a, 0, 0)
-reg: CNSTU4 "# reg\n" range(a, 0, 0)
-reg: CNSTP4 "# reg\n" range(a, 0, 0)
-stmt: ASGNI1(addr,reg) "sb $%1,%0\n" 1
-stmt: ASGNU1(addr,reg) "sb $%1,%0\n" 1
-stmt: ASGNI2(addr,reg) "sh $%1,%0\n" 1
-stmt: ASGNU2(addr,reg) "sh $%1,%0\n" 1
-stmt: ASGNI4(addr,reg) "sw $%1,%0\n" 1
-stmt: ASGNU4(addr,reg) "sw $%1,%0\n" 1
-stmt: ASGNP4(addr,reg) "sw $%1,%0\n" 1
-reg: INDIRI1(addr) "lb $%c,%0\n" 1
-reg: INDIRU1(addr) "lbu $%c,%0\n" 1
-reg: INDIRI2(addr) "lh $%c,%0\n" 1
-reg: INDIRU2(addr) "lhu $%c,%0\n" 1
-reg: INDIRI4(addr) "lw $%c,%0\n" 1
-reg: INDIRU4(addr) "lw $%c,%0\n" 1
-reg: INDIRP4(addr) "lw $%c,%0\n" 1
-
-reg: CVII4(INDIRI1(addr)) "lb $%c,%0\n" 1
-reg: CVII4(INDIRI2(addr)) "lh $%c,%0\n" 1
-reg: CVUU4(INDIRU1(addr)) "lbu $%c,%0\n" 1
-reg: CVUU4(INDIRU2(addr)) "lhu $%c,%0\n" 1
-reg: CVUI4(INDIRU1(addr)) "lbu $%c,%0\n" 1
-reg: CVUI4(INDIRU2(addr)) "lhu $%c,%0\n" 1
-reg: INDIRF4(addr) "l.s $f%c,%0\n" 1
-reg: INDIRF8(addr) "l.d $f%c,%0\n" 1
-stmt: ASGNF4(addr,reg) "s.s $f%1,%0\n" 1
-stmt: ASGNF8(addr,reg) "s.d $f%1,%0\n" 1
-reg: DIVI4(reg,reg) "div $%c,$%0,$%1\n" 1
-reg: DIVU4(reg,reg) "divu $%c,$%0,$%1\n" 1
-reg: MODI4(reg,reg) "rem $%c,$%0,$%1\n" 1
-reg: MODU4(reg,reg) "remu $%c,$%0,$%1\n" 1
-reg: MULI4(reg,reg) "mul $%c,$%0,$%1\n" 1
-reg: MULU4(reg,reg) "mul $%c,$%0,$%1\n" 1
-rc: con "%0"
-rc: reg "$%0"
-
-reg: ADDI4(reg,rc) "addu $%c,$%0,%1\n" 1
-reg: ADDP4(reg,rc) "addu $%c,$%0,%1\n" 1
-reg: ADDU4(reg,rc) "addu $%c,$%0,%1\n" 1
-reg: BANDI4(reg,rc) "and $%c,$%0,%1\n" 1
-reg: BORI4(reg,rc) "or $%c,$%0,%1\n" 1
-reg: BXORI4(reg,rc) "xor $%c,$%0,%1\n" 1
-reg: BANDU4(reg,rc) "and $%c,$%0,%1\n" 1
-reg: BORU4(reg,rc) "or $%c,$%0,%1\n" 1
-reg: BXORU4(reg,rc) "xor $%c,$%0,%1\n" 1
-reg: SUBI4(reg,rc) "subu $%c,$%0,%1\n" 1
-reg: SUBP4(reg,rc) "subu $%c,$%0,%1\n" 1
-reg: SUBU4(reg,rc) "subu $%c,$%0,%1\n" 1
-rc5: CNSTI4 "%a" range(a,0,31)
-rc5: reg "$%0"
-
-reg: LSHI4(reg,rc5) "sll $%c,$%0,%1\n" 1
-reg: LSHU4(reg,rc5) "sll $%c,$%0,%1\n" 1
-reg: RSHI4(reg,rc5) "sra $%c,$%0,%1\n" 1
-reg: RSHU4(reg,rc5) "srl $%c,$%0,%1\n" 1
-reg: BCOMI4(reg) "not $%c,$%0\n" 1
-reg: BCOMU4(reg) "not $%c,$%0\n" 1
-reg: NEGI4(reg) "negu $%c,$%0\n" 1
-reg: LOADI1(reg) "move $%c,$%0\n" move(a)
-reg: LOADU1(reg) "move $%c,$%0\n" move(a)
-reg: LOADI2(reg) "move $%c,$%0\n" move(a)
-reg: LOADU2(reg) "move $%c,$%0\n" move(a)
-reg: LOADI4(reg) "move $%c,$%0\n" move(a)
-reg: LOADP4(reg) "move $%c,$%0\n" move(a)
-reg: LOADU4(reg) "move $%c,$%0\n" move(a)
-reg: ADDF4(reg,reg) "add.s $f%c,$f%0,$f%1\n" 1
-reg: ADDF8(reg,reg) "add.d $f%c,$f%0,$f%1\n" 1
-reg: DIVF4(reg,reg) "div.s $f%c,$f%0,$f%1\n" 1
-reg: DIVF8(reg,reg) "div.d $f%c,$f%0,$f%1\n" 1
-reg: MULF4(reg,reg) "mul.s $f%c,$f%0,$f%1\n" 1
-reg: MULF8(reg,reg) "mul.d $f%c,$f%0,$f%1\n" 1
-reg: SUBF4(reg,reg) "sub.s $f%c,$f%0,$f%1\n" 1
-reg: SUBF8(reg,reg) "sub.d $f%c,$f%0,$f%1\n" 1
-reg: LOADF4(reg) "mov.s $f%c,$f%0\n" move(a)
-reg: LOADF8(reg) "mov.d $f%c,$f%0\n" move(a)
-reg: NEGF4(reg) "neg.s $f%c,$f%0\n" 1
-reg: NEGF8(reg) "neg.d $f%c,$f%0\n" 1
-reg: CVII4(reg) "sll $%c,$%0,8*(4-%a); sra $%c,$%c,8*(4-%a)\n" 2
-reg: CVUI4(reg) "and $%c,$%0,(1<<(8*%a))-1\n" 1
-reg: CVUU4(reg) "and $%c,$%0,(1<<(8*%a))-1\n" 1
-reg: CVFF4(reg) "cvt.s.d $f%c,$f%0\n" 1
-reg: CVFF8(reg) "cvt.d.s $f%c,$f%0\n" 1
-reg: CVIF4(reg) "mtc1 $%0,$f%c; cvt.s.w $f%c,$f%c\n" 2
-reg: CVIF8(reg) "mtc1 $%0,$f%c; cvt.d.w $f%c,$f%c\n" 2
-reg: CVFI4(reg) "trunc.w.s $f2,$f%0,$%c; mfc1 $%c,$f2\n" (a->syms[0]->u.c.v.i==4?2:LBURG_MAX)
-reg: CVFI4(reg) "trunc.w.d $f2,$f%0,$%c; mfc1 $%c,$f2\n" (a->syms[0]->u.c.v.i==8?2:LBURG_MAX)
-stmt: LABELV "%a:\n"
-stmt: JUMPV(acon) "b %0\n" 1
-stmt: JUMPV(reg) ".cpadd $%0\nj $%0\n" !pic
-stmt: JUMPV(reg) "j $%0\n" pic
-stmt: EQI4(reg,reg) "beq $%0,$%1,%a\n" 1
-stmt: EQU4(reg,reg) "beq $%0,$%1,%a\n" 1
-stmt: GEI4(reg,reg) "bge $%0,$%1,%a\n" 1
-stmt: GEU4(reg,reg) "bgeu $%0,$%1,%a\n" 1
-stmt: GTI4(reg,reg) "bgt $%0,$%1,%a\n" 1
-stmt: GTU4(reg,reg) "bgtu $%0,$%1,%a\n" 1
-stmt: LEI4(reg,reg) "ble $%0,$%1,%a\n" 1
-stmt: LEU4(reg,reg) "bleu $%0,$%1,%a\n" 1
-stmt: LTI4(reg,reg) "blt $%0,$%1,%a\n" 1
-stmt: LTU4(reg,reg) "bltu $%0,$%1,%a\n" 1
-stmt: NEI4(reg,reg) "bne $%0,$%1,%a\n" 1
-stmt: NEU4(reg,reg) "bne $%0,$%1,%a\n" 1
-stmt: EQF4(reg,reg) "c.eq.s $f%0,$f%1; bc1t %a\n" 2
-stmt: EQF8(reg,reg) "c.eq.d $f%0,$f%1; bc1t %a\n" 2
-stmt: LEF4(reg,reg) "c.le.s $f%0,$f%1; bc1t %a\n" 2
-stmt: LEF8(reg,reg) "c.le.d $f%0,$f%1; bc1t %a\n" 2
-stmt: LTF4(reg,reg) "c.lt.s $f%0,$f%1; bc1t %a\n" 2
-stmt: LTF8(reg,reg) "c.lt.d $f%0,$f%1; bc1t %a\n" 2
-stmt: GEF4(reg,reg) "c.lt.s $f%0,$f%1; bc1f %a\n" 2
-stmt: GEF8(reg,reg) "c.lt.d $f%0,$f%1; bc1f %a\n" 2
-stmt: GTF4(reg,reg) "c.le.s $f%0,$f%1; bc1f %a\n" 2
-stmt: GTF8(reg,reg) "c.le.d $f%0,$f%1; bc1f %a\n" 2
-stmt: NEF4(reg,reg) "c.eq.s $f%0,$f%1; bc1f %a\n" 2
-stmt: NEF8(reg,reg) "c.eq.d $f%0,$f%1; bc1f %a\n" 2
-ar: ADDRGP4 "%a"
-
-reg: CALLF4(ar) "jal %0\n" 1
-reg: CALLF8(ar) "jal %0\n" 1
-reg: CALLI4(ar) "jal %0\n" 1
-reg: CALLP4(ar) "jal %0\n" 1
-reg: CALLU4(ar) "jal %0\n" 1
-stmt: CALLV(ar) "jal %0\n" 1
-ar: reg "$%0"
-ar: CNSTP4 "%a" range(a, 0, 0x0fffffff)
-stmt: RETF4(reg) "# ret\n" 1
-stmt: RETF8(reg) "# ret\n" 1
-stmt: RETI4(reg) "# ret\n" 1
-stmt: RETU4(reg) "# ret\n" 1
-stmt: RETP4(reg) "# ret\n" 1
-stmt: RETV(reg) "# ret\n" 1
-stmt: ARGF4(reg) "# arg\n" 1
-stmt: ARGF8(reg) "# arg\n" 1
-stmt: ARGI4(reg) "# arg\n" 1
-stmt: ARGP4(reg) "# arg\n" 1
-stmt: ARGU4(reg) "# arg\n" 1
-
-stmt: ARGB(INDIRB(reg)) "# argb %0\n" 1
-stmt: ASGNB(reg,INDIRB(reg)) "# asgnb %0 %1\n" 1
-%%
-static void progend(void){}
-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;
- }
- print(".set reorder\n");
- pic = !IR->little_endian;
- parseflags(argc, argv);
- for (i = 0; i < argc; i++)
- if (strncmp(argv[i], "-G", 2) == 0)
- gnum = atoi(argv[i] + 2);
- else if (strcmp(argv[i], "-pic=1") == 0
- || strcmp(argv[i], "-pic=0") == 0)
- pic = argv[i][5]-'0';
- for (i = 0; i < 31; i += 2)
- freg2[i] = mkreg("%d", i, 3, FREG);
- for (i = 0; i < 32; i++)
- ireg[i] = mkreg("%d", i, 1, IREG);
- ireg[29]->x.name = "sp";
- d6 = mkreg("6", 6, 3, IREG);
- freg2w = mkwildcard(freg2);
- iregw = mkwildcard(ireg);
- tmask[IREG] = INTTMP; tmask[FREG] = FLTTMP;
- vmask[IREG] = INTVAR; vmask[FREG] = FLTVAR;
- blkreg = mkreg("8", 8, 7, IREG);
-}
-static Symbol rmap(int opk) {
- switch (optype(opk)) {
- case I: case U: case P: case B:
- return iregw;
- case F:
- return freg2w;
- default:
- return 0;
- }
-}
-static void target(Node p) {
- assert(p);
- switch (specific(p->op)) {
- case CNST+I: case CNST+U: case CNST+P:
- if (range(p, 0, 0) == 0) {
- setreg(p, ireg[0]);
- p->x.registered = 1;
- }
- break;
- case CALL+V:
- rtarget(p, 0, ireg[25]);
- break;
- case CALL+F:
- rtarget(p, 0, ireg[25]);
- setreg(p, freg2[0]);
- break;
- case CALL+I: case CALL+P: case CALL+U:
- rtarget(p, 0, ireg[25]);
- setreg(p, ireg[2]);
- break;
- case RET+F:
- rtarget(p, 0, freg2[0]);
- break;
- case RET+I: case RET+U: case RET+P:
- rtarget(p, 0, ireg[2]);
- break;
- case ARG+F: case ARG+I: case ARG+P: case ARG+U: {
- static int ty0;
- int ty = optype(p->op);
- Symbol q;
-
- q = argreg(p->x.argno, p->syms[2]->u.c.v.i, ty, opsize(p->op), ty0);
- if (p->x.argno == 0)
- ty0 = ty;
- if (q &&
- !(ty == F && q->x.regnode->set == IREG))
- rtarget(p, 0, q);
- break;
- }
- case ASGN+B: rtarget(p->kids[1], 0, blkreg); break;
- case ARG+B: rtarget(p->kids[0], 0, blkreg); break;
- }
-}
-static void clobber(Node p) {
- assert(p);
- switch (specific(p->op)) {
- case CALL+F:
- spill(INTTMP | INTRET, IREG, p);
- spill(FLTTMP, FREG, p);
- break;
- case CALL+I: case CALL+P: case CALL+U:
- spill(INTTMP, IREG, p);
- spill(FLTTMP | FLTRET, FREG, p);
- break;
- case CALL+V:
- spill(INTTMP | INTRET, IREG, p);
- spill(FLTTMP | FLTRET, FREG, p);
- break;
- }
-}
-static void emit2(Node p) {
- int dst, n, src, sz, ty;
- static int ty0;
- Symbol q;
-
- switch (specific(p->op)) {
- case ARG+F: case ARG+I: case ARG+P: case ARG+U:
- ty = optype(p->op);
- sz = opsize(p->op);
- if (p->x.argno == 0)
- ty0 = ty;
- q = argreg(p->x.argno, p->syms[2]->u.c.v.i, ty, sz, ty0);
- src = getregnum(p->x.kids[0]);
- if (q == NULL && ty == F && sz == 4)
- print("s.s $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i);
- else if (q == NULL && ty == F)
- print("s.d $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i);
- else if (q == NULL)
- print("sw $%d,%d($sp)\n", src, p->syms[2]->u.c.v.i);
- else if (ty == F && sz == 4 && q->x.regnode->set == IREG)
- print("mfc1 $%d,$f%d\n", q->x.regnode->number, src);
- else if (ty == F && q->x.regnode->set == IREG)
- print("mfc1.d $%d,$f%d\n", q->x.regnode->number, src);
- break;
- case ASGN+B:
- dalign = salign = p->syms[1]->u.c.v.i;
- blkcopy(getregnum(p->x.kids[0]), 0,
- getregnum(p->x.kids[1]), 0,
- p->syms[0]->u.c.v.i, tmpregs);
- break;
- case ARG+B:
- dalign = 4;
- salign = p->syms[1]->u.c.v.i;
- blkcopy(29, p->syms[2]->u.c.v.i,
- getregnum(p->x.kids[0]), 0,
- p->syms[0]->u.c.v.i, tmpregs);
- n = p->syms[2]->u.c.v.i + p->syms[0]->u.c.v.i;
- dst = p->syms[2]->u.c.v.i;
- for ( ; dst <= 12 && dst < n; dst += 4)
- print("lw $%d,%d($sp)\n", (dst/4)+4, dst);
- break;
- }
-}
-static Symbol argreg(int argno, int offset, int ty, int sz, int ty0) {
- assert((offset&3) == 0);
- if (offset > 12)
- return NULL;
- else if (argno == 0 && ty == F)
- return freg2[12];
- else if (argno == 1 && ty == F && ty0 == F)
- return freg2[14];
- else if (argno == 1 && ty == F && sz == 8)
- return d6; /* Pair! */
- else
- return ireg[(offset/4) + 4];
-}
-static void doarg(Node p) {
- static int argno;
- int align;
-
- if (argoffset == 0)
- argno = 0;
- p->x.argno = argno++;
- align = p->syms[1]->u.c.v.i < 4 ? 4 : p->syms[1]->u.c.v.i;
- p->syms[2] = intconst(mkactual(align,
- p->syms[0]->u.c.v.i));
-}
-static void local(Symbol p) {
- if (askregvar(p, rmap(ttob(p->type))) == 0)
- mkauto(p);
-}
-static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
- int i, saved, sizefsave, sizeisave, varargs;
- Symbol r, argregs[4];
-
- usedmask[0] = usedmask[1] = 0;
- freemask[0] = freemask[1] = ~(unsigned)0;
- offset = maxoffset = maxargoffset = 0;
- for (i = 0; callee[i]; i++)
- ;
- varargs = variadic(f->type)
- || i > 0 && strcmp(callee[i-1]->name, "va_alist") == 0;
- for (i = 0; callee[i]; i++) {
- Symbol p = callee[i];
- Symbol q = caller[i];
- assert(q);
- offset = roundup(offset, q->type->align);
- p->x.offset = q->x.offset = offset;
- p->x.name = q->x.name = stringd(offset);
- r = argreg(i, offset, optype(ttob(q->type)), q->type->size, optype(ttob(caller[0]->type)));
- if (i < 4)
- argregs[i] = r;
- offset = roundup(offset + q->type->size, 4);
- if (varargs)
- p->sclass = AUTO;
- else if (r && ncalls == 0 &&
- !isstruct(q->type) && !p->addressed &&
- !(isfloat(q->type) && r->x.regnode->set == IREG)
-) {
- p->sclass = q->sclass = REGISTER;
- askregvar(p, r);
- assert(p->x.regnode && p->x.regnode->vbl == p);
- q->x = p->x;
- q->type = p->type;
- }
- else if (askregvar(p, rmap(ttob(p->type)))
- && r != NULL
- && (isint(p->type) || p->type == q->type)) {
- assert(q->sclass != REGISTER);
- p->sclass = q->sclass = REGISTER;
- q->type = p->type;
- }
- }
- assert(!caller[i]);
- offset = 0;
- gencode(caller, callee);
- if (ncalls)
- usedmask[IREG] |= ((unsigned)1)<<31;
- usedmask[IREG] &= 0xc0ff0000;
- usedmask[FREG] &= 0xfff00000;
- if (pic && ncalls)
- usedmask[IREG] |= 1<<25;
- maxargoffset = roundup(maxargoffset, usedmask[FREG] ? 8 : 4);
- if (ncalls && maxargoffset < 16)
- maxargoffset = 16;
- sizefsave = 4*bitcount(usedmask[FREG]);
- sizeisave = 4*bitcount(usedmask[IREG]);
- framesize = roundup(maxargoffset + sizefsave
- + sizeisave + maxoffset, 8);
- segment(CODE);
- print(".align 2\n");
- print(".ent %s\n", f->x.name);
- print("%s:\n", f->x.name);
- i = maxargoffset + sizefsave - framesize;
- print(".frame $sp,%d,$31\n", framesize);
- if (pic)
- print(".set noreorder\n.cpload $25\n.set reorder\n");
- if (framesize > 0)
- print("addu $sp,$sp,%d\n", -framesize);
- if (usedmask[FREG])
- print(".fmask 0x%x,%d\n", usedmask[FREG], i - 8);
- if (usedmask[IREG])
- print(".mask 0x%x,%d\n", usedmask[IREG],
- i + sizeisave - 4);
- saved = maxargoffset;
- for (i = 20; i <= 30; i += 2)
- if (usedmask[FREG]&(3<<i)) {
- print("s.d $f%d,%d($sp)\n", i, saved);
- saved += 8;
- }
-
- for (i = 16; i <= 31; i++)
- if (usedmask[IREG]&(1<<i)) {
- if (i == 25)
- print(".cprestore %d\n", saved);
- else
- print("sw $%d,%d($sp)\n", i, saved);
- saved += 4;
- }
- for (i = 0; i < 4 && callee[i]; i++) {
- r = argregs[i];
- if (r && r->x.regnode != callee[i]->x.regnode) {
- Symbol out = callee[i];
- Symbol in = caller[i];
- int rn = r->x.regnode->number;
- int rs = r->x.regnode->set;
- int tyin = ttob(in->type);
-
- assert(out && in && r && r->x.regnode);
- assert(out->sclass != REGISTER || out->x.regnode);
- if (out->sclass == REGISTER
- && (isint(out->type) || out->type == in->type)) {
- int outn = out->x.regnode->number;
- if (rs == FREG && tyin == F+sizeop(8))
- print("mov.d $f%d,$f%d\n", outn, rn);
- else if (rs == FREG && tyin == F+sizeop(4))
- print("mov.s $f%d,$f%d\n", outn, rn);
- else if (rs == IREG && tyin == F+sizeop(8))
- print("mtc1.d $%d,$f%d\n", rn, outn);
- else if (rs == IREG && tyin == F+sizeop(4))
- print("mtc1 $%d,$f%d\n", rn, outn);
- else
- print("move $%d,$%d\n", outn, rn);
- } else {
- int off = in->x.offset + framesize;
- if (rs == FREG && tyin == F+sizeop(8))
- print("s.d $f%d,%d($sp)\n", rn, off);
- else if (rs == FREG && tyin == F+sizeop(4))
- print("s.s $f%d,%d($sp)\n", rn, off);
- else {
- int i, n = (in->type->size + 3)/4;
- for (i = rn; i < rn+n && i <= 7; i++)
- print("sw $%d,%d($sp)\n", i, off + (i-rn)*4);
- }
- }
- }
- }
- if (varargs && callee[i-1]) {
- i = callee[i-1]->x.offset + callee[i-1]->type->size;
- for (i = roundup(i, 4)/4; i <= 3; i++)
- print("sw $%d,%d($sp)\n", i + 4, framesize + 4*i);
- }
- emitcode();
- saved = maxargoffset;
- for (i = 20; i <= 30; i += 2)
- if (usedmask[FREG]&(3<<i)) {
- print("l.d $f%d,%d($sp)\n", i, saved);
- saved += 8;
- }
- for (i = 16; i <= 31; i++)
- if (usedmask[IREG]&(1<<i)) {
- print("lw $%d,%d($sp)\n", i, saved);
- saved += 4;
- }
- if (framesize > 0)
- print("addu $sp,$sp,%d\n", framesize);
- print("j $31\n");
- print(".end %s\n", f->x.name);
-}
-static void defconst(int suffix, int size, Value v) {
- if (suffix == F && size == 4) {
- float f = v.d;
- print(".word 0x%x\n", *(unsigned *)&f);
- }
- else if (suffix == F && size == 8) {
- double d = v.d;
- unsigned *p = (unsigned *)&d;
- print(".word 0x%x\n.word 0x%x\n", p[swap], p[!swap]);
- }
- else if (suffix == P)
- print(".word 0x%x\n", v.p);
- else if (size == 1)
- print(".byte 0x%x\n", suffix == I ? v.i : v.u);
- else if (size == 2)
- print(".half 0x%x\n", suffix == I ? v.i : v.u);
- else if (size == 4)
- print(".word 0x%x\n", suffix == I ? v.i : v.u);
-}
-static void defaddress(Symbol p) {
- if (pic && p->scope == LABELS)
- print(".gpword %s\n", p->x.name);
- else
- print(".word %s\n", p->x.name);
-}
-static void defstring(int n, char *str) {
- char *s;
-
- for (s = str; s < str + n; s++)
- print(".byte %d\n", (*s)&0377);
-}
-static void export(Symbol p) {
- print(".globl %s\n", p->x.name);
-}
-static void import(Symbol p) {
- if (!isfunc(p->type))
- print(".extern %s %d\n", p->name, p->type->size);
-}
-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
- assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)),
- 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 global(Symbol p) {
- if (p->u.seg == BSS) {
- if (p->sclass == STATIC || Aflag >= 2)
- print(".lcomm %s,%d\n", p->x.name, p->type->size);
- else
- print( ".comm %s,%d\n", p->x.name, p->type->size);
- } else {
- if (p->u.seg == DATA
- && (p->type->size == 0 || p->type->size > gnum))
- print(".data\n");
- else if (p->u.seg == DATA)
- print(".sdata\n");
- print(".align %c\n", ".01.2...3"[p->type->align]);
- print("%s:\n", p->x.name);
- }
-}
-static void segment(int n) {
- cseg = n;
- switch (n) {
- case CODE: print(".text\n"); break;
- case LIT: print(".rdata\n"); break;
- }
-}
-static void space(int n) {
- if (cseg != BSS)
- print(".space %d\n", n);
-}
-static void blkloop(int dreg, int doff, int sreg, int soff, int size, int tmps[]) {
- int lab = genlabel(1);
-
- print("addu $%d,$%d,%d\n", sreg, sreg, size&~7);
- print("addu $%d,$%d,%d\n", tmps[2], dreg, size&~7);
- blkcopy(tmps[2], doff, sreg, soff, size&7, tmps);
- print("L.%d:\n", lab);
- print("addu $%d,$%d,%d\n", sreg, sreg, -8);
- print("addu $%d,$%d,%d\n", tmps[2], tmps[2], -8);
- blkcopy(tmps[2], doff, sreg, soff, 8, tmps);
- print("bltu $%d,$%d,L.%d\n", dreg, tmps[2], lab);
-}
-static void blkfetch(int size, int off, int reg, int tmp) {
- assert(size == 1 || size == 2 || size == 4);
- if (size == 1)
- print("lbu $%d,%d($%d)\n", tmp, off, reg);
- else if (salign >= size && size == 2)
- print("lhu $%d,%d($%d)\n", tmp, off, reg);
- else if (salign >= size)
- print("lw $%d,%d($%d)\n", tmp, off, reg);
- else if (size == 2)
- print("ulhu $%d,%d($%d)\n", tmp, off, reg);
- else
- print("ulw $%d,%d($%d)\n", tmp, off, reg);
-}
-static void blkstore(int size, int off, int reg, int tmp) {
- if (size == 1)
- print("sb $%d,%d($%d)\n", tmp, off, reg);
- else if (dalign >= size && size == 2)
- print("sh $%d,%d($%d)\n", tmp, off, reg);
- else if (dalign >= size)
- print("sw $%d,%d($%d)\n", tmp, off, reg);
- else if (size == 2)
- print("ush $%d,%d($%d)\n", tmp, off, reg);
- else
- print("usw $%d,%d($%d)\n", tmp, off, reg);
-}
-static void stabinit(char *, int, char *[]);
-static void stabline(Coordinate *);
-static void stabsym(Symbol);
-
-static char *currentfile;
-
-static int bitcount(unsigned mask) {
- unsigned i, n = 0;
-
- for (i = 1; i; i <<= 1)
- if (mask&i)
- n++;
- return n;
-}
-
-/* stabinit - initialize stab output */
-static void stabinit(char *file, int argc, char *argv[]) {
- if (file) {
- print(".file 2,\"%s\"\n", file);
- currentfile = file;
- }
-}
-
-/* stabline - emit stab entry for source coordinate *cp */
-static void stabline(Coordinate *cp) {
- if (cp->file && cp->file != currentfile) {
- print(".file 2,\"%s\"\n", cp->file);
- currentfile = cp->file;
- }
- print(".loc 2,%d\n", cp->y);
-}
-
-/* stabsym - output a stab entry for symbol p */
-static void stabsym(Symbol p) {
- if (p == cfunc && IR->stabline)
- (*IR->stabline)(&p->src);
-}
-Interface mipsebIR = {
- 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, 1, 0, /* struct */
- 0, /* little_endian */
- 0, /* mulops_calls */
- 0, /* wants_callb */
- 1, /* wants_argb */
- 1, /* 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, stabinit, stabline, stabsym, 0,
- {
- 4, /* max_unaligned_load */
- rmap,
- blkfetch, blkstore, blkloop,
- _label,
- _rule,
- _nts,
- _kids,
- _string,
- _templates,
- _isinstruction,
- _ntname,
- emit2,
- doarg,
- target,
- clobber,
-
- }
-}, mipselIR = {
- 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, 1, 0, /* struct */
- 1, /* little_endian */
- 0, /* mulops_calls */
- 0, /* wants_callb */
- 1, /* wants_argb */
- 1, /* 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, stabinit, stabline, stabsym, 0,
- {
- 4, /* max_unaligned_load */
- rmap,
- blkfetch, blkstore, blkloop,
- _label,
- _rule,
- _nts,
- _kids,
- _string,
- _templates,
- _isinstruction,
- _ntname,
- emit2,
- doarg,
- target,
- clobber,
-
- }
-};
-static char rcsid[] = "$Id: mips.md 145 2001-10-17 21:53:10Z timo $";
+%{ +#define INTTMP 0x0100ff00 +#define INTVAR 0x40ff0000 +#define FLTTMP 0x000f0ff0 +#define FLTVAR 0xfff00000 + +#define INTRET 0x00000004 +#define FLTRET 0x00000003 + +#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)) + +#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); +static int bitcount (unsigned); +static Symbol argreg (int, int, int, int, int); + +static Symbol ireg[32], freg2[32], d6; +static Symbol iregw, freg2w; +static int tmpregs[] = {3, 9, 10}; +static Symbol blkreg; + +static int gnum = 8; +static int pic; + +static int cseg; +%} +%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: con "%0" +acon: ADDRGP4 "%a" +addr: ADDI4(reg,acon) "%1($%0)" +addr: ADDU4(reg,acon) "%1($%0)" +addr: ADDP4(reg,acon) "%1($%0)" +addr: acon "%0" +addr: reg "($%0)" +addr: ADDRFP4 "%a+%F($sp)" +addr: ADDRLP4 "%a+%F($sp)" +reg: addr "la $%c,%0\n" 1 +reg: CNSTI1 "# reg\n" range(a, 0, 0) +reg: CNSTI2 "# reg\n" range(a, 0, 0) +reg: CNSTI4 "# reg\n" range(a, 0, 0) +reg: CNSTU1 "# reg\n" range(a, 0, 0) +reg: CNSTU2 "# reg\n" range(a, 0, 0) +reg: CNSTU4 "# reg\n" range(a, 0, 0) +reg: CNSTP4 "# reg\n" range(a, 0, 0) +stmt: ASGNI1(addr,reg) "sb $%1,%0\n" 1 +stmt: ASGNU1(addr,reg) "sb $%1,%0\n" 1 +stmt: ASGNI2(addr,reg) "sh $%1,%0\n" 1 +stmt: ASGNU2(addr,reg) "sh $%1,%0\n" 1 +stmt: ASGNI4(addr,reg) "sw $%1,%0\n" 1 +stmt: ASGNU4(addr,reg) "sw $%1,%0\n" 1 +stmt: ASGNP4(addr,reg) "sw $%1,%0\n" 1 +reg: INDIRI1(addr) "lb $%c,%0\n" 1 +reg: INDIRU1(addr) "lbu $%c,%0\n" 1 +reg: INDIRI2(addr) "lh $%c,%0\n" 1 +reg: INDIRU2(addr) "lhu $%c,%0\n" 1 +reg: INDIRI4(addr) "lw $%c,%0\n" 1 +reg: INDIRU4(addr) "lw $%c,%0\n" 1 +reg: INDIRP4(addr) "lw $%c,%0\n" 1 + +reg: CVII4(INDIRI1(addr)) "lb $%c,%0\n" 1 +reg: CVII4(INDIRI2(addr)) "lh $%c,%0\n" 1 +reg: CVUU4(INDIRU1(addr)) "lbu $%c,%0\n" 1 +reg: CVUU4(INDIRU2(addr)) "lhu $%c,%0\n" 1 +reg: CVUI4(INDIRU1(addr)) "lbu $%c,%0\n" 1 +reg: CVUI4(INDIRU2(addr)) "lhu $%c,%0\n" 1 +reg: INDIRF4(addr) "l.s $f%c,%0\n" 1 +reg: INDIRF8(addr) "l.d $f%c,%0\n" 1 +stmt: ASGNF4(addr,reg) "s.s $f%1,%0\n" 1 +stmt: ASGNF8(addr,reg) "s.d $f%1,%0\n" 1 +reg: DIVI4(reg,reg) "div $%c,$%0,$%1\n" 1 +reg: DIVU4(reg,reg) "divu $%c,$%0,$%1\n" 1 +reg: MODI4(reg,reg) "rem $%c,$%0,$%1\n" 1 +reg: MODU4(reg,reg) "remu $%c,$%0,$%1\n" 1 +reg: MULI4(reg,reg) "mul $%c,$%0,$%1\n" 1 +reg: MULU4(reg,reg) "mul $%c,$%0,$%1\n" 1 +rc: con "%0" +rc: reg "$%0" + +reg: ADDI4(reg,rc) "addu $%c,$%0,%1\n" 1 +reg: ADDP4(reg,rc) "addu $%c,$%0,%1\n" 1 +reg: ADDU4(reg,rc) "addu $%c,$%0,%1\n" 1 +reg: BANDI4(reg,rc) "and $%c,$%0,%1\n" 1 +reg: BORI4(reg,rc) "or $%c,$%0,%1\n" 1 +reg: BXORI4(reg,rc) "xor $%c,$%0,%1\n" 1 +reg: BANDU4(reg,rc) "and $%c,$%0,%1\n" 1 +reg: BORU4(reg,rc) "or $%c,$%0,%1\n" 1 +reg: BXORU4(reg,rc) "xor $%c,$%0,%1\n" 1 +reg: SUBI4(reg,rc) "subu $%c,$%0,%1\n" 1 +reg: SUBP4(reg,rc) "subu $%c,$%0,%1\n" 1 +reg: SUBU4(reg,rc) "subu $%c,$%0,%1\n" 1 +rc5: CNSTI4 "%a" range(a,0,31) +rc5: reg "$%0" + +reg: LSHI4(reg,rc5) "sll $%c,$%0,%1\n" 1 +reg: LSHU4(reg,rc5) "sll $%c,$%0,%1\n" 1 +reg: RSHI4(reg,rc5) "sra $%c,$%0,%1\n" 1 +reg: RSHU4(reg,rc5) "srl $%c,$%0,%1\n" 1 +reg: BCOMI4(reg) "not $%c,$%0\n" 1 +reg: BCOMU4(reg) "not $%c,$%0\n" 1 +reg: NEGI4(reg) "negu $%c,$%0\n" 1 +reg: LOADI1(reg) "move $%c,$%0\n" move(a) +reg: LOADU1(reg) "move $%c,$%0\n" move(a) +reg: LOADI2(reg) "move $%c,$%0\n" move(a) +reg: LOADU2(reg) "move $%c,$%0\n" move(a) +reg: LOADI4(reg) "move $%c,$%0\n" move(a) +reg: LOADP4(reg) "move $%c,$%0\n" move(a) +reg: LOADU4(reg) "move $%c,$%0\n" move(a) +reg: ADDF4(reg,reg) "add.s $f%c,$f%0,$f%1\n" 1 +reg: ADDF8(reg,reg) "add.d $f%c,$f%0,$f%1\n" 1 +reg: DIVF4(reg,reg) "div.s $f%c,$f%0,$f%1\n" 1 +reg: DIVF8(reg,reg) "div.d $f%c,$f%0,$f%1\n" 1 +reg: MULF4(reg,reg) "mul.s $f%c,$f%0,$f%1\n" 1 +reg: MULF8(reg,reg) "mul.d $f%c,$f%0,$f%1\n" 1 +reg: SUBF4(reg,reg) "sub.s $f%c,$f%0,$f%1\n" 1 +reg: SUBF8(reg,reg) "sub.d $f%c,$f%0,$f%1\n" 1 +reg: LOADF4(reg) "mov.s $f%c,$f%0\n" move(a) +reg: LOADF8(reg) "mov.d $f%c,$f%0\n" move(a) +reg: NEGF4(reg) "neg.s $f%c,$f%0\n" 1 +reg: NEGF8(reg) "neg.d $f%c,$f%0\n" 1 +reg: CVII4(reg) "sll $%c,$%0,8*(4-%a); sra $%c,$%c,8*(4-%a)\n" 2 +reg: CVUI4(reg) "and $%c,$%0,(1<<(8*%a))-1\n" 1 +reg: CVUU4(reg) "and $%c,$%0,(1<<(8*%a))-1\n" 1 +reg: CVFF4(reg) "cvt.s.d $f%c,$f%0\n" 1 +reg: CVFF8(reg) "cvt.d.s $f%c,$f%0\n" 1 +reg: CVIF4(reg) "mtc1 $%0,$f%c; cvt.s.w $f%c,$f%c\n" 2 +reg: CVIF8(reg) "mtc1 $%0,$f%c; cvt.d.w $f%c,$f%c\n" 2 +reg: CVFI4(reg) "trunc.w.s $f2,$f%0,$%c; mfc1 $%c,$f2\n" (a->syms[0]->u.c.v.i==4?2:LBURG_MAX) +reg: CVFI4(reg) "trunc.w.d $f2,$f%0,$%c; mfc1 $%c,$f2\n" (a->syms[0]->u.c.v.i==8?2:LBURG_MAX) +stmt: LABELV "%a:\n" +stmt: JUMPV(acon) "b %0\n" 1 +stmt: JUMPV(reg) ".cpadd $%0\nj $%0\n" !pic +stmt: JUMPV(reg) "j $%0\n" pic +stmt: EQI4(reg,reg) "beq $%0,$%1,%a\n" 1 +stmt: EQU4(reg,reg) "beq $%0,$%1,%a\n" 1 +stmt: GEI4(reg,reg) "bge $%0,$%1,%a\n" 1 +stmt: GEU4(reg,reg) "bgeu $%0,$%1,%a\n" 1 +stmt: GTI4(reg,reg) "bgt $%0,$%1,%a\n" 1 +stmt: GTU4(reg,reg) "bgtu $%0,$%1,%a\n" 1 +stmt: LEI4(reg,reg) "ble $%0,$%1,%a\n" 1 +stmt: LEU4(reg,reg) "bleu $%0,$%1,%a\n" 1 +stmt: LTI4(reg,reg) "blt $%0,$%1,%a\n" 1 +stmt: LTU4(reg,reg) "bltu $%0,$%1,%a\n" 1 +stmt: NEI4(reg,reg) "bne $%0,$%1,%a\n" 1 +stmt: NEU4(reg,reg) "bne $%0,$%1,%a\n" 1 +stmt: EQF4(reg,reg) "c.eq.s $f%0,$f%1; bc1t %a\n" 2 +stmt: EQF8(reg,reg) "c.eq.d $f%0,$f%1; bc1t %a\n" 2 +stmt: LEF4(reg,reg) "c.le.s $f%0,$f%1; bc1t %a\n" 2 +stmt: LEF8(reg,reg) "c.le.d $f%0,$f%1; bc1t %a\n" 2 +stmt: LTF4(reg,reg) "c.lt.s $f%0,$f%1; bc1t %a\n" 2 +stmt: LTF8(reg,reg) "c.lt.d $f%0,$f%1; bc1t %a\n" 2 +stmt: GEF4(reg,reg) "c.lt.s $f%0,$f%1; bc1f %a\n" 2 +stmt: GEF8(reg,reg) "c.lt.d $f%0,$f%1; bc1f %a\n" 2 +stmt: GTF4(reg,reg) "c.le.s $f%0,$f%1; bc1f %a\n" 2 +stmt: GTF8(reg,reg) "c.le.d $f%0,$f%1; bc1f %a\n" 2 +stmt: NEF4(reg,reg) "c.eq.s $f%0,$f%1; bc1f %a\n" 2 +stmt: NEF8(reg,reg) "c.eq.d $f%0,$f%1; bc1f %a\n" 2 +ar: ADDRGP4 "%a" + +reg: CALLF4(ar) "jal %0\n" 1 +reg: CALLF8(ar) "jal %0\n" 1 +reg: CALLI4(ar) "jal %0\n" 1 +reg: CALLP4(ar) "jal %0\n" 1 +reg: CALLU4(ar) "jal %0\n" 1 +stmt: CALLV(ar) "jal %0\n" 1 +ar: reg "$%0" +ar: CNSTP4 "%a" range(a, 0, 0x0fffffff) +stmt: RETF4(reg) "# ret\n" 1 +stmt: RETF8(reg) "# ret\n" 1 +stmt: RETI4(reg) "# ret\n" 1 +stmt: RETU4(reg) "# ret\n" 1 +stmt: RETP4(reg) "# ret\n" 1 +stmt: RETV(reg) "# ret\n" 1 +stmt: ARGF4(reg) "# arg\n" 1 +stmt: ARGF8(reg) "# arg\n" 1 +stmt: ARGI4(reg) "# arg\n" 1 +stmt: ARGP4(reg) "# arg\n" 1 +stmt: ARGU4(reg) "# arg\n" 1 + +stmt: ARGB(INDIRB(reg)) "# argb %0\n" 1 +stmt: ASGNB(reg,INDIRB(reg)) "# asgnb %0 %1\n" 1 +%% +static void progend(void){} +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; + } + print(".set reorder\n"); + pic = !IR->little_endian; + parseflags(argc, argv); + for (i = 0; i < argc; i++) + if (strncmp(argv[i], "-G", 2) == 0) + gnum = atoi(argv[i] + 2); + else if (strcmp(argv[i], "-pic=1") == 0 + || strcmp(argv[i], "-pic=0") == 0) + pic = argv[i][5]-'0'; + for (i = 0; i < 31; i += 2) + freg2[i] = mkreg("%d", i, 3, FREG); + for (i = 0; i < 32; i++) + ireg[i] = mkreg("%d", i, 1, IREG); + ireg[29]->x.name = "sp"; + d6 = mkreg("6", 6, 3, IREG); + freg2w = mkwildcard(freg2); + iregw = mkwildcard(ireg); + tmask[IREG] = INTTMP; tmask[FREG] = FLTTMP; + vmask[IREG] = INTVAR; vmask[FREG] = FLTVAR; + blkreg = mkreg("8", 8, 7, IREG); +} +static Symbol rmap(int opk) { + switch (optype(opk)) { + case I: case U: case P: case B: + return iregw; + case F: + return freg2w; + default: + return 0; + } +} +static void target(Node p) { + assert(p); + switch (specific(p->op)) { + case CNST+I: case CNST+U: case CNST+P: + if (range(p, 0, 0) == 0) { + setreg(p, ireg[0]); + p->x.registered = 1; + } + break; + case CALL+V: + rtarget(p, 0, ireg[25]); + break; + case CALL+F: + rtarget(p, 0, ireg[25]); + setreg(p, freg2[0]); + break; + case CALL+I: case CALL+P: case CALL+U: + rtarget(p, 0, ireg[25]); + setreg(p, ireg[2]); + break; + case RET+F: + rtarget(p, 0, freg2[0]); + break; + case RET+I: case RET+U: case RET+P: + rtarget(p, 0, ireg[2]); + break; + case ARG+F: case ARG+I: case ARG+P: case ARG+U: { + static int ty0; + int ty = optype(p->op); + Symbol q; + + q = argreg(p->x.argno, p->syms[2]->u.c.v.i, ty, opsize(p->op), ty0); + if (p->x.argno == 0) + ty0 = ty; + if (q && + !(ty == F && q->x.regnode->set == IREG)) + rtarget(p, 0, q); + break; + } + case ASGN+B: rtarget(p->kids[1], 0, blkreg); break; + case ARG+B: rtarget(p->kids[0], 0, blkreg); break; + } +} +static void clobber(Node p) { + assert(p); + switch (specific(p->op)) { + case CALL+F: + spill(INTTMP | INTRET, IREG, p); + spill(FLTTMP, FREG, p); + break; + case CALL+I: case CALL+P: case CALL+U: + spill(INTTMP, IREG, p); + spill(FLTTMP | FLTRET, FREG, p); + break; + case CALL+V: + spill(INTTMP | INTRET, IREG, p); + spill(FLTTMP | FLTRET, FREG, p); + break; + } +} +static void emit2(Node p) { + int dst, n, src, sz, ty; + static int ty0; + Symbol q; + + switch (specific(p->op)) { + case ARG+F: case ARG+I: case ARG+P: case ARG+U: + ty = optype(p->op); + sz = opsize(p->op); + if (p->x.argno == 0) + ty0 = ty; + q = argreg(p->x.argno, p->syms[2]->u.c.v.i, ty, sz, ty0); + src = getregnum(p->x.kids[0]); + if (q == NULL && ty == F && sz == 4) + print("s.s $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i); + else if (q == NULL && ty == F) + print("s.d $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i); + else if (q == NULL) + print("sw $%d,%d($sp)\n", src, p->syms[2]->u.c.v.i); + else if (ty == F && sz == 4 && q->x.regnode->set == IREG) + print("mfc1 $%d,$f%d\n", q->x.regnode->number, src); + else if (ty == F && q->x.regnode->set == IREG) + print("mfc1.d $%d,$f%d\n", q->x.regnode->number, src); + break; + case ASGN+B: + dalign = salign = p->syms[1]->u.c.v.i; + blkcopy(getregnum(p->x.kids[0]), 0, + getregnum(p->x.kids[1]), 0, + p->syms[0]->u.c.v.i, tmpregs); + break; + case ARG+B: + dalign = 4; + salign = p->syms[1]->u.c.v.i; + blkcopy(29, p->syms[2]->u.c.v.i, + getregnum(p->x.kids[0]), 0, + p->syms[0]->u.c.v.i, tmpregs); + n = p->syms[2]->u.c.v.i + p->syms[0]->u.c.v.i; + dst = p->syms[2]->u.c.v.i; + for ( ; dst <= 12 && dst < n; dst += 4) + print("lw $%d,%d($sp)\n", (dst/4)+4, dst); + break; + } +} +static Symbol argreg(int argno, int offset, int ty, int sz, int ty0) { + assert((offset&3) == 0); + if (offset > 12) + return NULL; + else if (argno == 0 && ty == F) + return freg2[12]; + else if (argno == 1 && ty == F && ty0 == F) + return freg2[14]; + else if (argno == 1 && ty == F && sz == 8) + return d6; /* Pair! */ + else + return ireg[(offset/4) + 4]; +} +static void doarg(Node p) { + static int argno; + int align; + + if (argoffset == 0) + argno = 0; + p->x.argno = argno++; + align = p->syms[1]->u.c.v.i < 4 ? 4 : p->syms[1]->u.c.v.i; + p->syms[2] = intconst(mkactual(align, + p->syms[0]->u.c.v.i)); +} +static void local(Symbol p) { + if (askregvar(p, rmap(ttob(p->type))) == 0) + mkauto(p); +} +static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { + int i, saved, sizefsave, sizeisave, varargs; + Symbol r, argregs[4]; + + usedmask[0] = usedmask[1] = 0; + freemask[0] = freemask[1] = ~(unsigned)0; + offset = maxoffset = maxargoffset = 0; + for (i = 0; callee[i]; i++) + ; + varargs = variadic(f->type) + || i > 0 && strcmp(callee[i-1]->name, "va_alist") == 0; + for (i = 0; callee[i]; i++) { + Symbol p = callee[i]; + Symbol q = caller[i]; + assert(q); + offset = roundup(offset, q->type->align); + p->x.offset = q->x.offset = offset; + p->x.name = q->x.name = stringd(offset); + r = argreg(i, offset, optype(ttob(q->type)), q->type->size, optype(ttob(caller[0]->type))); + if (i < 4) + argregs[i] = r; + offset = roundup(offset + q->type->size, 4); + if (varargs) + p->sclass = AUTO; + else if (r && ncalls == 0 && + !isstruct(q->type) && !p->addressed && + !(isfloat(q->type) && r->x.regnode->set == IREG) +) { + p->sclass = q->sclass = REGISTER; + askregvar(p, r); + assert(p->x.regnode && p->x.regnode->vbl == p); + q->x = p->x; + q->type = p->type; + } + else if (askregvar(p, rmap(ttob(p->type))) + && r != NULL + && (isint(p->type) || p->type == q->type)) { + assert(q->sclass != REGISTER); + p->sclass = q->sclass = REGISTER; + q->type = p->type; + } + } + assert(!caller[i]); + offset = 0; + gencode(caller, callee); + if (ncalls) + usedmask[IREG] |= ((unsigned)1)<<31; + usedmask[IREG] &= 0xc0ff0000; + usedmask[FREG] &= 0xfff00000; + if (pic && ncalls) + usedmask[IREG] |= 1<<25; + maxargoffset = roundup(maxargoffset, usedmask[FREG] ? 8 : 4); + if (ncalls && maxargoffset < 16) + maxargoffset = 16; + sizefsave = 4*bitcount(usedmask[FREG]); + sizeisave = 4*bitcount(usedmask[IREG]); + framesize = roundup(maxargoffset + sizefsave + + sizeisave + maxoffset, 8); + segment(CODE); + print(".align 2\n"); + print(".ent %s\n", f->x.name); + print("%s:\n", f->x.name); + i = maxargoffset + sizefsave - framesize; + print(".frame $sp,%d,$31\n", framesize); + if (pic) + print(".set noreorder\n.cpload $25\n.set reorder\n"); + if (framesize > 0) + print("addu $sp,$sp,%d\n", -framesize); + if (usedmask[FREG]) + print(".fmask 0x%x,%d\n", usedmask[FREG], i - 8); + if (usedmask[IREG]) + print(".mask 0x%x,%d\n", usedmask[IREG], + i + sizeisave - 4); + saved = maxargoffset; + for (i = 20; i <= 30; i += 2) + if (usedmask[FREG]&(3<<i)) { + print("s.d $f%d,%d($sp)\n", i, saved); + saved += 8; + } + + for (i = 16; i <= 31; i++) + if (usedmask[IREG]&(1<<i)) { + if (i == 25) + print(".cprestore %d\n", saved); + else + print("sw $%d,%d($sp)\n", i, saved); + saved += 4; + } + for (i = 0; i < 4 && callee[i]; i++) { + r = argregs[i]; + if (r && r->x.regnode != callee[i]->x.regnode) { + Symbol out = callee[i]; + Symbol in = caller[i]; + int rn = r->x.regnode->number; + int rs = r->x.regnode->set; + int tyin = ttob(in->type); + + assert(out && in && r && r->x.regnode); + assert(out->sclass != REGISTER || out->x.regnode); + if (out->sclass == REGISTER + && (isint(out->type) || out->type == in->type)) { + int outn = out->x.regnode->number; + if (rs == FREG && tyin == F+sizeop(8)) + print("mov.d $f%d,$f%d\n", outn, rn); + else if (rs == FREG && tyin == F+sizeop(4)) + print("mov.s $f%d,$f%d\n", outn, rn); + else if (rs == IREG && tyin == F+sizeop(8)) + print("mtc1.d $%d,$f%d\n", rn, outn); + else if (rs == IREG && tyin == F+sizeop(4)) + print("mtc1 $%d,$f%d\n", rn, outn); + else + print("move $%d,$%d\n", outn, rn); + } else { + int off = in->x.offset + framesize; + if (rs == FREG && tyin == F+sizeop(8)) + print("s.d $f%d,%d($sp)\n", rn, off); + else if (rs == FREG && tyin == F+sizeop(4)) + print("s.s $f%d,%d($sp)\n", rn, off); + else { + int i, n = (in->type->size + 3)/4; + for (i = rn; i < rn+n && i <= 7; i++) + print("sw $%d,%d($sp)\n", i, off + (i-rn)*4); + } + } + } + } + if (varargs && callee[i-1]) { + i = callee[i-1]->x.offset + callee[i-1]->type->size; + for (i = roundup(i, 4)/4; i <= 3; i++) + print("sw $%d,%d($sp)\n", i + 4, framesize + 4*i); + } + emitcode(); + saved = maxargoffset; + for (i = 20; i <= 30; i += 2) + if (usedmask[FREG]&(3<<i)) { + print("l.d $f%d,%d($sp)\n", i, saved); + saved += 8; + } + for (i = 16; i <= 31; i++) + if (usedmask[IREG]&(1<<i)) { + print("lw $%d,%d($sp)\n", i, saved); + saved += 4; + } + if (framesize > 0) + print("addu $sp,$sp,%d\n", framesize); + print("j $31\n"); + print(".end %s\n", f->x.name); +} +static void defconst(int suffix, int size, Value v) { + if (suffix == F && size == 4) { + float f = v.d; + print(".word 0x%x\n", *(unsigned *)&f); + } + else if (suffix == F && size == 8) { + double d = v.d; + unsigned *p = (unsigned *)&d; + print(".word 0x%x\n.word 0x%x\n", p[swap], p[!swap]); + } + else if (suffix == P) + print(".word 0x%x\n", v.p); + else if (size == 1) + print(".byte 0x%x\n", suffix == I ? v.i : v.u); + else if (size == 2) + print(".half 0x%x\n", suffix == I ? v.i : v.u); + else if (size == 4) + print(".word 0x%x\n", suffix == I ? v.i : v.u); +} +static void defaddress(Symbol p) { + if (pic && p->scope == LABELS) + print(".gpword %s\n", p->x.name); + else + print(".word %s\n", p->x.name); +} +static void defstring(int n, char *str) { + char *s; + + for (s = str; s < str + n; s++) + print(".byte %d\n", (*s)&0377); +} +static void export(Symbol p) { + print(".globl %s\n", p->x.name); +} +static void import(Symbol p) { + if (!isfunc(p->type)) + print(".extern %s %d\n", p->name, p->type->size); +} +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 + assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)), + 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 global(Symbol p) { + if (p->u.seg == BSS) { + if (p->sclass == STATIC || Aflag >= 2) + print(".lcomm %s,%d\n", p->x.name, p->type->size); + else + print( ".comm %s,%d\n", p->x.name, p->type->size); + } else { + if (p->u.seg == DATA + && (p->type->size == 0 || p->type->size > gnum)) + print(".data\n"); + else if (p->u.seg == DATA) + print(".sdata\n"); + print(".align %c\n", ".01.2...3"[p->type->align]); + print("%s:\n", p->x.name); + } +} +static void segment(int n) { + cseg = n; + switch (n) { + case CODE: print(".text\n"); break; + case LIT: print(".rdata\n"); break; + } +} +static void space(int n) { + if (cseg != BSS) + print(".space %d\n", n); +} +static void blkloop(int dreg, int doff, int sreg, int soff, int size, int tmps[]) { + int lab = genlabel(1); + + print("addu $%d,$%d,%d\n", sreg, sreg, size&~7); + print("addu $%d,$%d,%d\n", tmps[2], dreg, size&~7); + blkcopy(tmps[2], doff, sreg, soff, size&7, tmps); + print("L.%d:\n", lab); + print("addu $%d,$%d,%d\n", sreg, sreg, -8); + print("addu $%d,$%d,%d\n", tmps[2], tmps[2], -8); + blkcopy(tmps[2], doff, sreg, soff, 8, tmps); + print("bltu $%d,$%d,L.%d\n", dreg, tmps[2], lab); +} +static void blkfetch(int size, int off, int reg, int tmp) { + assert(size == 1 || size == 2 || size == 4); + if (size == 1) + print("lbu $%d,%d($%d)\n", tmp, off, reg); + else if (salign >= size && size == 2) + print("lhu $%d,%d($%d)\n", tmp, off, reg); + else if (salign >= size) + print("lw $%d,%d($%d)\n", tmp, off, reg); + else if (size == 2) + print("ulhu $%d,%d($%d)\n", tmp, off, reg); + else + print("ulw $%d,%d($%d)\n", tmp, off, reg); +} +static void blkstore(int size, int off, int reg, int tmp) { + if (size == 1) + print("sb $%d,%d($%d)\n", tmp, off, reg); + else if (dalign >= size && size == 2) + print("sh $%d,%d($%d)\n", tmp, off, reg); + else if (dalign >= size) + print("sw $%d,%d($%d)\n", tmp, off, reg); + else if (size == 2) + print("ush $%d,%d($%d)\n", tmp, off, reg); + else + print("usw $%d,%d($%d)\n", tmp, off, reg); +} +static void stabinit(char *, int, char *[]); +static void stabline(Coordinate *); +static void stabsym(Symbol); + +static char *currentfile; + +static int bitcount(unsigned mask) { + unsigned i, n = 0; + + for (i = 1; i; i <<= 1) + if (mask&i) + n++; + return n; +} + +/* stabinit - initialize stab output */ +static void stabinit(char *file, int argc, char *argv[]) { + if (file) { + print(".file 2,\"%s\"\n", file); + currentfile = file; + } +} + +/* stabline - emit stab entry for source coordinate *cp */ +static void stabline(Coordinate *cp) { + if (cp->file && cp->file != currentfile) { + print(".file 2,\"%s\"\n", cp->file); + currentfile = cp->file; + } + print(".loc 2,%d\n", cp->y); +} + +/* stabsym - output a stab entry for symbol p */ +static void stabsym(Symbol p) { + if (p == cfunc && IR->stabline) + (*IR->stabline)(&p->src); +} +Interface mipsebIR = { + 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, 1, 0, /* struct */ + 0, /* little_endian */ + 0, /* mulops_calls */ + 0, /* wants_callb */ + 1, /* wants_argb */ + 1, /* 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, stabinit, stabline, stabsym, 0, + { + 4, /* max_unaligned_load */ + rmap, + blkfetch, blkstore, blkloop, + _label, + _rule, + _nts, + _kids, + _string, + _templates, + _isinstruction, + _ntname, + emit2, + doarg, + target, + clobber, + + } +}, mipselIR = { + 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, 1, 0, /* struct */ + 1, /* little_endian */ + 0, /* mulops_calls */ + 0, /* wants_callb */ + 1, /* wants_argb */ + 1, /* 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, stabinit, stabline, stabsym, 0, + { + 4, /* max_unaligned_load */ + rmap, + blkfetch, blkstore, blkloop, + _label, + _rule, + _nts, + _kids, + _string, + _templates, + _isinstruction, + _ntname, + emit2, + doarg, + target, + clobber, + + } +}; +static char rcsid[] = "$Id: mips.md 145 2001-10-17 21:53:10Z timo $"; diff --git a/lcc/src/null.c b/lcc/src/null.c index 52129fc..136e4a8 100755 --- a/lcc/src/null.c +++ b/lcc/src/null.c @@ -1,74 +1,74 @@ -#include "c.h"
-#define I(f) null_##f
-
-static Node I(gen)(Node p) { return p; }
-static void I(address)(Symbol q, Symbol p, long n) {}
-static void I(blockbeg)(Env *e) {}
-static void I(blockend)(Env *e) {}
-static void I(defaddress)(Symbol p) {}
-static void I(defconst)(int suffix, int size, Value v) {}
-static void I(defstring)(int len, char *s) {}
-static void I(defsymbol)(Symbol p) {}
-static void I(emit)(Node p) {}
-static void I(export)(Symbol p) {}
-static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {}
-static void I(global)(Symbol p) {}
-static void I(import)(Symbol p) {}
-static void I(local)(Symbol p) {}
-static void I(progbeg)(int argc, char *argv[]) {}
-static void I(progend)(void) {}
-static void I(segment)(int s) {}
-static void I(space)(int n) {}
-static void I(stabblock)(int brace, int lev, Symbol *p) {}
-static void I(stabend)(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {}
-static void I(stabfend)(Symbol p, int lineno) {}
-static void I(stabinit)(char *file, int argc, char *argv[]) {}
-static void I(stabline)(Coordinate *cp) {}
-static void I(stabsym)(Symbol p) {}
-static void I(stabtype)(Symbol p) {}
-
-
-Interface nullIR = {
- 1, 1, 0, /* char */
- 2, 2, 0, /* short */
- 4, 4, 0, /* int */
- 8, 8, 1, /* long */
- 8 ,8, 1, /* long long */
- 4, 4, 1, /* float */
- 8, 8, 1, /* double */
- 16,16,1, /* long double */
- 4, 4, 0, /* T* */
- 0, 4, 0, /* struct */
- 1, /* little_endian */
- 0, /* mulops_calls */
- 0, /* wants_callb */
- 0, /* wants_argb */
- 1, /* left_to_right */
- 0, /* wants_dag */
- 0, /* unsigned_char */
- I(address),
- I(blockbeg),
- I(blockend),
- I(defaddress),
- I(defconst),
- I(defstring),
- I(defsymbol),
- I(emit),
- I(export),
- I(function),
- I(gen),
- I(global),
- I(import),
- I(local),
- I(progbeg),
- I(progend),
- I(segment),
- I(space),
- I(stabblock),
- I(stabend),
- I(stabfend),
- I(stabinit),
- I(stabline),
- I(stabsym),
- I(stabtype)
-};
+#include "c.h" +#define I(f) null_##f + +static Node I(gen)(Node p) { return p; } +static void I(address)(Symbol q, Symbol p, long n) {} +static void I(blockbeg)(Env *e) {} +static void I(blockend)(Env *e) {} +static void I(defaddress)(Symbol p) {} +static void I(defconst)(int suffix, int size, Value v) {} +static void I(defstring)(int len, char *s) {} +static void I(defsymbol)(Symbol p) {} +static void I(emit)(Node p) {} +static void I(export)(Symbol p) {} +static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {} +static void I(global)(Symbol p) {} +static void I(import)(Symbol p) {} +static void I(local)(Symbol p) {} +static void I(progbeg)(int argc, char *argv[]) {} +static void I(progend)(void) {} +static void I(segment)(int s) {} +static void I(space)(int n) {} +static void I(stabblock)(int brace, int lev, Symbol *p) {} +static void I(stabend)(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {} +static void I(stabfend)(Symbol p, int lineno) {} +static void I(stabinit)(char *file, int argc, char *argv[]) {} +static void I(stabline)(Coordinate *cp) {} +static void I(stabsym)(Symbol p) {} +static void I(stabtype)(Symbol p) {} + + +Interface nullIR = { + 1, 1, 0, /* char */ + 2, 2, 0, /* short */ + 4, 4, 0, /* int */ + 8, 8, 1, /* long */ + 8 ,8, 1, /* long long */ + 4, 4, 1, /* float */ + 8, 8, 1, /* double */ + 16,16,1, /* long double */ + 4, 4, 0, /* T* */ + 0, 4, 0, /* struct */ + 1, /* little_endian */ + 0, /* mulops_calls */ + 0, /* wants_callb */ + 0, /* wants_argb */ + 1, /* left_to_right */ + 0, /* wants_dag */ + 0, /* unsigned_char */ + I(address), + I(blockbeg), + I(blockend), + I(defaddress), + I(defconst), + I(defstring), + I(defsymbol), + I(emit), + I(export), + I(function), + I(gen), + I(global), + I(import), + I(local), + I(progbeg), + I(progend), + I(segment), + I(space), + I(stabblock), + I(stabend), + I(stabfend), + I(stabinit), + I(stabline), + I(stabsym), + I(stabtype) +}; diff --git a/lcc/src/output.c b/lcc/src/output.c index e8fe6f5..dc7a698 100755 --- a/lcc/src/output.c +++ b/lcc/src/output.c @@ -1,134 +1,134 @@ -#include "c.h"
-
-
-static char *outs(const char *str, FILE *f, char *bp) {
- if (f)
- fputs(str, f);
- else
- while (*bp = *str++)
- bp++;
- return bp;
-}
-
-static char *outd(long n, FILE *f, char *bp) {
- unsigned long m;
- char buf[25], *s = buf + sizeof buf;
-
- *--s = '\0';
- if (n < 0)
- m = -n;
- else
- m = n;
- do
- *--s = m%10 + '0';
- while ((m /= 10) != 0);
- if (n < 0)
- *--s = '-';
- return outs(s, f, bp);
-}
-
-static char *outu(unsigned long n, int base, FILE *f, char *bp) {
- char buf[25], *s = buf + sizeof buf;
-
- *--s = '\0';
- do
- *--s = "0123456789abcdef"[n%base];
- while ((n /= base) != 0);
- return outs(s, f, bp);
-}
-void print(const char *fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
- vfprint(stdout, NULL, fmt, ap);
- va_end(ap);
-}
-/* fprint - formatted output to f */
-void fprint(FILE *f, const char *fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
- vfprint(f, NULL, fmt, ap);
- va_end(ap);
-}
-
-/* stringf - formatted output to a saved string */
-char *stringf(const char *fmt, ...) {
- char buf[1024];
- va_list ap;
-
- va_start(ap, fmt);
- vfprint(NULL, buf, fmt, ap);
- va_end(ap);
- return string(buf);
-}
-
-/* vfprint - formatted output to f or string bp */
-void vfprint(FILE *f, char *bp, const char *fmt, va_list ap) {
- for (; *fmt; fmt++)
- if (*fmt == '%')
- switch (*++fmt) {
- case 'd': bp = outd(va_arg(ap, int), f, bp); break;
- case 'D': bp = outd(va_arg(ap, long), f, bp); break;
- case 'U': bp = outu(va_arg(ap, unsigned long), 10, f, bp); break;
- case 'u': bp = outu(va_arg(ap, unsigned), 10, f, bp); break;
- case 'o': bp = outu(va_arg(ap, unsigned), 8, f, bp); break;
- case 'X': bp = outu(va_arg(ap, unsigned long), 16, f, bp); break;
- case 'x': bp = outu(va_arg(ap, unsigned), 16, f, bp); break;
- case 'f': case 'e':
- case 'g': {
- static char format[] = "%f";
- char buf[128];
- format[1] = *fmt;
- sprintf(buf, format, va_arg(ap, double));
- bp = outs(buf, f, bp);
- }
-; break;
- case 's': bp = outs(va_arg(ap, char *), f, bp); break;
- case 'p': {
- void *p = va_arg(ap, void *);
- if (p)
- bp = outs("0x", f, bp);
- bp = outu((unsigned long)p, 16, f, bp);
- break;
- }
- case 'c': if (f) fputc(va_arg(ap, int), f); else *bp++ = va_arg(ap, int); break;
- case 'S': { char *s = va_arg(ap, char *);
- int n = va_arg(ap, int);
- if (s)
- for ( ; n-- > 0; s++)
- if (f) (void)putc(*s, f); else *bp++ = *s;
- } break;
- case 'k': { int t = va_arg(ap, int);
- static char *tokens[] = {
-#define xx(a,b,c,d,e,f,g) g,
-#define yy(a,b,c,d,e,f,g) g,
-#include "token.h"
- };
- assert(tokens[t&0177]);
- bp = outs(tokens[t&0177], f, bp);
- } break;
- case 't': { Type ty = va_arg(ap, Type);
- assert(f);
- outtype(ty ? ty : voidtype, f);
- } break;
- case 'w': { Coordinate *p = va_arg(ap, Coordinate *);
- if (p->file && *p->file) {
- bp = outs(p->file, f, bp);
- bp = outs(":", f, bp);
- }
- bp = outd(p->y, f, bp);
- } break;
- case 'I': { int n = va_arg(ap, int);
- while (--n >= 0)
- if (f) (void)putc(' ', f); else *bp++ = ' ';
- } break;
- default: if (f) (void)putc(*fmt, f); else *bp++ = *fmt; break;
- }
- else if (f)
- (void)putc(*fmt, f);
- else
- *bp++ = *fmt;
- if (!f)
- *bp = '\0';
-}
+#include "c.h" + + +static char *outs(const char *str, FILE *f, char *bp) { + if (f) + fputs(str, f); + else + while (*bp = *str++) + bp++; + return bp; +} + +static char *outd(long n, FILE *f, char *bp) { + unsigned long m; + char buf[25], *s = buf + sizeof buf; + + *--s = '\0'; + if (n < 0) + m = -n; + else + m = n; + do + *--s = m%10 + '0'; + while ((m /= 10) != 0); + if (n < 0) + *--s = '-'; + return outs(s, f, bp); +} + +static char *outu(unsigned long n, int base, FILE *f, char *bp) { + char buf[25], *s = buf + sizeof buf; + + *--s = '\0'; + do + *--s = "0123456789abcdef"[n%base]; + while ((n /= base) != 0); + return outs(s, f, bp); +} +void print(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + vfprint(stdout, NULL, fmt, ap); + va_end(ap); +} +/* fprint - formatted output to f */ +void fprint(FILE *f, const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + vfprint(f, NULL, fmt, ap); + va_end(ap); +} + +/* stringf - formatted output to a saved string */ +char *stringf(const char *fmt, ...) { + char buf[1024]; + va_list ap; + + va_start(ap, fmt); + vfprint(NULL, buf, fmt, ap); + va_end(ap); + return string(buf); +} + +/* vfprint - formatted output to f or string bp */ +void vfprint(FILE *f, char *bp, const char *fmt, va_list ap) { + for (; *fmt; fmt++) + if (*fmt == '%') + switch (*++fmt) { + case 'd': bp = outd(va_arg(ap, int), f, bp); break; + case 'D': bp = outd(va_arg(ap, long), f, bp); break; + case 'U': bp = outu(va_arg(ap, unsigned long), 10, f, bp); break; + case 'u': bp = outu(va_arg(ap, unsigned), 10, f, bp); break; + case 'o': bp = outu(va_arg(ap, unsigned), 8, f, bp); break; + case 'X': bp = outu(va_arg(ap, unsigned long), 16, f, bp); break; + case 'x': bp = outu(va_arg(ap, unsigned), 16, f, bp); break; + case 'f': case 'e': + case 'g': { + static char format[] = "%f"; + char buf[128]; + format[1] = *fmt; + sprintf(buf, format, va_arg(ap, double)); + bp = outs(buf, f, bp); + } +; break; + case 's': bp = outs(va_arg(ap, char *), f, bp); break; + case 'p': { + void *p = va_arg(ap, void *); + if (p) + bp = outs("0x", f, bp); + bp = outu((unsigned long)p, 16, f, bp); + break; + } + case 'c': if (f) fputc(va_arg(ap, int), f); else *bp++ = va_arg(ap, int); break; + case 'S': { char *s = va_arg(ap, char *); + int n = va_arg(ap, int); + if (s) + for ( ; n-- > 0; s++) + if (f) (void)putc(*s, f); else *bp++ = *s; + } break; + case 'k': { int t = va_arg(ap, int); + static char *tokens[] = { +#define xx(a,b,c,d,e,f,g) g, +#define yy(a,b,c,d,e,f,g) g, +#include "token.h" + }; + assert(tokens[t&0177]); + bp = outs(tokens[t&0177], f, bp); + } break; + case 't': { Type ty = va_arg(ap, Type); + assert(f); + outtype(ty ? ty : voidtype, f); + } break; + case 'w': { Coordinate *p = va_arg(ap, Coordinate *); + if (p->file && *p->file) { + bp = outs(p->file, f, bp); + bp = outs(":", f, bp); + } + bp = outd(p->y, f, bp); + } break; + case 'I': { int n = va_arg(ap, int); + while (--n >= 0) + if (f) (void)putc(' ', f); else *bp++ = ' '; + } break; + default: if (f) (void)putc(*fmt, f); else *bp++ = *fmt; break; + } + else if (f) + (void)putc(*fmt, f); + else + *bp++ = *fmt; + if (!f) + *bp = '\0'; +} diff --git a/lcc/src/pass2.c b/lcc/src/pass2.c index f9e41cf..08d73cf 100755 --- a/lcc/src/pass2.c +++ b/lcc/src/pass2.c @@ -1,665 +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);}
-}
+#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);} +} diff --git a/lcc/src/prof.c b/lcc/src/prof.c index 59ce879..a5123b4 100755 --- a/lcc/src/prof.c +++ b/lcc/src/prof.c @@ -1,227 +1,227 @@ -#include "c.h"
-
-
-struct callsite {
- char *file, *name;
- union coordinate {
- unsigned int coord;
- struct { unsigned int y:16,x:10,index:6; } le;
- struct { unsigned int index:6,x:10,y:16; } be;
- } u;
-};
-struct func {
- struct func *link;
- struct caller *callers;
- char *name;
- union coordinate src;
-};
-struct map { /* source code map; 200 coordinates/map */
- int size;
- union coordinate u[200];
-};
-
-int npoints; /* # of execution points if -b specified */
-int ncalled = -1; /* #times prof.out says current function was called */
-static Symbol YYlink; /* symbol for file's struct _bbdata */
-static Symbol YYcounts; /* symbol for _YYcounts if -b specified */
-static List maplist; /* list of struct map *'s */
-static List filelist; /* list of file names */
-static Symbol funclist; /* list of struct func *'s */
-static Symbol afunc; /* current function's struct func */
-
-/* bbcall - build tree to set _callsite at call site *cp, emit call site data */
-static void bbcall(Symbol yycounts, Coordinate *cp, Tree *e) {
- static Symbol caller;
- Value v;
- union coordinate u;
- Symbol p = genident(STATIC, array(voidptype, 0, 0), GLOBAL);
- Tree t = *e;
-
- defglobal(p, LIT);
- defpointer(cp->file ? mkstr(cp->file)->u.c.loc : (Symbol)0);
- defpointer(mkstr(cfunc->name)->u.c.loc);
- if (IR->little_endian) {
- u.le.x = cp->x;
- u.le.y = cp->y;
- } else {
- u.be.x = cp->x;
- u.be.y = cp->y;
- }
- (*IR->defconst)(U, unsignedtype->size, (v.u = u.coord, v));
- if (caller == 0) {
- caller = mksymbol(EXTERN, "_caller", ptr(voidptype));
- caller->defined = 0;
- }
- if (generic((*e)->op) != CALL)
- t = (*e)->kids[0];
- assert(generic(t->op) == CALL);
- t = tree(t->op, t->type,
- tree(RIGHT, t->kids[0]->type,
- t->kids[0],
- tree(RIGHT, t->kids[0]->type, asgn(caller, idtree(p)), t->kids[0])),
- t->kids[1]);
- if (generic((*e)->op) != CALL)
- t = tree((*e)->op, (*e)->type, t, (*e)->kids[1]);
- *e = t;
-}
-
-/* bbentry - return tree for _prologue(&afunc, &YYlink)' */
-static void bbentry(Symbol yylink, Symbol f) {
- static Symbol prologue;
-
- afunc = genident(STATIC, array(voidptype, 4, 0), GLOBAL);
- if (prologue == 0) {
- prologue = mksymbol(EXTERN, "_prologue", ftype(inttype, voidptype));
- prologue->defined = 0;
- }
- walk(vcall(prologue, voidtype, pointer(idtree(afunc)), pointer(idtree(yylink)), NULL), 0, 0);
-
-}
-
-/* bbexit - return tree for _epilogue(&afunc)' */
-static void bbexit(Symbol yylink, Symbol f, Tree e) {
- static Symbol epilogue;
-
- if (epilogue == 0) {
- epilogue = mksymbol(EXTERN, "_epilogue", ftype(inttype, voidptype));
- epilogue->defined = 0;
- }
- walk(vcall(epilogue, voidtype, pointer(idtree(afunc)), NULL), 0, 0);
-}
-
-/* bbfile - add file to list of file names, return its index */
-static int bbfile(char *file) {
- if (file) {
- List lp;
- int i = 1;
- if ((lp = filelist) != NULL)
- do {
- lp = lp->link;
- if (((Symbol)lp->x)->u.c.v.p == file)
- return i;
- i++;
- } while (lp != filelist);
- filelist = append(mkstr(file), filelist);
- return i;
- }
- return 0;
-}
-
-/* bbfunc - emit function name and src coordinates */
-static void bbfunc(Symbol yylink, Symbol f) {
- Value v;
- union coordinate u;
-
- defglobal(afunc, DATA);
- defpointer(funclist);
- defpointer(NULL);
- defpointer(mkstr(f->name)->u.c.loc);
- if (IR->little_endian) {
- u.le.x = f->u.f.pt.x;
- u.le.y = f->u.f.pt.y;
- u.le.index = bbfile(f->u.f.pt.file);
- } else {
- u.be.x = f->u.f.pt.x;
- u.be.y = f->u.f.pt.y;
- u.be.index = bbfile(f->u.f.pt.file);
- }
- (*IR->defconst)(U, unsignedtype->size, (v.u = u.coord, v));
- funclist = afunc;
-}
-
-/* bbincr - build tree to increment execution point at *cp */
-static void bbincr(Symbol yycounts, Coordinate *cp, Tree *e) {
- struct map *mp = maplist->x;
- Tree t;
-
- /* append *cp to source map */
- if (mp->size >= NELEMS(mp->u)) {
- NEW(mp, PERM);
- mp->size = 0;
- maplist = append(mp, maplist);
- }
- if (IR->little_endian) {
- mp->u[mp->size].le.x = cp->x;
- mp->u[mp->size].le.y = cp->y;
- mp->u[mp->size++].le.index = bbfile(cp->file);
- } else {
- mp->u[mp->size].be.x = cp->x;
- mp->u[mp->size].be.y = cp->y;
- mp->u[mp->size++].be.index = bbfile(cp->file);
- }
- t = incr('+', rvalue((*optree['+'])(ADD, pointer(idtree(yycounts)),
- consttree(npoints++, inttype))), consttree(1, inttype));
- if (*e)
- *e = tree(RIGHT, (*e)->type, t, *e);
- else
- *e = t;
-}
-
-/* bbvars - emit definition for basic block counting data */
-static void bbvars(Symbol yylink) {
- int i, j, n = npoints;
- Value v;
- struct map **mp;
- Symbol coords, files, *p;
-
- if (!YYcounts && !yylink)
- return;
- if (YYcounts) {
- if (n <= 0)
- n = 1;
- YYcounts->type = array(unsignedtype, n, 0);
- defglobal(YYcounts, BSS);
- }
- files = genident(STATIC, array(charptype, 1, 0), GLOBAL);
- defglobal(files, LIT);
- for (p = ltov(&filelist, PERM); *p; p++)
- defpointer((*p)->u.c.loc);
- defpointer(NULL);
- coords = genident(STATIC, array(unsignedtype, n, 0), GLOBAL);
- defglobal(coords, LIT);
- for (i = n, mp = ltov(&maplist, PERM); *mp; i -= (*mp)->size, mp++)
- for (j = 0; j < (*mp)->size; j++)
- (*IR->defconst)(U, unsignedtype->size, (v.u = (*mp)->u[j].coord, v));
- if (i > 0)
- (*IR->space)(i*coords->type->type->size);
- defpointer(NULL);
- defglobal(yylink, DATA);
- defpointer(NULL);
- (*IR->defconst)(U, unsignedtype->size, (v.u = n, v));
- defpointer(YYcounts);
- defpointer(coords);
- defpointer(files);
- defpointer(funclist);
-}
-
-/* profInit - initialize basic block profiling options */
-void prof_init(int argc, char *argv[]) {
- int i;
- static int inited;
-
- if (inited)
- return;
- inited = 1;
- type_init(argc, argv);
- if (IR)
- for (i = 1; i < argc; i++)
- if (strncmp(argv[i], "-a", 2) == 0) {
- if (ncalled == -1
- && process(argv[i][2] ? &argv[i][2] : "prof.out") > 0)
- ncalled = 0;
- } else if ((strcmp(argv[i], "-b") == 0
- || strcmp(argv[i], "-C") == 0) && YYlink == 0) {
- YYlink = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL);
- attach((Apply)bbentry, YYlink, &events.entry);
- attach((Apply)bbexit, YYlink, &events.returns);
- attach((Apply)bbfunc, YYlink, &events.exit);
- attach((Apply)bbvars, YYlink, &events.end);
- if (strcmp(argv[i], "-b") == 0) {
- YYcounts = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL);
- maplist = append(allocate(sizeof (struct map), PERM), maplist);
- ((struct map *)maplist->x)->size = 0;
- attach((Apply)bbcall, YYcounts, &events.calls);
- attach((Apply)bbincr, YYcounts, &events.points);
- }
- }
-}
+#include "c.h" + + +struct callsite { + char *file, *name; + union coordinate { + unsigned int coord; + struct { unsigned int y:16,x:10,index:6; } le; + struct { unsigned int index:6,x:10,y:16; } be; + } u; +}; +struct func { + struct func *link; + struct caller *callers; + char *name; + union coordinate src; +}; +struct map { /* source code map; 200 coordinates/map */ + int size; + union coordinate u[200]; +}; + +int npoints; /* # of execution points if -b specified */ +int ncalled = -1; /* #times prof.out says current function was called */ +static Symbol YYlink; /* symbol for file's struct _bbdata */ +static Symbol YYcounts; /* symbol for _YYcounts if -b specified */ +static List maplist; /* list of struct map *'s */ +static List filelist; /* list of file names */ +static Symbol funclist; /* list of struct func *'s */ +static Symbol afunc; /* current function's struct func */ + +/* bbcall - build tree to set _callsite at call site *cp, emit call site data */ +static void bbcall(Symbol yycounts, Coordinate *cp, Tree *e) { + static Symbol caller; + Value v; + union coordinate u; + Symbol p = genident(STATIC, array(voidptype, 0, 0), GLOBAL); + Tree t = *e; + + defglobal(p, LIT); + defpointer(cp->file ? mkstr(cp->file)->u.c.loc : (Symbol)0); + defpointer(mkstr(cfunc->name)->u.c.loc); + if (IR->little_endian) { + u.le.x = cp->x; + u.le.y = cp->y; + } else { + u.be.x = cp->x; + u.be.y = cp->y; + } + (*IR->defconst)(U, unsignedtype->size, (v.u = u.coord, v)); + if (caller == 0) { + caller = mksymbol(EXTERN, "_caller", ptr(voidptype)); + caller->defined = 0; + } + if (generic((*e)->op) != CALL) + t = (*e)->kids[0]; + assert(generic(t->op) == CALL); + t = tree(t->op, t->type, + tree(RIGHT, t->kids[0]->type, + t->kids[0], + tree(RIGHT, t->kids[0]->type, asgn(caller, idtree(p)), t->kids[0])), + t->kids[1]); + if (generic((*e)->op) != CALL) + t = tree((*e)->op, (*e)->type, t, (*e)->kids[1]); + *e = t; +} + +/* bbentry - return tree for _prologue(&afunc, &YYlink)' */ +static void bbentry(Symbol yylink, Symbol f) { + static Symbol prologue; + + afunc = genident(STATIC, array(voidptype, 4, 0), GLOBAL); + if (prologue == 0) { + prologue = mksymbol(EXTERN, "_prologue", ftype(inttype, voidptype)); + prologue->defined = 0; + } + walk(vcall(prologue, voidtype, pointer(idtree(afunc)), pointer(idtree(yylink)), NULL), 0, 0); + +} + +/* bbexit - return tree for _epilogue(&afunc)' */ +static void bbexit(Symbol yylink, Symbol f, Tree e) { + static Symbol epilogue; + + if (epilogue == 0) { + epilogue = mksymbol(EXTERN, "_epilogue", ftype(inttype, voidptype)); + epilogue->defined = 0; + } + walk(vcall(epilogue, voidtype, pointer(idtree(afunc)), NULL), 0, 0); +} + +/* bbfile - add file to list of file names, return its index */ +static int bbfile(char *file) { + if (file) { + List lp; + int i = 1; + if ((lp = filelist) != NULL) + do { + lp = lp->link; + if (((Symbol)lp->x)->u.c.v.p == file) + return i; + i++; + } while (lp != filelist); + filelist = append(mkstr(file), filelist); + return i; + } + return 0; +} + +/* bbfunc - emit function name and src coordinates */ +static void bbfunc(Symbol yylink, Symbol f) { + Value v; + union coordinate u; + + defglobal(afunc, DATA); + defpointer(funclist); + defpointer(NULL); + defpointer(mkstr(f->name)->u.c.loc); + if (IR->little_endian) { + u.le.x = f->u.f.pt.x; + u.le.y = f->u.f.pt.y; + u.le.index = bbfile(f->u.f.pt.file); + } else { + u.be.x = f->u.f.pt.x; + u.be.y = f->u.f.pt.y; + u.be.index = bbfile(f->u.f.pt.file); + } + (*IR->defconst)(U, unsignedtype->size, (v.u = u.coord, v)); + funclist = afunc; +} + +/* bbincr - build tree to increment execution point at *cp */ +static void bbincr(Symbol yycounts, Coordinate *cp, Tree *e) { + struct map *mp = maplist->x; + Tree t; + + /* append *cp to source map */ + if (mp->size >= NELEMS(mp->u)) { + NEW(mp, PERM); + mp->size = 0; + maplist = append(mp, maplist); + } + if (IR->little_endian) { + mp->u[mp->size].le.x = cp->x; + mp->u[mp->size].le.y = cp->y; + mp->u[mp->size++].le.index = bbfile(cp->file); + } else { + mp->u[mp->size].be.x = cp->x; + mp->u[mp->size].be.y = cp->y; + mp->u[mp->size++].be.index = bbfile(cp->file); + } + t = incr('+', rvalue((*optree['+'])(ADD, pointer(idtree(yycounts)), + consttree(npoints++, inttype))), consttree(1, inttype)); + if (*e) + *e = tree(RIGHT, (*e)->type, t, *e); + else + *e = t; +} + +/* bbvars - emit definition for basic block counting data */ +static void bbvars(Symbol yylink) { + int i, j, n = npoints; + Value v; + struct map **mp; + Symbol coords, files, *p; + + if (!YYcounts && !yylink) + return; + if (YYcounts) { + if (n <= 0) + n = 1; + YYcounts->type = array(unsignedtype, n, 0); + defglobal(YYcounts, BSS); + } + files = genident(STATIC, array(charptype, 1, 0), GLOBAL); + defglobal(files, LIT); + for (p = ltov(&filelist, PERM); *p; p++) + defpointer((*p)->u.c.loc); + defpointer(NULL); + coords = genident(STATIC, array(unsignedtype, n, 0), GLOBAL); + defglobal(coords, LIT); + for (i = n, mp = ltov(&maplist, PERM); *mp; i -= (*mp)->size, mp++) + for (j = 0; j < (*mp)->size; j++) + (*IR->defconst)(U, unsignedtype->size, (v.u = (*mp)->u[j].coord, v)); + if (i > 0) + (*IR->space)(i*coords->type->type->size); + defpointer(NULL); + defglobal(yylink, DATA); + defpointer(NULL); + (*IR->defconst)(U, unsignedtype->size, (v.u = n, v)); + defpointer(YYcounts); + defpointer(coords); + defpointer(files); + defpointer(funclist); +} + +/* profInit - initialize basic block profiling options */ +void prof_init(int argc, char *argv[]) { + int i; + static int inited; + + if (inited) + return; + inited = 1; + type_init(argc, argv); + if (IR) + for (i = 1; i < argc; i++) + if (strncmp(argv[i], "-a", 2) == 0) { + if (ncalled == -1 + && process(argv[i][2] ? &argv[i][2] : "prof.out") > 0) + ncalled = 0; + } else if ((strcmp(argv[i], "-b") == 0 + || strcmp(argv[i], "-C") == 0) && YYlink == 0) { + YYlink = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL); + attach((Apply)bbentry, YYlink, &events.entry); + attach((Apply)bbexit, YYlink, &events.returns); + attach((Apply)bbfunc, YYlink, &events.exit); + attach((Apply)bbvars, YYlink, &events.end); + if (strcmp(argv[i], "-b") == 0) { + YYcounts = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL); + maplist = append(allocate(sizeof (struct map), PERM), maplist); + ((struct map *)maplist->x)->size = 0; + attach((Apply)bbcall, YYcounts, &events.calls); + attach((Apply)bbincr, YYcounts, &events.points); + } + } +} diff --git a/lcc/src/profio.c b/lcc/src/profio.c index 3e74770..e1ce8da 100755 --- a/lcc/src/profio.c +++ b/lcc/src/profio.c @@ -1,276 +1,276 @@ -/* C compiler: prof.out input
-
-prof.out format:
-#files
- name
- ... (#files-1 times)
-#functions
- name file# x y count caller file x y
- ... (#functions-1 times)
-#points
- file# x y count
- ... (#points-1 times)
-*/
-#include "c.h"
-
-
-struct count { /* count data: */
- int x, y; /* source coordinate */
- int count; /* associated execution count */
-};
-
-#define MAXTOKEN 64
-
-struct file { /* per-file prof.out data: */
- struct file *link; /* link to next file */
- char *name; /* file name */
- int size; /* size of counts[] */
- int count; /* counts[0..count-1] hold valid data */
- struct count *counts; /* count data */
- struct func { /* function data: */
- struct func *link; /* link to next function */
- char *name; /* function name */
- struct count count; /* total number of calls */
- struct caller { /* caller data: */
- struct caller *link; /* link to next caller */
- char *name; /* caller's name */
- char *file; /* call site: file, x, y */
- int x, y;
- int count; /* number of calls from this site */
- } *callers;
- } *funcs; /* list of functions */
-} *filelist;
-FILE *fp;
-
-/* acaller - add caller and site (file,x,y) to callee's callers list */
-static void acaller(char *caller, char *file, int x, int y, int count, struct func *callee) {
- struct caller *q;
-
- assert(callee);
- for (q = callee->callers; q && (caller != q->name
- || file != q->file || x != q->x || y != q->y); q = q->link)
- ;
- if (!q) {
- struct caller **r;
- NEW(q, PERM);
- q->name = caller;
- q->file = file;
- q->x = x;
- q->y = y;
- q->count = 0;
- for (r = &callee->callers; *r && (strcmp(q->name, (*r)->name) > 0
- || strcmp(q->file, (*r)->file) > 0 || q->y > (*r)->y || q->y > (*r)->y); r = &(*r)->link)
- ;
- q->link = *r;
- *r = q;
- }
- q->count += count;
-}
-
-/* compare - return <0, 0, >0 if a<b, a==b, a>b, resp. */
-static int compare(struct count *a, struct count *b) {
- if (a->y == b->y)
- return a->x - b->x;
- return a->y - b->y;
-}
-
-/* findfile - return file name's file list entry, or 0 */
-static struct file *findfile(char *name) {
- struct file *p;
-
- for (p = filelist; p; p = p->link)
- if (p->name == name)
- return p;
- return 0;
-}
-
-/* afunction - add function name and its data to file's function list */
-static struct func *afunction(char *name, char *file, int x, int y, int count) {
- struct file *p = findfile(file);
- struct func *q;
-
- assert(p);
- for (q = p->funcs; q && name != q->name; q = q->link)
- ;
- if (!q) {
- struct func **r;
- NEW(q, PERM);
- q->name = name;
- q->count.x = x;
- q->count.y = y;
- q->count.count = 0;
- q->callers = 0;
- for (r = &p->funcs; *r && compare(&q->count, &(*r)->count) > 0; r = &(*r)->link)
- ;
- q->link = *r;
- *r = q;
- }
- q->count.count += count;
- return q;
-}
-
-/* apoint - append execution point i to file's data */
-static void apoint(int i, char *file, int x, int y, int count) {
- struct file *p = findfile(file);
-
- assert(p);
- if (i >= p->size) {
- int j;
- if (p->size == 0) {
- p->size = i >= 200 ? 2*i : 200;
- p->counts = newarray(p->size, sizeof *p->counts, PERM);
- } else {
- struct count *new;
- p->size = 2*i;
- new = newarray(p->size, sizeof *new, PERM);
- for (j = 0; j < p->count; j++)
- new[j] = p->counts[j];
- p->counts = new;
- }
- for (j = p->count; j < p->size; j++) {
- static struct count z;
- p->counts[j] = z;
- }
- }
- p->counts[i].x = x;
- p->counts[i].y = y;
- p->counts[i].count += count;
- if (i >= p->count)
- p->count = i + 1;
-}
-
-/* findcount - return count associated with (file,x,y) or -1 */
-int findcount(char *file, int x, int y) {
- static struct file *cursor;
-
- if (cursor == 0 || cursor->name != file)
- cursor = findfile(file);
- if (cursor) {
- int l, u;
- struct count *c = cursor->counts;
- for (l = 0, u = cursor->count - 1; l <= u; ) {
- int k = (l + u)/2;
- if (c[k].y > y || c[k].y == y && c[k].x > x)
- u = k - 1;
- else if (c[k].y < y || c[k].y == y && c[k].x < x)
- l = k + 1;
- else
- return c[k].count;
- }
- }
- return -1;
-}
-
-/* findfunc - return count associated with function name in file or -1 */
-int findfunc(char *name, char *file) {
- static struct file *cursor;
-
- if (cursor == 0 || cursor->name != file)
- cursor = findfile(file);
- if (cursor) {
- struct func *p;
- for (p = cursor->funcs; p; p = p->link)
- if (p->name == name)
- return p->count.count;
- }
- return -1;
-}
-
-/* getd - read a nonnegative number */
-static int getd(void) {
- int c, n = 0;
-
- while ((c = getc(fp)) != EOF && (c == ' ' || c == '\n' || c == '\t'))
- ;
- if (c >= '0' && c <= '9') {
- do
- n = 10*n + (c - '0');
- while ((c = getc(fp)) >= '0' && c <= '9');
- return n;
- }
- return -1;
-}
-
-/* getstr - read a string */
-static char *getstr(void) {
- int c;
- char buf[MAXTOKEN], *s = buf;
-
- while ((c = getc(fp)) != EOF && c != ' ' && c != '\n' && c != '\t')
- if (s - buf < (int)sizeof buf - 2)
- *s++ = c;
- *s = 0;
- return s == buf ? (char *)0 : string(buf);
-}
-
-/* gather - read prof.out data from fd */
-static int gather(void) {
- int i, nfiles, nfuncs, npoints;
- char *files[64];
-
- if ((nfiles = getd()) < 0)
- return 0;
- assert(nfiles < NELEMS(files));
- for (i = 0; i < nfiles; i++) {
- if ((files[i] = getstr()) == 0)
- return -1;
- if (!findfile(files[i])) {
- struct file *new;
- NEW(new, PERM);
- new->name = files[i];
- new->size = new->count = 0;
- new->counts = 0;
- new->funcs = 0;
- new->link = filelist;
- filelist = new;
- }
- }
- if ((nfuncs = getd()) < 0)
- return -1;
- for (i = 0; i < nfuncs; i++) {
- struct func *q;
- char *name, *file;
- int f, x, y, count;
- if ((name = getstr()) == 0 || (f = getd()) <= 0
- || (x = getd()) < 0 || (y = getd()) < 0 || (count = getd()) < 0)
- return -1;
- q = afunction(name, files[f-1], x, y, count);
- if ((name = getstr()) == 0 || (file = getstr()) == 0
- || (x = getd()) < 0 || (y = getd()) < 0)
- return -1;
- if (*name != '?')
- acaller(name, file, x, y, count, q);
- }
- if ((npoints = getd()) < 0)
- return -1;
- for (i = 0; i < npoints; i++) {
- int f, x, y, count;
- if ((f = getd()) < 0 || (x = getd()) < 0 || (y = getd()) < 0
- || (count = getd()) < 0)
- return -1;
- if (f)
- apoint(i, files[f-1], x, y, count);
- }
- return 1;
-}
-
-/* process - read prof.out data from file */
-int process(char *file) {
- int more;
-
- if ((fp = fopen(file, "r")) != NULL) {
- struct file *p;
- while ((more = gather()) > 0)
- ;
- fclose(fp);
- if (more < 0)
- return more;
- for (p = filelist; p; p = p->link)
- qsort(p->counts, p->count, sizeof *p->counts,
- (int (*)(const void *, const void *))
- compare);
-
- return 1;
- }
- return 0;
-}
+/* C compiler: prof.out input + +prof.out format: +#files + name + ... (#files-1 times) +#functions + name file# x y count caller file x y + ... (#functions-1 times) +#points + file# x y count + ... (#points-1 times) +*/ +#include "c.h" + + +struct count { /* count data: */ + int x, y; /* source coordinate */ + int count; /* associated execution count */ +}; + +#define MAXTOKEN 64 + +struct file { /* per-file prof.out data: */ + struct file *link; /* link to next file */ + char *name; /* file name */ + int size; /* size of counts[] */ + int count; /* counts[0..count-1] hold valid data */ + struct count *counts; /* count data */ + struct func { /* function data: */ + struct func *link; /* link to next function */ + char *name; /* function name */ + struct count count; /* total number of calls */ + struct caller { /* caller data: */ + struct caller *link; /* link to next caller */ + char *name; /* caller's name */ + char *file; /* call site: file, x, y */ + int x, y; + int count; /* number of calls from this site */ + } *callers; + } *funcs; /* list of functions */ +} *filelist; +FILE *fp; + +/* acaller - add caller and site (file,x,y) to callee's callers list */ +static void acaller(char *caller, char *file, int x, int y, int count, struct func *callee) { + struct caller *q; + + assert(callee); + for (q = callee->callers; q && (caller != q->name + || file != q->file || x != q->x || y != q->y); q = q->link) + ; + if (!q) { + struct caller **r; + NEW(q, PERM); + q->name = caller; + q->file = file; + q->x = x; + q->y = y; + q->count = 0; + for (r = &callee->callers; *r && (strcmp(q->name, (*r)->name) > 0 + || strcmp(q->file, (*r)->file) > 0 || q->y > (*r)->y || q->y > (*r)->y); r = &(*r)->link) + ; + q->link = *r; + *r = q; + } + q->count += count; +} + +/* compare - return <0, 0, >0 if a<b, a==b, a>b, resp. */ +static int compare(struct count *a, struct count *b) { + if (a->y == b->y) + return a->x - b->x; + return a->y - b->y; +} + +/* findfile - return file name's file list entry, or 0 */ +static struct file *findfile(char *name) { + struct file *p; + + for (p = filelist; p; p = p->link) + if (p->name == name) + return p; + return 0; +} + +/* afunction - add function name and its data to file's function list */ +static struct func *afunction(char *name, char *file, int x, int y, int count) { + struct file *p = findfile(file); + struct func *q; + + assert(p); + for (q = p->funcs; q && name != q->name; q = q->link) + ; + if (!q) { + struct func **r; + NEW(q, PERM); + q->name = name; + q->count.x = x; + q->count.y = y; + q->count.count = 0; + q->callers = 0; + for (r = &p->funcs; *r && compare(&q->count, &(*r)->count) > 0; r = &(*r)->link) + ; + q->link = *r; + *r = q; + } + q->count.count += count; + return q; +} + +/* apoint - append execution point i to file's data */ +static void apoint(int i, char *file, int x, int y, int count) { + struct file *p = findfile(file); + + assert(p); + if (i >= p->size) { + int j; + if (p->size == 0) { + p->size = i >= 200 ? 2*i : 200; + p->counts = newarray(p->size, sizeof *p->counts, PERM); + } else { + struct count *new; + p->size = 2*i; + new = newarray(p->size, sizeof *new, PERM); + for (j = 0; j < p->count; j++) + new[j] = p->counts[j]; + p->counts = new; + } + for (j = p->count; j < p->size; j++) { + static struct count z; + p->counts[j] = z; + } + } + p->counts[i].x = x; + p->counts[i].y = y; + p->counts[i].count += count; + if (i >= p->count) + p->count = i + 1; +} + +/* findcount - return count associated with (file,x,y) or -1 */ +int findcount(char *file, int x, int y) { + static struct file *cursor; + + if (cursor == 0 || cursor->name != file) + cursor = findfile(file); + if (cursor) { + int l, u; + struct count *c = cursor->counts; + for (l = 0, u = cursor->count - 1; l <= u; ) { + int k = (l + u)/2; + if (c[k].y > y || c[k].y == y && c[k].x > x) + u = k - 1; + else if (c[k].y < y || c[k].y == y && c[k].x < x) + l = k + 1; + else + return c[k].count; + } + } + return -1; +} + +/* findfunc - return count associated with function name in file or -1 */ +int findfunc(char *name, char *file) { + static struct file *cursor; + + if (cursor == 0 || cursor->name != file) + cursor = findfile(file); + if (cursor) { + struct func *p; + for (p = cursor->funcs; p; p = p->link) + if (p->name == name) + return p->count.count; + } + return -1; +} + +/* getd - read a nonnegative number */ +static int getd(void) { + int c, n = 0; + + while ((c = getc(fp)) != EOF && (c == ' ' || c == '\n' || c == '\t')) + ; + if (c >= '0' && c <= '9') { + do + n = 10*n + (c - '0'); + while ((c = getc(fp)) >= '0' && c <= '9'); + return n; + } + return -1; +} + +/* getstr - read a string */ +static char *getstr(void) { + int c; + char buf[MAXTOKEN], *s = buf; + + while ((c = getc(fp)) != EOF && c != ' ' && c != '\n' && c != '\t') + if (s - buf < (int)sizeof buf - 2) + *s++ = c; + *s = 0; + return s == buf ? (char *)0 : string(buf); +} + +/* gather - read prof.out data from fd */ +static int gather(void) { + int i, nfiles, nfuncs, npoints; + char *files[64]; + + if ((nfiles = getd()) < 0) + return 0; + assert(nfiles < NELEMS(files)); + for (i = 0; i < nfiles; i++) { + if ((files[i] = getstr()) == 0) + return -1; + if (!findfile(files[i])) { + struct file *new; + NEW(new, PERM); + new->name = files[i]; + new->size = new->count = 0; + new->counts = 0; + new->funcs = 0; + new->link = filelist; + filelist = new; + } + } + if ((nfuncs = getd()) < 0) + return -1; + for (i = 0; i < nfuncs; i++) { + struct func *q; + char *name, *file; + int f, x, y, count; + if ((name = getstr()) == 0 || (f = getd()) <= 0 + || (x = getd()) < 0 || (y = getd()) < 0 || (count = getd()) < 0) + return -1; + q = afunction(name, files[f-1], x, y, count); + if ((name = getstr()) == 0 || (file = getstr()) == 0 + || (x = getd()) < 0 || (y = getd()) < 0) + return -1; + if (*name != '?') + acaller(name, file, x, y, count, q); + } + if ((npoints = getd()) < 0) + return -1; + for (i = 0; i < npoints; i++) { + int f, x, y, count; + if ((f = getd()) < 0 || (x = getd()) < 0 || (y = getd()) < 0 + || (count = getd()) < 0) + return -1; + if (f) + apoint(i, files[f-1], x, y, count); + } + return 1; +} + +/* process - read prof.out data from file */ +int process(char *file) { + int more; + + if ((fp = fopen(file, "r")) != NULL) { + struct file *p; + while ((more = gather()) > 0) + ; + fclose(fp); + if (more < 0) + return more; + for (p = filelist; p; p = p->link) + qsort(p->counts, p->count, sizeof *p->counts, + (int (*)(const void *, const void *)) + compare); + + return 1; + } + return 0; +} diff --git a/lcc/src/rcc.asdl b/lcc/src/rcc.asdl index 833478e..398e0d0 100755 --- a/lcc/src/rcc.asdl +++ b/lcc/src/rcc.asdl @@ -1,70 +1,70 @@ --- lcc IR
--- $Id: rcc.asdl 145 2001-10-17 21:53:10Z timo $
-module rcc {
-
--- Pickles start with an int version number, followed by rcc.program
-
-program = (int nuids,int nlabels,item* items,interface* interfaces,int argc,string *argv)
-
-real = (int msb,int lsb)
-
-item = Symbol(symbol symbol)
- | Type(type type)
- attributes(int uid)
-
-symbol = (identifier id,int type,int scope,int sclass,int ref,int flags)
-
-field = (identifier id,int type,int offset,int bitsize,int lsb)
-
-enum = (identifier id,int value)
-
-type = INT
- | UNSIGNED
- | FLOAT
- | VOID
- | POINTER(int type)
- | ENUM(identifier tag,enum* ids)
- | STRUCT(identifier tag,field* fields)
- | UNION(identifier tag,field* fields)
- | ARRAY(int type)
- | FUNCTION(int type,int* formals)
- | CONST(int type)
- | VOLATILE(int type)
- attributes(int size,int align)
-
-interface = Export(int p)
- | Import(int p)
- | Global(int p,int seg)
- | Local(int uid,symbol p) -- includes formals
- | Address(int uid,symbol q,int p,int n)
- | Segment(int seg)
- | Defaddress(int p)
- | Deflabel(int label)
- | Defconst(int suffix,int size,int value)
- | Defconstf(int size,real value)
- | Defstring(string s)
- | Space(int n)
- | Function(int f,int* caller,int* callee,int ncalls,interface* codelist)
- | Blockbeg
- | Blockend
- | Forest(node* nodes)
-
-node = CNST(int value)
- | CNSTF(real value)
- | ARG(node left,int len,int align)
- | ASGN(node left,node right,int len,int align)
- | CVT(int op,node left,int fromsize)
- | CALL(node left,int type)
- | CALLB(node left,node right,int type)
- | RET
- | ADDRG(int uid)
- | ADDRL(int uid)
- | ADDRF(int uid)
- | Unary(int op,node left) -- INDIR RET JUMP NEG BCOM
- | Binary(int op,node left,node right) -- ADD SUB DIV MUL MOD BOR BAND BXOR RSH LSH
- | Compare(int op,node left,node right,int label) -- EQ NE GT GE LE LT
- | LABEL(int label)
- | BRANCH(int label)
- | CSE(int uid,node node)
- attributes(int suffix,int size)
-}
+-- lcc IR +-- $Id: rcc.asdl 145 2001-10-17 21:53:10Z timo $ +module rcc { + +-- Pickles start with an int version number, followed by rcc.program + +program = (int nuids,int nlabels,item* items,interface* interfaces,int argc,string *argv) + +real = (int msb,int lsb) + +item = Symbol(symbol symbol) + | Type(type type) + attributes(int uid) + +symbol = (identifier id,int type,int scope,int sclass,int ref,int flags) + +field = (identifier id,int type,int offset,int bitsize,int lsb) + +enum = (identifier id,int value) + +type = INT + | UNSIGNED + | FLOAT + | VOID + | POINTER(int type) + | ENUM(identifier tag,enum* ids) + | STRUCT(identifier tag,field* fields) + | UNION(identifier tag,field* fields) + | ARRAY(int type) + | FUNCTION(int type,int* formals) + | CONST(int type) + | VOLATILE(int type) + attributes(int size,int align) + +interface = Export(int p) + | Import(int p) + | Global(int p,int seg) + | Local(int uid,symbol p) -- includes formals + | Address(int uid,symbol q,int p,int n) + | Segment(int seg) + | Defaddress(int p) + | Deflabel(int label) + | Defconst(int suffix,int size,int value) + | Defconstf(int size,real value) + | Defstring(string s) + | Space(int n) + | Function(int f,int* caller,int* callee,int ncalls,interface* codelist) + | Blockbeg + | Blockend + | Forest(node* nodes) + +node = CNST(int value) + | CNSTF(real value) + | ARG(node left,int len,int align) + | ASGN(node left,node right,int len,int align) + | CVT(int op,node left,int fromsize) + | CALL(node left,int type) + | CALLB(node left,node right,int type) + | RET + | ADDRG(int uid) + | ADDRL(int uid) + | ADDRF(int uid) + | Unary(int op,node left) -- INDIR RET JUMP NEG BCOM + | Binary(int op,node left,node right) -- ADD SUB DIV MUL MOD BOR BAND BXOR RSH LSH + | Compare(int op,node left,node right,int label) -- EQ NE GT GE LE LT + | LABEL(int label) + | BRANCH(int label) + | CSE(int uid,node node) + attributes(int suffix,int size) +} diff --git a/lcc/src/run.sh b/lcc/src/run.sh index 432872e..819e898 100755 --- a/lcc/src/run.sh +++ b/lcc/src/run.sh @@ -1,51 +1,51 @@ -#!/bin/sh
-# run .../target/os/tst/foo.s [ remotehost ]
-
-# set -x
-target=`echo $1 | awk -F/ '{ print $(NF-3) }'`
-os=`echo $1 | awk -F/ '{ print $(NF-2) }'`
-dir=$target/$os
-
-case "$1" in
-*symbolic/irix*) idir=include/mips/irix; remotehost=noexecute ;;
-*symbolic/osf*) idir=include/alpha/osf; remotehost=noexecute ;;
-*) idir=include/$dir; remotehost=${2-$REMOTEHOST} ;;
-esac
-
-if [ ! -d "$target/$os" -o ! -d "$idir" ]; then
- echo 2>&1 $0: unknown combination '"'$target/$os'"'
- exit 1
-fi
-
-C=`basename $1 .s`
-BUILDDIR=${BUILDDIR-.} LCC="${LCC-${BUILDDIR}/lcc} -Wo-lccdir=$BUILDDIR"
-TSTDIR=${TSTDIR-${BUILDDIR}/$dir/tst}
-if [ ! -d $TSTDIR ]; then mkdir -p $TSTDIR; fi
-
-echo ${BUILDDIR}/rcc$EXE -target=$target/$os $1: 1>&2
-$LCC -S -I$idir -Ualpha -Usun -Uvax -Umips -Ux86 \
- -Wf-errout=$TSTDIR/$C.2 -D$target -Wf-g0 \
- -Wf-target=$target/$os -o $1 tst/$C.c
-if [ $? != 0 ]; then remotehost=noexecute; fi
-if [ -r $dir/tst/$C.2bk ]; then
- diff $dir/tst/$C.2bk $TSTDIR/$C.2
-fi
-if [ -r $dir/tst/$C.sbk ]; then
- if diff $dir/tst/$C.sbk $TSTDIR/$C.s; then exit 0; fi
-fi
-
-case "$remotehost" in
-noexecute) exit 0 ;;
-""|"-") $LCC -o $TSTDIR/$C$EXE $1; $TSTDIR/$C$EXE <tst/$C.0 >$TSTDIR/$C.1 ;;
-*) rcp $1 $remotehost:
- if expr "$remotehost" : '.*@' >/dev/null ; then
- remotehost="`expr $remotehost : '.*@\(.*\)'` -l `expr $remotehost : '\(.*\)@'`"
- fi
- rsh $remotehost "cc -o $C$EXE $C.s -lm;./$C$EXE;rm -f $C$EXE $C.[so]" <tst/$C.0 >$TSTDIR/$C.1
- ;;
-esac
-if [ -r $dir/tst/$C.1bk ]; then
- diff $dir/tst/$C.1bk $TSTDIR/$C.1
- exit $?
-fi
-exit 0
+#!/bin/sh +# run .../target/os/tst/foo.s [ remotehost ] + +# set -x +target=`echo $1 | awk -F/ '{ print $(NF-3) }'` +os=`echo $1 | awk -F/ '{ print $(NF-2) }'` +dir=$target/$os + +case "$1" in +*symbolic/irix*) idir=include/mips/irix; remotehost=noexecute ;; +*symbolic/osf*) idir=include/alpha/osf; remotehost=noexecute ;; +*) idir=include/$dir; remotehost=${2-$REMOTEHOST} ;; +esac + +if [ ! -d "$target/$os" -o ! -d "$idir" ]; then + echo 2>&1 $0: unknown combination '"'$target/$os'"' + exit 1 +fi + +C=`basename $1 .s` +BUILDDIR=${BUILDDIR-.} LCC="${LCC-${BUILDDIR}/lcc} -Wo-lccdir=$BUILDDIR" +TSTDIR=${TSTDIR-${BUILDDIR}/$dir/tst} +if [ ! -d $TSTDIR ]; then mkdir -p $TSTDIR; fi + +echo ${BUILDDIR}/rcc$EXE -target=$target/$os $1: 1>&2 +$LCC -S -I$idir -Ualpha -Usun -Uvax -Umips -Ux86 \ + -Wf-errout=$TSTDIR/$C.2 -D$target -Wf-g0 \ + -Wf-target=$target/$os -o $1 tst/$C.c +if [ $? != 0 ]; then remotehost=noexecute; fi +if [ -r $dir/tst/$C.2bk ]; then + diff $dir/tst/$C.2bk $TSTDIR/$C.2 +fi +if [ -r $dir/tst/$C.sbk ]; then + if diff $dir/tst/$C.sbk $TSTDIR/$C.s; then exit 0; fi +fi + +case "$remotehost" in +noexecute) exit 0 ;; +""|"-") $LCC -o $TSTDIR/$C$EXE $1; $TSTDIR/$C$EXE <tst/$C.0 >$TSTDIR/$C.1 ;; +*) rcp $1 $remotehost: + if expr "$remotehost" : '.*@' >/dev/null ; then + remotehost="`expr $remotehost : '.*@\(.*\)'` -l `expr $remotehost : '\(.*\)@'`" + fi + rsh $remotehost "cc -o $C$EXE $C.s -lm;./$C$EXE;rm -f $C$EXE $C.[so]" <tst/$C.0 >$TSTDIR/$C.1 + ;; +esac +if [ -r $dir/tst/$C.1bk ]; then + diff $dir/tst/$C.1bk $TSTDIR/$C.1 + exit $? +fi +exit 0 diff --git a/lcc/src/simp.c b/lcc/src/simp.c index 04699bb..4d79af0 100755 --- a/lcc/src/simp.c +++ b/lcc/src/simp.c @@ -1,587 +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;
- Tree p;
-
- 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;
-}
-
+#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; + Tree p; + + 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; +} + diff --git a/lcc/src/sparc.md b/lcc/src/sparc.md index 0171492..f956d46 100755 --- a/lcc/src/sparc.md +++ b/lcc/src/sparc.md @@ -1,1163 +1,1163 @@ -%{
-#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);
-static int imm(Node);
-static void renameregs(void);
-extern Interface sparcIR, solarisIR;
-static void defsymbol2(Symbol);
-static void export2(Symbol);
-static void globalend(void);
-static void global2(Symbol);
-static void segment2(int);
-static void progend2(void);
-
-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 Symbol greg[32], gregw;
-static Symbol *oreg = &greg[8], *ireg = &greg[24];
-static Symbol freg[32], freg2[32];
-static Symbol fregw, freg2w;
-
-static int regvars;
-static int retstruct;
-
-static int pflag = 0;
-
-static int cseg;
-
-%}
-%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 ""
-reg: ADDRGP4 "set %a,%%%c\n" 1
-stk13: ADDRFP4 "%a" imm(a)
-stk13: ADDRLP4 "%a" imm(a)
-reg: stk13 "add %0,%%fp,%%%c\n" 1
-stk: ADDRFP4 "set %a,%%%c\n" 2
-stk: ADDRLP4 "set %a,%%%c\n" 2
-reg: ADDRFP4 "set %a,%%%c\nadd %%%c,%%fp,%%%c\n" 3
-reg: ADDRLP4 "set %a,%%%c\nadd %%%c,%%fp,%%%c\n" 3
-con13: CNSTI1 "%a" imm(a)
-con13: CNSTI2 "%a" imm(a)
-con13: CNSTI4 "%a" imm(a)
-con13: CNSTU1 "%a" imm(a)
-con13: CNSTU2 "%a" imm(a)
-con13: CNSTU4 "%a" imm(a)
-con13: CNSTP4 "%a" imm(a)
-base: ADDI4(reg,con13) "%%%0+%1"
-base: ADDP4(reg,con13) "%%%0+%1"
-base: ADDU4(reg,con13) "%%%0+%1"
-base: reg "%%%0"
-base: con13 "%0"
-base: stk13 "%%fp+%0"
-addr: base "%0"
-addr: ADDI4(reg,reg) "%%%0+%%%1"
-addr: ADDP4(reg,reg) "%%%0+%%%1"
-addr: ADDU4(reg,reg) "%%%0+%%%1"
-addr: stk "%%fp+%%%0"
-reg: INDIRI1(addr) "ldsb [%0],%%%c\n" 1
-reg: INDIRI2(addr) "ldsh [%0],%%%c\n" 1
-reg: INDIRI4(addr) "ld [%0],%%%c\n" 1
-reg: INDIRU1(addr) "ldub [%0],%%%c\n" 1
-reg: INDIRU2(addr) "lduh [%0],%%%c\n" 1
-reg: INDIRU4(addr) "ld [%0],%%%c\n" 1
-reg: INDIRP4(addr) "ld [%0],%%%c\n" 1
-reg: INDIRF4(addr) "ld [%0],%%f%c\n" 1
-stmt: ASGNI1(addr,reg) "stb %%%1,[%0]\n" 1
-stmt: ASGNI2(addr,reg) "sth %%%1,[%0]\n" 1
-stmt: ASGNI4(addr,reg) "st %%%1,[%0]\n" 1
-stmt: ASGNU1(addr,reg) "stb %%%1,[%0]\n" 1
-stmt: ASGNU2(addr,reg) "sth %%%1,[%0]\n" 1
-stmt: ASGNU4(addr,reg) "st %%%1,[%0]\n" 1
-stmt: ASGNP4(addr,reg) "st %%%1,[%0]\n" 1
-stmt: ASGNF4(addr,reg) "st %%f%1,[%0]\n" 1
-addrl: ADDRLP4 "%%%fp+%a" imm(a)
-
-reg: INDIRF8(addrl) "ldd [%0],%%f%c\n" 1
-stmt: ASGNF8(addrl,reg) "std %%f%1,[%0]\n" 1
-reg: INDIRF8(base) "ld2 [%0],%%f%c\n" 2
-stmt: ASGNF8(base,reg) "st2 %%f%1,[%0]\n" 2
-spill: ADDRLP4 "%a" !imm(a)
-
-stmt: ASGNI1(spill,reg) "set %0,%%g1\nstb %%%1,[%%fp+%%g1]\n"
-stmt: ASGNI2(spill,reg) "set %0,%%g1\nsth %%%1,[%%fp+%%g1]\n"
-stmt: ASGNI4(spill,reg) "set %0,%%g1\nst %%%1,[%%fp+%%g1]\n"
-stmt: ASGNU1(spill,reg) "set %0,%%g1\nstb %%%1,[%%fp+%%g1]\n"
-stmt: ASGNU2(spill,reg) "set %0,%%g1\nsth %%%1,[%%fp+%%g1]\n"
-stmt: ASGNU4(spill,reg) "set %0,%%g1\nst %%%1,[%%fp+%%g1]\n"
-stmt: ASGNP4(spill,reg) "set %0,%%g1\nst %%%1,[%%fp+%%g1]\n"
-stmt: ASGNF4(spill,reg) "set %0,%%g1\nst %%f%1,[%%fp+%%g1]\n"
-stmt: ASGNF8(spill,reg) "set %0,%%g1\nstd %%f%1,[%%fp+%%g1]\n"
-reg: CVII4(INDIRI1(addr)) "ldsb [%0],%%%c\n" 1
-reg: CVII4(INDIRI2(addr)) "ldsh [%0],%%%c\n" 1
-reg: CVUU4(INDIRU1(addr)) "ldub [%0],%%%c\n" 1
-reg: CVUU4(INDIRU2(addr)) "lduh [%0],%%%c\n" 1
-reg: CVUI4(INDIRU1(addr)) "ldub [%0],%%%c\n" 1
-reg: CVUI4(INDIRU2(addr)) "lduh [%0],%%%c\n" 1
-reg: LOADI1(reg) "mov %%%0,%%%c\n" move(a)
-reg: LOADI2(reg) "mov %%%0,%%%c\n" move(a)
-reg: LOADI4(reg) "mov %%%0,%%%c\n" move(a)
-reg: LOADP4(reg) "mov %%%0,%%%c\n" move(a)
-reg: LOADU1(reg) "mov %%%0,%%%c\n" move(a)
-reg: LOADU2(reg) "mov %%%0,%%%c\n" move(a)
-reg: LOADU4(reg) "mov %%%0,%%%c\n" move(a)
-reg: CNSTI1 "# reg\n" range(a, 0, 0)
-reg: CNSTI2 "# reg\n" range(a, 0, 0)
-reg: CNSTI4 "# reg\n" range(a, 0, 0)
-reg: CNSTP4 "# reg\n" range(a, 0, 0)
-reg: CNSTU1 "# reg\n" range(a, 0, 0)
-reg: CNSTU2 "# reg\n" range(a, 0, 0)
-reg: CNSTU4 "# reg\n" range(a, 0, 0)
-reg: con "set %0,%%%c\n" 1
-rc: con13 "%0"
-rc: reg "%%%0"
-reg: ADDI4(reg,rc) "add %%%0,%1,%%%c\n" 1
-reg: ADDP4(reg,rc) "add %%%0,%1,%%%c\n" 1
-reg: ADDU4(reg,rc) "add %%%0,%1,%%%c\n" 1
-reg: BANDI4(reg,rc) "and %%%0,%1,%%%c\n" 1
-reg: BORI4(reg,rc) "or %%%0,%1,%%%c\n" 1
-reg: BXORI4(reg,rc) "xor %%%0,%1,%%%c\n" 1
-reg: BANDU4(reg,rc) "and %%%0,%1,%%%c\n" 1
-reg: BORU4(reg,rc) "or %%%0,%1,%%%c\n" 1
-reg: BXORU4(reg,rc) "xor %%%0,%1,%%%c\n" 1
-reg: SUBI4(reg,rc) "sub %%%0,%1,%%%c\n" 1
-reg: SUBP4(reg,rc) "sub %%%0,%1,%%%c\n" 1
-reg: SUBU4(reg,rc) "sub %%%0,%1,%%%c\n" 1
-rc5: CNSTI4 "%a" range(a, 0, 31)
-rc5: reg "%%%0"
-reg: LSHI4(reg,rc5) "sll %%%0,%1,%%%c\n" 1
-reg: LSHU4(reg,rc5) "sll %%%0,%1,%%%c\n" 1
-reg: RSHI4(reg,rc5) "sra %%%0,%1,%%%c\n" 1
-reg: RSHU4(reg,rc5) "srl %%%0,%1,%%%c\n" 1
-reg: BANDI4(reg,BCOMI4(rc)) "andn %%%0,%1,%%%c\n" 1
-reg: BORI4(reg,BCOMI4(rc)) "orn %%%0,%1,%%%c\n" 1
-reg: BXORI4(reg,BCOMI4(rc)) "xnor %%%0,%1,%%%c\n" 1
-reg: BANDU4(reg,BCOMU4(rc)) "andn %%%0,%1,%%%c\n" 1
-reg: BORU4(reg,BCOMU4(rc)) "orn %%%0,%1,%%%c\n" 1
-reg: BXORU4(reg,BCOMU4(rc)) "xnor %%%0,%1,%%%c\n" 1
-reg: NEGI4(reg) "neg %%%0,%%%c\n" 1
-reg: BCOMI4(reg) "not %%%0,%%%c\n" 1
-reg: BCOMU4(reg) "not %%%0,%%%c\n" 1
-reg: CVII4(reg) "sll %%%0,8*(4-%a),%%%c; sra %%%c,8*(4-%a),%%%c\n" 2
-reg: CVUU4(reg) "sll %%%0,8*(4-%a),%%%c; srl %%%c,8*(4-%a),%%%c\n" 2
-reg: CVUU4(reg) "and %%%0,0xff,%%%c\n" (a->syms[0]->u.c.v.i == 1 ? 1 : LBURG_MAX)
-reg: CVUU4(reg) "set 0xffff,%%g1; and %%%0,%%g1,%%%c\n" 2
-reg: CVUI4(reg) "and %%%0,0xff,%%%c\n" (a->syms[0]->u.c.v.i == 1 ? 1 : LBURG_MAX)
-reg: CVUI4(reg) "set 0xffff,%%g1; and %%%0,%%g1,%%%c\n" 2
-addrg: ADDRGP4 "%a"
-stmt: JUMPV(addrg) "ba %0; nop\n" 2
-stmt: JUMPV(addr) "jmp %0; nop\n" 2
-stmt: LABELV "%a:\n"
-stmt: EQI4(reg,rc) "cmp %%%0,%1; be %a; nop\n" 3
-stmt: EQU4(reg,rc) "cmp %%%0,%1; be %a; nop\n" 3
-stmt: GEI4(reg,rc) "cmp %%%0,%1; bge %a; nop\n" 3
-stmt: GEU4(reg,rc) "cmp %%%0,%1; bgeu %a; nop\n" 3
-stmt: GTI4(reg,rc) "cmp %%%0,%1; bg %a; nop\n" 3
-stmt: GTU4(reg,rc) "cmp %%%0,%1; bgu %a; nop\n" 3
-stmt: LEI4(reg,rc) "cmp %%%0,%1; ble %a; nop\n" 3
-stmt: LEU4(reg,rc) "cmp %%%0,%1; bleu %a; nop\n" 3
-stmt: LTI4(reg,rc) "cmp %%%0,%1; bl %a; nop\n" 3
-stmt: LTU4(reg,rc) "cmp %%%0,%1; blu %a; nop\n" 3
-stmt: NEI4(reg,rc) "cmp %%%0,%1; bne %a; nop\n" 3
-stmt: NEU4(reg,rc) "cmp %%%0,%1; bne %a; nop\n" 3
-call: ADDRGP4 "%a"
-call: addr "%0"
-reg: CALLF8(call) "call %0; nop\n" 2
-reg: CALLF4(call) "call %0; nop\n" 2
-reg: CALLI4(call) "call %0; nop\n" 2
-reg: CALLP4(call) "call %0; nop\n" 2
-reg: CALLU4(call) "call %0; nop\n" 2
-stmt: CALLV(call) "call %0; nop\n" 2
-stmt: CALLB(call,reg) "call %0; st %%%1,[%%sp+64]; unimp %b&0xfff\n" 3
-
-stmt: RETF8(reg) "# ret\n" 1
-stmt: RETF4(reg) "# ret\n" 1
-stmt: RETI4(reg) "# ret\n" 1
-stmt: RETU4(reg) "# ret\n" 1
-stmt: RETP4(reg) "# ret\n" 1
-stmt: ARGI4(reg) "st %%%0,[%%sp+4*%c+68]\n" 1
-stmt: ARGU4(reg) "st %%%0,[%%sp+4*%c+68]\n" 1
-stmt: ARGP4(reg) "st %%%0,[%%sp+4*%c+68]\n" 1
-stmt: ARGF4(reg) "# ARGF4\n" 1
-stmt: ARGF8(reg) "# ARGF8\n" 1
-
-reg: DIVI4(reg,rc) "sra %%%0,31,%%g1; wr %%g0,%%g1,%%y; nop; nop; nop; sdiv %%%0,%1,%%%c\n" 6
-
-reg: DIVU4(reg,rc) "wr %%g0,%%g0,%%y; nop; nop; nop; udiv %%%0,%1,%%%c\n" 5
-
-reg: MODI4(reg,rc) "sra %%%0,31,%%g1; wr %%g0,%%g1,%%y; nop; nop; nop; sdiv %%%0,%1,%%g1\n; smul %%g1,%1,%%g1; sub %%%0,%%g1,%%%c\n" 8
-
-
-reg: MODU4(reg,rc) "wr %%g0,%%g0,%%y; nop; nop; nop; udiv %%%0,%1,%%g1\n; umul %%g1,%1,%%g1; sub %%%0,%%g1,%%%c\n" 7
-
-
-reg: MULI4(rc,reg) "smul %%%1,%0,%%%c\n" 1
-reg: MULU4(rc,reg) "umul %%%1,%0,%%%c\n" 1
-reg: ADDF8(reg,reg) "faddd %%f%0,%%f%1,%%f%c\n" 1
-reg: ADDF4(reg,reg) "fadds %%f%0,%%f%1,%%f%c\n" 1
-reg: DIVF8(reg,reg) "fdivd %%f%0,%%f%1,%%f%c\n" 1
-reg: DIVF4(reg,reg) "fdivs %%f%0,%%f%1,%%f%c\n" 1
-reg: MULF8(reg,reg) "fmuld %%f%0,%%f%1,%%f%c\n" 1
-reg: MULF4(reg,reg) "fmuls %%f%0,%%f%1,%%f%c\n" 1
-reg: SUBF8(reg,reg) "fsubd %%f%0,%%f%1,%%f%c\n" 1
-reg: SUBF4(reg,reg) "fsubs %%f%0,%%f%1,%%f%c\n" 1
-reg: NEGF4(reg) "fnegs %%f%0,%%f%c\n" 1
-reg: LOADF4(reg) "fmovs %%f%0,%%f%c\n" 1
-reg: CVFF4(reg) "fdtos %%f%0,%%f%c\n" 1
-reg: CVFF8(reg) "fstod %%f%0,%%f%c\n" 1
-reg: CVFI4(reg) "fstoi %%f%0,%%f0; st %%f0,[%%sp+64]; ld [%%sp+64],%%%c\n" (a->syms[0]->u.c.v.i==4?3:LBURG_MAX)
-
-reg: CVFI4(reg) "fdtoi %%f%0,%%f0; st %%f0,[%%sp+64]; ld [%%sp+64],%%%c\n" (a->syms[0]->u.c.v.i==8?3:LBURG_MAX)
-
-reg: CVIF4(reg) "st %%%0,[%%sp+64]; ld [%%sp+64],%%f%c; fitos %%f%c,%%f%c\n" 3
-
-reg: CVIF8(reg) "st %%%0,[%%sp+64]; ld [%%sp+64],%%f%c; fitod %%f%c,%%f%c\n" 3
-
-rel: EQF8(reg,reg) "fcmped %%f%0,%%f%1; nop; fbue"
-rel: EQF4(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbue"
-rel: GEF8(reg,reg) "fcmped %%f%0,%%f%1; nop; fbuge"
-rel: GEF4(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbuge"
-rel: GTF8(reg,reg) "fcmped %%f%0,%%f%1; nop; fbug"
-rel: GTF4(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbug"
-rel: LEF8(reg,reg) "fcmped %%f%0,%%f%1; nop; fbule"
-rel: LEF4(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbule"
-rel: LTF8(reg,reg) "fcmped %%f%0,%%f%1; nop; fbul"
-rel: LTF4(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbul"
-rel: NEF8(reg,reg) "fcmped %%f%0,%%f%1; nop; fbne"
-rel: NEF4(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbne"
-
-stmt: rel "%0 %a; nop\n" 4
-reg: LOADF8(reg) "# LOADD\n" 2
-
-reg: NEGF8(reg) "# NEGD\n" 2
-
-stmt: ASGNB(reg,INDIRB(reg)) "# ASGNB\n"
-
-%%
-static void progend(void){}
-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);
- for (i = 0; i < argc; i++)
- if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "-pg") == 0)
- pflag = 1;
- if (IR == &solarisIR)
- stabprefix = ".LL";
- else
- stabprefix = "L";
- for (i = 0; i < 8; i++) {
- greg[i + 0] = mkreg(stringf("g%d", i), i + 0, 1, IREG);
- greg[i + 8] = mkreg(stringf("o%d", i), i + 8, 1, IREG);
- greg[i + 16] = mkreg(stringf("l%d", i), i + 16, 1, IREG);
- greg[i + 24] = mkreg(stringf("i%d", i), i + 24, 1, IREG);
- }
- gregw = mkwildcard(greg);
- for (i = 0; i < 32; i++)
- freg[i] = mkreg("%d", i, 1, FREG);
- for (i = 0; i < 31; i += 2)
- freg2[i] = mkreg("%d", i, 3, FREG);
- fregw = mkwildcard(freg);
- freg2w = mkwildcard(freg2);
- tmask[IREG] = 0x3fff3e00;
- vmask[IREG] = 0x3ff00000;
- tmask[FREG] = ~(unsigned)0;
- vmask[FREG] = 0;
-}
-static Symbol rmap(int opk) {
- switch (optype(opk)) {
- case I: case U: case P: case B:
- return gregw;
- case F:
- return opsize(opk) == 4 ? fregw : freg2w;
- default:
- return 0;
- }
-}
-static void target(Node p) {
- assert(p);
- switch (specific(p->op)) {
- case CNST+I: case CNST+U: case CNST+P:
- if (range(p, 0, 0) == 0) {
- setreg(p, greg[0]);
- p->x.registered = 1;
- }
- break;
- case CALL+B:
- assert(p->syms[1] && p->syms[1]->type && isfunc(p->syms[1]->type));
- p->syms[1] = intconst(freturn(p->syms[1]->type)->size);
- break;
- case CALL+F: setreg(p, opsize(p->op)==4?freg[0]:freg2[0]); break;
- case CALL+I: case CALL+P: case CALL+U:
- case CALL+V: setreg(p, oreg[0]); break;
- case RET+F: rtarget(p, 0, opsize(p->op)==4?freg[0]:freg2[0]); break;
- case RET+I: case RET+P: case RET+U:
- rtarget(p, 0, ireg[0]);
- p->kids[0]->x.registered = 1;
- break;
- case ARG+I: case ARG+P: case ARG+U:
- if (p->syms[RX]->u.c.v.i < 6) {
- rtarget(p, 0, oreg[p->syms[RX]->u.c.v.i]);
- p->op = LOAD+opkind(p->op);
- setreg(p, oreg[p->syms[RX]->u.c.v.i]);
- }
- break;
- }
-}
-static void clobber(Node p) {
- assert(p);
- switch (specific(p->op)) {
- case CALL+B: case CALL+F: case CALL+I:
- spill(~(unsigned)3, FREG, p);
- break;
- case CALL+V:
- spill(oreg[0]->x.regnode->mask, IREG, p);
- spill(~(unsigned)3, FREG, p);
- break;
- case ARG+F:
- if (opsize(p->op) == 4 && p->syms[2]->u.c.v.i <= 6)
- spill((1<<(p->syms[2]->u.c.v.i + 8)), IREG, p);
- else if (opsize(p->op) == 8 && p->syms[2]->u.c.v.i <= 5)
- spill((3<<(p->syms[2]->u.c.v.i + 8))&0xff00, IREG, p);
- break;
- }
-}
-static int imm(Node p) {
- return range(p, -4096, 4091);
-}
-static void doarg(Node p) {
- assert(p && p->syms[0] && p->op != ARG+B);
- p->syms[RX] = intconst(mkactual(4,
- p->syms[0]->u.c.v.i)/4);
-}
-static void emit2(Node p) {
- switch (p->op) {
- case ARG+F+sizeop(4): {
- int n = p->syms[RX]->u.c.v.i;
- print("st %%f%d,[%%sp+4*%d+68]\n",
- getregnum(p->x.kids[0]), n);
- if (n <= 5)
- print("ld [%%sp+4*%d+68],%%o%d\n", n, n);
- break;
- }
- case ARG+F+sizeop(8): {
- int n = p->syms[RX]->u.c.v.i;
- int src = getregnum(p->x.kids[0]);
- print("st %%f%d,[%%sp+4*%d+68]\n", src, n);
- print("st %%f%d,[%%sp+4*%d+68]\n", src+1, n+1);
- if (n <= 5)
- print("ld [%%sp+4*%d+68],%%o%d\n", n, n);
- if (n <= 4)
- print("ld [%%sp+4*%d+68],%%o%d\n", n+1, n+1);
- break;
- }
- case LOAD+F+sizeop(8): {
- int dst = getregnum(p);
- int src = getregnum(p->x.kids[0]);
- print("fmovs %%f%d,%%f%d; ", src, dst);
- print("fmovs %%f%d,%%f%d\n", src+1, dst+1);
- break;
- }
- case NEG+F+sizeop(8): {
- int dst = getregnum(p);
- int src = getregnum(p->x.kids[0]);
- print("fnegs %%f%d,%%f%d; ", src, dst);
- print("fmovs %%f%d,%%f%d\n", src+1, dst+1);
- break;
- }
- case ASGN+B: {
- static int tmpregs[] = { 1, 2, 3 };
- dalign = salign = p->syms[1]->u.c.v.i;
- blkcopy(getregnum(p->x.kids[0]), 0,
- getregnum(p->x.kids[1]), 0,
- p->syms[0]->u.c.v.i, tmpregs);
- break;
- }
- }
-}
-static void local(Symbol p) {
- if (retstruct) {
- assert(p == retv);
- p->x.name = stringd(4*16);
- p->x.offset = 4*16;
- p->sclass = AUTO;
- retstruct = 0;
- return;
- }
- if (isscalar(p->type) && !p->addressed && !isfloat(p->type))
- p->sclass = REGISTER;
- if (askregvar(p, rmap(ttob(p->type))) == 0)
- mkauto(p);
- else if (p->scope > LOCAL)
- regvars++;
-}
-static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
- int autos = 0, i, leaf, reg, varargs;
-
- if (IR == &solarisIR)
- globalend();
- regvars = 0;
- for (i = 0; callee[i]; i++)
- ;
- varargs = variadic(f->type)
- || i > 0 && strcmp(callee[i-1]->name,
- "__builtin_va_alist") == 0;
- usedmask[0] = usedmask[1] = 0;
- freemask[0] = freemask[1] = ~(unsigned)0;
- for (i = 0; i < 8; i++)
- ireg[i]->x.regnode->vbl = NULL;
- offset = 68;
- maxargoffset = 24;
- reg = 0;
- for (i = 0; callee[i]; i++) {
- Symbol p = callee[i], q = caller[i];
- int size = roundup(q->type->size, 4);
- assert(q);
- if (isfloat(p->type) || reg >= 6) {
- p->x.offset = q->x.offset = offset;
- p->x.name = q->x.name = stringd(offset);
- p->sclass = q->sclass = AUTO;
- autos++;
- }
- else if (p->addressed || varargs) {
- p->x.offset = offset;
- p->x.name = stringd(p->x.offset);
- p->sclass = AUTO;
- q->sclass = REGISTER;
- askregvar(q, ireg[reg]);
- assert(q->x.regnode);
- autos++;
- }
- else {
- p->sclass = q->sclass = REGISTER;
- askregvar(p, ireg[reg]);
- assert(p->x.regnode);
- q->x.name = p->x.name;
- }
- offset += size;
- reg += isstruct(p->type) ? 1 : size/4;
- }
- assert(caller[i] == 0);
- offset = maxoffset = 0;
- retstruct = isstruct(freturn(f->type));
- gencode(caller, callee);
- maxargoffset = roundup(maxargoffset, 4);
- framesize = roundup(maxoffset + maxargoffset + 4*(16+1), 8);
- assert(!varargs || autos);
- leaf = (!ncalls
- && !maxoffset && !autos && !regvars
- && !isstruct(freturn(f->type))
- && !(usedmask[IREG]&0x00ffff01)
- && !(usedmask[FREG]&~(unsigned)3)
- && !pflag && !glevel);
- print(".align 4\n%s:\n", f->x.name);
- if (leaf) {
- for (i = 0; caller[i] && callee[i]; i++) {
- Symbol p = caller[i], q = callee[i];
- if (p->sclass == REGISTER && q->sclass == REGISTER) {
- assert(q->x.regnode);
- assert(q->x.regnode->set == IREG);
- assert(q->x.regnode->number >= 24);
- assert(q->x.regnode->number <= 31);
- p->x.name = greg[q->x.regnode->number - 16]->x.name;
- }
- }
- renameregs();
- } else if (framesize <= 4095)
- print("save %%sp,%d,%%sp\n", -framesize);
- else
- print("set %d,%%g1; save %%sp,%%g1,%%sp\n", -framesize);
- if (varargs)
- for (; reg < 6; reg++)
- print("st %%i%d,[%%fp+%d]\n", reg, 4*reg + 68);
- else {
- offset = 4*(16 + 1);
- reg = 0;
- for (i = 0; caller[i]; i++) {
- Symbol p = caller[i];
- if (isfloat(p->type) && p->type->size == 8 && reg <= 4) {
- print("st %%r%d,[%%fp+%d]\n",
- ireg[reg++]->x.regnode->number, offset);
- print("st %%r%d,[%%fp+%d]\n",
- ireg[reg++]->x.regnode->number, offset + 4);
- } else if (isfloat(p->type) && p->type->size == 4 && reg <= 5)
- print("st %%r%d,[%%fp+%d]\n",
- ireg[reg++]->x.regnode->number, offset);
- else
- reg++;
- offset += roundup(p->type->size, 4);
- }
- }
- if (pflag) {
- int lab = genlabel(1);
- print("set L%d,%%o0; call mcount; nop\n", lab);
- print(".seg \"data\"\n.align 4; L%d:.word 0\n.seg \"text\"\n", lab);
- }
- emitcode();
- if (isstruct(freturn(f->type)))
- print("jmp %%i7+12; restore\n");
- else if (!leaf)
- print("ret; restore\n");
- else {
- renameregs();
- print("retl; nop\n");
- }
- if (IR == &solarisIR) {
- print(".type %s,#function\n", f->x.name);
- print(".size %s,.-%s\n", f->x.name, f->x.name);
- }
-}
-#define exch(x, y, t) (((t) = x), ((x) = (y)), ((y) = (t)))
-
-static void renameregs(void) {
- int i;
-
- for (i = 0; i < 8; i++) {
- char *ptmp;
- int itmp;
- if (ireg[i]->x.regnode->vbl)
- ireg[i]->x.regnode->vbl->x.name = oreg[i]->x.name;
- exch(ireg[i]->x.name, oreg[i]->x.name, ptmp);
- exch(ireg[i]->x.regnode->number,
- oreg[i]->x.regnode->number, itmp);
- }
-}
-static void defconst(int suffix, int size, Value v) {
- if (suffix == F && size == 4) {
- float f = v.d;
- print(".word 0x%x\n", *(unsigned *)&f);
- } else if (suffix == F && size == 8) {
- double d = v.d;
- unsigned *p = (unsigned *)&d;
- print(".word 0x%x\n.word 0x%x\n", p[swap], p[!swap]);
- } else if (suffix == P)
- print(".word 0x%x\n", v.p);
- else if (size == 1)
- print(".byte 0x%x\n", suffix == I ? v.i : v.u);
- else if (size == 2)
- print(".half 0x%x\n", suffix == I ? v.i : v.u);
- else if (size == 4)
- print(".word 0x%x\n", suffix == I ? v.i : v.u);
- else assert(0);
-}
-
-static void defaddress(Symbol p) {
- print(".word %s\n", p->x.name);
-}
-
-static void defstring(int n, char *str) {
- char *s;
-
- for (s = str; s < str + n; s++)
- print(".byte %d\n", (*s)&0377);
-}
-
-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 export(Symbol p) {
- print(".global %s\n", p->x.name);
-}
-static void import(Symbol p) {}
-static void defsymbol(Symbol p) {
- if (p->scope >= LOCAL && p->sclass == STATIC)
- p->x.name = stringf("%d", genlabel(1));
- else
- assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)),
- p->x.name = p->name;
- if (p->scope >= LABELS)
- p->x.name = stringf(p->generated ? "L%s" : "_%s",
- p->x.name);
-}
-static void segment(int n) {
- cseg = n;
- switch (n) {
- case CODE: print(".seg \"text\"\n"); break;
- case BSS: print(".seg \"bss\"\n"); break;
- case DATA: print(".seg \"data\"\n"); break;
- case LIT: print(".seg \"text\"\n"); break;
- }
-}
-static void space(int n) {
- if (cseg != BSS)
- print(".skip %d\n", n);
-}
-static void global(Symbol p) {
- print(".align %d\n", p->type->align);
- assert(p->u.seg);
- if (p->u.seg == BSS
- && (p->sclass == STATIC || Aflag >= 2))
- print(".reserve %s,%d\n", p->x.name, p->type->size);
- else if (p->u.seg == BSS)
- print(".common %s,%d\n", p->x.name, p->type->size);
- else
- print("%s:\n", p->x.name);
-}
-static void blkfetch(int k, int off, int reg, int tmp) {
- assert(k == 1 || k == 2 || k == 4);
- assert(salign >= k);
- if (k == 1)
- print("ldub [%%r%d+%d],%%r%d\n", reg, off, tmp);
- else if (k == 2)
- print("lduh [%%r%d+%d],%%r%d\n", reg, off, tmp);
- else
- print("ld [%%r%d+%d],%%r%d\n", reg, off, tmp);
-}
-static void blkstore(int k, int off, int reg, int tmp) {
- assert(k == 1 || k == 2 || k == 4);
- assert(dalign >= k);
- if (k == 1)
- print("stb %%r%d,[%%r%d+%d]\n", tmp, reg, off);
- else if (k == 2)
- print("sth %%r%d,[%%r%d+%d]\n", tmp, reg, off);
- else
- print("st %%r%d,[%%r%d+%d]\n", tmp, reg, off);
-}
-static void blkloop(int dreg, int doff, int sreg, int soff, int size, int tmps[]) {
- if ((size&~7) < 4096) {
- print("add %%r%d,%d,%%r%d\n", sreg, size&~7, sreg);
- print("add %%r%d,%d,%%r%d\n", dreg, size&~7, tmps[2]);
- } else {
- print("set %d,%%r%d\n", size&~7, tmps[2]);
- print("add %%r%d,%%r%d,%%r%d\n", sreg, tmps[2], sreg);
- print("add %%r%d,%%r%d,%%r%d\n", dreg, tmps[2], tmps[2]);
- }
- blkcopy(tmps[2], doff, sreg, soff, size&7, tmps);
- print("1: dec 8,%%r%d\n", tmps[2]);
- blkcopy(tmps[2], doff, sreg, soff - 8, 8, tmps);
- print("cmp %%r%d,%%r%d; ", tmps[2], dreg);
- print("bgt 1b; ");
- print("dec 8,%%r%d\n", sreg);
-}
-static void defsymbol2(Symbol p) {
- if (p->scope >= LOCAL && p->sclass == STATIC)
- p->x.name = stringf(".%d", genlabel(1));
- else
- assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)),
- p->x.name = p->name;
- if (p->scope >= LABELS)
- p->x.name = stringf(p->generated ? ".L%s" : "%s",
- p->x.name);
-}
-
-static Symbol prevg;
-
-static void globalend(void) {
- if (prevg && prevg->type->size > 0)
- print(".size %s,%d\n", prevg->x.name, prevg->type->size);
- prevg = NULL;
-}
-
-static void export2(Symbol p) {
- globalend();
- print(".global %s\n", p->x.name);
-}
-
-static void progend2(void) {
- globalend();
-}
-
-static void global2(Symbol p) {
- globalend();
- assert(p->u.seg);
- if (!p->generated) {
- print(".type %s,#%s\n", p->x.name,
- isfunc(p->type) ? "function" : "object");
- if (p->type->size > 0)
- print(".size %s,%d\n", p->x.name, p->type->size);
- else
- prevg = p;
- }
- if (p->u.seg == BSS && p->sclass == STATIC)
- print(".local %s\n.common %s,%d,%d\n", p->x.name, p->x.name,
- p->type->size, p->type->align);
- else if (p->u.seg == BSS && Aflag >= 2)
- print(".align %d\n%s:.skip %d\n", p->type->align, p->x.name,
- p->type->size);
- else if (p->u.seg == BSS)
- print(".common %s,%d,%d\n", p->x.name, p->type->size, p->type->align);
- else
- print(".align %d\n%s:\n", p->type->align, p->x.name);
-}
-
-static void segment2(int n) {
- cseg = n;
- switch (n) {
- case CODE: print(".section \".text\"\n"); break;
- case BSS: print(".section \".bss\"\n"); break;
- case DATA: print(".section \".data\"\n"); break;
- case LIT: print(".section \".rodata\"\n"); break;
- }
-}
-Interface sparcIR = {
- 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, 1, 0, /* struct */
- 0, /* little_endian */
- 0, /* mulops_calls */
- 1, /* wants_callb */
- 0, /* wants_argb */
- 1, /* 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,
- stabblock, 0, 0, stabinit, stabline, stabsym, stabtype,
- {
- 1, /* max_unaligned_load */
- rmap,
- blkfetch, blkstore, blkloop,
- _label,
- _rule,
- _nts,
- _kids,
- _string,
- _templates,
- _isinstruction,
- _ntname,
- emit2,
- doarg,
- target,
- clobber,
-
- }
-};
-
-Interface solarisIR = {
- 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, 1, 0, /* struct */
- 0, /* little_endian */
- 0, /* mulops_calls */
- 1, /* wants_callb */
- 0, /* wants_argb */
- 1, /* left_to_right */
- 0, /* wants_dag */
- 0, /* unsigned_char */
- address,
- blockbeg,
- blockend,
- defaddress,
- defconst,
- defstring,
- defsymbol2,
- emit,
- export2,
- function,
- gen,
- global2,
- import,
- local,
- progbeg,
- progend2,
- segment2,
- space,
- stabblock, 0, 0, stabinit, stabline, stabsym, stabtype,
- {
- 1, /* max_unaligned_load */
- rmap,
- blkfetch, blkstore, blkloop,
- _label,
- _rule,
- _nts,
- _kids,
- _string,
- _templates,
- _isinstruction,
- _ntname,
- emit2,
- doarg,
- target,
- clobber,
-
- }
-};
-static char rcsid[] = "$Id: sparc.md 145 2001-10-17 21:53:10Z timo $";
+%{ +#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); +static int imm(Node); +static void renameregs(void); +extern Interface sparcIR, solarisIR; +static void defsymbol2(Symbol); +static void export2(Symbol); +static void globalend(void); +static void global2(Symbol); +static void segment2(int); +static void progend2(void); + +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 Symbol greg[32], gregw; +static Symbol *oreg = &greg[8], *ireg = &greg[24]; +static Symbol freg[32], freg2[32]; +static Symbol fregw, freg2w; + +static int regvars; +static int retstruct; + +static int pflag = 0; + +static int cseg; + +%} +%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 "" +reg: ADDRGP4 "set %a,%%%c\n" 1 +stk13: ADDRFP4 "%a" imm(a) +stk13: ADDRLP4 "%a" imm(a) +reg: stk13 "add %0,%%fp,%%%c\n" 1 +stk: ADDRFP4 "set %a,%%%c\n" 2 +stk: ADDRLP4 "set %a,%%%c\n" 2 +reg: ADDRFP4 "set %a,%%%c\nadd %%%c,%%fp,%%%c\n" 3 +reg: ADDRLP4 "set %a,%%%c\nadd %%%c,%%fp,%%%c\n" 3 +con13: CNSTI1 "%a" imm(a) +con13: CNSTI2 "%a" imm(a) +con13: CNSTI4 "%a" imm(a) +con13: CNSTU1 "%a" imm(a) +con13: CNSTU2 "%a" imm(a) +con13: CNSTU4 "%a" imm(a) +con13: CNSTP4 "%a" imm(a) +base: ADDI4(reg,con13) "%%%0+%1" +base: ADDP4(reg,con13) "%%%0+%1" +base: ADDU4(reg,con13) "%%%0+%1" +base: reg "%%%0" +base: con13 "%0" +base: stk13 "%%fp+%0" +addr: base "%0" +addr: ADDI4(reg,reg) "%%%0+%%%1" +addr: ADDP4(reg,reg) "%%%0+%%%1" +addr: ADDU4(reg,reg) "%%%0+%%%1" +addr: stk "%%fp+%%%0" +reg: INDIRI1(addr) "ldsb [%0],%%%c\n" 1 +reg: INDIRI2(addr) "ldsh [%0],%%%c\n" 1 +reg: INDIRI4(addr) "ld [%0],%%%c\n" 1 +reg: INDIRU1(addr) "ldub [%0],%%%c\n" 1 +reg: INDIRU2(addr) "lduh [%0],%%%c\n" 1 +reg: INDIRU4(addr) "ld [%0],%%%c\n" 1 +reg: INDIRP4(addr) "ld [%0],%%%c\n" 1 +reg: INDIRF4(addr) "ld [%0],%%f%c\n" 1 +stmt: ASGNI1(addr,reg) "stb %%%1,[%0]\n" 1 +stmt: ASGNI2(addr,reg) "sth %%%1,[%0]\n" 1 +stmt: ASGNI4(addr,reg) "st %%%1,[%0]\n" 1 +stmt: ASGNU1(addr,reg) "stb %%%1,[%0]\n" 1 +stmt: ASGNU2(addr,reg) "sth %%%1,[%0]\n" 1 +stmt: ASGNU4(addr,reg) "st %%%1,[%0]\n" 1 +stmt: ASGNP4(addr,reg) "st %%%1,[%0]\n" 1 +stmt: ASGNF4(addr,reg) "st %%f%1,[%0]\n" 1 +addrl: ADDRLP4 "%%%fp+%a" imm(a) + +reg: INDIRF8(addrl) "ldd [%0],%%f%c\n" 1 +stmt: ASGNF8(addrl,reg) "std %%f%1,[%0]\n" 1 +reg: INDIRF8(base) "ld2 [%0],%%f%c\n" 2 +stmt: ASGNF8(base,reg) "st2 %%f%1,[%0]\n" 2 +spill: ADDRLP4 "%a" !imm(a) + +stmt: ASGNI1(spill,reg) "set %0,%%g1\nstb %%%1,[%%fp+%%g1]\n" +stmt: ASGNI2(spill,reg) "set %0,%%g1\nsth %%%1,[%%fp+%%g1]\n" +stmt: ASGNI4(spill,reg) "set %0,%%g1\nst %%%1,[%%fp+%%g1]\n" +stmt: ASGNU1(spill,reg) "set %0,%%g1\nstb %%%1,[%%fp+%%g1]\n" +stmt: ASGNU2(spill,reg) "set %0,%%g1\nsth %%%1,[%%fp+%%g1]\n" +stmt: ASGNU4(spill,reg) "set %0,%%g1\nst %%%1,[%%fp+%%g1]\n" +stmt: ASGNP4(spill,reg) "set %0,%%g1\nst %%%1,[%%fp+%%g1]\n" +stmt: ASGNF4(spill,reg) "set %0,%%g1\nst %%f%1,[%%fp+%%g1]\n" +stmt: ASGNF8(spill,reg) "set %0,%%g1\nstd %%f%1,[%%fp+%%g1]\n" +reg: CVII4(INDIRI1(addr)) "ldsb [%0],%%%c\n" 1 +reg: CVII4(INDIRI2(addr)) "ldsh [%0],%%%c\n" 1 +reg: CVUU4(INDIRU1(addr)) "ldub [%0],%%%c\n" 1 +reg: CVUU4(INDIRU2(addr)) "lduh [%0],%%%c\n" 1 +reg: CVUI4(INDIRU1(addr)) "ldub [%0],%%%c\n" 1 +reg: CVUI4(INDIRU2(addr)) "lduh [%0],%%%c\n" 1 +reg: LOADI1(reg) "mov %%%0,%%%c\n" move(a) +reg: LOADI2(reg) "mov %%%0,%%%c\n" move(a) +reg: LOADI4(reg) "mov %%%0,%%%c\n" move(a) +reg: LOADP4(reg) "mov %%%0,%%%c\n" move(a) +reg: LOADU1(reg) "mov %%%0,%%%c\n" move(a) +reg: LOADU2(reg) "mov %%%0,%%%c\n" move(a) +reg: LOADU4(reg) "mov %%%0,%%%c\n" move(a) +reg: CNSTI1 "# reg\n" range(a, 0, 0) +reg: CNSTI2 "# reg\n" range(a, 0, 0) +reg: CNSTI4 "# reg\n" range(a, 0, 0) +reg: CNSTP4 "# reg\n" range(a, 0, 0) +reg: CNSTU1 "# reg\n" range(a, 0, 0) +reg: CNSTU2 "# reg\n" range(a, 0, 0) +reg: CNSTU4 "# reg\n" range(a, 0, 0) +reg: con "set %0,%%%c\n" 1 +rc: con13 "%0" +rc: reg "%%%0" +reg: ADDI4(reg,rc) "add %%%0,%1,%%%c\n" 1 +reg: ADDP4(reg,rc) "add %%%0,%1,%%%c\n" 1 +reg: ADDU4(reg,rc) "add %%%0,%1,%%%c\n" 1 +reg: BANDI4(reg,rc) "and %%%0,%1,%%%c\n" 1 +reg: BORI4(reg,rc) "or %%%0,%1,%%%c\n" 1 +reg: BXORI4(reg,rc) "xor %%%0,%1,%%%c\n" 1 +reg: BANDU4(reg,rc) "and %%%0,%1,%%%c\n" 1 +reg: BORU4(reg,rc) "or %%%0,%1,%%%c\n" 1 +reg: BXORU4(reg,rc) "xor %%%0,%1,%%%c\n" 1 +reg: SUBI4(reg,rc) "sub %%%0,%1,%%%c\n" 1 +reg: SUBP4(reg,rc) "sub %%%0,%1,%%%c\n" 1 +reg: SUBU4(reg,rc) "sub %%%0,%1,%%%c\n" 1 +rc5: CNSTI4 "%a" range(a, 0, 31) +rc5: reg "%%%0" +reg: LSHI4(reg,rc5) "sll %%%0,%1,%%%c\n" 1 +reg: LSHU4(reg,rc5) "sll %%%0,%1,%%%c\n" 1 +reg: RSHI4(reg,rc5) "sra %%%0,%1,%%%c\n" 1 +reg: RSHU4(reg,rc5) "srl %%%0,%1,%%%c\n" 1 +reg: BANDI4(reg,BCOMI4(rc)) "andn %%%0,%1,%%%c\n" 1 +reg: BORI4(reg,BCOMI4(rc)) "orn %%%0,%1,%%%c\n" 1 +reg: BXORI4(reg,BCOMI4(rc)) "xnor %%%0,%1,%%%c\n" 1 +reg: BANDU4(reg,BCOMU4(rc)) "andn %%%0,%1,%%%c\n" 1 +reg: BORU4(reg,BCOMU4(rc)) "orn %%%0,%1,%%%c\n" 1 +reg: BXORU4(reg,BCOMU4(rc)) "xnor %%%0,%1,%%%c\n" 1 +reg: NEGI4(reg) "neg %%%0,%%%c\n" 1 +reg: BCOMI4(reg) "not %%%0,%%%c\n" 1 +reg: BCOMU4(reg) "not %%%0,%%%c\n" 1 +reg: CVII4(reg) "sll %%%0,8*(4-%a),%%%c; sra %%%c,8*(4-%a),%%%c\n" 2 +reg: CVUU4(reg) "sll %%%0,8*(4-%a),%%%c; srl %%%c,8*(4-%a),%%%c\n" 2 +reg: CVUU4(reg) "and %%%0,0xff,%%%c\n" (a->syms[0]->u.c.v.i == 1 ? 1 : LBURG_MAX) +reg: CVUU4(reg) "set 0xffff,%%g1; and %%%0,%%g1,%%%c\n" 2 +reg: CVUI4(reg) "and %%%0,0xff,%%%c\n" (a->syms[0]->u.c.v.i == 1 ? 1 : LBURG_MAX) +reg: CVUI4(reg) "set 0xffff,%%g1; and %%%0,%%g1,%%%c\n" 2 +addrg: ADDRGP4 "%a" +stmt: JUMPV(addrg) "ba %0; nop\n" 2 +stmt: JUMPV(addr) "jmp %0; nop\n" 2 +stmt: LABELV "%a:\n" +stmt: EQI4(reg,rc) "cmp %%%0,%1; be %a; nop\n" 3 +stmt: EQU4(reg,rc) "cmp %%%0,%1; be %a; nop\n" 3 +stmt: GEI4(reg,rc) "cmp %%%0,%1; bge %a; nop\n" 3 +stmt: GEU4(reg,rc) "cmp %%%0,%1; bgeu %a; nop\n" 3 +stmt: GTI4(reg,rc) "cmp %%%0,%1; bg %a; nop\n" 3 +stmt: GTU4(reg,rc) "cmp %%%0,%1; bgu %a; nop\n" 3 +stmt: LEI4(reg,rc) "cmp %%%0,%1; ble %a; nop\n" 3 +stmt: LEU4(reg,rc) "cmp %%%0,%1; bleu %a; nop\n" 3 +stmt: LTI4(reg,rc) "cmp %%%0,%1; bl %a; nop\n" 3 +stmt: LTU4(reg,rc) "cmp %%%0,%1; blu %a; nop\n" 3 +stmt: NEI4(reg,rc) "cmp %%%0,%1; bne %a; nop\n" 3 +stmt: NEU4(reg,rc) "cmp %%%0,%1; bne %a; nop\n" 3 +call: ADDRGP4 "%a" +call: addr "%0" +reg: CALLF8(call) "call %0; nop\n" 2 +reg: CALLF4(call) "call %0; nop\n" 2 +reg: CALLI4(call) "call %0; nop\n" 2 +reg: CALLP4(call) "call %0; nop\n" 2 +reg: CALLU4(call) "call %0; nop\n" 2 +stmt: CALLV(call) "call %0; nop\n" 2 +stmt: CALLB(call,reg) "call %0; st %%%1,[%%sp+64]; unimp %b&0xfff\n" 3 + +stmt: RETF8(reg) "# ret\n" 1 +stmt: RETF4(reg) "# ret\n" 1 +stmt: RETI4(reg) "# ret\n" 1 +stmt: RETU4(reg) "# ret\n" 1 +stmt: RETP4(reg) "# ret\n" 1 +stmt: ARGI4(reg) "st %%%0,[%%sp+4*%c+68]\n" 1 +stmt: ARGU4(reg) "st %%%0,[%%sp+4*%c+68]\n" 1 +stmt: ARGP4(reg) "st %%%0,[%%sp+4*%c+68]\n" 1 +stmt: ARGF4(reg) "# ARGF4\n" 1 +stmt: ARGF8(reg) "# ARGF8\n" 1 + +reg: DIVI4(reg,rc) "sra %%%0,31,%%g1; wr %%g0,%%g1,%%y; nop; nop; nop; sdiv %%%0,%1,%%%c\n" 6 + +reg: DIVU4(reg,rc) "wr %%g0,%%g0,%%y; nop; nop; nop; udiv %%%0,%1,%%%c\n" 5 + +reg: MODI4(reg,rc) "sra %%%0,31,%%g1; wr %%g0,%%g1,%%y; nop; nop; nop; sdiv %%%0,%1,%%g1\n; smul %%g1,%1,%%g1; sub %%%0,%%g1,%%%c\n" 8 + + +reg: MODU4(reg,rc) "wr %%g0,%%g0,%%y; nop; nop; nop; udiv %%%0,%1,%%g1\n; umul %%g1,%1,%%g1; sub %%%0,%%g1,%%%c\n" 7 + + +reg: MULI4(rc,reg) "smul %%%1,%0,%%%c\n" 1 +reg: MULU4(rc,reg) "umul %%%1,%0,%%%c\n" 1 +reg: ADDF8(reg,reg) "faddd %%f%0,%%f%1,%%f%c\n" 1 +reg: ADDF4(reg,reg) "fadds %%f%0,%%f%1,%%f%c\n" 1 +reg: DIVF8(reg,reg) "fdivd %%f%0,%%f%1,%%f%c\n" 1 +reg: DIVF4(reg,reg) "fdivs %%f%0,%%f%1,%%f%c\n" 1 +reg: MULF8(reg,reg) "fmuld %%f%0,%%f%1,%%f%c\n" 1 +reg: MULF4(reg,reg) "fmuls %%f%0,%%f%1,%%f%c\n" 1 +reg: SUBF8(reg,reg) "fsubd %%f%0,%%f%1,%%f%c\n" 1 +reg: SUBF4(reg,reg) "fsubs %%f%0,%%f%1,%%f%c\n" 1 +reg: NEGF4(reg) "fnegs %%f%0,%%f%c\n" 1 +reg: LOADF4(reg) "fmovs %%f%0,%%f%c\n" 1 +reg: CVFF4(reg) "fdtos %%f%0,%%f%c\n" 1 +reg: CVFF8(reg) "fstod %%f%0,%%f%c\n" 1 +reg: CVFI4(reg) "fstoi %%f%0,%%f0; st %%f0,[%%sp+64]; ld [%%sp+64],%%%c\n" (a->syms[0]->u.c.v.i==4?3:LBURG_MAX) + +reg: CVFI4(reg) "fdtoi %%f%0,%%f0; st %%f0,[%%sp+64]; ld [%%sp+64],%%%c\n" (a->syms[0]->u.c.v.i==8?3:LBURG_MAX) + +reg: CVIF4(reg) "st %%%0,[%%sp+64]; ld [%%sp+64],%%f%c; fitos %%f%c,%%f%c\n" 3 + +reg: CVIF8(reg) "st %%%0,[%%sp+64]; ld [%%sp+64],%%f%c; fitod %%f%c,%%f%c\n" 3 + +rel: EQF8(reg,reg) "fcmped %%f%0,%%f%1; nop; fbue" +rel: EQF4(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbue" +rel: GEF8(reg,reg) "fcmped %%f%0,%%f%1; nop; fbuge" +rel: GEF4(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbuge" +rel: GTF8(reg,reg) "fcmped %%f%0,%%f%1; nop; fbug" +rel: GTF4(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbug" +rel: LEF8(reg,reg) "fcmped %%f%0,%%f%1; nop; fbule" +rel: LEF4(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbule" +rel: LTF8(reg,reg) "fcmped %%f%0,%%f%1; nop; fbul" +rel: LTF4(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbul" +rel: NEF8(reg,reg) "fcmped %%f%0,%%f%1; nop; fbne" +rel: NEF4(reg,reg) "fcmpes %%f%0,%%f%1; nop; fbne" + +stmt: rel "%0 %a; nop\n" 4 +reg: LOADF8(reg) "# LOADD\n" 2 + +reg: NEGF8(reg) "# NEGD\n" 2 + +stmt: ASGNB(reg,INDIRB(reg)) "# ASGNB\n" + +%% +static void progend(void){} +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); + for (i = 0; i < argc; i++) + if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "-pg") == 0) + pflag = 1; + if (IR == &solarisIR) + stabprefix = ".LL"; + else + stabprefix = "L"; + for (i = 0; i < 8; i++) { + greg[i + 0] = mkreg(stringf("g%d", i), i + 0, 1, IREG); + greg[i + 8] = mkreg(stringf("o%d", i), i + 8, 1, IREG); + greg[i + 16] = mkreg(stringf("l%d", i), i + 16, 1, IREG); + greg[i + 24] = mkreg(stringf("i%d", i), i + 24, 1, IREG); + } + gregw = mkwildcard(greg); + for (i = 0; i < 32; i++) + freg[i] = mkreg("%d", i, 1, FREG); + for (i = 0; i < 31; i += 2) + freg2[i] = mkreg("%d", i, 3, FREG); + fregw = mkwildcard(freg); + freg2w = mkwildcard(freg2); + tmask[IREG] = 0x3fff3e00; + vmask[IREG] = 0x3ff00000; + tmask[FREG] = ~(unsigned)0; + vmask[FREG] = 0; +} +static Symbol rmap(int opk) { + switch (optype(opk)) { + case I: case U: case P: case B: + return gregw; + case F: + return opsize(opk) == 4 ? fregw : freg2w; + default: + return 0; + } +} +static void target(Node p) { + assert(p); + switch (specific(p->op)) { + case CNST+I: case CNST+U: case CNST+P: + if (range(p, 0, 0) == 0) { + setreg(p, greg[0]); + p->x.registered = 1; + } + break; + case CALL+B: + assert(p->syms[1] && p->syms[1]->type && isfunc(p->syms[1]->type)); + p->syms[1] = intconst(freturn(p->syms[1]->type)->size); + break; + case CALL+F: setreg(p, opsize(p->op)==4?freg[0]:freg2[0]); break; + case CALL+I: case CALL+P: case CALL+U: + case CALL+V: setreg(p, oreg[0]); break; + case RET+F: rtarget(p, 0, opsize(p->op)==4?freg[0]:freg2[0]); break; + case RET+I: case RET+P: case RET+U: + rtarget(p, 0, ireg[0]); + p->kids[0]->x.registered = 1; + break; + case ARG+I: case ARG+P: case ARG+U: + if (p->syms[RX]->u.c.v.i < 6) { + rtarget(p, 0, oreg[p->syms[RX]->u.c.v.i]); + p->op = LOAD+opkind(p->op); + setreg(p, oreg[p->syms[RX]->u.c.v.i]); + } + break; + } +} +static void clobber(Node p) { + assert(p); + switch (specific(p->op)) { + case CALL+B: case CALL+F: case CALL+I: + spill(~(unsigned)3, FREG, p); + break; + case CALL+V: + spill(oreg[0]->x.regnode->mask, IREG, p); + spill(~(unsigned)3, FREG, p); + break; + case ARG+F: + if (opsize(p->op) == 4 && p->syms[2]->u.c.v.i <= 6) + spill((1<<(p->syms[2]->u.c.v.i + 8)), IREG, p); + else if (opsize(p->op) == 8 && p->syms[2]->u.c.v.i <= 5) + spill((3<<(p->syms[2]->u.c.v.i + 8))&0xff00, IREG, p); + break; + } +} +static int imm(Node p) { + return range(p, -4096, 4091); +} +static void doarg(Node p) { + assert(p && p->syms[0] && p->op != ARG+B); + p->syms[RX] = intconst(mkactual(4, + p->syms[0]->u.c.v.i)/4); +} +static void emit2(Node p) { + switch (p->op) { + case ARG+F+sizeop(4): { + int n = p->syms[RX]->u.c.v.i; + print("st %%f%d,[%%sp+4*%d+68]\n", + getregnum(p->x.kids[0]), n); + if (n <= 5) + print("ld [%%sp+4*%d+68],%%o%d\n", n, n); + break; + } + case ARG+F+sizeop(8): { + int n = p->syms[RX]->u.c.v.i; + int src = getregnum(p->x.kids[0]); + print("st %%f%d,[%%sp+4*%d+68]\n", src, n); + print("st %%f%d,[%%sp+4*%d+68]\n", src+1, n+1); + if (n <= 5) + print("ld [%%sp+4*%d+68],%%o%d\n", n, n); + if (n <= 4) + print("ld [%%sp+4*%d+68],%%o%d\n", n+1, n+1); + break; + } + case LOAD+F+sizeop(8): { + int dst = getregnum(p); + int src = getregnum(p->x.kids[0]); + print("fmovs %%f%d,%%f%d; ", src, dst); + print("fmovs %%f%d,%%f%d\n", src+1, dst+1); + break; + } + case NEG+F+sizeop(8): { + int dst = getregnum(p); + int src = getregnum(p->x.kids[0]); + print("fnegs %%f%d,%%f%d; ", src, dst); + print("fmovs %%f%d,%%f%d\n", src+1, dst+1); + break; + } + case ASGN+B: { + static int tmpregs[] = { 1, 2, 3 }; + dalign = salign = p->syms[1]->u.c.v.i; + blkcopy(getregnum(p->x.kids[0]), 0, + getregnum(p->x.kids[1]), 0, + p->syms[0]->u.c.v.i, tmpregs); + break; + } + } +} +static void local(Symbol p) { + if (retstruct) { + assert(p == retv); + p->x.name = stringd(4*16); + p->x.offset = 4*16; + p->sclass = AUTO; + retstruct = 0; + return; + } + if (isscalar(p->type) && !p->addressed && !isfloat(p->type)) + p->sclass = REGISTER; + if (askregvar(p, rmap(ttob(p->type))) == 0) + mkauto(p); + else if (p->scope > LOCAL) + regvars++; +} +static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { + int autos = 0, i, leaf, reg, varargs; + + if (IR == &solarisIR) + globalend(); + regvars = 0; + for (i = 0; callee[i]; i++) + ; + varargs = variadic(f->type) + || i > 0 && strcmp(callee[i-1]->name, + "__builtin_va_alist") == 0; + usedmask[0] = usedmask[1] = 0; + freemask[0] = freemask[1] = ~(unsigned)0; + for (i = 0; i < 8; i++) + ireg[i]->x.regnode->vbl = NULL; + offset = 68; + maxargoffset = 24; + reg = 0; + for (i = 0; callee[i]; i++) { + Symbol p = callee[i], q = caller[i]; + int size = roundup(q->type->size, 4); + assert(q); + if (isfloat(p->type) || reg >= 6) { + p->x.offset = q->x.offset = offset; + p->x.name = q->x.name = stringd(offset); + p->sclass = q->sclass = AUTO; + autos++; + } + else if (p->addressed || varargs) { + p->x.offset = offset; + p->x.name = stringd(p->x.offset); + p->sclass = AUTO; + q->sclass = REGISTER; + askregvar(q, ireg[reg]); + assert(q->x.regnode); + autos++; + } + else { + p->sclass = q->sclass = REGISTER; + askregvar(p, ireg[reg]); + assert(p->x.regnode); + q->x.name = p->x.name; + } + offset += size; + reg += isstruct(p->type) ? 1 : size/4; + } + assert(caller[i] == 0); + offset = maxoffset = 0; + retstruct = isstruct(freturn(f->type)); + gencode(caller, callee); + maxargoffset = roundup(maxargoffset, 4); + framesize = roundup(maxoffset + maxargoffset + 4*(16+1), 8); + assert(!varargs || autos); + leaf = (!ncalls + && !maxoffset && !autos && !regvars + && !isstruct(freturn(f->type)) + && !(usedmask[IREG]&0x00ffff01) + && !(usedmask[FREG]&~(unsigned)3) + && !pflag && !glevel); + print(".align 4\n%s:\n", f->x.name); + if (leaf) { + for (i = 0; caller[i] && callee[i]; i++) { + Symbol p = caller[i], q = callee[i]; + if (p->sclass == REGISTER && q->sclass == REGISTER) { + assert(q->x.regnode); + assert(q->x.regnode->set == IREG); + assert(q->x.regnode->number >= 24); + assert(q->x.regnode->number <= 31); + p->x.name = greg[q->x.regnode->number - 16]->x.name; + } + } + renameregs(); + } else if (framesize <= 4095) + print("save %%sp,%d,%%sp\n", -framesize); + else + print("set %d,%%g1; save %%sp,%%g1,%%sp\n", -framesize); + if (varargs) + for (; reg < 6; reg++) + print("st %%i%d,[%%fp+%d]\n", reg, 4*reg + 68); + else { + offset = 4*(16 + 1); + reg = 0; + for (i = 0; caller[i]; i++) { + Symbol p = caller[i]; + if (isfloat(p->type) && p->type->size == 8 && reg <= 4) { + print("st %%r%d,[%%fp+%d]\n", + ireg[reg++]->x.regnode->number, offset); + print("st %%r%d,[%%fp+%d]\n", + ireg[reg++]->x.regnode->number, offset + 4); + } else if (isfloat(p->type) && p->type->size == 4 && reg <= 5) + print("st %%r%d,[%%fp+%d]\n", + ireg[reg++]->x.regnode->number, offset); + else + reg++; + offset += roundup(p->type->size, 4); + } + } + if (pflag) { + int lab = genlabel(1); + print("set L%d,%%o0; call mcount; nop\n", lab); + print(".seg \"data\"\n.align 4; L%d:.word 0\n.seg \"text\"\n", lab); + } + emitcode(); + if (isstruct(freturn(f->type))) + print("jmp %%i7+12; restore\n"); + else if (!leaf) + print("ret; restore\n"); + else { + renameregs(); + print("retl; nop\n"); + } + if (IR == &solarisIR) { + print(".type %s,#function\n", f->x.name); + print(".size %s,.-%s\n", f->x.name, f->x.name); + } +} +#define exch(x, y, t) (((t) = x), ((x) = (y)), ((y) = (t))) + +static void renameregs(void) { + int i; + + for (i = 0; i < 8; i++) { + char *ptmp; + int itmp; + if (ireg[i]->x.regnode->vbl) + ireg[i]->x.regnode->vbl->x.name = oreg[i]->x.name; + exch(ireg[i]->x.name, oreg[i]->x.name, ptmp); + exch(ireg[i]->x.regnode->number, + oreg[i]->x.regnode->number, itmp); + } +} +static void defconst(int suffix, int size, Value v) { + if (suffix == F && size == 4) { + float f = v.d; + print(".word 0x%x\n", *(unsigned *)&f); + } else if (suffix == F && size == 8) { + double d = v.d; + unsigned *p = (unsigned *)&d; + print(".word 0x%x\n.word 0x%x\n", p[swap], p[!swap]); + } else if (suffix == P) + print(".word 0x%x\n", v.p); + else if (size == 1) + print(".byte 0x%x\n", suffix == I ? v.i : v.u); + else if (size == 2) + print(".half 0x%x\n", suffix == I ? v.i : v.u); + else if (size == 4) + print(".word 0x%x\n", suffix == I ? v.i : v.u); + else assert(0); +} + +static void defaddress(Symbol p) { + print(".word %s\n", p->x.name); +} + +static void defstring(int n, char *str) { + char *s; + + for (s = str; s < str + n; s++) + print(".byte %d\n", (*s)&0377); +} + +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 export(Symbol p) { + print(".global %s\n", p->x.name); +} +static void import(Symbol p) {} +static void defsymbol(Symbol p) { + if (p->scope >= LOCAL && p->sclass == STATIC) + p->x.name = stringf("%d", genlabel(1)); + else + assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)), + p->x.name = p->name; + if (p->scope >= LABELS) + p->x.name = stringf(p->generated ? "L%s" : "_%s", + p->x.name); +} +static void segment(int n) { + cseg = n; + switch (n) { + case CODE: print(".seg \"text\"\n"); break; + case BSS: print(".seg \"bss\"\n"); break; + case DATA: print(".seg \"data\"\n"); break; + case LIT: print(".seg \"text\"\n"); break; + } +} +static void space(int n) { + if (cseg != BSS) + print(".skip %d\n", n); +} +static void global(Symbol p) { + print(".align %d\n", p->type->align); + assert(p->u.seg); + if (p->u.seg == BSS + && (p->sclass == STATIC || Aflag >= 2)) + print(".reserve %s,%d\n", p->x.name, p->type->size); + else if (p->u.seg == BSS) + print(".common %s,%d\n", p->x.name, p->type->size); + else + print("%s:\n", p->x.name); +} +static void blkfetch(int k, int off, int reg, int tmp) { + assert(k == 1 || k == 2 || k == 4); + assert(salign >= k); + if (k == 1) + print("ldub [%%r%d+%d],%%r%d\n", reg, off, tmp); + else if (k == 2) + print("lduh [%%r%d+%d],%%r%d\n", reg, off, tmp); + else + print("ld [%%r%d+%d],%%r%d\n", reg, off, tmp); +} +static void blkstore(int k, int off, int reg, int tmp) { + assert(k == 1 || k == 2 || k == 4); + assert(dalign >= k); + if (k == 1) + print("stb %%r%d,[%%r%d+%d]\n", tmp, reg, off); + else if (k == 2) + print("sth %%r%d,[%%r%d+%d]\n", tmp, reg, off); + else + print("st %%r%d,[%%r%d+%d]\n", tmp, reg, off); +} +static void blkloop(int dreg, int doff, int sreg, int soff, int size, int tmps[]) { + if ((size&~7) < 4096) { + print("add %%r%d,%d,%%r%d\n", sreg, size&~7, sreg); + print("add %%r%d,%d,%%r%d\n", dreg, size&~7, tmps[2]); + } else { + print("set %d,%%r%d\n", size&~7, tmps[2]); + print("add %%r%d,%%r%d,%%r%d\n", sreg, tmps[2], sreg); + print("add %%r%d,%%r%d,%%r%d\n", dreg, tmps[2], tmps[2]); + } + blkcopy(tmps[2], doff, sreg, soff, size&7, tmps); + print("1: dec 8,%%r%d\n", tmps[2]); + blkcopy(tmps[2], doff, sreg, soff - 8, 8, tmps); + print("cmp %%r%d,%%r%d; ", tmps[2], dreg); + print("bgt 1b; "); + print("dec 8,%%r%d\n", sreg); +} +static void defsymbol2(Symbol p) { + if (p->scope >= LOCAL && p->sclass == STATIC) + p->x.name = stringf(".%d", genlabel(1)); + else + assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)), + p->x.name = p->name; + if (p->scope >= LABELS) + p->x.name = stringf(p->generated ? ".L%s" : "%s", + p->x.name); +} + +static Symbol prevg; + +static void globalend(void) { + if (prevg && prevg->type->size > 0) + print(".size %s,%d\n", prevg->x.name, prevg->type->size); + prevg = NULL; +} + +static void export2(Symbol p) { + globalend(); + print(".global %s\n", p->x.name); +} + +static void progend2(void) { + globalend(); +} + +static void global2(Symbol p) { + globalend(); + assert(p->u.seg); + if (!p->generated) { + print(".type %s,#%s\n", p->x.name, + isfunc(p->type) ? "function" : "object"); + if (p->type->size > 0) + print(".size %s,%d\n", p->x.name, p->type->size); + else + prevg = p; + } + if (p->u.seg == BSS && p->sclass == STATIC) + print(".local %s\n.common %s,%d,%d\n", p->x.name, p->x.name, + p->type->size, p->type->align); + else if (p->u.seg == BSS && Aflag >= 2) + print(".align %d\n%s:.skip %d\n", p->type->align, p->x.name, + p->type->size); + else if (p->u.seg == BSS) + print(".common %s,%d,%d\n", p->x.name, p->type->size, p->type->align); + else + print(".align %d\n%s:\n", p->type->align, p->x.name); +} + +static void segment2(int n) { + cseg = n; + switch (n) { + case CODE: print(".section \".text\"\n"); break; + case BSS: print(".section \".bss\"\n"); break; + case DATA: print(".section \".data\"\n"); break; + case LIT: print(".section \".rodata\"\n"); break; + } +} +Interface sparcIR = { + 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, 1, 0, /* struct */ + 0, /* little_endian */ + 0, /* mulops_calls */ + 1, /* wants_callb */ + 0, /* wants_argb */ + 1, /* 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, + stabblock, 0, 0, stabinit, stabline, stabsym, stabtype, + { + 1, /* max_unaligned_load */ + rmap, + blkfetch, blkstore, blkloop, + _label, + _rule, + _nts, + _kids, + _string, + _templates, + _isinstruction, + _ntname, + emit2, + doarg, + target, + clobber, + + } +}; + +Interface solarisIR = { + 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, 1, 0, /* struct */ + 0, /* little_endian */ + 0, /* mulops_calls */ + 1, /* wants_callb */ + 0, /* wants_argb */ + 1, /* left_to_right */ + 0, /* wants_dag */ + 0, /* unsigned_char */ + address, + blockbeg, + blockend, + defaddress, + defconst, + defstring, + defsymbol2, + emit, + export2, + function, + gen, + global2, + import, + local, + progbeg, + progend2, + segment2, + space, + stabblock, 0, 0, stabinit, stabline, stabsym, stabtype, + { + 1, /* max_unaligned_load */ + rmap, + blkfetch, blkstore, blkloop, + _label, + _rule, + _nts, + _kids, + _string, + _templates, + _isinstruction, + _ntname, + emit2, + doarg, + target, + clobber, + + } +}; +static char rcsid[] = "$Id: sparc.md 145 2001-10-17 21:53:10Z timo $"; diff --git a/lcc/src/stab.c b/lcc/src/stab.c index 152b778..e1b52cf 100755 --- a/lcc/src/stab.c +++ b/lcc/src/stab.c @@ -1,330 +1,330 @@ -#include <string.h>
-#include <stdlib.h>
-#include "c.h"
-#include "stab.h"
-
-
-static char *currentfile; /* current file name */
-static int ntypes;
-
-extern Interface sparcIR;
-
-char *stabprefix = "L";
-
-extern char *stabprefix;
-extern void stabblock(int, int, Symbol*);
-extern void stabend(Coordinate *, Symbol, Coordinate **, Symbol *, Symbol *);
-extern void stabfend(Symbol, int);
-extern void stabinit(char *, int, char *[]);
-extern void stabline(Coordinate *);
-extern void stabsym(Symbol);
-extern void stabtype(Symbol);
-
-static void asgncode(Type, int);
-static void dbxout(Type);
-static int dbxtype(Type);
-static int emittype(Type, int, int);
-
-/* asgncode - assign type code to ty */
-static void asgncode(Type ty, int lev) {
- if (ty->x.marked || ty->x.typeno)
- return;
- ty->x.marked = 1;
- switch (ty->op) {
- case VOLATILE: case CONST: case VOLATILE+CONST:
- asgncode(ty->type, lev);
- ty->x.typeno = ty->type->x.typeno;
- break;
- case POINTER: case FUNCTION: case ARRAY:
- asgncode(ty->type, lev + 1);
- /* fall thru */
- case VOID: case INT: case UNSIGNED: case FLOAT:
- break;
- case STRUCT: case UNION: {
- Field p;
- for (p = fieldlist(ty); p; p = p->link)
- asgncode(p->type, lev + 1);
- /* fall thru */
- case ENUM:
- if (ty->x.typeno == 0)
- ty->x.typeno = ++ntypes;
- if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9'))
- dbxout(ty);
- break;
- }
- default:
- assert(0);
- }
-}
-
-/* dbxout - output .stabs entry for type ty */
-static void dbxout(Type ty) {
- ty = unqual(ty);
- if (!ty->x.printed) {
- int col = 0;
- print(".stabs \""), col += 8;
- if (ty->u.sym && !(isfunc(ty) || isarray(ty) || isptr(ty)))
- print("%s", ty->u.sym->name), col += strlen(ty->u.sym->name);
- print(":%c", isstruct(ty) || isenum(ty) ? 'T' : 't'), col += 2;
- emittype(ty, 0, col);
- print("\",%d,0,0,0\n", N_LSYM);
- }
-}
-
-/* dbxtype - emit a stabs entry for type ty, return type code */
-static int dbxtype(Type ty) {
- asgncode(ty, 0);
- dbxout(ty);
- return ty->x.typeno;
-}
-
-/*
- * emittype - emit ty's type number, emitting its definition if necessary.
- * Returns the output column number after emission; col is the approximate
- * output column before emission and is used to emit continuation lines for long
- * struct, union, and enum types. Continuations are not emitted for other types,
- * even if the definition is long. lev is the depth of calls to emittype.
- */
-static int emittype(Type ty, int lev, int col) {
- int tc = ty->x.typeno;
-
- if (isconst(ty) || isvolatile(ty)) {
- col = emittype(ty->type, lev, col);
- ty->x.typeno = ty->type->x.typeno;
- ty->x.printed = 1;
- return col;
- }
- if (tc == 0) {
- ty->x.typeno = tc = ++ntypes;
-/* fprint(2,"`%t'=%d\n", ty, tc); */
- }
- print("%d", tc), col += 3;
- if (ty->x.printed)
- return col;
- ty->x.printed = 1;
- switch (ty->op) {
- case VOID: /* void is defined as itself */
- print("=%d", tc), col += 1+3;
- break;
- case INT:
- if (ty == chartype) /* plain char is a subrange of itself */
- print("=r%d;%d;%d;", tc, ty->u.sym->u.limits.min.i, ty->u.sym->u.limits.max.i),
- col += 2+3+2*2.408*ty->size+2;
- else /* other signed ints are subranges of int */
- print("=r1;%D;%D;", ty->u.sym->u.limits.min.i, ty->u.sym->u.limits.max.i),
- col += 4+2*2.408*ty->size+2;
- break;
- case UNSIGNED:
- if (ty == chartype) /* plain char is a subrange of itself */
- print("=r%d;0;%u;", tc, ty->u.sym->u.limits.max.i),
- col += 2+3+2+2.408*ty->size+1;
- else /* other signed ints are subranges of int */
- print("=r1;0;%U;", ty->u.sym->u.limits.max.i),
- col += 4+2.408*ty->size+1;
- break;
- case FLOAT: /* float, double, long double get sizes, not ranges */
- print("=r1;%d;0;", ty->size), col += 4+1+3;
- break;
- case POINTER:
- print("=*"), col += 2;
- col = emittype(ty->type, lev + 1, col);
- break;
- case FUNCTION:
- print("=f"), col += 2;
- col = emittype(ty->type, lev + 1, col);
- break;
- case ARRAY: /* array includes subscript as an int range */
- if (ty->size && ty->type->size)
- print("=ar1;0;%d;", ty->size/ty->type->size - 1), col += 7+3+1;
- else
- print("=ar1;0;-1;"), col += 10;
- col = emittype(ty->type, lev + 1, col);
- break;
- case STRUCT: case UNION: {
- Field p;
- if (!ty->u.sym->defined) {
- print("=x%c%s:", ty->op == STRUCT ? 's' : 'u', ty->u.sym->name);
- col += 2+1+strlen(ty->u.sym->name)+1;
- break;
- }
- if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9')) {
- ty->x.printed = 0;
- break;
- }
- print("=%c%d", ty->op == STRUCT ? 's' : 'u', ty->size), col += 1+1+3;
- for (p = fieldlist(ty); p; p = p->link) {
- if (p->name)
- print("%s:", p->name), col += strlen(p->name)+1;
- else
- print(":"), col += 1;
- col = emittype(p->type, lev + 1, col);
- if (p->lsb)
- print(",%d,%d;", 8*p->offset +
- (IR->little_endian ? fieldright(p) : fieldleft(p)),
- fieldsize(p));
- else
- print(",%d,%d;", 8*p->offset, 8*p->type->size);
- col += 1+3+1+3+1; /* accounts for ,%d,%d; */
- if (col >= 80 && p->link) {
- print("\\\\\",%d,0,0,0\n.stabs \"", N_LSYM);
- col = 8;
- }
- }
- print(";"), col += 1;
- break;
- }
- case ENUM: {
- Symbol *p;
- if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9')) {
- ty->x.printed = 0;
- break;
- }
- print("=e"), col += 2;
- for (p = ty->u.sym->u.idlist; *p; p++) {
- print("%s:%d,", (*p)->name, (*p)->u.value), col += strlen((*p)->name)+3;
- if (col >= 80 && p[1]) {
- print("\\\\\",%d,0,0,0\n.stabs \"", N_LSYM);
- col = 8;
- }
- }
- print(";"), col += 1;
- break;
- }
- default:
- assert(0);
- }
- return col;
-}
-
-/* stabblock - output a stab entry for '{' or '}' at level lev */
-void stabblock(int brace, int lev, Symbol *p) {
- if (brace == '{')
- while (*p)
- stabsym(*p++);
- if (IR == &sparcIR)
- print(".stabd 0x%x,0,%d\n", brace == '{' ? N_LBRAC : N_RBRAC, lev);
- else {
- int lab = genlabel(1);
- print(".stabn 0x%x,0,%d,%s%d-%s\n", brace == '{' ? N_LBRAC : N_RBRAC, lev,
- stabprefix, lab, cfunc->x.name);
- print("%s%d:\n", stabprefix, lab);
- }
-}
-
-/* stabinit - initialize stab output */
-void stabinit(char *file, int argc, char *argv[]) {
- typedef void (*Closure)(Symbol, void *);
- extern char *getcwd(char *, size_t);
-
- print(".stabs \"lcc4_compiled.\",0x%x,0,0,0\n", N_OPT);
- if (file && *file) {
- char buf[1024], *cwd = getcwd(buf, sizeof buf);
- if (cwd)
- print(".stabs \"%s/\",0x%x,0,3,%stext0\n", cwd, N_SO, stabprefix);
- print(".stabs \"%s\",0x%x,0,3,%stext0\n", file, N_SO, stabprefix);
- (*IR->segment)(CODE);
- print("%stext0:\n", stabprefix, N_SO);
- currentfile = file;
- }
- dbxtype(inttype);
- dbxtype(chartype);
- dbxtype(doubletype);
- dbxtype(floattype);
- dbxtype(longdouble);
- dbxtype(longtype);
- dbxtype(longlong);
- dbxtype(shorttype);
- dbxtype(signedchar);
- dbxtype(unsignedchar);
- dbxtype(unsignedlong);
- dbxtype(unsignedlonglong);
- dbxtype(unsignedshort);
- dbxtype(unsignedtype);
- dbxtype(voidtype);
- foreach(types, GLOBAL, (Closure)stabtype, NULL);
-}
-
-/* stabline - emit stab entry for source coordinate *cp */
-void stabline(Coordinate *cp) {
- if (cp->file && cp->file != currentfile) {
- int lab = genlabel(1);
- print(".stabs \"%s\",0x%x,0,0,%s%d\n", cp->file, N_SOL, stabprefix, lab);
- print("%s%d:\n", stabprefix, lab);
- currentfile = cp->file;
- }
- if (IR == &sparcIR)
- print(".stabd 0x%x,0,%d\n", N_SLINE, cp->y);
- else {
- int lab = genlabel(1);
- print(".stabn 0x%x,0,%d,%s%d-%s\n", N_SLINE, cp->y,
- stabprefix, lab, cfunc->x.name);
- print("%s%d:\n", stabprefix, lab);
- }
-}
-
-/* stabsym - output a stab entry for symbol p */
-void stabsym(Symbol p) {
- int code, tc, sz = p->type->size;
-
- if (p->generated || p->computed)
- return;
- if (isfunc(p->type)) {
- print(".stabs \"%s:%c%d\",%d,0,0,%s\n", p->name,
- p->sclass == STATIC ? 'f' : 'F', dbxtype(freturn(p->type)),
- N_FUN, p->x.name);
- return;
- }
- if (!IR->wants_argb && p->scope == PARAM && p->structarg) {
- assert(isptr(p->type) && isstruct(p->type->type));
- tc = dbxtype(p->type->type);
- sz = p->type->type->size;
- } else
- tc = dbxtype(p->type);
- if (p->sclass == AUTO && p->scope == GLOBAL || p->sclass == EXTERN) {
- print(".stabs \"%s:G", p->name);
- code = N_GSYM;
- } else if (p->sclass == STATIC) {
- print(".stabs \"%s:%c%d\",%d,0,0,%s\n", p->name, p->scope == GLOBAL ? 'S' : 'V',
- tc, p->u.seg == BSS ? N_LCSYM : N_STSYM, p->x.name);
- return;
- } else if (p->sclass == REGISTER) {
- if (p->x.regnode) {
- int r = p->x.regnode->number;
- if (p->x.regnode->set == FREG)
- r += 32; /* floating point */
- print(".stabs \"%s:%c%d\",%d,0,", p->name,
- p->scope == PARAM ? 'P' : 'r', tc, N_RSYM);
- print("%d,%d\n", sz, r);
- }
- return;
- } else if (p->scope == PARAM) {
- print(".stabs \"%s:p", p->name);
- code = N_PSYM;
- } else if (p->scope >= LOCAL) {
- print(".stabs \"%s:", p->name);
- code = N_LSYM;
- } else
- assert(0);
- print("%d\",%d,0,0,%s\n", tc, code,
- p->scope >= PARAM && p->sclass != EXTERN ? p->x.name : "0");
-}
-
-/* stabtype - output a stab entry for type *p */
-void stabtype(Symbol p) {
- if (p->type) {
- if (p->sclass == 0)
- dbxtype(p->type);
- else if (p->sclass == TYPEDEF)
- print(".stabs \"%s:t%d\",%d,0,0,0\n", p->name, dbxtype(p->type), N_LSYM);
- }
-}
-
-/* stabend - finalize a function */
-void stabfend(Symbol p, int lineno) {}
-
-/* stabend - finalize stab output */
-void stabend(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {
- (*IR->segment)(CODE);
- print(".stabs \"\", %d, 0, 0,%setext\n", N_SO, stabprefix);
- print("%setext:\n", stabprefix);
-}
+#include <string.h> +#include <stdlib.h> +#include "c.h" +#include "stab.h" + + +static char *currentfile; /* current file name */ +static int ntypes; + +extern Interface sparcIR; + +char *stabprefix = "L"; + +extern char *stabprefix; +extern void stabblock(int, int, Symbol*); +extern void stabend(Coordinate *, Symbol, Coordinate **, Symbol *, Symbol *); +extern void stabfend(Symbol, int); +extern void stabinit(char *, int, char *[]); +extern void stabline(Coordinate *); +extern void stabsym(Symbol); +extern void stabtype(Symbol); + +static void asgncode(Type, int); +static void dbxout(Type); +static int dbxtype(Type); +static int emittype(Type, int, int); + +/* asgncode - assign type code to ty */ +static void asgncode(Type ty, int lev) { + if (ty->x.marked || ty->x.typeno) + return; + ty->x.marked = 1; + switch (ty->op) { + case VOLATILE: case CONST: case VOLATILE+CONST: + asgncode(ty->type, lev); + ty->x.typeno = ty->type->x.typeno; + break; + case POINTER: case FUNCTION: case ARRAY: + asgncode(ty->type, lev + 1); + /* fall thru */ + case VOID: case INT: case UNSIGNED: case FLOAT: + break; + case STRUCT: case UNION: { + Field p; + for (p = fieldlist(ty); p; p = p->link) + asgncode(p->type, lev + 1); + /* fall thru */ + case ENUM: + if (ty->x.typeno == 0) + ty->x.typeno = ++ntypes; + if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9')) + dbxout(ty); + break; + } + default: + assert(0); + } +} + +/* dbxout - output .stabs entry for type ty */ +static void dbxout(Type ty) { + ty = unqual(ty); + if (!ty->x.printed) { + int col = 0; + print(".stabs \""), col += 8; + if (ty->u.sym && !(isfunc(ty) || isarray(ty) || isptr(ty))) + print("%s", ty->u.sym->name), col += strlen(ty->u.sym->name); + print(":%c", isstruct(ty) || isenum(ty) ? 'T' : 't'), col += 2; + emittype(ty, 0, col); + print("\",%d,0,0,0\n", N_LSYM); + } +} + +/* dbxtype - emit a stabs entry for type ty, return type code */ +static int dbxtype(Type ty) { + asgncode(ty, 0); + dbxout(ty); + return ty->x.typeno; +} + +/* + * emittype - emit ty's type number, emitting its definition if necessary. + * Returns the output column number after emission; col is the approximate + * output column before emission and is used to emit continuation lines for long + * struct, union, and enum types. Continuations are not emitted for other types, + * even if the definition is long. lev is the depth of calls to emittype. + */ +static int emittype(Type ty, int lev, int col) { + int tc = ty->x.typeno; + + if (isconst(ty) || isvolatile(ty)) { + col = emittype(ty->type, lev, col); + ty->x.typeno = ty->type->x.typeno; + ty->x.printed = 1; + return col; + } + if (tc == 0) { + ty->x.typeno = tc = ++ntypes; +/* fprint(2,"`%t'=%d\n", ty, tc); */ + } + print("%d", tc), col += 3; + if (ty->x.printed) + return col; + ty->x.printed = 1; + switch (ty->op) { + case VOID: /* void is defined as itself */ + print("=%d", tc), col += 1+3; + break; + case INT: + if (ty == chartype) /* plain char is a subrange of itself */ + print("=r%d;%d;%d;", tc, ty->u.sym->u.limits.min.i, ty->u.sym->u.limits.max.i), + col += 2+3+2*2.408*ty->size+2; + else /* other signed ints are subranges of int */ + print("=r1;%D;%D;", ty->u.sym->u.limits.min.i, ty->u.sym->u.limits.max.i), + col += 4+2*2.408*ty->size+2; + break; + case UNSIGNED: + if (ty == chartype) /* plain char is a subrange of itself */ + print("=r%d;0;%u;", tc, ty->u.sym->u.limits.max.i), + col += 2+3+2+2.408*ty->size+1; + else /* other signed ints are subranges of int */ + print("=r1;0;%U;", ty->u.sym->u.limits.max.i), + col += 4+2.408*ty->size+1; + break; + case FLOAT: /* float, double, long double get sizes, not ranges */ + print("=r1;%d;0;", ty->size), col += 4+1+3; + break; + case POINTER: + print("=*"), col += 2; + col = emittype(ty->type, lev + 1, col); + break; + case FUNCTION: + print("=f"), col += 2; + col = emittype(ty->type, lev + 1, col); + break; + case ARRAY: /* array includes subscript as an int range */ + if (ty->size && ty->type->size) + print("=ar1;0;%d;", ty->size/ty->type->size - 1), col += 7+3+1; + else + print("=ar1;0;-1;"), col += 10; + col = emittype(ty->type, lev + 1, col); + break; + case STRUCT: case UNION: { + Field p; + if (!ty->u.sym->defined) { + print("=x%c%s:", ty->op == STRUCT ? 's' : 'u', ty->u.sym->name); + col += 2+1+strlen(ty->u.sym->name)+1; + break; + } + if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9')) { + ty->x.printed = 0; + break; + } + print("=%c%d", ty->op == STRUCT ? 's' : 'u', ty->size), col += 1+1+3; + for (p = fieldlist(ty); p; p = p->link) { + if (p->name) + print("%s:", p->name), col += strlen(p->name)+1; + else + print(":"), col += 1; + col = emittype(p->type, lev + 1, col); + if (p->lsb) + print(",%d,%d;", 8*p->offset + + (IR->little_endian ? fieldright(p) : fieldleft(p)), + fieldsize(p)); + else + print(",%d,%d;", 8*p->offset, 8*p->type->size); + col += 1+3+1+3+1; /* accounts for ,%d,%d; */ + if (col >= 80 && p->link) { + print("\\\\\",%d,0,0,0\n.stabs \"", N_LSYM); + col = 8; + } + } + print(";"), col += 1; + break; + } + case ENUM: { + Symbol *p; + if (lev > 0 && (*ty->u.sym->name < '0' || *ty->u.sym->name > '9')) { + ty->x.printed = 0; + break; + } + print("=e"), col += 2; + for (p = ty->u.sym->u.idlist; *p; p++) { + print("%s:%d,", (*p)->name, (*p)->u.value), col += strlen((*p)->name)+3; + if (col >= 80 && p[1]) { + print("\\\\\",%d,0,0,0\n.stabs \"", N_LSYM); + col = 8; + } + } + print(";"), col += 1; + break; + } + default: + assert(0); + } + return col; +} + +/* stabblock - output a stab entry for '{' or '}' at level lev */ +void stabblock(int brace, int lev, Symbol *p) { + if (brace == '{') + while (*p) + stabsym(*p++); + if (IR == &sparcIR) + print(".stabd 0x%x,0,%d\n", brace == '{' ? N_LBRAC : N_RBRAC, lev); + else { + int lab = genlabel(1); + print(".stabn 0x%x,0,%d,%s%d-%s\n", brace == '{' ? N_LBRAC : N_RBRAC, lev, + stabprefix, lab, cfunc->x.name); + print("%s%d:\n", stabprefix, lab); + } +} + +/* stabinit - initialize stab output */ +void stabinit(char *file, int argc, char *argv[]) { + typedef void (*Closure)(Symbol, void *); + extern char *getcwd(char *, size_t); + + print(".stabs \"lcc4_compiled.\",0x%x,0,0,0\n", N_OPT); + if (file && *file) { + char buf[1024], *cwd = getcwd(buf, sizeof buf); + if (cwd) + print(".stabs \"%s/\",0x%x,0,3,%stext0\n", cwd, N_SO, stabprefix); + print(".stabs \"%s\",0x%x,0,3,%stext0\n", file, N_SO, stabprefix); + (*IR->segment)(CODE); + print("%stext0:\n", stabprefix, N_SO); + currentfile = file; + } + dbxtype(inttype); + dbxtype(chartype); + dbxtype(doubletype); + dbxtype(floattype); + dbxtype(longdouble); + dbxtype(longtype); + dbxtype(longlong); + dbxtype(shorttype); + dbxtype(signedchar); + dbxtype(unsignedchar); + dbxtype(unsignedlong); + dbxtype(unsignedlonglong); + dbxtype(unsignedshort); + dbxtype(unsignedtype); + dbxtype(voidtype); + foreach(types, GLOBAL, (Closure)stabtype, NULL); +} + +/* stabline - emit stab entry for source coordinate *cp */ +void stabline(Coordinate *cp) { + if (cp->file && cp->file != currentfile) { + int lab = genlabel(1); + print(".stabs \"%s\",0x%x,0,0,%s%d\n", cp->file, N_SOL, stabprefix, lab); + print("%s%d:\n", stabprefix, lab); + currentfile = cp->file; + } + if (IR == &sparcIR) + print(".stabd 0x%x,0,%d\n", N_SLINE, cp->y); + else { + int lab = genlabel(1); + print(".stabn 0x%x,0,%d,%s%d-%s\n", N_SLINE, cp->y, + stabprefix, lab, cfunc->x.name); + print("%s%d:\n", stabprefix, lab); + } +} + +/* stabsym - output a stab entry for symbol p */ +void stabsym(Symbol p) { + int code, tc, sz = p->type->size; + + if (p->generated || p->computed) + return; + if (isfunc(p->type)) { + print(".stabs \"%s:%c%d\",%d,0,0,%s\n", p->name, + p->sclass == STATIC ? 'f' : 'F', dbxtype(freturn(p->type)), + N_FUN, p->x.name); + return; + } + if (!IR->wants_argb && p->scope == PARAM && p->structarg) { + assert(isptr(p->type) && isstruct(p->type->type)); + tc = dbxtype(p->type->type); + sz = p->type->type->size; + } else + tc = dbxtype(p->type); + if (p->sclass == AUTO && p->scope == GLOBAL || p->sclass == EXTERN) { + print(".stabs \"%s:G", p->name); + code = N_GSYM; + } else if (p->sclass == STATIC) { + print(".stabs \"%s:%c%d\",%d,0,0,%s\n", p->name, p->scope == GLOBAL ? 'S' : 'V', + tc, p->u.seg == BSS ? N_LCSYM : N_STSYM, p->x.name); + return; + } else if (p->sclass == REGISTER) { + if (p->x.regnode) { + int r = p->x.regnode->number; + if (p->x.regnode->set == FREG) + r += 32; /* floating point */ + print(".stabs \"%s:%c%d\",%d,0,", p->name, + p->scope == PARAM ? 'P' : 'r', tc, N_RSYM); + print("%d,%d\n", sz, r); + } + return; + } else if (p->scope == PARAM) { + print(".stabs \"%s:p", p->name); + code = N_PSYM; + } else if (p->scope >= LOCAL) { + print(".stabs \"%s:", p->name); + code = N_LSYM; + } else + assert(0); + print("%d\",%d,0,0,%s\n", tc, code, + p->scope >= PARAM && p->sclass != EXTERN ? p->x.name : "0"); +} + +/* stabtype - output a stab entry for type *p */ +void stabtype(Symbol p) { + if (p->type) { + if (p->sclass == 0) + dbxtype(p->type); + else if (p->sclass == TYPEDEF) + print(".stabs \"%s:t%d\",%d,0,0,0\n", p->name, dbxtype(p->type), N_LSYM); + } +} + +/* stabend - finalize a function */ +void stabfend(Symbol p, int lineno) {} + +/* stabend - finalize stab output */ +void stabend(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) { + (*IR->segment)(CODE); + print(".stabs \"\", %d, 0, 0,%setext\n", N_SO, stabprefix); + print("%setext:\n", stabprefix); +} diff --git a/lcc/src/stab.h b/lcc/src/stab.h index bfb7ebf..198b1fe 100755 --- a/lcc/src/stab.h +++ b/lcc/src/stab.h @@ -1,113 +1,113 @@ -/* @(#)stab.h 1.11 92/05/11 SMI */
-/*
- * Copyright (c) 1990 by Sun Microsystems, Inc.
- */
-
-/*
- * This file gives definitions supplementing <a.out.h>
- * for permanent symbol table entries.
- * These must have one of the N_STAB bits on,
- * and are subject to relocation according to the masks in <a.out.h>.
- */
-
-#ifndef _STAB_H
-#define _STAB_H
-
-
-#if !defined(_a_out_h) && !defined(_A_OUT_H)
-/* this file contains fragments of a.out.h and stab.h relevant to
- * support of stabX processing within ELF files - see the
- * Format of a symbol table entry
- */
-struct nlist {
- union {
- char *n_name; /* for use when in-core */
- long n_strx; /* index into file string table */
- } n_un;
- unsigned char n_type; /* type flag (N_TEXT,..) */
- char n_other; /* unused */
- short n_desc; /* see <stab.h> */
- unsigned long n_value; /* value of symbol (or sdb offset) */
-};
-
-/*
- * Simple values for n_type.
- */
-#define N_UNDF 0x0 /* undefined */
-#define N_ABS 0x2 /* absolute */
-#define N_TEXT 0x4 /* text */
-#define N_DATA 0x6 /* data */
-#define N_BSS 0x8 /* bss */
-#define N_COMM 0x12 /* common (internal to ld) */
-#define N_FN 0x1f /* file name symbol */
-
-#define N_EXT 01 /* external bit, or'ed in */
-#define N_TYPE 0x1e /* mask for all the type bits */
-
-#endif
-
-/*
- * for symbolic debugger, sdb(1):
- */
-#define N_GSYM 0x20 /* global symbol: name,,0,type,0 */
-#define N_FNAME 0x22 /* procedure name (f77 kludge): name,,0 */
-#define N_FUN 0x24 /* procedure: name,,0,linenumber,address */
-#define N_STSYM 0x26 /* static symbol: name,,0,type,address */
-#define N_LCSYM 0x28 /* .lcomm symbol: name,,0,type,address */
-#define N_MAIN 0x2a /* name of main routine : name,,0,0,0 */
-#define N_ROSYM 0x2c /* ro_data objects */
-#define N_OBJ 0x38 /* object file path or name */
-#define N_OPT 0x3c /* compiler options */
-#define N_RSYM 0x40 /* register sym: name,,0,type,register */
-#define N_SLINE 0x44 /* src line: 0,,0,linenumber,address */
-#define N_FLINE 0x4c /* function start.end */
-#define N_SSYM 0x60 /* structure elt: name,,0,type,struct_offset */
-#define N_ENDM 0x62 /* last stab emitted for module */
-#define N_SO 0x64 /* source file name: name,,0,0,address */
-#define N_LSYM 0x80 /* local sym: name,,0,type,offset */
-#define N_BINCL 0x82 /* header file: name,,0,0,0 */
-#define N_SOL 0x84 /* #included file name: name,,0,0,address */
-#define N_PSYM 0xa0 /* parameter: name,,0,type,offset */
-#define N_EINCL 0xa2 /* end of include file */
-#define N_ENTRY 0xa4 /* alternate entry: name,linenumber,address */
-#define N_LBRAC 0xc0 /* left bracket: 0,,0,nesting level,address */
-#define N_EXCL 0xc2 /* excluded include file */
-#define N_RBRAC 0xe0 /* right bracket: 0,,0,nesting level,address */
-#define N_BCOMM 0xe2 /* begin common: name,, */
-#define N_ECOMM 0xe4 /* end common: name,, */
-#define N_ECOML 0xe8 /* end common (local name): ,,address */
-#define N_LENG 0xfe /* second stab entry with length information */
-
-/*
- * for the berkeley pascal compiler, pc(1):
- */
-#define N_PC 0x30 /* global pascal symbol: name,,0,subtype,line */
-#define N_WITH 0xea /* pascal with statement: type,,0,0,offset */
-
-/*
- * for code browser only
- */
-#define N_BROWS 0x48 /* path to associated .cb file */
-
-/*
- * Optional langauge designations for N_SO
- */
-#define N_SO_AS 1 /* Assembler */
-#define N_SO_C 2 /* C */
-#define N_SO_ANSI_C 3 /* ANSI C */
-#define N_SO_CC 4 /* C++ */
-#define N_SO_FORTRAN 5 /* Fortran 77 */
-#define N_SO_PASCAL 6 /* Pascal */
-
-/*
- * Floating point type values
- */
-#define NF_NONE 0 /* Undefined type */
-#define NF_SINGLE 1 /* IEEE 32 bit float */
-#define NF_DOUBLE 2 /* IEEE 64 bit float */
-#define NF_COMPLEX 3 /* Fortran complex */
-#define NF_COMPLEX16 4 /* Fortran double complex */
-#define NF_COMPLEX32 5 /* Fortran complex*16 */
-#define NF_LDOUBLE 6 /* Long double */
-
-#endif
+/* @(#)stab.h 1.11 92/05/11 SMI */ +/* + * Copyright (c) 1990 by Sun Microsystems, Inc. + */ + +/* + * This file gives definitions supplementing <a.out.h> + * for permanent symbol table entries. + * These must have one of the N_STAB bits on, + * and are subject to relocation according to the masks in <a.out.h>. + */ + +#ifndef _STAB_H +#define _STAB_H + + +#if !defined(_a_out_h) && !defined(_A_OUT_H) +/* this file contains fragments of a.out.h and stab.h relevant to + * support of stabX processing within ELF files - see the + * Format of a symbol table entry + */ +struct nlist { + union { + char *n_name; /* for use when in-core */ + long n_strx; /* index into file string table */ + } n_un; + unsigned char n_type; /* type flag (N_TEXT,..) */ + char n_other; /* unused */ + short n_desc; /* see <stab.h> */ + unsigned long n_value; /* value of symbol (or sdb offset) */ +}; + +/* + * Simple values for n_type. + */ +#define N_UNDF 0x0 /* undefined */ +#define N_ABS 0x2 /* absolute */ +#define N_TEXT 0x4 /* text */ +#define N_DATA 0x6 /* data */ +#define N_BSS 0x8 /* bss */ +#define N_COMM 0x12 /* common (internal to ld) */ +#define N_FN 0x1f /* file name symbol */ + +#define N_EXT 01 /* external bit, or'ed in */ +#define N_TYPE 0x1e /* mask for all the type bits */ + +#endif + +/* + * for symbolic debugger, sdb(1): + */ +#define N_GSYM 0x20 /* global symbol: name,,0,type,0 */ +#define N_FNAME 0x22 /* procedure name (f77 kludge): name,,0 */ +#define N_FUN 0x24 /* procedure: name,,0,linenumber,address */ +#define N_STSYM 0x26 /* static symbol: name,,0,type,address */ +#define N_LCSYM 0x28 /* .lcomm symbol: name,,0,type,address */ +#define N_MAIN 0x2a /* name of main routine : name,,0,0,0 */ +#define N_ROSYM 0x2c /* ro_data objects */ +#define N_OBJ 0x38 /* object file path or name */ +#define N_OPT 0x3c /* compiler options */ +#define N_RSYM 0x40 /* register sym: name,,0,type,register */ +#define N_SLINE 0x44 /* src line: 0,,0,linenumber,address */ +#define N_FLINE 0x4c /* function start.end */ +#define N_SSYM 0x60 /* structure elt: name,,0,type,struct_offset */ +#define N_ENDM 0x62 /* last stab emitted for module */ +#define N_SO 0x64 /* source file name: name,,0,0,address */ +#define N_LSYM 0x80 /* local sym: name,,0,type,offset */ +#define N_BINCL 0x82 /* header file: name,,0,0,0 */ +#define N_SOL 0x84 /* #included file name: name,,0,0,address */ +#define N_PSYM 0xa0 /* parameter: name,,0,type,offset */ +#define N_EINCL 0xa2 /* end of include file */ +#define N_ENTRY 0xa4 /* alternate entry: name,linenumber,address */ +#define N_LBRAC 0xc0 /* left bracket: 0,,0,nesting level,address */ +#define N_EXCL 0xc2 /* excluded include file */ +#define N_RBRAC 0xe0 /* right bracket: 0,,0,nesting level,address */ +#define N_BCOMM 0xe2 /* begin common: name,, */ +#define N_ECOMM 0xe4 /* end common: name,, */ +#define N_ECOML 0xe8 /* end common (local name): ,,address */ +#define N_LENG 0xfe /* second stab entry with length information */ + +/* + * for the berkeley pascal compiler, pc(1): + */ +#define N_PC 0x30 /* global pascal symbol: name,,0,subtype,line */ +#define N_WITH 0xea /* pascal with statement: type,,0,0,offset */ + +/* + * for code browser only + */ +#define N_BROWS 0x48 /* path to associated .cb file */ + +/* + * Optional langauge designations for N_SO + */ +#define N_SO_AS 1 /* Assembler */ +#define N_SO_C 2 /* C */ +#define N_SO_ANSI_C 3 /* ANSI C */ +#define N_SO_CC 4 /* C++ */ +#define N_SO_FORTRAN 5 /* Fortran 77 */ +#define N_SO_PASCAL 6 /* Pascal */ + +/* + * Floating point type values + */ +#define NF_NONE 0 /* Undefined type */ +#define NF_SINGLE 1 /* IEEE 32 bit float */ +#define NF_DOUBLE 2 /* IEEE 64 bit float */ +#define NF_COMPLEX 3 /* Fortran complex */ +#define NF_COMPLEX16 4 /* Fortran double complex */ +#define NF_COMPLEX32 5 /* Fortran complex*16 */ +#define NF_LDOUBLE 6 /* Long double */ + +#endif diff --git a/lcc/src/stmt.c b/lcc/src/stmt.c index b742a32..94ab403 100755 --- a/lcc/src/stmt.c +++ b/lcc/src/stmt.c @@ -1,697 +1,697 @@ -#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) {
- Code cp;
-
- 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);
-}
+#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) { + Code cp; + + 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); +} diff --git a/lcc/src/string.c b/lcc/src/string.c index 4fee2c9..73cfc85 100755 --- a/lcc/src/string.c +++ b/lcc/src/string.c @@ -1,122 +1,122 @@ -#include "c.h"
-
-
-static struct string {
- char *str;
- int len;
- struct string *link;
-} *buckets[1024];
-static int scatter[] = { /* map characters to random values */
- 2078917053, 143302914, 1027100827, 1953210302, 755253631,
- 2002600785, 1405390230, 45248011, 1099951567, 433832350,
- 2018585307, 438263339, 813528929, 1703199216, 618906479,
- 573714703, 766270699, 275680090, 1510320440, 1583583926,
- 1723401032, 1965443329, 1098183682, 1636505764, 980071615,
- 1011597961, 643279273, 1315461275, 157584038, 1069844923,
- 471560540, 89017443, 1213147837, 1498661368, 2042227746,
- 1968401469, 1353778505, 1300134328, 2013649480, 306246424,
- 1733966678, 1884751139, 744509763, 400011959, 1440466707,
- 1363416242, 973726663, 59253759, 1639096332, 336563455,
- 1642837685, 1215013716, 154523136, 593537720, 704035832,
- 1134594751, 1605135681, 1347315106, 302572379, 1762719719,
- 269676381, 774132919, 1851737163, 1482824219, 125310639,
- 1746481261, 1303742040, 1479089144, 899131941, 1169907872,
- 1785335569, 485614972, 907175364, 382361684, 885626931,
- 200158423, 1745777927, 1859353594, 259412182, 1237390611,
- 48433401, 1902249868, 304920680, 202956538, 348303940,
- 1008956512, 1337551289, 1953439621, 208787970, 1640123668,
- 1568675693, 478464352, 266772940, 1272929208, 1961288571,
- 392083579, 871926821, 1117546963, 1871172724, 1771058762,
- 139971187, 1509024645, 109190086, 1047146551, 1891386329,
- 994817018, 1247304975, 1489680608, 706686964, 1506717157,
- 579587572, 755120366, 1261483377, 884508252, 958076904,
- 1609787317, 1893464764, 148144545, 1415743291, 2102252735,
- 1788268214, 836935336, 433233439, 2055041154, 2109864544,
- 247038362, 299641085, 834307717, 1364585325, 23330161,
- 457882831, 1504556512, 1532354806, 567072918, 404219416,
- 1276257488, 1561889936, 1651524391, 618454448, 121093252,
- 1010757900, 1198042020, 876213618, 124757630, 2082550272,
- 1834290522, 1734544947, 1828531389, 1982435068, 1002804590,
- 1783300476, 1623219634, 1839739926, 69050267, 1530777140,
- 1802120822, 316088629, 1830418225, 488944891, 1680673954,
- 1853748387, 946827723, 1037746818, 1238619545, 1513900641,
- 1441966234, 367393385, 928306929, 946006977, 985847834,
- 1049400181, 1956764878, 36406206, 1925613800, 2081522508,
- 2118956479, 1612420674, 1668583807, 1800004220, 1447372094,
- 523904750, 1435821048, 923108080, 216161028, 1504871315,
- 306401572, 2018281851, 1820959944, 2136819798, 359743094,
- 1354150250, 1843084537, 1306570817, 244413420, 934220434,
- 672987810, 1686379655, 1301613820, 1601294739, 484902984,
- 139978006, 503211273, 294184214, 176384212, 281341425,
- 228223074, 147857043, 1893762099, 1896806882, 1947861263,
- 1193650546, 273227984, 1236198663, 2116758626, 489389012,
- 593586330, 275676551, 360187215, 267062626, 265012701,
- 719930310, 1621212876, 2108097238, 2026501127, 1865626297,
- 894834024, 552005290, 1404522304, 48964196, 5816381,
- 1889425288, 188942202, 509027654, 36125855, 365326415,
- 790369079, 264348929, 513183458, 536647531, 13672163,
- 313561074, 1730298077, 286900147, 1549759737, 1699573055,
- 776289160, 2143346068, 1975249606, 1136476375, 262925046,
- 92778659, 1856406685, 1884137923, 53392249, 1735424165,
- 1602280572
-};
-char *string(const char *str) {
- const char *s;
-
- for (s = str; *s; s++)
- ;
- return stringn(str, s - str);
-}
-char *stringd(long n) {
- char str[25], *s = str + sizeof (str);
- unsigned long m;
-
- if (n == LONG_MIN)
- m = (unsigned long)LONG_MAX + 1;
- else if (n < 0)
- m = -n;
- else
- m = n;
- do
- *--s = m%10 + '0';
- while ((m /= 10) != 0);
- if (n < 0)
- *--s = '-';
- return stringn(s, str + sizeof (str) - s);
-}
-char *stringn(const char *str, int len) {
- int i;
- unsigned int h;
- const char *end;
- struct string *p;
-
- assert(str);
- for (h = 0, i = len, end = str; i > 0; i--)
- h = (h<<1) + scatter[*(unsigned char *)end++];
- h &= NELEMS(buckets)-1;
- for (p = buckets[h]; p; p = p->link)
- if (len == p->len) {
- const char *s1 = str;
- char *s2 = p->str;
- do {
- if (s1 == end)
- return p->str;
- } while (*s1++ == *s2++);
- }
- {
- static char *next, *strlimit;
- if (len + 1 >= strlimit - next) {
- int n = len + 4*1024;
- next = allocate(n, PERM);
- strlimit = next + n;
- }
- NEW(p, PERM);
- p->len = len;
- for (p->str = next; str < end; )
- *next++ = *str++;
- *next++ = 0;
- p->link = buckets[h];
- buckets[h] = p;
- return p->str;
- }
-}
+#include "c.h" + + +static struct string { + char *str; + int len; + struct string *link; +} *buckets[1024]; +static int scatter[] = { /* map characters to random values */ + 2078917053, 143302914, 1027100827, 1953210302, 755253631, + 2002600785, 1405390230, 45248011, 1099951567, 433832350, + 2018585307, 438263339, 813528929, 1703199216, 618906479, + 573714703, 766270699, 275680090, 1510320440, 1583583926, + 1723401032, 1965443329, 1098183682, 1636505764, 980071615, + 1011597961, 643279273, 1315461275, 157584038, 1069844923, + 471560540, 89017443, 1213147837, 1498661368, 2042227746, + 1968401469, 1353778505, 1300134328, 2013649480, 306246424, + 1733966678, 1884751139, 744509763, 400011959, 1440466707, + 1363416242, 973726663, 59253759, 1639096332, 336563455, + 1642837685, 1215013716, 154523136, 593537720, 704035832, + 1134594751, 1605135681, 1347315106, 302572379, 1762719719, + 269676381, 774132919, 1851737163, 1482824219, 125310639, + 1746481261, 1303742040, 1479089144, 899131941, 1169907872, + 1785335569, 485614972, 907175364, 382361684, 885626931, + 200158423, 1745777927, 1859353594, 259412182, 1237390611, + 48433401, 1902249868, 304920680, 202956538, 348303940, + 1008956512, 1337551289, 1953439621, 208787970, 1640123668, + 1568675693, 478464352, 266772940, 1272929208, 1961288571, + 392083579, 871926821, 1117546963, 1871172724, 1771058762, + 139971187, 1509024645, 109190086, 1047146551, 1891386329, + 994817018, 1247304975, 1489680608, 706686964, 1506717157, + 579587572, 755120366, 1261483377, 884508252, 958076904, + 1609787317, 1893464764, 148144545, 1415743291, 2102252735, + 1788268214, 836935336, 433233439, 2055041154, 2109864544, + 247038362, 299641085, 834307717, 1364585325, 23330161, + 457882831, 1504556512, 1532354806, 567072918, 404219416, + 1276257488, 1561889936, 1651524391, 618454448, 121093252, + 1010757900, 1198042020, 876213618, 124757630, 2082550272, + 1834290522, 1734544947, 1828531389, 1982435068, 1002804590, + 1783300476, 1623219634, 1839739926, 69050267, 1530777140, + 1802120822, 316088629, 1830418225, 488944891, 1680673954, + 1853748387, 946827723, 1037746818, 1238619545, 1513900641, + 1441966234, 367393385, 928306929, 946006977, 985847834, + 1049400181, 1956764878, 36406206, 1925613800, 2081522508, + 2118956479, 1612420674, 1668583807, 1800004220, 1447372094, + 523904750, 1435821048, 923108080, 216161028, 1504871315, + 306401572, 2018281851, 1820959944, 2136819798, 359743094, + 1354150250, 1843084537, 1306570817, 244413420, 934220434, + 672987810, 1686379655, 1301613820, 1601294739, 484902984, + 139978006, 503211273, 294184214, 176384212, 281341425, + 228223074, 147857043, 1893762099, 1896806882, 1947861263, + 1193650546, 273227984, 1236198663, 2116758626, 489389012, + 593586330, 275676551, 360187215, 267062626, 265012701, + 719930310, 1621212876, 2108097238, 2026501127, 1865626297, + 894834024, 552005290, 1404522304, 48964196, 5816381, + 1889425288, 188942202, 509027654, 36125855, 365326415, + 790369079, 264348929, 513183458, 536647531, 13672163, + 313561074, 1730298077, 286900147, 1549759737, 1699573055, + 776289160, 2143346068, 1975249606, 1136476375, 262925046, + 92778659, 1856406685, 1884137923, 53392249, 1735424165, + 1602280572 +}; +char *string(const char *str) { + const char *s; + + for (s = str; *s; s++) + ; + return stringn(str, s - str); +} +char *stringd(long n) { + char str[25], *s = str + sizeof (str); + unsigned long m; + + if (n == LONG_MIN) + m = (unsigned long)LONG_MAX + 1; + else if (n < 0) + m = -n; + else + m = n; + do + *--s = m%10 + '0'; + while ((m /= 10) != 0); + if (n < 0) + *--s = '-'; + return stringn(s, str + sizeof (str) - s); +} +char *stringn(const char *str, int len) { + int i; + unsigned int h; + const char *end; + struct string *p; + + assert(str); + for (h = 0, i = len, end = str; i > 0; i--) + h = (h<<1) + scatter[*(unsigned char *)end++]; + h &= NELEMS(buckets)-1; + for (p = buckets[h]; p; p = p->link) + if (len == p->len) { + const char *s1 = str; + char *s2 = p->str; + do { + if (s1 == end) + return p->str; + } while (*s1++ == *s2++); + } + { + static char *next, *strlimit; + if (len + 1 >= strlimit - next) { + int n = len + 4*1024; + next = allocate(n, PERM); + strlimit = next + n; + } + NEW(p, PERM); + p->len = len; + for (p->str = next; str < end; ) + *next++ = *str++; + *next++ = 0; + p->link = buckets[h]; + buckets[h] = p; + return p->str; + } +} diff --git a/lcc/src/sym.c b/lcc/src/sym.c index 1d754d4..723cdd4 100755 --- a/lcc/src/sym.c +++ b/lcc/src/sym.c @@ -1,315 +1,315 @@ -#include "c.h"
-#include <stdio.h>
-
-
-#define equalp(x) v.x == p->sym.u.c.v.x
-
-struct table {
- int level;
- Table previous;
- struct entry {
- struct symbol sym;
- struct entry *link;
- } *buckets[256];
- Symbol all;
-};
-#define HASHSIZE NELEMS(((Table)0)->buckets)
-static struct table
- cns = { CONSTANTS },
- ext = { GLOBAL },
- ids = { GLOBAL },
- tys = { GLOBAL };
-Table constants = &cns;
-Table externals = &ext;
-Table identifiers = &ids;
-Table globals = &ids;
-Table types = &tys;
-Table labels;
-int level = GLOBAL;
-static int tempid;
-List loci, symbols;
-
-Table table(Table tp, int level) {
- Table new;
-
- NEW0(new, FUNC);
- new->previous = tp;
- new->level = level;
- if (tp)
- new->all = tp->all;
- return new;
-}
-void foreach(Table tp, int lev, void (*apply)(Symbol, void *), void *cl) {
- assert(tp);
- while (tp && tp->level > lev)
- tp = tp->previous;
- if (tp && tp->level == lev) {
- Symbol p;
- Coordinate sav;
- sav = src;
- for (p = tp->all; p && p->scope == lev; p = p->up) {
- src = p->src;
- (*apply)(p, cl);
- }
- src = sav;
- }
-}
-void enterscope(void) {
- if (++level == LOCAL)
- tempid = 0;
-}
-void exitscope(void) {
- rmtypes(level);
- if (types->level == level)
- types = types->previous;
- if (identifiers->level == level) {
- if (Aflag >= 2) {
- int n = 0;
- Symbol p;
- for (p = identifiers->all; p && p->scope == level; p = p->up)
- if (++n > 127) {
- warning("more than 127 identifiers declared in a block\n");
- break;
- }
- }
- identifiers = identifiers->previous;
- }
- assert(level >= GLOBAL);
- --level;
-}
-Symbol install(const char *name, Table *tpp, int level, int arena) {
- Table tp = *tpp;
- struct entry *p;
- unsigned h = (unsigned long)name&(HASHSIZE-1);
-
- assert(level == 0 || level >= tp->level);
- if (level > 0 && tp->level < level)
- tp = *tpp = table(tp, level);
- NEW0(p, arena);
- p->sym.name = (char *)name;
- p->sym.scope = level;
- p->sym.up = tp->all;
- tp->all = &p->sym;
- p->link = tp->buckets[h];
- tp->buckets[h] = p;
- return &p->sym;
-}
-Symbol relocate(const char *name, Table src, Table dst) {
- struct entry *p, **q;
- Symbol *r;
- unsigned h = (unsigned long)name&(HASHSIZE-1);
-
- for (q = &src->buckets[h]; *q; q = &(*q)->link)
- if (name == (*q)->sym.name)
- break;
- assert(*q);
- /*
- Remove the entry from src's hash chain
- and from its list of all symbols.
- */
- p = *q;
- *q = (*q)->link;
- for (r = &src->all; *r && *r != &p->sym; r = &(*r)->up)
- ;
- assert(*r == &p->sym);
- *r = p->sym.up;
- /*
- Insert the entry into dst's hash chain
- and into its list of all symbols.
- Return the symbol-table entry.
- */
- p->link = dst->buckets[h];
- dst->buckets[h] = p;
- p->sym.up = dst->all;
- dst->all = &p->sym;
- return &p->sym;
-}
-Symbol lookup(const char *name, Table tp) {
- struct entry *p;
- unsigned h = (unsigned long)name&(HASHSIZE-1);
-
- assert(tp);
- do
- for (p = tp->buckets[h]; p; p = p->link)
- if (name == p->sym.name)
- return &p->sym;
- while ((tp = tp->previous) != NULL);
- return NULL;
-}
-int genlabel(int n) {
- static int label = 1;
-
- label += n;
- return label - n;
-}
-Symbol findlabel(int lab) {
- struct entry *p;
- unsigned h = lab&(HASHSIZE-1);
-
- for (p = labels->buckets[h]; p; p = p->link)
- if (lab == p->sym.u.l.label)
- return &p->sym;
- NEW0(p, FUNC);
- p->sym.name = stringd(lab);
- p->sym.scope = LABELS;
- p->sym.up = labels->all;
- labels->all = &p->sym;
- p->link = labels->buckets[h];
- labels->buckets[h] = p;
- p->sym.generated = 1;
- p->sym.u.l.label = lab;
- (*IR->defsymbol)(&p->sym);
- return &p->sym;
-}
-Symbol constant(Type ty, Value v) {
- struct entry *p;
- unsigned h = v.u&(HASHSIZE-1);
-
- ty = unqual(ty);
- for (p = constants->buckets[h]; p; p = p->link)
- if (eqtype(ty, p->sym.type, 1))
- switch (ty->op) {
- case INT: if (equalp(i)) return &p->sym; break;
- case UNSIGNED: if (equalp(u)) return &p->sym; break;
- case FLOAT: if (equalp(d)) return &p->sym; break;
- case FUNCTION: if (equalp(g)) return &p->sym; break;
- case ARRAY:
- case POINTER: if (equalp(p)) return &p->sym; break;
- default: assert(0);
- }
- NEW0(p, PERM);
- p->sym.name = vtoa(ty, v);
- p->sym.scope = CONSTANTS;
- p->sym.type = ty;
- p->sym.sclass = STATIC;
- p->sym.u.c.v = v;
- p->link = constants->buckets[h];
- p->sym.up = constants->all;
- constants->all = &p->sym;
- constants->buckets[h] = p;
- if (ty->u.sym && !ty->u.sym->addressed)
- (*IR->defsymbol)(&p->sym);
- p->sym.defined = 1;
- return &p->sym;
-}
-Symbol intconst(int n) {
- Value v;
-
- v.i = n;
- return constant(inttype, v);
-}
-Symbol genident(int scls, Type ty, int lev) {
- Symbol p;
-
- NEW0(p, lev >= LOCAL ? FUNC : PERM);
- p->name = stringd(genlabel(1));
- p->scope = lev;
- p->sclass = scls;
- p->type = ty;
- p->generated = 1;
- if (lev == GLOBAL)
- (*IR->defsymbol)(p);
- return p;
-}
-
-Symbol temporary(int scls, Type ty) {
- Symbol p;
-
- NEW0(p, FUNC);
- p->name = stringd(++tempid);
- p->scope = level < LOCAL ? LOCAL : level;
- p->sclass = scls;
- p->type = ty;
- p->temporary = 1;
- p->generated = 1;
- return p;
-}
-Symbol newtemp(int sclass, int tc, int size) {
- Symbol p = temporary(sclass, btot(tc, size));
-
- (*IR->local)(p);
- p->defined = 1;
- return p;
-}
-
-Symbol allsymbols(Table tp) {
- return tp->all;
-}
-
-void locus(Table tp, Coordinate *cp) {
- loci = append(cp, loci);
- symbols = append(allsymbols(tp), symbols);
-}
-
-void use(Symbol p, Coordinate src) {
- Coordinate *cp;
-
- NEW(cp, PERM);
- *cp = src;
- p->uses = append(cp, p->uses);
-}
-/* findtype - find type ty in identifiers */
-Symbol findtype(Type ty) {
- Table tp = identifiers;
- int i;
- struct entry *p;
-
- assert(tp);
- do
- for (i = 0; i < HASHSIZE; i++)
- for (p = tp->buckets[i]; p; p = p->link)
- if (p->sym.type == ty && p->sym.sclass == TYPEDEF)
- return &p->sym;
- while ((tp = tp->previous) != NULL);
- return NULL;
-}
-
-/* mkstr - make a string constant */
-Symbol mkstr(char *str) {
- Value v;
- Symbol p;
-
- v.p = str;
- p = constant(array(chartype, strlen(v.p) + 1, 0), v);
- if (p->u.c.loc == NULL)
- p->u.c.loc = genident(STATIC, p->type, GLOBAL);
- return p;
-}
-
-/* mksymbol - make a symbol for name, install in &globals if sclass==EXTERN */
-Symbol mksymbol(int sclass, const char *name, Type ty) {
- Symbol p;
-
- if (sclass == EXTERN)
- p = install(string(name), &globals, GLOBAL, PERM);
- else {
- NEW0(p, PERM);
- p->name = string(name);
- p->scope = GLOBAL;
- }
- p->sclass = sclass;
- p->type = ty;
- (*IR->defsymbol)(p);
- p->defined = 1;
- return p;
-}
-
-/* vtoa - return string for the constant v of type ty */
-char *vtoa(Type ty, Value v) {
- char buf[50];
-
- ty = unqual(ty);
- switch (ty->op) {
- case INT: return stringd(v.i);
- case UNSIGNED: return stringf((v.u&~0x7FFF) ? "0x%X" : "%U", v.u);
- case FLOAT: return stringf("%g", (double)v.d);
- case ARRAY:
- if (ty->type == chartype || ty->type == signedchar
- || ty->type == unsignedchar)
- return v.p;
- return stringf("%p", v.p);
- case POINTER: return stringf("%p", v.p);
- case FUNCTION: return stringf("%p", v.g);
- }
- assert(0); return NULL;
-}
+#include "c.h" +#include <stdio.h> + + +#define equalp(x) v.x == p->sym.u.c.v.x + +struct table { + int level; + Table previous; + struct entry { + struct symbol sym; + struct entry *link; + } *buckets[256]; + Symbol all; +}; +#define HASHSIZE NELEMS(((Table)0)->buckets) +static struct table + cns = { CONSTANTS }, + ext = { GLOBAL }, + ids = { GLOBAL }, + tys = { GLOBAL }; +Table constants = &cns; +Table externals = &ext; +Table identifiers = &ids; +Table globals = &ids; +Table types = &tys; +Table labels; +int level = GLOBAL; +static int tempid; +List loci, symbols; + +Table table(Table tp, int level) { + Table new; + + NEW0(new, FUNC); + new->previous = tp; + new->level = level; + if (tp) + new->all = tp->all; + return new; +} +void foreach(Table tp, int lev, void (*apply)(Symbol, void *), void *cl) { + assert(tp); + while (tp && tp->level > lev) + tp = tp->previous; + if (tp && tp->level == lev) { + Symbol p; + Coordinate sav; + sav = src; + for (p = tp->all; p && p->scope == lev; p = p->up) { + src = p->src; + (*apply)(p, cl); + } + src = sav; + } +} +void enterscope(void) { + if (++level == LOCAL) + tempid = 0; +} +void exitscope(void) { + rmtypes(level); + if (types->level == level) + types = types->previous; + if (identifiers->level == level) { + if (Aflag >= 2) { + int n = 0; + Symbol p; + for (p = identifiers->all; p && p->scope == level; p = p->up) + if (++n > 127) { + warning("more than 127 identifiers declared in a block\n"); + break; + } + } + identifiers = identifiers->previous; + } + assert(level >= GLOBAL); + --level; +} +Symbol install(const char *name, Table *tpp, int level, int arena) { + Table tp = *tpp; + struct entry *p; + unsigned h = (unsigned long)name&(HASHSIZE-1); + + assert(level == 0 || level >= tp->level); + if (level > 0 && tp->level < level) + tp = *tpp = table(tp, level); + NEW0(p, arena); + p->sym.name = (char *)name; + p->sym.scope = level; + p->sym.up = tp->all; + tp->all = &p->sym; + p->link = tp->buckets[h]; + tp->buckets[h] = p; + return &p->sym; +} +Symbol relocate(const char *name, Table src, Table dst) { + struct entry *p, **q; + Symbol *r; + unsigned h = (unsigned long)name&(HASHSIZE-1); + + for (q = &src->buckets[h]; *q; q = &(*q)->link) + if (name == (*q)->sym.name) + break; + assert(*q); + /* + Remove the entry from src's hash chain + and from its list of all symbols. + */ + p = *q; + *q = (*q)->link; + for (r = &src->all; *r && *r != &p->sym; r = &(*r)->up) + ; + assert(*r == &p->sym); + *r = p->sym.up; + /* + Insert the entry into dst's hash chain + and into its list of all symbols. + Return the symbol-table entry. + */ + p->link = dst->buckets[h]; + dst->buckets[h] = p; + p->sym.up = dst->all; + dst->all = &p->sym; + return &p->sym; +} +Symbol lookup(const char *name, Table tp) { + struct entry *p; + unsigned h = (unsigned long)name&(HASHSIZE-1); + + assert(tp); + do + for (p = tp->buckets[h]; p; p = p->link) + if (name == p->sym.name) + return &p->sym; + while ((tp = tp->previous) != NULL); + return NULL; +} +int genlabel(int n) { + static int label = 1; + + label += n; + return label - n; +} +Symbol findlabel(int lab) { + struct entry *p; + unsigned h = lab&(HASHSIZE-1); + + for (p = labels->buckets[h]; p; p = p->link) + if (lab == p->sym.u.l.label) + return &p->sym; + NEW0(p, FUNC); + p->sym.name = stringd(lab); + p->sym.scope = LABELS; + p->sym.up = labels->all; + labels->all = &p->sym; + p->link = labels->buckets[h]; + labels->buckets[h] = p; + p->sym.generated = 1; + p->sym.u.l.label = lab; + (*IR->defsymbol)(&p->sym); + return &p->sym; +} +Symbol constant(Type ty, Value v) { + struct entry *p; + unsigned h = v.u&(HASHSIZE-1); + + ty = unqual(ty); + for (p = constants->buckets[h]; p; p = p->link) + if (eqtype(ty, p->sym.type, 1)) + switch (ty->op) { + case INT: if (equalp(i)) return &p->sym; break; + case UNSIGNED: if (equalp(u)) return &p->sym; break; + case FLOAT: if (equalp(d)) return &p->sym; break; + case FUNCTION: if (equalp(g)) return &p->sym; break; + case ARRAY: + case POINTER: if (equalp(p)) return &p->sym; break; + default: assert(0); + } + NEW0(p, PERM); + p->sym.name = vtoa(ty, v); + p->sym.scope = CONSTANTS; + p->sym.type = ty; + p->sym.sclass = STATIC; + p->sym.u.c.v = v; + p->link = constants->buckets[h]; + p->sym.up = constants->all; + constants->all = &p->sym; + constants->buckets[h] = p; + if (ty->u.sym && !ty->u.sym->addressed) + (*IR->defsymbol)(&p->sym); + p->sym.defined = 1; + return &p->sym; +} +Symbol intconst(int n) { + Value v; + + v.i = n; + return constant(inttype, v); +} +Symbol genident(int scls, Type ty, int lev) { + Symbol p; + + NEW0(p, lev >= LOCAL ? FUNC : PERM); + p->name = stringd(genlabel(1)); + p->scope = lev; + p->sclass = scls; + p->type = ty; + p->generated = 1; + if (lev == GLOBAL) + (*IR->defsymbol)(p); + return p; +} + +Symbol temporary(int scls, Type ty) { + Symbol p; + + NEW0(p, FUNC); + p->name = stringd(++tempid); + p->scope = level < LOCAL ? LOCAL : level; + p->sclass = scls; + p->type = ty; + p->temporary = 1; + p->generated = 1; + return p; +} +Symbol newtemp(int sclass, int tc, int size) { + Symbol p = temporary(sclass, btot(tc, size)); + + (*IR->local)(p); + p->defined = 1; + return p; +} + +Symbol allsymbols(Table tp) { + return tp->all; +} + +void locus(Table tp, Coordinate *cp) { + loci = append(cp, loci); + symbols = append(allsymbols(tp), symbols); +} + +void use(Symbol p, Coordinate src) { + Coordinate *cp; + + NEW(cp, PERM); + *cp = src; + p->uses = append(cp, p->uses); +} +/* findtype - find type ty in identifiers */ +Symbol findtype(Type ty) { + Table tp = identifiers; + int i; + struct entry *p; + + assert(tp); + do + for (i = 0; i < HASHSIZE; i++) + for (p = tp->buckets[i]; p; p = p->link) + if (p->sym.type == ty && p->sym.sclass == TYPEDEF) + return &p->sym; + while ((tp = tp->previous) != NULL); + return NULL; +} + +/* mkstr - make a string constant */ +Symbol mkstr(char *str) { + Value v; + Symbol p; + + v.p = str; + p = constant(array(chartype, strlen(v.p) + 1, 0), v); + if (p->u.c.loc == NULL) + p->u.c.loc = genident(STATIC, p->type, GLOBAL); + return p; +} + +/* mksymbol - make a symbol for name, install in &globals if sclass==EXTERN */ +Symbol mksymbol(int sclass, const char *name, Type ty) { + Symbol p; + + if (sclass == EXTERN) + p = install(string(name), &globals, GLOBAL, PERM); + else { + NEW0(p, PERM); + p->name = string(name); + p->scope = GLOBAL; + } + p->sclass = sclass; + p->type = ty; + (*IR->defsymbol)(p); + p->defined = 1; + return p; +} + +/* vtoa - return string for the constant v of type ty */ +char *vtoa(Type ty, Value v) { + char buf[50]; + + ty = unqual(ty); + switch (ty->op) { + case INT: return stringd(v.i); + case UNSIGNED: return stringf((v.u&~0x7FFF) ? "0x%X" : "%U", v.u); + case FLOAT: return stringf("%g", (double)v.d); + case ARRAY: + if (ty->type == chartype || ty->type == signedchar + || ty->type == unsignedchar) + return v.p; + return stringf("%p", v.p); + case POINTER: return stringf("%p", v.p); + case FUNCTION: return stringf("%p", v.g); + } + assert(0); return NULL; +} diff --git a/lcc/src/symbolic.c b/lcc/src/symbolic.c index 35ff55c..dcb613e 100755 --- a/lcc/src/symbolic.c +++ b/lcc/src/symbolic.c @@ -1,494 +1,494 @@ -#include <time.h>
-#include <ctype.h>
-#include "c.h"
-
-#define I(f) s_##f
-
-static Node *tail;
-static int off, maxoff, uid = 0, verbose = 0, html = 0;
-
-static const char *yyBEGIN(const char *tag) {
- if (html)
- print("<%s>", tag);
- return tag;
-}
-
-static void yyEND(const char *tag) {
- if (html)
- print("</%s>", tag);
- if (isupper(*tag))
- print("\n");
-}
-
-#define BEGIN(tag) do { const char *yytag=yyBEGIN(#tag);
-#define END yyEND(yytag); } while (0)
-#define ITEM BEGIN(li)
-#define START BEGIN(LI)
-#define ANCHOR(attr,code) do { const char *yytag="a"; if (html) { printf("<a " #attr "=\""); code; print("\">"); }
-#define NEWLINE print(html ? "<br>\n" : "\n")
-
-static void emitCoord(Coordinate src) {
- if (src.file && *src.file) {
- ANCHOR(href,print("%s", src.file)); print("%s", src.file); END;
- print(":");
- }
- print("%d.%d", src.y, src.x);
-}
-
-static void emitString(int len, const char *s) {
- for ( ; len-- > 0; s++)
- if (*s == '&' && html)
- print("&");
- else if (*s == '<' && html)
- print("<");
- else if (*s == '>' && html)
- print("<");
- else if (*s == '"' || *s == '\\')
- print("\\%c", *s);
- else if (*s >= ' ' && *s < 0177)
- print("%c", *s);
- else
- print("\\%d%d%d", (*s>>6)&3, (*s>>3)&7, *s&7);
-}
-
-static void emitSymRef(Symbol p) {
- (*IR->defsymbol)(p);
- ANCHOR(href,print("#%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END;
-}
-
-static void emitSymbol(Symbol p) {
- (*IR->defsymbol)(p);
- ANCHOR(name,print("%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END;
- BEGIN(ul);
-#define xx(field,code) ITEM; if (!html) print(" "); print(#field "="); code; END
- if (verbose && (src.y || src.x))
- xx(src,emitCoord(p->src));
- xx(type,print("%t", p->type));
- xx(sclass,print("%k", p->sclass));
- switch (p->scope) {
- case CONSTANTS: xx(scope,print("CONSTANTS")); break;
- case LABELS: xx(scope,print("LABELS")); break;
- case GLOBAL: xx(scope,print("GLOBAL")); break;
- case PARAM: xx(scope,print("PARAM")); break;
- case LOCAL: xx(scope,print("LOCAL")); break;
- default:
- if (p->scope > LOCAL)
- xx(scope,print("LOCAL+%d", p->scope-LOCAL));
- else
- xx(scope,print("%d", p->scope));
- }
- if (p->scope >= PARAM && p->sclass != STATIC)
- xx(offset,print("%d", p->x.offset));
- xx(ref,print("%f", p->ref));
- if (p->temporary && p->u.t.cse)
- xx(u.t.cse,print("%p", p->u.t.cse));
- END;
-#undef xx
-}
-
-/* address - initialize q for addressing expression p+n */
-static void I(address)(Symbol q, Symbol p, long n) {
- q->name = stringf("%s%s%D", p->name, n > 0 ? "+" : "", n);
- (*IR->defsymbol)(q);
- START; print("address "); emitSymbol(q); END;
-}
-
-/* blockbeg - start a block */
-static void I(blockbeg)(Env *e) {
- e->offset = off;
- START; print("blockbeg off=%d", off); END;
-}
-
-/* blockend - start a block */
-static void I(blockend)(Env *e) {
- if (off > maxoff)
- maxoff = off;
- START; print("blockend off=%d", off); END;
- off = e->offset;
-}
-
-/* defaddress - initialize an address */
-static void I(defaddress)(Symbol p){
- START; print("defaddress "); emitSymRef(p); END;
-}
-
-/* defconst - define a constant */
-static void I(defconst)(int suffix, int size, Value v) {
- START;
- print("defconst ");
- switch (suffix) {
- case I:
- print("int.%d ", size);
- BEGIN(code);
- if (size > sizeof (int))
- print("%D", v.i);
- else
- print("%d", (int)v.i);
- END;
- break;
- case U:
- print("unsigned.%d ", size);
- BEGIN(code);
- if (size > sizeof (unsigned))
- print("%U", v.u);
- else
- print("%u", (unsigned)v.u);
- END;
- break;
- case P: print("void*.%d ", size); BEGIN(code); print("%p", v.p); END; break;
- case F: print("float.%d ", size); BEGIN(code); print("%g", (double)v.d); END; break;
- default: assert(0);
- }
- END;
-}
-
-/* defstring - emit a string constant */
-static void I(defstring)(int len, char *s) {
- START; print("defstring ");
- BEGIN(code); print("\""); emitString(len, s); print("\""); END;
- END;
-}
-
-/* defsymbol - define a symbol: initialize p->x */
-static void I(defsymbol)(Symbol p) {
- if (p->x.name == NULL)
- p->x.name = stringd(++uid);
-}
-
-/* emit - emit the dags on list p */
-static void I(emit)(Node p){
- ITEM;
- if (!html)
- print(" ");
- for (; p; p = p->x.next) {
- if (p->op == LABEL+V) {
- assert(p->syms[0]);
- ANCHOR(name,print("%s", p->syms[0]->x.name));
- BEGIN(code); print("%s", p->syms[0]->name); END;
- END;
- print(":");
- } else {
- int i;
- if (p->x.listed) {
- BEGIN(strong); print("%d", p->x.inst); END; print("'");
- print(" %s", opname(p->op));
- } else
- print("%d. %s", p->x.inst, opname(p->op));
- if (p->count > 1)
- print(" count=%d", p->count);
- for (i = 0; i < NELEMS(p->kids) && p->kids[i]; i++)
- print(" #%d", p->kids[i]->x.inst);
- if (generic(p->op) == CALL && p->syms[0] && p->syms[0]->type)
- print(" {%t}", p->syms[0]->type);
- else
- for (i = 0; i < NELEMS(p->syms) && p->syms[i]; i++) {
- print(" ");
- if (p->syms[i]->scope == CONSTANTS)
- print(p->syms[i]->name);
- else
- emitSymRef(p->syms[i]);
- }
- }
- NEWLINE;
- }
- END;
-}
-
-/* export - announce p as exported */
-static void I(export)(Symbol p) {
- START; print("export "); emitSymRef(p); END;
-}
-
-/* function - generate code for a function */
-static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
- int i;
-
- (*IR->defsymbol)(f);
- off = 0;
- for (i = 0; caller[i] && callee[i]; i++) {
- off = roundup(off, caller[i]->type->align);
- caller[i]->x.offset = callee[i]->x.offset = off;
- off += caller[i]->type->size;
- }
- if (!html) {
- print("function ");
- emitSymbol(f);
- print(" ncalls=%d\n", ncalls);
- for (i = 0; caller[i]; i++)
- START; print("caller "); emitSymbol(caller[i]); END;
- for (i = 0; callee[i]; i++)
- START; print("callee "); emitSymbol(callee[i]); END;
- } else {
- START;
- print("function");
- BEGIN(UL);
-#define xx(field,code) ITEM; print(#field "="); code; END
- xx(f,emitSymbol(f));
- xx(ncalls,print("%d", ncalls));
- if (caller[0]) {
- ITEM; print("caller"); BEGIN(OL);
- for (i = 0; caller[i]; i++)
- ITEM; emitSymbol(caller[i]); END;
- END; END;
- ITEM; print("callee"); BEGIN(OL);
- for (i = 0; callee[i]; i++)
- ITEM; emitSymbol(callee[i]); END;
- END; END;
- } else {
- xx(caller,BEGIN(em); print("empty"); END);
- xx(callee,BEGIN(em); print("empty"); END);
- }
- END;
- END;
- }
- maxoff = off = 0;
- gencode(caller, callee);
- if (html)
- START; print("emitcode"); BEGIN(ul); emitcode(); END; END;
- else
- emitcode();
- START; print("maxoff=%d", maxoff); END;
-#undef xx
-}
-
-/* visit - generate code for *p */
-static int visit(Node p, int n) {
- if (p && p->x.inst == 0) {
- p->x.inst = ++n;
- n = visit(p->kids[0], n);
- n = visit(p->kids[1], n);
- *tail = p;
- tail = &p->x.next;
- }
- return n;
-}
-
-/* gen0 - generate code for the dags on list p */
-static Node I(gen)(Node p) {
- int n;
- Node nodelist;
-
- tail = &nodelist;
- for (n = 0; p; p = p->link) {
- switch (generic(p->op)) { /* check for valid forest */
- case CALL:
- assert(IR->wants_dag || p->count == 0);
- break;
- case ARG:
- case ASGN: case JUMP: case LABEL: case RET:
- case EQ: case GE: case GT: case LE: case LT: case NE:
- assert(p->count == 0);
- break;
- case INDIR:
- assert(IR->wants_dag && p->count > 0);
- break;
- default:
- assert(0);
- }
- check(p);
- p->x.listed = 1;
- n = visit(p, n);
- }
- *tail = 0;
- return nodelist;
-}
-
-/* global - announce a global */
-static void I(global)(Symbol p) {
- START; print("global "); emitSymbol(p); END;
-}
-
-/* import - import a symbol */
-static void I(import)(Symbol p) {
- START; print("import "); emitSymRef(p); END;
-}
-
-/* local - local variable */
-static void I(local)(Symbol p) {
- if (p->temporary)
- p->name = stringf("t%s", p->name);
- (*IR->defsymbol)(p);
- off = roundup(off, p->type->align);
- p->x.offset = off;
- off += p->type->size;
- START; print(p->temporary ? "temporary " : "local "); emitSymbol(p); END;
-}
-
-/* progbeg - beginning of program */
-static void I(progbeg)(int argc, char *argv[]) {
- int i;
-
- for (i = 1; i < argc; i++)
- if (strcmp(argv[i], "-v") == 0)
- verbose++;
- else if (strcmp(argv[i], "-html") == 0)
- html++;
- if (html) {
- print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n");
- print("<html>");
- BEGIN(head);
- if (firstfile && *firstfile)
- BEGIN(title); emitString(strlen(firstfile), firstfile); END;
- print("<link rev=made href=\"mailto:drh@microsoft.com\">\n");
- END;
- print("<body>\n");
- if (firstfile && *firstfile)
- BEGIN(h1); emitString(strlen(firstfile), firstfile); END;
- BEGIN(P); BEGIN(em);
- print("Links lead from uses of identifiers and labels to their definitions.");
- END; END;
- print("<ul>\n");
- START;
- print("progbeg");
- BEGIN(ol);
- for (i = 1; i < argc; i++) {
- ITEM;
- BEGIN(code); print("\""); emitString(strlen(argv[i]), argv[i]); print("\""); END;
- END;
- }
- END;
- END;
- }
-}
-
-/* progend - end of program */
-static void I(progend)(void) {
- START; print("progend"); END;
- if (html) {
- time_t t;
- print("</ul>\n");
- time(&t);
- print("<hr><address>%s</address>\n", ctime(&t));
- print("</body></html>\n");
- }
-}
-
-/* segment - switch to segment s */
-static void I(segment)(int s) {
- START; print("segment %s", &"text\0bss\0.data\0lit\0.sym\0."[5*s-5]); END;
-}
-
-/* space - initialize n bytes of space */
-static void I(space)(int n) {
- START; print("space %d", n); END;
-}
-
-static void I(stabblock)(int brace, int lev, Symbol *p) {}
-
-/* stabend - finalize stab output */
-static void I(stabend)(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {
- int i;
-
- if (p)
- emitSymRef(p);
- print("\n");
- if (cpp && sp)
- for (i = 0; cpp[i] && sp[i]; i++) {
- print("%w.%d: ", cpp[i], cpp[i]->x);
- emitSymRef(sp[i]);
- print("\n");
- }
-}
-
-static void I(stabfend)(Symbol p, int lineno) {}
-static void I(stabinit)(char *file, int argc, char *argv[]) {}
-
-/* stabline - emit line number information for source coordinate *cp */
-static void I(stabline)(Coordinate *cp) {
- if (cp->file)
- print("%s:", cp->file);
- print("%d.%d:\n", cp->y, cp->x);
-}
-
-static void I(stabsym)(Symbol p) {}
-static void I(stabtype)(Symbol p) {}
-
-Interface symbolicIR = {
- 1, 1, 0, /* char */
- 2, 2, 0, /* short */
- 4, 4, 0, /* int */
- 4, 4, 0, /* long */
- 4, 4, 0, /* long long */
- 4, 4, 1, /* float */
- 8, 8, 1, /* double */
- 8, 8, 1, /* long double */
- 4, 4, 0, /* T* */
- 0, 4, 0, /* struct */
- 0, /* little_endian */
- 0, /* mulops_calls */
- 0, /* wants_callb */
- 1, /* wants_argb */
- 1, /* left_to_right */
- 1, /* wants_dag */
- 0, /* unsigned_char */
- I(address),
- I(blockbeg),
- I(blockend),
- I(defaddress),
- I(defconst),
- I(defstring),
- I(defsymbol),
- I(emit),
- I(export),
- I(function),
- I(gen),
- I(global),
- I(import),
- I(local),
- I(progbeg),
- I(progend),
- I(segment),
- I(space),
- I(stabblock),
- I(stabend),
- I(stabfend),
- I(stabinit),
- I(stabline),
- I(stabsym),
- I(stabtype)
-};
-
-Interface symbolic64IR = {
- 1, 1, 0, /* char */
- 2, 2, 0, /* short */
- 4, 4, 0, /* int */
- 8, 8, 0, /* long */
- 8, 8, 0, /* long long */
- 4, 4, 1, /* float */
- 8, 8, 1, /* double */
- 8, 8, 1, /* long double */
- 8, 8, 0, /* T* */
- 0, 1, 0, /* struct */
- 1, /* little_endian */
- 0, /* mulops_calls */
- 0, /* wants_callb */
- 1, /* wants_argb */
- 1, /* left_to_right */
- 1, /* wants_dag */
- 0, /* unsigned_char */
- I(address),
- I(blockbeg),
- I(blockend),
- I(defaddress),
- I(defconst),
- I(defstring),
- I(defsymbol),
- I(emit),
- I(export),
- I(function),
- I(gen),
- I(global),
- I(import),
- I(local),
- I(progbeg),
- I(progend),
- I(segment),
- I(space),
- I(stabblock),
- I(stabend),
- I(stabfend),
- I(stabinit),
- I(stabline),
- I(stabsym),
- I(stabtype)
-};
+#include <time.h> +#include <ctype.h> +#include "c.h" + +#define I(f) s_##f + +static Node *tail; +static int off, maxoff, uid = 0, verbose = 0, html = 0; + +static const char *yyBEGIN(const char *tag) { + if (html) + print("<%s>", tag); + return tag; +} + +static void yyEND(const char *tag) { + if (html) + print("</%s>", tag); + if (isupper(*tag)) + print("\n"); +} + +#define BEGIN(tag) do { const char *yytag=yyBEGIN(#tag); +#define END yyEND(yytag); } while (0) +#define ITEM BEGIN(li) +#define START BEGIN(LI) +#define ANCHOR(attr,code) do { const char *yytag="a"; if (html) { printf("<a " #attr "=\""); code; print("\">"); } +#define NEWLINE print(html ? "<br>\n" : "\n") + +static void emitCoord(Coordinate src) { + if (src.file && *src.file) { + ANCHOR(href,print("%s", src.file)); print("%s", src.file); END; + print(":"); + } + print("%d.%d", src.y, src.x); +} + +static void emitString(int len, const char *s) { + for ( ; len-- > 0; s++) + if (*s == '&' && html) + print("&"); + else if (*s == '<' && html) + print("<"); + else if (*s == '>' && html) + print("<"); + else if (*s == '"' || *s == '\\') + print("\\%c", *s); + else if (*s >= ' ' && *s < 0177) + print("%c", *s); + else + print("\\%d%d%d", (*s>>6)&3, (*s>>3)&7, *s&7); +} + +static void emitSymRef(Symbol p) { + (*IR->defsymbol)(p); + ANCHOR(href,print("#%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END; +} + +static void emitSymbol(Symbol p) { + (*IR->defsymbol)(p); + ANCHOR(name,print("%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END; + BEGIN(ul); +#define xx(field,code) ITEM; if (!html) print(" "); print(#field "="); code; END + if (verbose && (src.y || src.x)) + xx(src,emitCoord(p->src)); + xx(type,print("%t", p->type)); + xx(sclass,print("%k", p->sclass)); + switch (p->scope) { + case CONSTANTS: xx(scope,print("CONSTANTS")); break; + case LABELS: xx(scope,print("LABELS")); break; + case GLOBAL: xx(scope,print("GLOBAL")); break; + case PARAM: xx(scope,print("PARAM")); break; + case LOCAL: xx(scope,print("LOCAL")); break; + default: + if (p->scope > LOCAL) + xx(scope,print("LOCAL+%d", p->scope-LOCAL)); + else + xx(scope,print("%d", p->scope)); + } + if (p->scope >= PARAM && p->sclass != STATIC) + xx(offset,print("%d", p->x.offset)); + xx(ref,print("%f", p->ref)); + if (p->temporary && p->u.t.cse) + xx(u.t.cse,print("%p", p->u.t.cse)); + END; +#undef xx +} + +/* address - initialize q for addressing expression p+n */ +static void I(address)(Symbol q, Symbol p, long n) { + q->name = stringf("%s%s%D", p->name, n > 0 ? "+" : "", n); + (*IR->defsymbol)(q); + START; print("address "); emitSymbol(q); END; +} + +/* blockbeg - start a block */ +static void I(blockbeg)(Env *e) { + e->offset = off; + START; print("blockbeg off=%d", off); END; +} + +/* blockend - start a block */ +static void I(blockend)(Env *e) { + if (off > maxoff) + maxoff = off; + START; print("blockend off=%d", off); END; + off = e->offset; +} + +/* defaddress - initialize an address */ +static void I(defaddress)(Symbol p){ + START; print("defaddress "); emitSymRef(p); END; +} + +/* defconst - define a constant */ +static void I(defconst)(int suffix, int size, Value v) { + START; + print("defconst "); + switch (suffix) { + case I: + print("int.%d ", size); + BEGIN(code); + if (size > sizeof (int)) + print("%D", v.i); + else + print("%d", (int)v.i); + END; + break; + case U: + print("unsigned.%d ", size); + BEGIN(code); + if (size > sizeof (unsigned)) + print("%U", v.u); + else + print("%u", (unsigned)v.u); + END; + break; + case P: print("void*.%d ", size); BEGIN(code); print("%p", v.p); END; break; + case F: print("float.%d ", size); BEGIN(code); print("%g", (double)v.d); END; break; + default: assert(0); + } + END; +} + +/* defstring - emit a string constant */ +static void I(defstring)(int len, char *s) { + START; print("defstring "); + BEGIN(code); print("\""); emitString(len, s); print("\""); END; + END; +} + +/* defsymbol - define a symbol: initialize p->x */ +static void I(defsymbol)(Symbol p) { + if (p->x.name == NULL) + p->x.name = stringd(++uid); +} + +/* emit - emit the dags on list p */ +static void I(emit)(Node p){ + ITEM; + if (!html) + print(" "); + for (; p; p = p->x.next) { + if (p->op == LABEL+V) { + assert(p->syms[0]); + ANCHOR(name,print("%s", p->syms[0]->x.name)); + BEGIN(code); print("%s", p->syms[0]->name); END; + END; + print(":"); + } else { + int i; + if (p->x.listed) { + BEGIN(strong); print("%d", p->x.inst); END; print("'"); + print(" %s", opname(p->op)); + } else + print("%d. %s", p->x.inst, opname(p->op)); + if (p->count > 1) + print(" count=%d", p->count); + for (i = 0; i < NELEMS(p->kids) && p->kids[i]; i++) + print(" #%d", p->kids[i]->x.inst); + if (generic(p->op) == CALL && p->syms[0] && p->syms[0]->type) + print(" {%t}", p->syms[0]->type); + else + for (i = 0; i < NELEMS(p->syms) && p->syms[i]; i++) { + print(" "); + if (p->syms[i]->scope == CONSTANTS) + print(p->syms[i]->name); + else + emitSymRef(p->syms[i]); + } + } + NEWLINE; + } + END; +} + +/* export - announce p as exported */ +static void I(export)(Symbol p) { + START; print("export "); emitSymRef(p); END; +} + +/* function - generate code for a function */ +static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { + int i; + + (*IR->defsymbol)(f); + off = 0; + for (i = 0; caller[i] && callee[i]; i++) { + off = roundup(off, caller[i]->type->align); + caller[i]->x.offset = callee[i]->x.offset = off; + off += caller[i]->type->size; + } + if (!html) { + print("function "); + emitSymbol(f); + print(" ncalls=%d\n", ncalls); + for (i = 0; caller[i]; i++) + START; print("caller "); emitSymbol(caller[i]); END; + for (i = 0; callee[i]; i++) + START; print("callee "); emitSymbol(callee[i]); END; + } else { + START; + print("function"); + BEGIN(UL); +#define xx(field,code) ITEM; print(#field "="); code; END + xx(f,emitSymbol(f)); + xx(ncalls,print("%d", ncalls)); + if (caller[0]) { + ITEM; print("caller"); BEGIN(OL); + for (i = 0; caller[i]; i++) + ITEM; emitSymbol(caller[i]); END; + END; END; + ITEM; print("callee"); BEGIN(OL); + for (i = 0; callee[i]; i++) + ITEM; emitSymbol(callee[i]); END; + END; END; + } else { + xx(caller,BEGIN(em); print("empty"); END); + xx(callee,BEGIN(em); print("empty"); END); + } + END; + END; + } + maxoff = off = 0; + gencode(caller, callee); + if (html) + START; print("emitcode"); BEGIN(ul); emitcode(); END; END; + else + emitcode(); + START; print("maxoff=%d", maxoff); END; +#undef xx +} + +/* visit - generate code for *p */ +static int visit(Node p, int n) { + if (p && p->x.inst == 0) { + p->x.inst = ++n; + n = visit(p->kids[0], n); + n = visit(p->kids[1], n); + *tail = p; + tail = &p->x.next; + } + return n; +} + +/* gen0 - generate code for the dags on list p */ +static Node I(gen)(Node p) { + int n; + Node nodelist; + + tail = &nodelist; + for (n = 0; p; p = p->link) { + switch (generic(p->op)) { /* check for valid forest */ + case CALL: + assert(IR->wants_dag || p->count == 0); + break; + case ARG: + case ASGN: case JUMP: case LABEL: case RET: + case EQ: case GE: case GT: case LE: case LT: case NE: + assert(p->count == 0); + break; + case INDIR: + assert(IR->wants_dag && p->count > 0); + break; + default: + assert(0); + } + check(p); + p->x.listed = 1; + n = visit(p, n); + } + *tail = 0; + return nodelist; +} + +/* global - announce a global */ +static void I(global)(Symbol p) { + START; print("global "); emitSymbol(p); END; +} + +/* import - import a symbol */ +static void I(import)(Symbol p) { + START; print("import "); emitSymRef(p); END; +} + +/* local - local variable */ +static void I(local)(Symbol p) { + if (p->temporary) + p->name = stringf("t%s", p->name); + (*IR->defsymbol)(p); + off = roundup(off, p->type->align); + p->x.offset = off; + off += p->type->size; + START; print(p->temporary ? "temporary " : "local "); emitSymbol(p); END; +} + +/* progbeg - beginning of program */ +static void I(progbeg)(int argc, char *argv[]) { + int i; + + for (i = 1; i < argc; i++) + if (strcmp(argv[i], "-v") == 0) + verbose++; + else if (strcmp(argv[i], "-html") == 0) + html++; + if (html) { + print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"); + print("<html>"); + BEGIN(head); + if (firstfile && *firstfile) + BEGIN(title); emitString(strlen(firstfile), firstfile); END; + print("<link rev=made href=\"mailto:drh@microsoft.com\">\n"); + END; + print("<body>\n"); + if (firstfile && *firstfile) + BEGIN(h1); emitString(strlen(firstfile), firstfile); END; + BEGIN(P); BEGIN(em); + print("Links lead from uses of identifiers and labels to their definitions."); + END; END; + print("<ul>\n"); + START; + print("progbeg"); + BEGIN(ol); + for (i = 1; i < argc; i++) { + ITEM; + BEGIN(code); print("\""); emitString(strlen(argv[i]), argv[i]); print("\""); END; + END; + } + END; + END; + } +} + +/* progend - end of program */ +static void I(progend)(void) { + START; print("progend"); END; + if (html) { + time_t t; + print("</ul>\n"); + time(&t); + print("<hr><address>%s</address>\n", ctime(&t)); + print("</body></html>\n"); + } +} + +/* segment - switch to segment s */ +static void I(segment)(int s) { + START; print("segment %s", &"text\0bss\0.data\0lit\0.sym\0."[5*s-5]); END; +} + +/* space - initialize n bytes of space */ +static void I(space)(int n) { + START; print("space %d", n); END; +} + +static void I(stabblock)(int brace, int lev, Symbol *p) {} + +/* stabend - finalize stab output */ +static void I(stabend)(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) { + int i; + + if (p) + emitSymRef(p); + print("\n"); + if (cpp && sp) + for (i = 0; cpp[i] && sp[i]; i++) { + print("%w.%d: ", cpp[i], cpp[i]->x); + emitSymRef(sp[i]); + print("\n"); + } +} + +static void I(stabfend)(Symbol p, int lineno) {} +static void I(stabinit)(char *file, int argc, char *argv[]) {} + +/* stabline - emit line number information for source coordinate *cp */ +static void I(stabline)(Coordinate *cp) { + if (cp->file) + print("%s:", cp->file); + print("%d.%d:\n", cp->y, cp->x); +} + +static void I(stabsym)(Symbol p) {} +static void I(stabtype)(Symbol p) {} + +Interface symbolicIR = { + 1, 1, 0, /* char */ + 2, 2, 0, /* short */ + 4, 4, 0, /* int */ + 4, 4, 0, /* long */ + 4, 4, 0, /* long long */ + 4, 4, 1, /* float */ + 8, 8, 1, /* double */ + 8, 8, 1, /* long double */ + 4, 4, 0, /* T* */ + 0, 4, 0, /* struct */ + 0, /* little_endian */ + 0, /* mulops_calls */ + 0, /* wants_callb */ + 1, /* wants_argb */ + 1, /* left_to_right */ + 1, /* wants_dag */ + 0, /* unsigned_char */ + I(address), + I(blockbeg), + I(blockend), + I(defaddress), + I(defconst), + I(defstring), + I(defsymbol), + I(emit), + I(export), + I(function), + I(gen), + I(global), + I(import), + I(local), + I(progbeg), + I(progend), + I(segment), + I(space), + I(stabblock), + I(stabend), + I(stabfend), + I(stabinit), + I(stabline), + I(stabsym), + I(stabtype) +}; + +Interface symbolic64IR = { + 1, 1, 0, /* char */ + 2, 2, 0, /* short */ + 4, 4, 0, /* int */ + 8, 8, 0, /* long */ + 8, 8, 0, /* long long */ + 4, 4, 1, /* float */ + 8, 8, 1, /* double */ + 8, 8, 1, /* long double */ + 8, 8, 0, /* T* */ + 0, 1, 0, /* struct */ + 1, /* little_endian */ + 0, /* mulops_calls */ + 0, /* wants_callb */ + 1, /* wants_argb */ + 1, /* left_to_right */ + 1, /* wants_dag */ + 0, /* unsigned_char */ + I(address), + I(blockbeg), + I(blockend), + I(defaddress), + I(defconst), + I(defstring), + I(defsymbol), + I(emit), + I(export), + I(function), + I(gen), + I(global), + I(import), + I(local), + I(progbeg), + I(progend), + I(segment), + I(space), + I(stabblock), + I(stabend), + I(stabfend), + I(stabinit), + I(stabline), + I(stabsym), + I(stabtype) +}; diff --git a/lcc/src/token.h b/lcc/src/token.h index f92bf6a..d309f9b 100755 --- a/lcc/src/token.h +++ b/lcc/src/token.h @@ -1,133 +1,133 @@ -/*
-xx(symbol, value, prec, op, optree, kind, string)
-*/
-yy(0, 0, 0, 0, 0, 0, 0)
-xx(FLOAT, 1, 0, 0, 0, CHAR, "float")
-xx(DOUBLE, 2, 0, 0, 0, CHAR, "double")
-xx(CHAR, 3, 0, 0, 0, CHAR, "char")
-xx(SHORT, 4, 0, 0, 0, CHAR, "short")
-xx(INT, 5, 0, 0, 0, CHAR, "int")
-xx(UNSIGNED, 6, 0, 0, 0, CHAR, "unsigned")
-xx(POINTER, 7, 0, 0, 0, 0, "pointer")
-xx(VOID, 8, 0, 0, 0, CHAR, "void")
-xx(STRUCT, 9, 0, 0, 0, CHAR, "struct")
-xx(UNION, 10, 0, 0, 0, CHAR, "union")
-xx(FUNCTION, 11, 0, 0, 0, 0, "function")
-xx(ARRAY, 12, 0, 0, 0, 0, "array")
-xx(ENUM, 13, 0, 0, 0, CHAR, "enum")
-xx(LONG, 14, 0, 0, 0, CHAR, "long")
-xx(CONST, 15, 0, 0, 0, CHAR, "const")
-xx(VOLATILE, 16, 0, 0, 0, CHAR, "volatile")
-yy(0, 17, 0, 0, 0, 0, 0)
-yy(0, 18, 0, 0, 0, 0, 0)
-yy(0, 19, 0, 0, 0, 0, 0)
-yy(0, 20, 0, 0, 0, 0, 0)
-yy(0, 21, 0, 0, 0, 0, 0)
-yy(0, 22, 0, 0, 0, 0, 0)
-yy(0, 23, 0, 0, 0, 0, 0)
-yy(0, 24, 0, 0, 0, 0, 0)
-yy(0, 25, 0, 0, 0, 0, 0)
-yy(0, 26, 0, 0, 0, 0, 0)
-yy(0, 27, 0, 0, 0, 0, 0)
-yy(0, 28, 0, 0, 0, 0, "long long")
-yy(0, 29, 0, 0, 0, 0, 0)
-yy(0, 30, 0, 0, 0, 0, 0)
-yy(0, 31, 0, 0, 0, 0, "const volatile")
-xx(ID, 32, 0, 0, 0, ID, "identifier")
-yy(0, 33, 0, 0, 0, ID, "!")
-xx(FCON, 34, 0, 0, 0, ID, "floating constant")
-xx(ICON, 35, 0, 0, 0, ID, "integer constant")
-xx(SCON, 36, 0, 0, 0, ID, "string constant")
-yy(0, 37, 13, MOD, bittree,'%', "%")
-yy(0, 38, 8, BAND, bittree,ID, "&")
-xx(INCR, 39, 0, ADD, addtree,ID, "++")
-yy(0, 40, 0, 0, 0, ID, "(")
-yy(0, 41, 0, 0, 0, ')', ")")
-yy(0, 42, 13, MUL, multree,ID, "*")
-yy(0, 43, 12, ADD, addtree,ID, "+")
-yy(0, 44, 1, 0, 0, ',', ",")
-yy(0, 45, 12, SUB, subtree,ID, "-")
-yy(0, 46, 0, 0, 0, '.', ".")
-yy(0, 47, 13, DIV, multree,'/', "/")
-xx(DECR, 48, 0, SUB, subtree,ID, "--")
-xx(DEREF, 49, 0, 0, 0, DEREF, "->")
-xx(ANDAND, 50, 5, AND, andtree,ANDAND, "&&")
-xx(OROR, 51, 4, OR, andtree,OROR, "||")
-xx(LEQ, 52, 10, LE, cmptree,LEQ, "<=")
-xx(EQL, 53, 9, EQ, eqtree, EQL, "==")
-xx(NEQ, 54, 9, NE, eqtree, NEQ, "!=")
-xx(GEQ, 55, 10, GE, cmptree,GEQ, ">=")
-xx(RSHIFT, 56, 11, RSH, shtree, RSHIFT, ">>")
-xx(LSHIFT, 57, 11, LSH, shtree, LSHIFT, "<<")
-yy(0, 58, 0, 0, 0, ':', ":")
-yy(0, 59, 0, 0, 0, IF, ";")
-yy(0, 60, 10, LT, cmptree,'<', "<")
-yy(0, 61, 2, ASGN, asgntree,'=', "=")
-yy(0, 62, 10, GT, cmptree,'>', ">")
-yy(0, 63, 0, 0, 0, '?', "?")
-xx(ELLIPSIS, 64, 0, 0, 0, ELLIPSIS,"...")
-xx(SIZEOF, 65, 0, 0, 0, ID, "sizeof")
-yy(0, 66, 0, 0, 0, 0, 0)
-xx(AUTO, 67, 0, 0, 0, STATIC, "auto")
-xx(BREAK, 68, 0, 0, 0, IF, "break")
-xx(CASE, 69, 0, 0, 0, IF, "case")
-xx(CONTINUE, 70, 0, 0, 0, IF, "continue")
-xx(DEFAULT, 71, 0, 0, 0, IF, "default")
-xx(DO, 72, 0, 0, 0, IF, "do")
-xx(ELSE, 73, 0, 0, 0, IF, "else")
-xx(EXTERN, 74, 0, 0, 0, STATIC, "extern")
-xx(FOR, 75, 0, 0, 0, IF, "for")
-xx(GOTO, 76, 0, 0, 0, IF, "goto")
-xx(IF, 77, 0, 0, 0, IF, "if")
-xx(REGISTER, 78, 0, 0, 0, STATIC, "register")
-xx(RETURN, 79, 0, 0, 0, IF, "return")
-xx(SIGNED, 80, 0, 0, 0, CHAR, "signed")
-xx(STATIC, 81, 0, 0, 0, STATIC, "static")
-xx(SWITCH, 82, 0, 0, 0, IF, "switch")
-xx(TYPEDEF, 83, 0, 0, 0, STATIC, "typedef")
-xx(WHILE, 84, 0, 0, 0, IF, "while")
-xx(TYPECODE, 85, 0, 0, 0, ID, "__typecode")
-xx(FIRSTARG, 86, 0, 0, 0, ID, "__firstarg")
-yy(0, 87, 0, 0, 0, 0, 0)
-yy(0, 88, 0, 0, 0, 0, 0)
-yy(0, 89, 0, 0, 0, 0, 0)
-yy(0, 90, 0, 0, 0, 0, 0)
-yy(0, 91, 0, 0, 0, '[', "[")
-yy(0, 92, 0, 0, 0, 0, 0)
-yy(0, 93, 0, 0, 0, ']', "]")
-yy(0, 94, 7, BXOR, bittree,'^', "^")
-yy(0, 95, 0, 0, 0, 0, 0)
-yy(0, 96, 0, 0, 0, 0, 0)
-yy(0, 97, 0, 0, 0, 0, 0)
-yy(0, 98, 0, 0, 0, 0, 0)
-yy(0, 99, 0, 0, 0, 0, 0)
-yy(0, 100, 0, 0, 0, 0, 0)
-yy(0, 101, 0, 0, 0, 0, 0)
-yy(0, 102, 0, 0, 0, 0, 0)
-yy(0, 103, 0, 0, 0, 0, 0)
-yy(0, 104, 0, 0, 0, 0, 0)
-yy(0, 105, 0, 0, 0, 0, 0)
-yy(0, 106, 0, 0, 0, 0, 0)
-yy(0, 107, 0, 0, 0, 0, 0)
-yy(0, 108, 0, 0, 0, 0, 0)
-yy(0, 109, 0, 0, 0, 0, 0)
-yy(0, 110, 0, 0, 0, 0, 0)
-yy(0, 111, 0, 0, 0, 0, 0)
-yy(0, 112, 0, 0, 0, 0, 0)
-yy(0, 113, 0, 0, 0, 0, 0)
-yy(0, 114, 0, 0, 0, 0, 0)
-yy(0, 115, 0, 0, 0, 0, 0)
-yy(0, 116, 0, 0, 0, 0, 0)
-yy(0, 117, 0, 0, 0, 0, 0)
-yy(0, 118, 0, 0, 0, 0, 0)
-yy(0, 119, 0, 0, 0, 0, 0)
-yy(0, 120, 0, 0, 0, 0, 0)
-yy(0, 121, 0, 0, 0, 0, 0)
-yy(0, 122, 0, 0, 0, 0, 0)
-yy(0, 123, 0, 0, 0, IF, "{")
-yy(0, 124, 6, BOR, bittree,'|', "|")
-yy(0, 125, 0, 0, 0, '}', "}")
-yy(0, 126, 0, BCOM, 0, ID, "~")
-xx(EOI, 127, 0, 0, 0, EOI, "end of input")
-#undef xx
-#undef yy
+/* +xx(symbol, value, prec, op, optree, kind, string) +*/ +yy(0, 0, 0, 0, 0, 0, 0) +xx(FLOAT, 1, 0, 0, 0, CHAR, "float") +xx(DOUBLE, 2, 0, 0, 0, CHAR, "double") +xx(CHAR, 3, 0, 0, 0, CHAR, "char") +xx(SHORT, 4, 0, 0, 0, CHAR, "short") +xx(INT, 5, 0, 0, 0, CHAR, "int") +xx(UNSIGNED, 6, 0, 0, 0, CHAR, "unsigned") +xx(POINTER, 7, 0, 0, 0, 0, "pointer") +xx(VOID, 8, 0, 0, 0, CHAR, "void") +xx(STRUCT, 9, 0, 0, 0, CHAR, "struct") +xx(UNION, 10, 0, 0, 0, CHAR, "union") +xx(FUNCTION, 11, 0, 0, 0, 0, "function") +xx(ARRAY, 12, 0, 0, 0, 0, "array") +xx(ENUM, 13, 0, 0, 0, CHAR, "enum") +xx(LONG, 14, 0, 0, 0, CHAR, "long") +xx(CONST, 15, 0, 0, 0, CHAR, "const") +xx(VOLATILE, 16, 0, 0, 0, CHAR, "volatile") +yy(0, 17, 0, 0, 0, 0, 0) +yy(0, 18, 0, 0, 0, 0, 0) +yy(0, 19, 0, 0, 0, 0, 0) +yy(0, 20, 0, 0, 0, 0, 0) +yy(0, 21, 0, 0, 0, 0, 0) +yy(0, 22, 0, 0, 0, 0, 0) +yy(0, 23, 0, 0, 0, 0, 0) +yy(0, 24, 0, 0, 0, 0, 0) +yy(0, 25, 0, 0, 0, 0, 0) +yy(0, 26, 0, 0, 0, 0, 0) +yy(0, 27, 0, 0, 0, 0, 0) +yy(0, 28, 0, 0, 0, 0, "long long") +yy(0, 29, 0, 0, 0, 0, 0) +yy(0, 30, 0, 0, 0, 0, 0) +yy(0, 31, 0, 0, 0, 0, "const volatile") +xx(ID, 32, 0, 0, 0, ID, "identifier") +yy(0, 33, 0, 0, 0, ID, "!") +xx(FCON, 34, 0, 0, 0, ID, "floating constant") +xx(ICON, 35, 0, 0, 0, ID, "integer constant") +xx(SCON, 36, 0, 0, 0, ID, "string constant") +yy(0, 37, 13, MOD, bittree,'%', "%") +yy(0, 38, 8, BAND, bittree,ID, "&") +xx(INCR, 39, 0, ADD, addtree,ID, "++") +yy(0, 40, 0, 0, 0, ID, "(") +yy(0, 41, 0, 0, 0, ')', ")") +yy(0, 42, 13, MUL, multree,ID, "*") +yy(0, 43, 12, ADD, addtree,ID, "+") +yy(0, 44, 1, 0, 0, ',', ",") +yy(0, 45, 12, SUB, subtree,ID, "-") +yy(0, 46, 0, 0, 0, '.', ".") +yy(0, 47, 13, DIV, multree,'/', "/") +xx(DECR, 48, 0, SUB, subtree,ID, "--") +xx(DEREF, 49, 0, 0, 0, DEREF, "->") +xx(ANDAND, 50, 5, AND, andtree,ANDAND, "&&") +xx(OROR, 51, 4, OR, andtree,OROR, "||") +xx(LEQ, 52, 10, LE, cmptree,LEQ, "<=") +xx(EQL, 53, 9, EQ, eqtree, EQL, "==") +xx(NEQ, 54, 9, NE, eqtree, NEQ, "!=") +xx(GEQ, 55, 10, GE, cmptree,GEQ, ">=") +xx(RSHIFT, 56, 11, RSH, shtree, RSHIFT, ">>") +xx(LSHIFT, 57, 11, LSH, shtree, LSHIFT, "<<") +yy(0, 58, 0, 0, 0, ':', ":") +yy(0, 59, 0, 0, 0, IF, ";") +yy(0, 60, 10, LT, cmptree,'<', "<") +yy(0, 61, 2, ASGN, asgntree,'=', "=") +yy(0, 62, 10, GT, cmptree,'>', ">") +yy(0, 63, 0, 0, 0, '?', "?") +xx(ELLIPSIS, 64, 0, 0, 0, ELLIPSIS,"...") +xx(SIZEOF, 65, 0, 0, 0, ID, "sizeof") +yy(0, 66, 0, 0, 0, 0, 0) +xx(AUTO, 67, 0, 0, 0, STATIC, "auto") +xx(BREAK, 68, 0, 0, 0, IF, "break") +xx(CASE, 69, 0, 0, 0, IF, "case") +xx(CONTINUE, 70, 0, 0, 0, IF, "continue") +xx(DEFAULT, 71, 0, 0, 0, IF, "default") +xx(DO, 72, 0, 0, 0, IF, "do") +xx(ELSE, 73, 0, 0, 0, IF, "else") +xx(EXTERN, 74, 0, 0, 0, STATIC, "extern") +xx(FOR, 75, 0, 0, 0, IF, "for") +xx(GOTO, 76, 0, 0, 0, IF, "goto") +xx(IF, 77, 0, 0, 0, IF, "if") +xx(REGISTER, 78, 0, 0, 0, STATIC, "register") +xx(RETURN, 79, 0, 0, 0, IF, "return") +xx(SIGNED, 80, 0, 0, 0, CHAR, "signed") +xx(STATIC, 81, 0, 0, 0, STATIC, "static") +xx(SWITCH, 82, 0, 0, 0, IF, "switch") +xx(TYPEDEF, 83, 0, 0, 0, STATIC, "typedef") +xx(WHILE, 84, 0, 0, 0, IF, "while") +xx(TYPECODE, 85, 0, 0, 0, ID, "__typecode") +xx(FIRSTARG, 86, 0, 0, 0, ID, "__firstarg") +yy(0, 87, 0, 0, 0, 0, 0) +yy(0, 88, 0, 0, 0, 0, 0) +yy(0, 89, 0, 0, 0, 0, 0) +yy(0, 90, 0, 0, 0, 0, 0) +yy(0, 91, 0, 0, 0, '[', "[") +yy(0, 92, 0, 0, 0, 0, 0) +yy(0, 93, 0, 0, 0, ']', "]") +yy(0, 94, 7, BXOR, bittree,'^', "^") +yy(0, 95, 0, 0, 0, 0, 0) +yy(0, 96, 0, 0, 0, 0, 0) +yy(0, 97, 0, 0, 0, 0, 0) +yy(0, 98, 0, 0, 0, 0, 0) +yy(0, 99, 0, 0, 0, 0, 0) +yy(0, 100, 0, 0, 0, 0, 0) +yy(0, 101, 0, 0, 0, 0, 0) +yy(0, 102, 0, 0, 0, 0, 0) +yy(0, 103, 0, 0, 0, 0, 0) +yy(0, 104, 0, 0, 0, 0, 0) +yy(0, 105, 0, 0, 0, 0, 0) +yy(0, 106, 0, 0, 0, 0, 0) +yy(0, 107, 0, 0, 0, 0, 0) +yy(0, 108, 0, 0, 0, 0, 0) +yy(0, 109, 0, 0, 0, 0, 0) +yy(0, 110, 0, 0, 0, 0, 0) +yy(0, 111, 0, 0, 0, 0, 0) +yy(0, 112, 0, 0, 0, 0, 0) +yy(0, 113, 0, 0, 0, 0, 0) +yy(0, 114, 0, 0, 0, 0, 0) +yy(0, 115, 0, 0, 0, 0, 0) +yy(0, 116, 0, 0, 0, 0, 0) +yy(0, 117, 0, 0, 0, 0, 0) +yy(0, 118, 0, 0, 0, 0, 0) +yy(0, 119, 0, 0, 0, 0, 0) +yy(0, 120, 0, 0, 0, 0, 0) +yy(0, 121, 0, 0, 0, 0, 0) +yy(0, 122, 0, 0, 0, 0, 0) +yy(0, 123, 0, 0, 0, IF, "{") +yy(0, 124, 6, BOR, bittree,'|', "|") +yy(0, 125, 0, 0, 0, '}', "}") +yy(0, 126, 0, BCOM, 0, ID, "~") +xx(EOI, 127, 0, 0, 0, EOI, "end of input") +#undef xx +#undef yy diff --git a/lcc/src/trace.c b/lcc/src/trace.c index 55b18a1..06b627d 100755 --- a/lcc/src/trace.c +++ b/lcc/src/trace.c @@ -1,180 +1,180 @@ -#include "c.h"
-
-
-static char *fmt, *fp, *fmtend; /* format string, current & limit pointer */
-static Tree args; /* printf arguments */
-static Symbol frameno; /* local holding frame number */
-
-/* appendstr - append str to the evolving format string, expanding it if necessary */
-static void appendstr(char *str) {
- do
- if (fp == fmtend)
- if (fp) {
- char *s = allocate(2*(fmtend - fmt), FUNC);
- strncpy(s, fmt, fmtend - fmt);
- fp = s + (fmtend - fmt);
- fmtend = s + 2*(fmtend - fmt);
- fmt = s;
- } else {
- fp = fmt = allocate(80, FUNC);
- fmtend = fmt + 80;
- }
- while ((*fp++ = *str++) != 0);
- fp--;
-}
-
-/* tracevalue - append format and argument to print the value of e */
-static void tracevalue(Tree e, int lev) {
- Type ty = unqual(e->type);
-
- switch (ty->op) {
- case INT:
- if (ty == chartype || ty == signedchar)
- appendstr("'\\x%02x'");
- else if (ty == longtype)
- appendstr("0x%ld");
- else
- appendstr("0x%d");
- break;
- case UNSIGNED:
- if (ty == chartype || ty == unsignedchar)
- appendstr("'\\x%02x'");
- else if (ty == unsignedlong)
- appendstr("0x%lx");
- else
- appendstr("0x%x");
- break;
- case FLOAT:
- if (ty == longdouble)
- appendstr("%Lg");
- else
- appendstr("%g");
- break;
- case POINTER:
- if (unqual(ty->type) == chartype
- || unqual(ty->type) == signedchar
- || unqual(ty->type) == unsignedchar) {
- static Symbol null;
- if (null == NULL)
- null = mkstr("(null)");
- tracevalue(cast(e, unsignedtype), lev + 1);
- appendstr(" \"%.30s\"");
- e = condtree(e, e, pointer(idtree(null->u.c.loc)));
- } else {
- appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x");
- }
- break;
- case STRUCT: {
- Field q;
- appendstr("("); appendstr(typestring(ty, "")); appendstr("){");
- for (q = ty->u.sym->u.s.flist; q; q = q->link) {
- appendstr(q->name); appendstr("=");
- tracevalue(field(addrof(e), q->name), lev + 1);
- if (q->link)
- appendstr(",");
- }
- appendstr("}");
- return;
- }
- case UNION:
- appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}");
- return;
- case ARRAY:
- if (lev && ty->type->size > 0) {
- int i;
- e = pointer(e);
- appendstr("{");
- for (i = 0; i < ty->size/ty->type->size; i++) {
- Tree p = (*optree['+'])(ADD, e, consttree(i, inttype));
- if (isptr(p->type) && isarray(p->type->type))
- p = retype(p, p->type->type);
- else
- p = rvalue(p);
- if (i)
- appendstr(",");
- tracevalue(p, lev + 1);
- }
- appendstr("}");
- } else
- appendstr(typestring(ty, ""));
- return;
- default:
- assert(0);
- }
- e = cast(e, promote(ty));
- args = tree(mkop(ARG,e->type), e->type, e, args);
-}
-
-/* tracefinis - complete & generate the trace call to print */
-static void tracefinis(Symbol printer) {
- Tree *ap;
- Symbol p;
-
- *fp = 0;
- p = mkstr(string(fmt));
- for (ap = &args; *ap; ap = &(*ap)->kids[1])
- ;
- *ap = tree(ARG+P, charptype, pointer(idtree(p->u.c.loc)), 0);
- walk(calltree(pointer(idtree(printer)), freturn(printer->type), args, NULL), 0, 0);
- args = 0;
- fp = fmtend = 0;
-}
-
-/* tracecall - generate code to trace entry to f */
-static void tracecall(Symbol printer, Symbol f) {
- int i;
- Symbol counter = genident(STATIC, inttype, GLOBAL);
-
- defglobal(counter, BSS);
- (*IR->space)(counter->type->size);
- frameno = genident(AUTO, inttype, level);
- addlocal(frameno);
- appendstr(f->name); appendstr("#");
- tracevalue(asgn(frameno, incr(INCR, idtree(counter), consttree(1, inttype))), 0);
- appendstr("(");
- for (i = 0; f->u.f.callee[i]; i++) {
- if (i)
- appendstr(",");
- appendstr(f->u.f.callee[i]->name); appendstr("=");
- tracevalue(idtree(f->u.f.callee[i]), 0);
- }
- if (variadic(f->type))
- appendstr(",...");
- appendstr(") called\n");
- tracefinis(printer);
-}
-
-/* tracereturn - generate code to trace return e */
-static void tracereturn(Symbol printer, Symbol f, Tree e) {
- appendstr(f->name); appendstr("#");
- tracevalue(idtree(frameno), 0);
- appendstr(" returned");
- if (freturn(f->type) != voidtype && e) {
- appendstr(" ");
- tracevalue(e, 0);
- }
- appendstr("\n");
- tracefinis(printer);
-}
-
-/* trace_init - initialize for tracing */
-void trace_init(int argc, char *argv[]) {
- int i;
- static int inited;
-
- if (inited)
- return;
- inited = 1;
- type_init(argc, argv);
- if (IR)
- for (i = 1; i < argc; i++)
- if (strncmp(argv[i], "-t", 2) == 0 && strchr(argv[i], '=') == NULL) {
- Symbol printer = mksymbol(EXTERN,
- argv[i][2] ? &argv[i][2] : "printf",
- ftype(inttype, ptr(qual(CONST, chartype))));
- printer->defined = 0;
- attach((Apply)tracecall, printer, &events.entry);
- attach((Apply)tracereturn, printer, &events.returns);
- break;
- }
-}
+#include "c.h" + + +static char *fmt, *fp, *fmtend; /* format string, current & limit pointer */ +static Tree args; /* printf arguments */ +static Symbol frameno; /* local holding frame number */ + +/* appendstr - append str to the evolving format string, expanding it if necessary */ +static void appendstr(char *str) { + do + if (fp == fmtend) + if (fp) { + char *s = allocate(2*(fmtend - fmt), FUNC); + strncpy(s, fmt, fmtend - fmt); + fp = s + (fmtend - fmt); + fmtend = s + 2*(fmtend - fmt); + fmt = s; + } else { + fp = fmt = allocate(80, FUNC); + fmtend = fmt + 80; + } + while ((*fp++ = *str++) != 0); + fp--; +} + +/* tracevalue - append format and argument to print the value of e */ +static void tracevalue(Tree e, int lev) { + Type ty = unqual(e->type); + + switch (ty->op) { + case INT: + if (ty == chartype || ty == signedchar) + appendstr("'\\x%02x'"); + else if (ty == longtype) + appendstr("0x%ld"); + else + appendstr("0x%d"); + break; + case UNSIGNED: + if (ty == chartype || ty == unsignedchar) + appendstr("'\\x%02x'"); + else if (ty == unsignedlong) + appendstr("0x%lx"); + else + appendstr("0x%x"); + break; + case FLOAT: + if (ty == longdouble) + appendstr("%Lg"); + else + appendstr("%g"); + break; + case POINTER: + if (unqual(ty->type) == chartype + || unqual(ty->type) == signedchar + || unqual(ty->type) == unsignedchar) { + static Symbol null; + if (null == NULL) + null = mkstr("(null)"); + tracevalue(cast(e, unsignedtype), lev + 1); + appendstr(" \"%.30s\""); + e = condtree(e, e, pointer(idtree(null->u.c.loc))); + } else { + appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x"); + } + break; + case STRUCT: { + Field q; + appendstr("("); appendstr(typestring(ty, "")); appendstr("){"); + for (q = ty->u.sym->u.s.flist; q; q = q->link) { + appendstr(q->name); appendstr("="); + tracevalue(field(addrof(e), q->name), lev + 1); + if (q->link) + appendstr(","); + } + appendstr("}"); + return; + } + case UNION: + appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}"); + return; + case ARRAY: + if (lev && ty->type->size > 0) { + int i; + e = pointer(e); + appendstr("{"); + for (i = 0; i < ty->size/ty->type->size; i++) { + Tree p = (*optree['+'])(ADD, e, consttree(i, inttype)); + if (isptr(p->type) && isarray(p->type->type)) + p = retype(p, p->type->type); + else + p = rvalue(p); + if (i) + appendstr(","); + tracevalue(p, lev + 1); + } + appendstr("}"); + } else + appendstr(typestring(ty, "")); + return; + default: + assert(0); + } + e = cast(e, promote(ty)); + args = tree(mkop(ARG,e->type), e->type, e, args); +} + +/* tracefinis - complete & generate the trace call to print */ +static void tracefinis(Symbol printer) { + Tree *ap; + Symbol p; + + *fp = 0; + p = mkstr(string(fmt)); + for (ap = &args; *ap; ap = &(*ap)->kids[1]) + ; + *ap = tree(ARG+P, charptype, pointer(idtree(p->u.c.loc)), 0); + walk(calltree(pointer(idtree(printer)), freturn(printer->type), args, NULL), 0, 0); + args = 0; + fp = fmtend = 0; +} + +/* tracecall - generate code to trace entry to f */ +static void tracecall(Symbol printer, Symbol f) { + int i; + Symbol counter = genident(STATIC, inttype, GLOBAL); + + defglobal(counter, BSS); + (*IR->space)(counter->type->size); + frameno = genident(AUTO, inttype, level); + addlocal(frameno); + appendstr(f->name); appendstr("#"); + tracevalue(asgn(frameno, incr(INCR, idtree(counter), consttree(1, inttype))), 0); + appendstr("("); + for (i = 0; f->u.f.callee[i]; i++) { + if (i) + appendstr(","); + appendstr(f->u.f.callee[i]->name); appendstr("="); + tracevalue(idtree(f->u.f.callee[i]), 0); + } + if (variadic(f->type)) + appendstr(",..."); + appendstr(") called\n"); + tracefinis(printer); +} + +/* tracereturn - generate code to trace return e */ +static void tracereturn(Symbol printer, Symbol f, Tree e) { + appendstr(f->name); appendstr("#"); + tracevalue(idtree(frameno), 0); + appendstr(" returned"); + if (freturn(f->type) != voidtype && e) { + appendstr(" "); + tracevalue(e, 0); + } + appendstr("\n"); + tracefinis(printer); +} + +/* trace_init - initialize for tracing */ +void trace_init(int argc, char *argv[]) { + int i; + static int inited; + + if (inited) + return; + inited = 1; + type_init(argc, argv); + if (IR) + for (i = 1; i < argc; i++) + if (strncmp(argv[i], "-t", 2) == 0 && strchr(argv[i], '=') == NULL) { + Symbol printer = mksymbol(EXTERN, + argv[i][2] ? &argv[i][2] : "printf", + ftype(inttype, ptr(qual(CONST, chartype)))); + printer->defined = 0; + attach((Apply)tracecall, printer, &events.entry); + attach((Apply)tracereturn, printer, &events.returns); + break; + } +} diff --git a/lcc/src/tree.c b/lcc/src/tree.c index 1f5b49c..d2b6a91 100755 --- a/lcc/src/tree.c +++ b/lcc/src/tree.c @@ -1,223 +1,223 @@ -#include "c.h"
-
-
-int where = STMT;
-static int warn;
-static int nid = 1; /* identifies trees & nodes in debugging output */
-static struct nodeid {
- int printed;
- Tree node;
-} ids[500]; /* if ids[i].node == p, then p's id is i */
-
-static void printtree1(Tree, int, int);
-
-Tree tree(int op, Type type, Tree left, Tree right) {
- Tree p;
-
- NEW0(p, where);
- p->op = op;
- p->type = type;
- p->kids[0] = left;
- p->kids[1] = right;
- return p;
-}
-
-Tree texpr(Tree (*f)(int), int tok, int a) {
- int save = where;
- Tree p;
-
- where = a;
- p = (*f)(tok);
- where = save;
- return p;
-}
-static Tree root1(Tree p) {
- if (p == NULL)
- return p;
- if (p->type == voidtype)
- warn++;
- switch (generic(p->op)) {
- case COND: {
- Tree q = p->kids[1];
- assert(q && q->op == RIGHT);
- if (p->u.sym && q->kids[0] && generic(q->kids[0]->op) == ASGN)
- q->kids[0] = root1(q->kids[0]->kids[1]);
- else
- q->kids[0] = root1(q->kids[0]);
- if (p->u.sym && q->kids[1] && generic(q->kids[1]->op) == ASGN)
- q->kids[1] = root1(q->kids[1]->kids[1]);
- else
- q->kids[1] = root1(q->kids[1]);
- p->u.sym = 0;
- if (q->kids[0] == 0 && q->kids[1] == 0)
- p = root1(p->kids[0]);
- }
- break;
- case AND: case OR:
- if ((p->kids[1] = root1(p->kids[1])) == 0)
- p = root1(p->kids[0]);
- break;
- case NOT:
- if (warn++ == 0)
- warning("expression with no effect elided\n");
- return root1(p->kids[0]);
- case RIGHT:
- if (p->kids[1] == 0)
- return root1(p->kids[0]);
- if (p->kids[0] && p->kids[0]->op == CALL+B
- && p->kids[1] && p->kids[1]->op == INDIR+B)
- /* avoid premature release of the CALL+B temporary */
- return p->kids[0];
- if (p->kids[0] && p->kids[0]->op == RIGHT
- && p->kids[1] == p->kids[0]->kids[0])
- /* de-construct e++ construction */
- return p->kids[0]->kids[1];
- p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1]));
- return p->kids[0] || p->kids[1] ? p : (Tree)0;
- case EQ: case NE: case GT: case GE: case LE: case LT:
- case ADD: case SUB: case MUL: case DIV: case MOD:
- case LSH: case RSH: case BAND: case BOR: case BXOR:
- if (warn++ == 0)
- warning("expression with no effect elided\n");
- p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1]));
- return p->kids[0] || p->kids[1] ? p : (Tree)0;
- case INDIR:
- if (p->type->size == 0 && unqual(p->type) != voidtype)
- warning("reference to `%t' elided\n", p->type);
- if (isptr(p->kids[0]->type) && isvolatile(p->kids[0]->type->type))
- warning("reference to `volatile %t' elided\n", p->type);
- /* fall thru */
- case CVI: case CVF: case CVU: case CVP:
- case NEG: case BCOM: case FIELD:
- if (warn++ == 0)
- warning("expression with no effect elided\n");
- return root1(p->kids[0]);
- case ADDRL: case ADDRG: case ADDRF: case CNST:
- if (needconst)
- return p;
- if (warn++ == 0)
- warning("expression with no effect elided\n");
- return NULL;
- case ARG: case ASGN: case CALL: case JUMP: case LABEL:
- break;
- default: assert(0);
- }
- return p;
-}
-
-Tree root(Tree p) {
- warn = 0;
- return root1(p);
-}
-
-char *opname(int op) {
- static char *opnames[] = {
- "",
- "CNST",
- "ARG",
- "ASGN",
- "INDIR",
- "CVC",
- "CVD",
- "CVF",
- "CVI",
- "CVP",
- "CVS",
- "CVU",
- "NEG",
- "CALL",
- "*LOAD*",
- "RET",
- "ADDRG",
- "ADDRF",
- "ADDRL",
- "ADD",
- "SUB",
- "LSH",
- "MOD",
- "RSH",
- "BAND",
- "BCOM",
- "BOR",
- "BXOR",
- "DIV",
- "MUL",
- "EQ",
- "GE",
- "GT",
- "LE",
- "LT",
- "NE",
- "JUMP",
- "LABEL",
- "AND",
- "NOT",
- "OR",
- "COND",
- "RIGHT",
- "FIELD"
- }, *suffixes[] = {
- "0", "F", "D", "C", "S", "I", "U", "P", "V", "B",
- "10","11","12","13","14","15"
- };
-
- if (generic(op) >= AND && generic(op) <= FIELD && opsize(op) == 0)
- return opnames[opindex(op)];
- return stringf("%s%s%s",
- opindex(op) > 0 && opindex(op) < NELEMS(opnames) ?
- opnames[opindex(op)] : stringd(opindex(op)),
- suffixes[optype(op)], opsize(op) > 0 ? stringd(opsize(op)) : "");
-}
-
-int nodeid(Tree p) {
- int i = 1;
-
- ids[nid].node = p;
- while (ids[i].node != p)
- i++;
- if (i == nid)
- ids[nid++].printed = 0;
- return i;
-}
-
-/* printed - return pointer to ids[id].printed */
-int *printed(int id) {
- if (id)
- return &ids[id].printed;
- nid = 1;
- return 0;
-}
-
-/* printtree - print tree p on fd */
-void printtree(Tree p, int fd) {
- (void)printed(0);
- printtree1(p, fd, 1);
-}
-
-/* printtree1 - recursively print tree p */
-static void printtree1(Tree p, int fd, int lev) {
- FILE *f = fd == 1 ? stdout : stderr;
- int i;
- static char blanks[] = " ";
-
- if (p == 0 || *printed(i = nodeid(p)))
- return;
- fprint(f, "#%d%S%S", i, blanks, i < 10 ? 2 : i < 100 ? 1 : 0, blanks, lev);
- fprint(f, "%s %t", opname(p->op), p->type);
- *printed(i) = 1;
- for (i = 0; i < NELEMS(p->kids); i++)
- if (p->kids[i])
- fprint(f, " #%d", nodeid(p->kids[i]));
- if (p->op == FIELD && p->u.field)
- fprint(f, " %s %d..%d", p->u.field->name,
- fieldsize(p->u.field) + fieldright(p->u.field), fieldright(p->u.field));
- else if (generic(p->op) == CNST)
- fprint(f, " %s", vtoa(p->type, p->u.v));
- else if (p->u.sym)
- fprint(f, " %s", p->u.sym->name);
- if (p->node)
- fprint(f, " node=%p", p->node);
- fprint(f, "\n");
- for (i = 0; i < NELEMS(p->kids); i++)
- printtree1(p->kids[i], fd, lev + 1);
-}
+#include "c.h" + + +int where = STMT; +static int warn; +static int nid = 1; /* identifies trees & nodes in debugging output */ +static struct nodeid { + int printed; + Tree node; +} ids[500]; /* if ids[i].node == p, then p's id is i */ + +static void printtree1(Tree, int, int); + +Tree tree(int op, Type type, Tree left, Tree right) { + Tree p; + + NEW0(p, where); + p->op = op; + p->type = type; + p->kids[0] = left; + p->kids[1] = right; + return p; +} + +Tree texpr(Tree (*f)(int), int tok, int a) { + int save = where; + Tree p; + + where = a; + p = (*f)(tok); + where = save; + return p; +} +static Tree root1(Tree p) { + if (p == NULL) + return p; + if (p->type == voidtype) + warn++; + switch (generic(p->op)) { + case COND: { + Tree q = p->kids[1]; + assert(q && q->op == RIGHT); + if (p->u.sym && q->kids[0] && generic(q->kids[0]->op) == ASGN) + q->kids[0] = root1(q->kids[0]->kids[1]); + else + q->kids[0] = root1(q->kids[0]); + if (p->u.sym && q->kids[1] && generic(q->kids[1]->op) == ASGN) + q->kids[1] = root1(q->kids[1]->kids[1]); + else + q->kids[1] = root1(q->kids[1]); + p->u.sym = 0; + if (q->kids[0] == 0 && q->kids[1] == 0) + p = root1(p->kids[0]); + } + break; + case AND: case OR: + if ((p->kids[1] = root1(p->kids[1])) == 0) + p = root1(p->kids[0]); + break; + case NOT: + if (warn++ == 0) + warning("expression with no effect elided\n"); + return root1(p->kids[0]); + case RIGHT: + if (p->kids[1] == 0) + return root1(p->kids[0]); + if (p->kids[0] && p->kids[0]->op == CALL+B + && p->kids[1] && p->kids[1]->op == INDIR+B) + /* avoid premature release of the CALL+B temporary */ + return p->kids[0]; + if (p->kids[0] && p->kids[0]->op == RIGHT + && p->kids[1] == p->kids[0]->kids[0]) + /* de-construct e++ construction */ + return p->kids[0]->kids[1]; + p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1])); + return p->kids[0] || p->kids[1] ? p : (Tree)0; + case EQ: case NE: case GT: case GE: case LE: case LT: + case ADD: case SUB: case MUL: case DIV: case MOD: + case LSH: case RSH: case BAND: case BOR: case BXOR: + if (warn++ == 0) + warning("expression with no effect elided\n"); + p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1])); + return p->kids[0] || p->kids[1] ? p : (Tree)0; + case INDIR: + if (p->type->size == 0 && unqual(p->type) != voidtype) + warning("reference to `%t' elided\n", p->type); + if (isptr(p->kids[0]->type) && isvolatile(p->kids[0]->type->type)) + warning("reference to `volatile %t' elided\n", p->type); + /* fall thru */ + case CVI: case CVF: case CVU: case CVP: + case NEG: case BCOM: case FIELD: + if (warn++ == 0) + warning("expression with no effect elided\n"); + return root1(p->kids[0]); + case ADDRL: case ADDRG: case ADDRF: case CNST: + if (needconst) + return p; + if (warn++ == 0) + warning("expression with no effect elided\n"); + return NULL; + case ARG: case ASGN: case CALL: case JUMP: case LABEL: + break; + default: assert(0); + } + return p; +} + +Tree root(Tree p) { + warn = 0; + return root1(p); +} + +char *opname(int op) { + static char *opnames[] = { + "", + "CNST", + "ARG", + "ASGN", + "INDIR", + "CVC", + "CVD", + "CVF", + "CVI", + "CVP", + "CVS", + "CVU", + "NEG", + "CALL", + "*LOAD*", + "RET", + "ADDRG", + "ADDRF", + "ADDRL", + "ADD", + "SUB", + "LSH", + "MOD", + "RSH", + "BAND", + "BCOM", + "BOR", + "BXOR", + "DIV", + "MUL", + "EQ", + "GE", + "GT", + "LE", + "LT", + "NE", + "JUMP", + "LABEL", + "AND", + "NOT", + "OR", + "COND", + "RIGHT", + "FIELD" + }, *suffixes[] = { + "0", "F", "D", "C", "S", "I", "U", "P", "V", "B", + "10","11","12","13","14","15" + }; + + if (generic(op) >= AND && generic(op) <= FIELD && opsize(op) == 0) + return opnames[opindex(op)]; + return stringf("%s%s%s", + opindex(op) > 0 && opindex(op) < NELEMS(opnames) ? + opnames[opindex(op)] : stringd(opindex(op)), + suffixes[optype(op)], opsize(op) > 0 ? stringd(opsize(op)) : ""); +} + +int nodeid(Tree p) { + int i = 1; + + ids[nid].node = p; + while (ids[i].node != p) + i++; + if (i == nid) + ids[nid++].printed = 0; + return i; +} + +/* printed - return pointer to ids[id].printed */ +int *printed(int id) { + if (id) + return &ids[id].printed; + nid = 1; + return 0; +} + +/* printtree - print tree p on fd */ +void printtree(Tree p, int fd) { + (void)printed(0); + printtree1(p, fd, 1); +} + +/* printtree1 - recursively print tree p */ +static void printtree1(Tree p, int fd, int lev) { + FILE *f = fd == 1 ? stdout : stderr; + int i; + static char blanks[] = " "; + + if (p == 0 || *printed(i = nodeid(p))) + return; + fprint(f, "#%d%S%S", i, blanks, i < 10 ? 2 : i < 100 ? 1 : 0, blanks, lev); + fprint(f, "%s %t", opname(p->op), p->type); + *printed(i) = 1; + for (i = 0; i < NELEMS(p->kids); i++) + if (p->kids[i]) + fprint(f, " #%d", nodeid(p->kids[i])); + if (p->op == FIELD && p->u.field) + fprint(f, " %s %d..%d", p->u.field->name, + fieldsize(p->u.field) + fieldright(p->u.field), fieldright(p->u.field)); + else if (generic(p->op) == CNST) + fprint(f, " %s", vtoa(p->type, p->u.v)); + else if (p->u.sym) + fprint(f, " %s", p->u.sym->name); + if (p->node) + fprint(f, " node=%p", p->node); + fprint(f, "\n"); + for (i = 0; i < NELEMS(p->kids); i++) + printtree1(p->kids[i], fd, lev + 1); +} diff --git a/lcc/src/types.c b/lcc/src/types.c index eead3e1..207cdb5 100755 --- a/lcc/src/types.c +++ b/lcc/src/types.c @@ -1,748 +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;
-}
-
+#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; +} + diff --git a/lcc/src/x86.md b/lcc/src/x86.md index 7e8b84f..6c4e1c4 100755 --- a/lcc/src/x86.md +++ b/lcc/src/x86.md @@ -1,998 +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 $";
+%{ +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 $"; diff --git a/lcc/src/x86linux.md b/lcc/src/x86linux.md index b7baaff..d185f56 100755 --- a/lcc/src/x86linux.md +++ b/lcc/src/x86linux.md @@ -1,1081 +1,1081 @@ -%{
-/* x86/linux lburg spec. Derived from x86.md by
-Marcos Ramirez <marcos@inf.utfsm.cl>
-Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
-Jacob Navia <jacob@jacob.remcomp.fr>
-*/
-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)
-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;
-
-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 int pflag = 0;
-static char rcsid[] = "$Id: x86linux.md 145 2001-10-17 21:53:10Z timo $";
-
-#define hasargs(p) (p->syms[0] && p->syms[0]->u.c.v.i > 0 ? 0 : LBURG_MAX)
-%}
-%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: INDIRI4(VREGP) "# read register\n"
-reg: INDIRP4(VREGP) "# read register\n"
-reg: INDIRU4(VREGP) "# read register\n"
-
-reg: INDIRI8(VREGP) "# read register\n"
-reg: INDIRP8(VREGP) "# read register\n"
-reg: INDIRU8(VREGP) "# read register\n"
-
-freg: INDIRF4(VREGP) "# read register\n"
-freg: INDIRF8(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"
-
-cnst: CNSTI1 "%a"
-cnst: CNSTU1 "%a"
-
-cnst: CNSTI2 "%a"
-cnst: CNSTU2 "%a"
-
-cnst: CNSTI4 "%a"
-cnst: CNSTU4 "%a"
-cnst: CNSTP4 "%a"
-
-cnst: CNSTI8 "%a"
-cnst: CNSTU8 "%a"
-cnst: CNSTP8 "%a"
-
-con: cnst "$%0"
-
-stmt: reg ""
-stmt: freg ""
-
-acon: ADDRGP4 "%a"
-acon: ADDRGP8 "%a"
-acon: cnst "%0"
-
-baseaddr: 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"
-index: LSHU4(reg,con1) "%0,2"
-index: LSHU4(reg,con2) "%0,4"
-index: LSHU4(reg,con3) "%0,8"
-
-con0: CNSTI4 "1" range(a, 0, 0)
-con0: CNSTU4 "1" range(a, 0, 0)
-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)
-
-addr: base "%0"
-addr: baseaddr "%0"
-addr: ADDI4(index,baseaddr) "%1(,%0)"
-addr: ADDP4(index,baseaddr) "%1(,%0)"
-addr: ADDU4(index,baseaddr) "%1(,%0)"
-
-addr: ADDI4(reg,baseaddr) "%1(%0)"
-addr: ADDP4(reg,baseaddr) "%1(%0)"
-addr: ADDU4(reg,baseaddr) "%1(%0)"
-
-addr: ADDI4(index,reg) "(%1,%0)"
-addr: ADDP4(index,reg) "(%1,%0)"
-addr: ADDU4(index,reg) "(%1,%0)"
-
-addr: index "(,%0)"
-
-mem1: INDIRI1(addr) "%0"
-mem1: INDIRU1(addr) "%0"
-mem2: INDIRI2(addr) "%0"
-mem2: INDIRU2(addr) "%0"
-mem4: INDIRI4(addr) "%0"
-mem4: INDIRU4(addr) "%0"
-mem4: INDIRP4(addr) "%0"
-
-rc: reg "%0"
-rc: con "%0"
-
-mr: reg "%0"
-mr: mem4 "%0"
-
-mr1: reg "%0"
-mr1: mem1 "%0"
-
-mr2: reg "%0"
-mr2: mem2 "%0"
-
-mrc: mem4 "%0" 1
-mrc: mem1 "%0" 1
-mrc: mem2 "%0" 1
-mrc: rc "%0"
-
-reg: addr "leal %0,%c\n" 1
-reg: mr "movl %0,%c\n" 1
-reg: mr1 "movb %0,%c\n" 1
-reg: mr2 "movw %0,%c\n" 1
-reg: con "movl %0,%c\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,mrc) "?movl %0,%c\naddl %1,%c\n" 1
-reg: ADDP4(reg,mrc) "?movl %0,%c\naddl %1,%c\n" 1
-reg: ADDU4(reg,mrc) "?movl %0,%c\naddl %1,%c\n" 1
-reg: SUBI4(reg,mrc) "?movl %0,%c\nsubl %1,%c\n" 1
-reg: SUBP4(reg,mrc) "?movl %0,%c\nsubl %1,%c\n" 1
-reg: SUBU4(reg,mrc) "?movl %0,%c\nsubl %1,%c\n" 1
-reg: BANDI4(reg,mrc) "?movl %0,%c\nandl %1,%c\n" 1
-reg: BORI4(reg,mrc) "?movl %0,%c\norl %1,%c\n" 1
-reg: BXORI4(reg,mrc) "?movl %0,%c\nxorl %1,%c\n" 1
-reg: BANDU4(reg,mrc) "?movl %0,%c\nandl %1,%c\n" 1
-reg: BORU4(reg,mrc) "?movl %0,%c\norl %1,%c\n" 1
-reg: BXORU4(reg,mrc) "?movl %0,%c\nxorl %1,%c\n" 1
-
-stmt: ASGNI4(addr,ADDI4(mem4,con1)) "incl %1\n" memop(a)
-stmt: ASGNI4(addr,ADDU4(mem4,con1)) "incl %1\n" memop(a)
-stmt: ASGNP4(addr,ADDP4(mem4,con1)) "incl %1\n" memop(a)
-stmt: ASGNI4(addr,SUBI4(mem4,con1)) "decl %1\n" memop(a)
-stmt: ASGNI4(addr,SUBU4(mem4,con1)) "decl %1\n" memop(a)
-stmt: ASGNP4(addr,SUBP4(mem4,con1)) "decl %1\n" memop(a)
-stmt: ASGNI4(addr,ADDI4(mem4,rc)) "addl %2,%1\n" memop(a)
-stmt: ASGNI4(addr,SUBI4(mem4,rc)) "sub %2,%1\n" memop(a)
-stmt: ASGNU4(addr,ADDU4(mem4,rc)) "add %2,%1\n" memop(a)
-stmt: ASGNU4(addr,SUBU4(mem4,rc)) "sub %2,%1\n" memop(a)
-
-stmt: ASGNI4(addr,BANDI4(mem4,rc)) "andl %2,%1\n" memop(a)
-stmt: ASGNI4(addr,BORI4(mem4,rc)) "orl %2,%1\n" memop(a)
-stmt: ASGNI4(addr,BXORI4(mem4,rc)) "xorl %2,%1\n" memop(a)
-stmt: ASGNU4(addr,BANDU4(mem4,rc)) "andl %2,%1\n" memop(a)
-stmt: ASGNU4(addr,BORU4(mem4,rc)) "orl %2,%1\n" memop(a)
-stmt: ASGNU4(addr,BXORU4(mem4,rc)) "xorl %2,%1\n" memop(a)
-reg: BCOMI4(reg) "?movl %0,%c\nnotl %c\n" 2
-reg: BCOMU4(reg) "?movl %0,%c\nnotl %c\n" 2
-reg: NEGI4(reg) "?movl %0,%c\nnegl %c\n" 2
-
-stmt: ASGNI4(addr,BCOMI4(mem4)) "notl %1\n" memop(a)
-stmt: ASGNU4(addr,BCOMU4(mem4)) "notl %1\n" memop(a)
-stmt: ASGNI4(addr,NEGI4(mem4)) "negl %1\n" memop(a)
-reg: LSHI4(reg,rc5) "?movl %0,%c\nsall %1,%c\n" 2
-reg: LSHU4(reg,rc5) "?movl %0,%c\nshll %1,%c\n" 2
-reg: RSHI4(reg,rc5) "?movl %0,%c\nsarl %1,%c\n" 2
-reg: RSHU4(reg,rc5) "?movl %0,%c\nshrl %1,%c\n" 2
-
-stmt: ASGNI4(addr,LSHI4(mem4,rc5)) "sall %2,%1\n" memop(a)
-stmt: ASGNI4(addr,LSHU4(mem4,rc5)) "shll %2,%1\n" memop(a)
-stmt: ASGNI4(addr,RSHI4(mem4,rc5)) "sarl %2,%1\n" memop(a)
-stmt: ASGNI4(addr,RSHU4(mem4,rc5)) "shrl %2,%1\n" memop(a)
-
-rc5: CNSTI4 "$%a" range(a, 0, 31)
-rc5: reg "%%cl"
-reg: MULI4(reg,mrc) "?movl %0,%c\nimull %1,%c\n" 14
-reg: MULI4(con,mr) "imul %0,%1,%c\n" 13
-reg: MULU4(reg,mr) "mull %1\n" 13
-reg: DIVU4(reg,reg) "xorl %%edx,%%edx\ndivl %1\n"
-reg: MODU4(reg,reg) "xorl %%edx,%%edx\ndivl %1\n"
-reg: DIVI4(reg,reg) "cdq\nidivl %1\n"
-reg: MODI4(reg,reg) "cdq\nidivl %1\n"
-reg: CVPU4(reg) "movl %0,%c\n" move(a)
-reg: CVUP4(reg) "movl %0,%c\n" move(a)
-reg: CVII4(INDIRI1(addr)) "movsbl %0,%c\n" 3
-reg: CVII4(INDIRI2(addr)) "movswl %0,%c\n" 3
-reg: CVUU4(INDIRU1(addr)) "movzbl %0,%c\n" 3
-reg: CVUU4(INDIRU2(addr)) "movzwl %0,%c\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
-
-mrca: mem4 "%0"
-mrca: rc "%0"
-mrca: ADDRGP4 "$%a"
-mrca: ADDRGP8 "$%a"
-
-stmt: ASGNI1(addr,rc) "movb %1,%0\n" 1
-stmt: ASGNI2(addr,rc) "movw %1,%0\n" 1
-stmt: ASGNI4(addr,rc) "movl %1,%0\n" 1
-stmt: ASGNU1(addr,rc) "movb %1,%0\n" 1
-stmt: ASGNU2(addr,rc) "movw %1,%0\n" 1
-stmt: ASGNU4(addr,rc) "movl %1,%0\n" 1
-stmt: ASGNP4(addr,rc) "movl %1,%0\n" 1
-stmt: ARGI4(mrca) "pushl %0\n" 1
-stmt: ARGU4(mrca) "pushl %0\n" 1
-stmt: ARGP4(mrca) "pushl %0\n" 1
-stmt: ASGNB(reg,INDIRB(reg)) "movl $%a,%%ecx\nrep\nmovsb\n"
-stmt: ARGB(INDIRB(reg)) "subl $%a,%%esp\nmovl %%esp,%%edi\nmovl $%a,%%ecx\nrep\nmovsb\n"
-
-memf: INDIRF8(addr) "l %0"
-memf: INDIRF4(addr) "s %0"
-memf: CVFF8(INDIRF4(addr)) "s %0"
-memf: CVFF4(INDIRF8(addr)) "l %0"
-
-freg: memf "fld%0\n" 3
-
-stmt: ASGNF8(addr,freg) "fstpl %0\n" 7
-stmt: ASGNF4(addr,freg) "fstps %0\n" 7
-stmt: ASGNF4(addr,CVFF4(freg)) "fstps %0\n" 7
-
-stmt: ARGF8(freg) "subl $8,%%esp\nfstpl (%%esp)\n"
-stmt: ARGF4(freg) "subl $4,%%esp\nfstps (%%esp)\n"
-freg: NEGF8(freg) "fchs\n"
-freg: NEGF4(freg) "fchs\n"
-
-flt: memf "%0"
-flt: freg "p %%st(1),%%st"
-
-freg: ADDF4(freg,flt) "fadd%1\n"
-freg: ADDF8(freg,flt) "fadd%1\n"
-
-freg: DIVF4(freg,flt) "fdiv%1\n"
-freg: DIVF8(freg,flt) "fdiv%1\n"
-
-freg: MULF4(freg,flt) "fmul%1\n"
-freg: MULF8(freg,flt) "fmul%1\n"
-
-freg: SUBF4(freg,flt) "fsub%1\n"
-freg: SUBF8(freg,flt) "fsub%1\n"
-
-freg: CVFF8(freg) "# CVFF8\n"
-freg: CVFF4(freg) "sub $4,%%esp\nfstps (%%esp)\nflds (%%esp)\naddl $4,%%esp\n" 12
-
-stmt: ASGNI4(addr,CVFI4(freg)) "fistpl %0\n" 29
-reg: CVFI4(freg) "subl $4,%%esp\nfistpl 0(%%esp)\npopl %c\n" 31
-
-freg: CVIF8(INDIRI4(addr)) "fildl %0\n" 10
-freg: CVIF8(reg) "pushl %0\nfildl (%%esp)\naddl $4,%%esp\n" 12
-
-freg: CVIF4(INDIRI4(addr)) "fildl %0\n" 10
-freg: CVIF4(reg) "pushl %0\nfildl (%%esp)\naddl $4,%%esp\n" 12
-
-addrj: ADDRGP4 "%a"
-addrj: reg "*%0" 2
-addrj: mem4 "*%0" 2
-
-stmt: LABELV "%a:\n"
-stmt: JUMPV(addrj) "jmp %0\n" 3
-stmt: EQI4(mem4,rc) "cmpl %1,%0\nje %a\n" 5
-stmt: GEI4(mem4,rc) "cmpl %1,%0\njge %a\n" 5
-stmt: GTI4(mem4,rc) "cmpl %1,%0\njg %a\n" 5
-stmt: LEI4(mem4,rc) "cmpl %1,%0\njle %a\n" 5
-stmt: LTI4(mem4,rc) "cmpl %1,%0\njl %a\n" 5
-stmt: NEI4(mem4,rc) "cmpl %1,%0\njne %a\n" 5
-stmt: GEU4(mem4,rc) "cmpl %1,%0\njae %a\n" 5
-stmt: GTU4(mem4,rc) "cmpl %1,%0\nja %a\n" 5
-stmt: LEU4(mem4,rc) "cmpl %1,%0\njbe %a\n" 5
-stmt: LTU4(mem4,rc) "cmpl %1,%0\njb %a\n" 5
-stmt: EQI4(reg,mrc) "cmpl %1,%0\nje %a\n" 4
-stmt: GEI4(reg,mrc) "cmpl %1,%0\njge %a\n" 4
-stmt: GTI4(reg,mrc) "cmpl %1,%0\njg %a\n" 4
-stmt: LEI4(reg,mrc) "cmpl %1,%0\njle %a\n" 4
-stmt: LTI4(reg,mrc) "cmpl %1,%0\njl %a\n" 4
-stmt: NEI4(reg,mrc) "cmpl %1,%0\njne %a\n" 4
-
-stmt: EQU4(reg,mrc) "cmpl %1,%0\nje %a\n" 4
-stmt: GEU4(reg,mrc) "cmpl %1,%0\njae %a\n" 4
-stmt: GTU4(reg,mrc) "cmpl %1,%0\nja %a\n" 4
-stmt: LEU4(reg,mrc) "cmpl %1,%0\njbe %a\n" 4
-stmt: LTU4(reg,mrc) "cmpl %1,%0\njb %a\n" 4
-stmt: NEU4(reg,mrc) "cmpl %1,%0\njne %a\n" 4
-
-stmt: EQI4(BANDU4(mr,con),con0) "testl %1,%0\nje %a\n" 3
-stmt: NEI4(BANDU4(mr,con),con0) "testl %1,%0\njne %a\n"
-
-stmt: EQI4(BANDU4(CVII2(INDIRI2(addr)),con),con0) "testw %1,%0\nje %a\n"
-stmt: NEI4(BANDU4(CVII2(INDIRI2(addr)),con),con0) "testw %1,%0\njne %a\n"
-stmt: EQI4(BANDU4(CVIU2(INDIRI2(addr)),con),con0) "testw %1,%0\nje %a\n"
-stmt: NEI4(BANDU4(CVIU2(INDIRI2(addr)),con),con0) "testw %1,%0\njne %a\n"
-stmt: EQI4(BANDU4(CVII1(INDIRI1(addr)),con),con0) "testb %1,%0\nje %a\n"
-
-cmpf: INDIRF8(addr) "l %0"
-cmpf: INDIRF4(addr) "s %0"
-cmpf: CVFF8(INDIRF4(addr)) "s %0"
-cmpf: freg "p"
-
-stmt: EQF8(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\nje %a\n"
-stmt: GEF8(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njbe %a\n"
-stmt: GTF8(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njb %a\n"
-stmt: LEF8(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njae %a\n"
-stmt: LTF8(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\nja %a\n"
-stmt: NEF8(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njne %a\n"
-
-stmt: EQF4(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\nje %a\n"
-stmt: GEF4(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njbe %a\n"
-stmt: GTF4(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njb %a\n"
-stmt: LEF4(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njae %a\n"
-stmt: LTF4(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\nja %a\n"
-stmt: NEF4(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njne %a\n"
-
-freg: DIVF8(freg,CVIF8(INDIRI4(addr))) "fidivl %1\n"
-freg: DIVF8(CVIF8(INDIRI4(addr)),freg) "fidivrl %0\n"
-freg: DIVF8(freg,CVIF8(CVII2(INDIRI2(addr)))) "fidivs %1\n"
-freg: DIVF8(CVIF8(CVII2(INDIRI2(addr))),freg) "fidivrs %0\n"
-freg: MULF8(freg,CVIF8(INDIRI4(addr))) "fimull %1\n"
-freg: MULF8(freg,CVIF8(CVII2(INDIRI2(addr)))) "fimuls %1\n"
-freg: SUBF8(freg,CVIF8(INDIRI4(addr))) "fisubl %1\n"
-freg: SUBF8(CVIF8(INDIRI4(addr)),freg) "fisubrl %0\n"
-freg: SUBF8(freg,CVIF8(CVII2(INDIRI2(addr)))) "fisubs %1\n"
-freg: SUBF8(CVIF8(CVII2(INDIRI2(addr))),freg) "fisubrs %0\n"
-freg: ADDF8(freg,CVIF8(INDIRI4(addr))) "fiaddl %1\n"
-freg: ADDF8(freg,CVIF8(CVII2(INDIRI2(addr)))) "fiadds %1\n"
-freg: ADDF8(freg,CVFF8(INDIRF4(addr))) "fdivs %1\n"
-freg: SUBF8(freg,CVFF8(INDIRF4(addr))) "fsubs %1\n"
-freg: MULF8(freg,CVFF8(INDIRF4(addr))) "fmuls %1\n"
-freg: DIVF8(freg,CVFF8(INDIRF4(addr))) "fdivs %1\n"
-freg: LOADF8(memf) "fld%0\n"
-
-reg: CALLI4(addrj) "call %0\naddl $%a,%%esp\n" hasargs(a)
-reg: CALLU4(addrj) "call %0\naddl $%a,%%esp\n" hasargs(a)
-reg: CALLP4(addrj) "call %0\naddl $%a,%%esp\n" hasargs(a)
-
-reg: CALLI4(addrj) "call %0\n" 1
-reg: CALLU4(addrj) "call %0\n" 1
-reg: CALLP4(addrj) "call %0\n" 1
-
-stmt: CALLV(addrj) "call %0\naddl $%a,%%esp\n" hasargs(a)
-stmt: CALLV(addrj) "call %0\n" 1
-
-freg: CALLF4(addrj) "call %0\naddl $%a,%%esp\n" hasargs(a)
-freg: CALLF4(addrj) "call %0\n" 1
-
-stmt: CALLF4(addrj) "call %0\naddl $%a,%%esp\nfstp %%st(0)\n" hasargs(a)
-stmt: CALLF4(addrj) "call %0\nfstp %%st(0)\n" 1
-
-freg: CALLF8(addrj) "call %0\naddl $%a,%%esp\n" hasargs(a)
-freg: CALLF8(addrj) "call %0\n" 1
-
-stmt: CALLF8(addrj) "call %0\naddl $%a,%%esp\nfstp %%st(0)\n" hasargs(a)
-stmt: CALLF8(addrj) "call %0\nfstp %%st(0)\n" 1
-
-stmt: RETI4(reg) "# ret\n"
-stmt: RETU4(reg) "# ret\n"
-stmt: RETP4(reg) "# ret\n"
-stmt: RETF4(freg) "# ret\n"
-stmt: RETF8(freg) "# 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);
- for (i = 0; i < argc; i++)
- if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "-pg") == 0)
- pflag = 1;
- 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;
-
- 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;
-
- stabprefix = ".LL";
-}
-
-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 Symbol prevg;
-
-static void globalend(void) {
- if (prevg && prevg->type->size > 0)
- print(".size %s,%d\n", prevg->x.name, prevg->type->size);
- prevg = NULL;
-}
-
-static void progend(void) {
- globalend();
- (*IR->segment)(CODE);
- print(".ident \"LCC: 4.1\"\n");
-}
-
-static void target(Node p) {
- assert(p);
- 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)) {
- rtarget(p, 1, intreg[ECX]);
- setreg(p, intreg[EAX]);
- }
- break;
- case MUL+U:
- setreg(p, quo);
- rtarget(p, 0, intreg[EAX]);
- break;
- case DIV+I: case DIV+U:
- setreg(p, quo);
- rtarget(p, 0, intreg[EAX]);
- rtarget(p, 1, intreg[ECX]);
- break;
- case MOD+I: case MOD+U:
- setreg(p, rem);
- rtarget(p, 0, intreg[EAX]);
- rtarget(p, 1, intreg[ECX]);
- 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 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;
- }
-}
-
-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("movsbl %s,%s\n", preg(charreg), p->syms[RX]->x.name);
- else if (op == CVI+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1)
- print("movsbl %s,%s\n", preg(charreg), p->syms[RX]->x.name);
- else if (op == CVI+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2)
- print("movswl %s,%s\n", preg(shortreg), p->syms[RX]->x.name);
- else if (op == CVI+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2)
- print("movswl %s,%s\n", preg(shortreg), p->syms[RX]->x.name);
- else if (op == CVU+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1)
- print("movzbl %s,%s\n", preg(charreg), p->syms[RX]->x.name);
- else if (op == CVU+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1)
- print("movzbl %s,%s\n", preg(charreg), p->syms[RX]->x.name);
- else if (op == CVU+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2)
- print("movzwl %s,%s\n", preg(shortreg), p->syms[RX]->x.name);
- else if (op == CVU+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2)
- print("movzwl %s,%s\n", preg(shortreg), p->syms[RX]->x.name);
- 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("movl %s,%s\n", src, dst);
- }
-}
-
-static void function(Symbol f, Symbol caller[], Symbol callee[], int n) {
- int i;
-
- globalend();
- print(".align 16\n");
- print(".type %s,@function\n", f->x.name);
- print("%s:\n", f->x.name);
- print("pushl %%ebp\n");
- if (pflag) {
- static int plab;
- print("movl %%esp,%%ebp\n");
- (*IR->segment)(DATA);
- print(".align 4\n.LP%d:\n.long 0\n", plab);
- (*IR->segment)(CODE);
- print("movl $.LP%d,%%edx\ncall mcount\n", plab);
- plab++;
- }
- print("pushl %%ebx\n");
- print("pushl %%esi\n");
- print("pushl %%edi\n");
- print("movl %%esp,%%ebp\n");
-
- usedmask[0] = usedmask[1] = 0;
- freemask[0] = freemask[1] = ~0U;
- offset = 16 + 4;
- for (i = 0; callee[i]; i++) {
- Symbol p = callee[i];
- Symbol q = caller[i];
- assert(q);
- offset = roundup(offset, q->type->align);
- 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("subl $%d,%%esp\n", framesize);
- emitcode();
- print("movl %%ebp,%%esp\n");
- print("popl %%edi\n");
- print("popl %%esi\n");
- print("popl %%ebx\n");
- print("popl %%ebp\n");
- print("ret\n");
- { int l = genlabel(1);
- print(".Lf%d:\n", l);
- print(".size %s,.Lf%d-%s\n", f->x.name, l, f->x.name);
- }
-}
-
-static void defsymbol(Symbol p) {
- if (p->scope >= LOCAL && p->sclass == STATIC)
- p->x.name = stringf("%s.%d", p->name, genlabel(1));
- else if (p->generated)
- p->x.name = stringf(".LC%s", p->name);
- else if (p->scope == GLOBAL || p->sclass == EXTERN)
- p->x.name = stringf("%s", p->name);
- else
- p->x.name = p->name;
-}
-
-static void segment(int n) {
- if (n == cseg)
- return;
- cseg = n;
- if (cseg == CODE)
- print(".text\n");
- else if (cseg == BSS)
- print(".bss\n");
- else if (cseg == DATA || cseg == LIT)
- print(".data\n");
-}
-
-static void defconst(int suffix, int size, Value v) {
- if (suffix == I && size == 1)
- print(".byte %d\n", v.u);
- else if (suffix == I && size == 2)
- print(".word %d\n", v.i);
- else if (suffix == I && size == 4)
- print(".long %d\n", v.i);
- else if (suffix == U && size == 1)
- print(".byte %d\n", v.u);
- else if (suffix == U && size == 2)
- print(".word %d\n", v.u);
- else if (suffix == U && size == 4)
- print(".long %d\n", v.u);
- else if (suffix == P && size == 4)
- print(".long %d\n", v.p);
- else if (suffix == F && size == 4) {
- float f = v.d;
- print(".long %d\n", *(unsigned *)&f);
- } else if (suffix == F && size == 8) {
- double d = v.d;
- unsigned *p = (unsigned *)&d;
- print(".long %d\n.long %d\n", p[swap], p[!swap]);
- }
- else assert(0);
-}
-
-static void defaddress(Symbol p) {
- print(".long %s\n", p->x.name);
-}
-
-static void defstring(int n, char *str) {
- char *s;
-
- for (s = str; s < str + n; s++)
- print(".byte %d\n", (*s)&0377);
-}
-
-static void export(Symbol p) {
- globalend();
- print(".globl %s\n", p->x.name);
-}
-
-static void import(Symbol p) {}
-
-static void global(Symbol p) {
- globalend();
- print(".align %d\n", p->type->align > 4 ? 4 : p->type->align);
- if (!p->generated) {
- print(".type %s,@%s\n", p->x.name,
- isfunc(p->type) ? "function" : "object");
- if (p->type->size > 0)
- print(".size %s,%d\n", p->x.name, p->type->size);
- else
- prevg = p;
- }
- if (p->u.seg == BSS) {
- if (p->sclass == STATIC)
- print(".lcomm %s,%d\n", p->x.name, p->type->size);
- else
- print(".comm %s,%d\n", p->x.name, p->type->size);
- } else {
- print("%s:\n", p->x.name);
- }
-}
-
-static void space(int n) {
- if (cseg != BSS)
- print(".space %d\n", n);
-}
-
-Interface x86linuxIR = {
- 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 */
- 0, /* address */
- blockbeg,
- blockend,
- defaddress,
- defconst,
- defstring,
- defsymbol,
- emit,
- export,
- function,
- gen,
- global,
- import,
- 0, /* local */
- progbeg,
- progend,
- segment,
- space,
- stabblock, stabend, 0, stabinit, stabline, stabsym, stabtype,
- {1, rmap,
- 0, 0, 0, /* blkfetch, blkstore, blkloop */
- _label,
- _rule,
- _nts,
- _kids,
- _string,
- _templates,
- _isinstruction,
- _ntname,
- emit2,
- 0, /* doarg */
- target,
- clobber,
- }
-};
-
-void x86linux_init(int argc, char *argv[]) {
- static int inited;
- extern Interface x86IR;
-
- if (inited)
- return;
- inited = 1;
-#define xx(f) assert(!x86linuxIR.f); x86linuxIR.f = x86IR.f
- xx(address);
- xx(local);
- xx(x.blkfetch);
- xx(x.blkstore);
- xx(x.blkloop);
- xx(x.doarg);
-#undef xx
-}
+%{ +/* x86/linux lburg spec. Derived from x86.md by +Marcos Ramirez <marcos@inf.utfsm.cl> +Horst von Brand <vonbrand@sleipnir.valparaiso.cl> +Jacob Navia <jacob@jacob.remcomp.fr> +*/ +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) +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; + +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 int pflag = 0; +static char rcsid[] = "$Id: x86linux.md 145 2001-10-17 21:53:10Z timo $"; + +#define hasargs(p) (p->syms[0] && p->syms[0]->u.c.v.i > 0 ? 0 : LBURG_MAX) +%} +%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: INDIRI4(VREGP) "# read register\n" +reg: INDIRP4(VREGP) "# read register\n" +reg: INDIRU4(VREGP) "# read register\n" + +reg: INDIRI8(VREGP) "# read register\n" +reg: INDIRP8(VREGP) "# read register\n" +reg: INDIRU8(VREGP) "# read register\n" + +freg: INDIRF4(VREGP) "# read register\n" +freg: INDIRF8(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" + +cnst: CNSTI1 "%a" +cnst: CNSTU1 "%a" + +cnst: CNSTI2 "%a" +cnst: CNSTU2 "%a" + +cnst: CNSTI4 "%a" +cnst: CNSTU4 "%a" +cnst: CNSTP4 "%a" + +cnst: CNSTI8 "%a" +cnst: CNSTU8 "%a" +cnst: CNSTP8 "%a" + +con: cnst "$%0" + +stmt: reg "" +stmt: freg "" + +acon: ADDRGP4 "%a" +acon: ADDRGP8 "%a" +acon: cnst "%0" + +baseaddr: 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" +index: LSHU4(reg,con1) "%0,2" +index: LSHU4(reg,con2) "%0,4" +index: LSHU4(reg,con3) "%0,8" + +con0: CNSTI4 "1" range(a, 0, 0) +con0: CNSTU4 "1" range(a, 0, 0) +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) + +addr: base "%0" +addr: baseaddr "%0" +addr: ADDI4(index,baseaddr) "%1(,%0)" +addr: ADDP4(index,baseaddr) "%1(,%0)" +addr: ADDU4(index,baseaddr) "%1(,%0)" + +addr: ADDI4(reg,baseaddr) "%1(%0)" +addr: ADDP4(reg,baseaddr) "%1(%0)" +addr: ADDU4(reg,baseaddr) "%1(%0)" + +addr: ADDI4(index,reg) "(%1,%0)" +addr: ADDP4(index,reg) "(%1,%0)" +addr: ADDU4(index,reg) "(%1,%0)" + +addr: index "(,%0)" + +mem1: INDIRI1(addr) "%0" +mem1: INDIRU1(addr) "%0" +mem2: INDIRI2(addr) "%0" +mem2: INDIRU2(addr) "%0" +mem4: INDIRI4(addr) "%0" +mem4: INDIRU4(addr) "%0" +mem4: INDIRP4(addr) "%0" + +rc: reg "%0" +rc: con "%0" + +mr: reg "%0" +mr: mem4 "%0" + +mr1: reg "%0" +mr1: mem1 "%0" + +mr2: reg "%0" +mr2: mem2 "%0" + +mrc: mem4 "%0" 1 +mrc: mem1 "%0" 1 +mrc: mem2 "%0" 1 +mrc: rc "%0" + +reg: addr "leal %0,%c\n" 1 +reg: mr "movl %0,%c\n" 1 +reg: mr1 "movb %0,%c\n" 1 +reg: mr2 "movw %0,%c\n" 1 +reg: con "movl %0,%c\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,mrc) "?movl %0,%c\naddl %1,%c\n" 1 +reg: ADDP4(reg,mrc) "?movl %0,%c\naddl %1,%c\n" 1 +reg: ADDU4(reg,mrc) "?movl %0,%c\naddl %1,%c\n" 1 +reg: SUBI4(reg,mrc) "?movl %0,%c\nsubl %1,%c\n" 1 +reg: SUBP4(reg,mrc) "?movl %0,%c\nsubl %1,%c\n" 1 +reg: SUBU4(reg,mrc) "?movl %0,%c\nsubl %1,%c\n" 1 +reg: BANDI4(reg,mrc) "?movl %0,%c\nandl %1,%c\n" 1 +reg: BORI4(reg,mrc) "?movl %0,%c\norl %1,%c\n" 1 +reg: BXORI4(reg,mrc) "?movl %0,%c\nxorl %1,%c\n" 1 +reg: BANDU4(reg,mrc) "?movl %0,%c\nandl %1,%c\n" 1 +reg: BORU4(reg,mrc) "?movl %0,%c\norl %1,%c\n" 1 +reg: BXORU4(reg,mrc) "?movl %0,%c\nxorl %1,%c\n" 1 + +stmt: ASGNI4(addr,ADDI4(mem4,con1)) "incl %1\n" memop(a) +stmt: ASGNI4(addr,ADDU4(mem4,con1)) "incl %1\n" memop(a) +stmt: ASGNP4(addr,ADDP4(mem4,con1)) "incl %1\n" memop(a) +stmt: ASGNI4(addr,SUBI4(mem4,con1)) "decl %1\n" memop(a) +stmt: ASGNI4(addr,SUBU4(mem4,con1)) "decl %1\n" memop(a) +stmt: ASGNP4(addr,SUBP4(mem4,con1)) "decl %1\n" memop(a) +stmt: ASGNI4(addr,ADDI4(mem4,rc)) "addl %2,%1\n" memop(a) +stmt: ASGNI4(addr,SUBI4(mem4,rc)) "sub %2,%1\n" memop(a) +stmt: ASGNU4(addr,ADDU4(mem4,rc)) "add %2,%1\n" memop(a) +stmt: ASGNU4(addr,SUBU4(mem4,rc)) "sub %2,%1\n" memop(a) + +stmt: ASGNI4(addr,BANDI4(mem4,rc)) "andl %2,%1\n" memop(a) +stmt: ASGNI4(addr,BORI4(mem4,rc)) "orl %2,%1\n" memop(a) +stmt: ASGNI4(addr,BXORI4(mem4,rc)) "xorl %2,%1\n" memop(a) +stmt: ASGNU4(addr,BANDU4(mem4,rc)) "andl %2,%1\n" memop(a) +stmt: ASGNU4(addr,BORU4(mem4,rc)) "orl %2,%1\n" memop(a) +stmt: ASGNU4(addr,BXORU4(mem4,rc)) "xorl %2,%1\n" memop(a) +reg: BCOMI4(reg) "?movl %0,%c\nnotl %c\n" 2 +reg: BCOMU4(reg) "?movl %0,%c\nnotl %c\n" 2 +reg: NEGI4(reg) "?movl %0,%c\nnegl %c\n" 2 + +stmt: ASGNI4(addr,BCOMI4(mem4)) "notl %1\n" memop(a) +stmt: ASGNU4(addr,BCOMU4(mem4)) "notl %1\n" memop(a) +stmt: ASGNI4(addr,NEGI4(mem4)) "negl %1\n" memop(a) +reg: LSHI4(reg,rc5) "?movl %0,%c\nsall %1,%c\n" 2 +reg: LSHU4(reg,rc5) "?movl %0,%c\nshll %1,%c\n" 2 +reg: RSHI4(reg,rc5) "?movl %0,%c\nsarl %1,%c\n" 2 +reg: RSHU4(reg,rc5) "?movl %0,%c\nshrl %1,%c\n" 2 + +stmt: ASGNI4(addr,LSHI4(mem4,rc5)) "sall %2,%1\n" memop(a) +stmt: ASGNI4(addr,LSHU4(mem4,rc5)) "shll %2,%1\n" memop(a) +stmt: ASGNI4(addr,RSHI4(mem4,rc5)) "sarl %2,%1\n" memop(a) +stmt: ASGNI4(addr,RSHU4(mem4,rc5)) "shrl %2,%1\n" memop(a) + +rc5: CNSTI4 "$%a" range(a, 0, 31) +rc5: reg "%%cl" +reg: MULI4(reg,mrc) "?movl %0,%c\nimull %1,%c\n" 14 +reg: MULI4(con,mr) "imul %0,%1,%c\n" 13 +reg: MULU4(reg,mr) "mull %1\n" 13 +reg: DIVU4(reg,reg) "xorl %%edx,%%edx\ndivl %1\n" +reg: MODU4(reg,reg) "xorl %%edx,%%edx\ndivl %1\n" +reg: DIVI4(reg,reg) "cdq\nidivl %1\n" +reg: MODI4(reg,reg) "cdq\nidivl %1\n" +reg: CVPU4(reg) "movl %0,%c\n" move(a) +reg: CVUP4(reg) "movl %0,%c\n" move(a) +reg: CVII4(INDIRI1(addr)) "movsbl %0,%c\n" 3 +reg: CVII4(INDIRI2(addr)) "movswl %0,%c\n" 3 +reg: CVUU4(INDIRU1(addr)) "movzbl %0,%c\n" 3 +reg: CVUU4(INDIRU2(addr)) "movzwl %0,%c\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 + +mrca: mem4 "%0" +mrca: rc "%0" +mrca: ADDRGP4 "$%a" +mrca: ADDRGP8 "$%a" + +stmt: ASGNI1(addr,rc) "movb %1,%0\n" 1 +stmt: ASGNI2(addr,rc) "movw %1,%0\n" 1 +stmt: ASGNI4(addr,rc) "movl %1,%0\n" 1 +stmt: ASGNU1(addr,rc) "movb %1,%0\n" 1 +stmt: ASGNU2(addr,rc) "movw %1,%0\n" 1 +stmt: ASGNU4(addr,rc) "movl %1,%0\n" 1 +stmt: ASGNP4(addr,rc) "movl %1,%0\n" 1 +stmt: ARGI4(mrca) "pushl %0\n" 1 +stmt: ARGU4(mrca) "pushl %0\n" 1 +stmt: ARGP4(mrca) "pushl %0\n" 1 +stmt: ASGNB(reg,INDIRB(reg)) "movl $%a,%%ecx\nrep\nmovsb\n" +stmt: ARGB(INDIRB(reg)) "subl $%a,%%esp\nmovl %%esp,%%edi\nmovl $%a,%%ecx\nrep\nmovsb\n" + +memf: INDIRF8(addr) "l %0" +memf: INDIRF4(addr) "s %0" +memf: CVFF8(INDIRF4(addr)) "s %0" +memf: CVFF4(INDIRF8(addr)) "l %0" + +freg: memf "fld%0\n" 3 + +stmt: ASGNF8(addr,freg) "fstpl %0\n" 7 +stmt: ASGNF4(addr,freg) "fstps %0\n" 7 +stmt: ASGNF4(addr,CVFF4(freg)) "fstps %0\n" 7 + +stmt: ARGF8(freg) "subl $8,%%esp\nfstpl (%%esp)\n" +stmt: ARGF4(freg) "subl $4,%%esp\nfstps (%%esp)\n" +freg: NEGF8(freg) "fchs\n" +freg: NEGF4(freg) "fchs\n" + +flt: memf "%0" +flt: freg "p %%st(1),%%st" + +freg: ADDF4(freg,flt) "fadd%1\n" +freg: ADDF8(freg,flt) "fadd%1\n" + +freg: DIVF4(freg,flt) "fdiv%1\n" +freg: DIVF8(freg,flt) "fdiv%1\n" + +freg: MULF4(freg,flt) "fmul%1\n" +freg: MULF8(freg,flt) "fmul%1\n" + +freg: SUBF4(freg,flt) "fsub%1\n" +freg: SUBF8(freg,flt) "fsub%1\n" + +freg: CVFF8(freg) "# CVFF8\n" +freg: CVFF4(freg) "sub $4,%%esp\nfstps (%%esp)\nflds (%%esp)\naddl $4,%%esp\n" 12 + +stmt: ASGNI4(addr,CVFI4(freg)) "fistpl %0\n" 29 +reg: CVFI4(freg) "subl $4,%%esp\nfistpl 0(%%esp)\npopl %c\n" 31 + +freg: CVIF8(INDIRI4(addr)) "fildl %0\n" 10 +freg: CVIF8(reg) "pushl %0\nfildl (%%esp)\naddl $4,%%esp\n" 12 + +freg: CVIF4(INDIRI4(addr)) "fildl %0\n" 10 +freg: CVIF4(reg) "pushl %0\nfildl (%%esp)\naddl $4,%%esp\n" 12 + +addrj: ADDRGP4 "%a" +addrj: reg "*%0" 2 +addrj: mem4 "*%0" 2 + +stmt: LABELV "%a:\n" +stmt: JUMPV(addrj) "jmp %0\n" 3 +stmt: EQI4(mem4,rc) "cmpl %1,%0\nje %a\n" 5 +stmt: GEI4(mem4,rc) "cmpl %1,%0\njge %a\n" 5 +stmt: GTI4(mem4,rc) "cmpl %1,%0\njg %a\n" 5 +stmt: LEI4(mem4,rc) "cmpl %1,%0\njle %a\n" 5 +stmt: LTI4(mem4,rc) "cmpl %1,%0\njl %a\n" 5 +stmt: NEI4(mem4,rc) "cmpl %1,%0\njne %a\n" 5 +stmt: GEU4(mem4,rc) "cmpl %1,%0\njae %a\n" 5 +stmt: GTU4(mem4,rc) "cmpl %1,%0\nja %a\n" 5 +stmt: LEU4(mem4,rc) "cmpl %1,%0\njbe %a\n" 5 +stmt: LTU4(mem4,rc) "cmpl %1,%0\njb %a\n" 5 +stmt: EQI4(reg,mrc) "cmpl %1,%0\nje %a\n" 4 +stmt: GEI4(reg,mrc) "cmpl %1,%0\njge %a\n" 4 +stmt: GTI4(reg,mrc) "cmpl %1,%0\njg %a\n" 4 +stmt: LEI4(reg,mrc) "cmpl %1,%0\njle %a\n" 4 +stmt: LTI4(reg,mrc) "cmpl %1,%0\njl %a\n" 4 +stmt: NEI4(reg,mrc) "cmpl %1,%0\njne %a\n" 4 + +stmt: EQU4(reg,mrc) "cmpl %1,%0\nje %a\n" 4 +stmt: GEU4(reg,mrc) "cmpl %1,%0\njae %a\n" 4 +stmt: GTU4(reg,mrc) "cmpl %1,%0\nja %a\n" 4 +stmt: LEU4(reg,mrc) "cmpl %1,%0\njbe %a\n" 4 +stmt: LTU4(reg,mrc) "cmpl %1,%0\njb %a\n" 4 +stmt: NEU4(reg,mrc) "cmpl %1,%0\njne %a\n" 4 + +stmt: EQI4(BANDU4(mr,con),con0) "testl %1,%0\nje %a\n" 3 +stmt: NEI4(BANDU4(mr,con),con0) "testl %1,%0\njne %a\n" + +stmt: EQI4(BANDU4(CVII2(INDIRI2(addr)),con),con0) "testw %1,%0\nje %a\n" +stmt: NEI4(BANDU4(CVII2(INDIRI2(addr)),con),con0) "testw %1,%0\njne %a\n" +stmt: EQI4(BANDU4(CVIU2(INDIRI2(addr)),con),con0) "testw %1,%0\nje %a\n" +stmt: NEI4(BANDU4(CVIU2(INDIRI2(addr)),con),con0) "testw %1,%0\njne %a\n" +stmt: EQI4(BANDU4(CVII1(INDIRI1(addr)),con),con0) "testb %1,%0\nje %a\n" + +cmpf: INDIRF8(addr) "l %0" +cmpf: INDIRF4(addr) "s %0" +cmpf: CVFF8(INDIRF4(addr)) "s %0" +cmpf: freg "p" + +stmt: EQF8(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\nje %a\n" +stmt: GEF8(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njbe %a\n" +stmt: GTF8(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njb %a\n" +stmt: LEF8(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njae %a\n" +stmt: LTF8(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\nja %a\n" +stmt: NEF8(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njne %a\n" + +stmt: EQF4(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\nje %a\n" +stmt: GEF4(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njbe %a\n" +stmt: GTF4(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njb %a\n" +stmt: LEF4(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njae %a\n" +stmt: LTF4(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\nja %a\n" +stmt: NEF4(cmpf,freg) "fcomp%0\nfstsw %%ax\nsahf\njne %a\n" + +freg: DIVF8(freg,CVIF8(INDIRI4(addr))) "fidivl %1\n" +freg: DIVF8(CVIF8(INDIRI4(addr)),freg) "fidivrl %0\n" +freg: DIVF8(freg,CVIF8(CVII2(INDIRI2(addr)))) "fidivs %1\n" +freg: DIVF8(CVIF8(CVII2(INDIRI2(addr))),freg) "fidivrs %0\n" +freg: MULF8(freg,CVIF8(INDIRI4(addr))) "fimull %1\n" +freg: MULF8(freg,CVIF8(CVII2(INDIRI2(addr)))) "fimuls %1\n" +freg: SUBF8(freg,CVIF8(INDIRI4(addr))) "fisubl %1\n" +freg: SUBF8(CVIF8(INDIRI4(addr)),freg) "fisubrl %0\n" +freg: SUBF8(freg,CVIF8(CVII2(INDIRI2(addr)))) "fisubs %1\n" +freg: SUBF8(CVIF8(CVII2(INDIRI2(addr))),freg) "fisubrs %0\n" +freg: ADDF8(freg,CVIF8(INDIRI4(addr))) "fiaddl %1\n" +freg: ADDF8(freg,CVIF8(CVII2(INDIRI2(addr)))) "fiadds %1\n" +freg: ADDF8(freg,CVFF8(INDIRF4(addr))) "fdivs %1\n" +freg: SUBF8(freg,CVFF8(INDIRF4(addr))) "fsubs %1\n" +freg: MULF8(freg,CVFF8(INDIRF4(addr))) "fmuls %1\n" +freg: DIVF8(freg,CVFF8(INDIRF4(addr))) "fdivs %1\n" +freg: LOADF8(memf) "fld%0\n" + +reg: CALLI4(addrj) "call %0\naddl $%a,%%esp\n" hasargs(a) +reg: CALLU4(addrj) "call %0\naddl $%a,%%esp\n" hasargs(a) +reg: CALLP4(addrj) "call %0\naddl $%a,%%esp\n" hasargs(a) + +reg: CALLI4(addrj) "call %0\n" 1 +reg: CALLU4(addrj) "call %0\n" 1 +reg: CALLP4(addrj) "call %0\n" 1 + +stmt: CALLV(addrj) "call %0\naddl $%a,%%esp\n" hasargs(a) +stmt: CALLV(addrj) "call %0\n" 1 + +freg: CALLF4(addrj) "call %0\naddl $%a,%%esp\n" hasargs(a) +freg: CALLF4(addrj) "call %0\n" 1 + +stmt: CALLF4(addrj) "call %0\naddl $%a,%%esp\nfstp %%st(0)\n" hasargs(a) +stmt: CALLF4(addrj) "call %0\nfstp %%st(0)\n" 1 + +freg: CALLF8(addrj) "call %0\naddl $%a,%%esp\n" hasargs(a) +freg: CALLF8(addrj) "call %0\n" 1 + +stmt: CALLF8(addrj) "call %0\naddl $%a,%%esp\nfstp %%st(0)\n" hasargs(a) +stmt: CALLF8(addrj) "call %0\nfstp %%st(0)\n" 1 + +stmt: RETI4(reg) "# ret\n" +stmt: RETU4(reg) "# ret\n" +stmt: RETP4(reg) "# ret\n" +stmt: RETF4(freg) "# ret\n" +stmt: RETF8(freg) "# 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); + for (i = 0; i < argc; i++) + if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "-pg") == 0) + pflag = 1; + 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; + + 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; + + stabprefix = ".LL"; +} + +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 Symbol prevg; + +static void globalend(void) { + if (prevg && prevg->type->size > 0) + print(".size %s,%d\n", prevg->x.name, prevg->type->size); + prevg = NULL; +} + +static void progend(void) { + globalend(); + (*IR->segment)(CODE); + print(".ident \"LCC: 4.1\"\n"); +} + +static void target(Node p) { + assert(p); + 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)) { + rtarget(p, 1, intreg[ECX]); + setreg(p, intreg[EAX]); + } + break; + case MUL+U: + setreg(p, quo); + rtarget(p, 0, intreg[EAX]); + break; + case DIV+I: case DIV+U: + setreg(p, quo); + rtarget(p, 0, intreg[EAX]); + rtarget(p, 1, intreg[ECX]); + break; + case MOD+I: case MOD+U: + setreg(p, rem); + rtarget(p, 0, intreg[EAX]); + rtarget(p, 1, intreg[ECX]); + 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 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; + } +} + +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("movsbl %s,%s\n", preg(charreg), p->syms[RX]->x.name); + else if (op == CVI+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1) + print("movsbl %s,%s\n", preg(charreg), p->syms[RX]->x.name); + else if (op == CVI+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2) + print("movswl %s,%s\n", preg(shortreg), p->syms[RX]->x.name); + else if (op == CVI+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2) + print("movswl %s,%s\n", preg(shortreg), p->syms[RX]->x.name); + else if (op == CVU+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1) + print("movzbl %s,%s\n", preg(charreg), p->syms[RX]->x.name); + else if (op == CVU+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1) + print("movzbl %s,%s\n", preg(charreg), p->syms[RX]->x.name); + else if (op == CVU+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2) + print("movzwl %s,%s\n", preg(shortreg), p->syms[RX]->x.name); + else if (op == CVU+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2) + print("movzwl %s,%s\n", preg(shortreg), p->syms[RX]->x.name); + 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("movl %s,%s\n", src, dst); + } +} + +static void function(Symbol f, Symbol caller[], Symbol callee[], int n) { + int i; + + globalend(); + print(".align 16\n"); + print(".type %s,@function\n", f->x.name); + print("%s:\n", f->x.name); + print("pushl %%ebp\n"); + if (pflag) { + static int plab; + print("movl %%esp,%%ebp\n"); + (*IR->segment)(DATA); + print(".align 4\n.LP%d:\n.long 0\n", plab); + (*IR->segment)(CODE); + print("movl $.LP%d,%%edx\ncall mcount\n", plab); + plab++; + } + print("pushl %%ebx\n"); + print("pushl %%esi\n"); + print("pushl %%edi\n"); + print("movl %%esp,%%ebp\n"); + + usedmask[0] = usedmask[1] = 0; + freemask[0] = freemask[1] = ~0U; + offset = 16 + 4; + for (i = 0; callee[i]; i++) { + Symbol p = callee[i]; + Symbol q = caller[i]; + assert(q); + offset = roundup(offset, q->type->align); + 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("subl $%d,%%esp\n", framesize); + emitcode(); + print("movl %%ebp,%%esp\n"); + print("popl %%edi\n"); + print("popl %%esi\n"); + print("popl %%ebx\n"); + print("popl %%ebp\n"); + print("ret\n"); + { int l = genlabel(1); + print(".Lf%d:\n", l); + print(".size %s,.Lf%d-%s\n", f->x.name, l, f->x.name); + } +} + +static void defsymbol(Symbol p) { + if (p->scope >= LOCAL && p->sclass == STATIC) + p->x.name = stringf("%s.%d", p->name, genlabel(1)); + else if (p->generated) + p->x.name = stringf(".LC%s", p->name); + else if (p->scope == GLOBAL || p->sclass == EXTERN) + p->x.name = stringf("%s", p->name); + else + p->x.name = p->name; +} + +static void segment(int n) { + if (n == cseg) + return; + cseg = n; + if (cseg == CODE) + print(".text\n"); + else if (cseg == BSS) + print(".bss\n"); + else if (cseg == DATA || cseg == LIT) + print(".data\n"); +} + +static void defconst(int suffix, int size, Value v) { + if (suffix == I && size == 1) + print(".byte %d\n", v.u); + else if (suffix == I && size == 2) + print(".word %d\n", v.i); + else if (suffix == I && size == 4) + print(".long %d\n", v.i); + else if (suffix == U && size == 1) + print(".byte %d\n", v.u); + else if (suffix == U && size == 2) + print(".word %d\n", v.u); + else if (suffix == U && size == 4) + print(".long %d\n", v.u); + else if (suffix == P && size == 4) + print(".long %d\n", v.p); + else if (suffix == F && size == 4) { + float f = v.d; + print(".long %d\n", *(unsigned *)&f); + } else if (suffix == F && size == 8) { + double d = v.d; + unsigned *p = (unsigned *)&d; + print(".long %d\n.long %d\n", p[swap], p[!swap]); + } + else assert(0); +} + +static void defaddress(Symbol p) { + print(".long %s\n", p->x.name); +} + +static void defstring(int n, char *str) { + char *s; + + for (s = str; s < str + n; s++) + print(".byte %d\n", (*s)&0377); +} + +static void export(Symbol p) { + globalend(); + print(".globl %s\n", p->x.name); +} + +static void import(Symbol p) {} + +static void global(Symbol p) { + globalend(); + print(".align %d\n", p->type->align > 4 ? 4 : p->type->align); + if (!p->generated) { + print(".type %s,@%s\n", p->x.name, + isfunc(p->type) ? "function" : "object"); + if (p->type->size > 0) + print(".size %s,%d\n", p->x.name, p->type->size); + else + prevg = p; + } + if (p->u.seg == BSS) { + if (p->sclass == STATIC) + print(".lcomm %s,%d\n", p->x.name, p->type->size); + else + print(".comm %s,%d\n", p->x.name, p->type->size); + } else { + print("%s:\n", p->x.name); + } +} + +static void space(int n) { + if (cseg != BSS) + print(".space %d\n", n); +} + +Interface x86linuxIR = { + 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 */ + 0, /* address */ + blockbeg, + blockend, + defaddress, + defconst, + defstring, + defsymbol, + emit, + export, + function, + gen, + global, + import, + 0, /* local */ + progbeg, + progend, + segment, + space, + stabblock, stabend, 0, stabinit, stabline, stabsym, stabtype, + {1, rmap, + 0, 0, 0, /* blkfetch, blkstore, blkloop */ + _label, + _rule, + _nts, + _kids, + _string, + _templates, + _isinstruction, + _ntname, + emit2, + 0, /* doarg */ + target, + clobber, + } +}; + +void x86linux_init(int argc, char *argv[]) { + static int inited; + extern Interface x86IR; + + if (inited) + return; + inited = 1; +#define xx(f) assert(!x86linuxIR.f); x86linuxIR.f = x86IR.f + xx(address); + xx(local); + xx(x.blkfetch); + xx(x.blkstore); + xx(x.blkloop); + xx(x.doarg); +#undef xx +} |