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 +}  | 
