Perform initial (i.e. feature complete and compiling, but not necessarily
working) port of the B compiler to EM.
This commit is contained in:
parent
cfc723250f
commit
707585b67d
|
@ -1,11 +1,11 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <em.h>
|
||||||
|
|
||||||
#define NCPS 8 /* chars per symbol */
|
#define NCPS 8 /* chars per symbol */
|
||||||
#define NCPW 4 /* chars per word */
|
|
||||||
#define ALIGN 4 /* Passed directly to the assembler's .align */
|
|
||||||
#define HSHSIZ 400 /* hash table size */
|
#define HSHSIZ 400 /* hash table size */
|
||||||
#define SWSIZ 230 /* switch table size */
|
#define SWSIZ 230 /* switch table size */
|
||||||
#define CMSIZ 40 /* symbol stack size */
|
#define CMSIZ 40 /* symbol stack size */
|
||||||
|
@ -40,6 +40,7 @@ struct swtab {
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int wordsize;
|
extern int wordsize;
|
||||||
|
int paramsize;
|
||||||
struct hshtab hshtab[HSHSIZ];
|
struct hshtab hshtab[HSHSIZ];
|
||||||
int hshused;
|
int hshused;
|
||||||
int eof;
|
int eof;
|
||||||
|
@ -71,9 +72,12 @@ void error(char *s, ...);
|
||||||
void printtoken(int tok, FILE *out);
|
void printtoken(int tok, FILE *out);
|
||||||
struct tnode * block(int op, int value, struct tnode *tr1, struct tnode *tr2);
|
struct tnode * block(int op, int value, struct tnode *tr1, struct tnode *tr2);
|
||||||
void rcexpr(struct tnode *tr);
|
void rcexpr(struct tnode *tr);
|
||||||
void cbranch(struct tnode *t, int lab, int val);
|
void cbranch(struct tnode *t, int lab);
|
||||||
void jump(int lab);
|
void jump(int lab);
|
||||||
void label(int l);
|
void fnlabel(int l);
|
||||||
|
void tonativeaddr(void);
|
||||||
|
void fromnativeaddr(void);
|
||||||
|
char* manglename(char* name, char prefix);
|
||||||
|
|
||||||
#define EOFC 0
|
#define EOFC 0
|
||||||
#define SEMI 1
|
#define SEMI 1
|
||||||
|
|
|
@ -4,7 +4,6 @@ void extdef(void);
|
||||||
struct hshtab * lookup(void);
|
struct hshtab * lookup(void);
|
||||||
void blkhed(void);
|
void blkhed(void);
|
||||||
void blkend(void);
|
void blkend(void);
|
||||||
void retseq(void);
|
|
||||||
void statement(int d);
|
void statement(int d);
|
||||||
struct tnode * tree(void);
|
struct tnode * tree(void);
|
||||||
void errflush(int o);
|
void errflush(int o);
|
||||||
|
@ -15,6 +14,9 @@ int contlab = -1;
|
||||||
int brklab = -1;
|
int brklab = -1;
|
||||||
|
|
||||||
int wordsize = 4;
|
int wordsize = 4;
|
||||||
|
int bsymb_part;
|
||||||
|
int code_part;
|
||||||
|
int string_part;
|
||||||
|
|
||||||
void
|
void
|
||||||
init(char *s, int val)
|
init(char *s, int val)
|
||||||
|
@ -76,10 +78,33 @@ main(int argc, char *argv[])
|
||||||
init("return", RETURN);
|
init("return", RETURN);
|
||||||
init("default", DEFAULT);
|
init("default", DEFAULT);
|
||||||
init("break", BREAK);
|
init("break", BREAK);
|
||||||
|
|
||||||
|
C_init(wordsize, wordsize);
|
||||||
|
C_open(NULL);
|
||||||
|
C_magic();
|
||||||
|
C_ms_emx(wordsize, wordsize);
|
||||||
|
bsymb_part = 0;
|
||||||
|
string_part = 0;
|
||||||
|
code_part = C_getid();
|
||||||
|
C_beginpart(code_part);
|
||||||
while (!eof) {
|
while (!eof) {
|
||||||
extdef();
|
extdef();
|
||||||
blkend();
|
blkend();
|
||||||
}
|
}
|
||||||
|
C_endpart(code_part);
|
||||||
|
C_insertpart(code_part);
|
||||||
|
|
||||||
|
if (string_part)
|
||||||
|
C_insertpart(string_part);
|
||||||
|
|
||||||
|
C_exp("bsymb_start");
|
||||||
|
C_exp("bsymb_end");
|
||||||
|
if (bsymb_part)
|
||||||
|
C_insertpart(bsymb_part);
|
||||||
|
C_df_dnam("bsymb_end");
|
||||||
|
|
||||||
|
C_close();
|
||||||
|
|
||||||
return nerror != 0;
|
return nerror != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,9 +217,9 @@ getcc(void)
|
||||||
cc = 0;
|
cc = 0;
|
||||||
cp = (char*) &cval;
|
cp = (char*) &cval;
|
||||||
while ((c = mapch('\'')) >= 0)
|
while ((c = mapch('\'')) >= 0)
|
||||||
if (cc++ < NCPW)
|
if (cc++ < wordsize)
|
||||||
*cp++ = c;
|
*cp++ = c;
|
||||||
if (cc > NCPW)
|
if (cc > wordsize)
|
||||||
error("Long character constant");
|
error("Long character constant");
|
||||||
return CON;
|
return CON;
|
||||||
}
|
}
|
||||||
|
@ -204,17 +229,31 @@ getstr(void)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
int i;
|
int i;
|
||||||
|
char b;
|
||||||
|
int partid;
|
||||||
|
|
||||||
printf("\t.align %d\n", wordsize);
|
partid = C_getid();
|
||||||
printf("L%d:", cval = isn++);
|
C_beginpart(partid);
|
||||||
if ((c = mapch('"')) >= 0)
|
if (string_part)
|
||||||
printf("\t.byte %04o", c);
|
C_insertpart(string_part);
|
||||||
for (i = 2; (c = mapch('"')) >= 0; i++)
|
|
||||||
printf(",%04o", c);
|
cval = isn++;
|
||||||
printf(",04");
|
C_df_dlb(cval);
|
||||||
|
for (i = 1; (c = mapch('"')) >= 0; i++) {
|
||||||
|
b = c;
|
||||||
|
C_con_scon(&b, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
b = 04;
|
||||||
|
C_con_scon(&b, 1);
|
||||||
|
|
||||||
|
b = 0;
|
||||||
while ((i++%4) != 0)
|
while ((i++%4) != 0)
|
||||||
printf(",00");
|
C_con_scon(&b, 1);
|
||||||
printf("\n");
|
|
||||||
|
C_endpart(partid);
|
||||||
|
string_part = partid;
|
||||||
|
|
||||||
return STRING;
|
return STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,26 +486,30 @@ declist(void)
|
||||||
void
|
void
|
||||||
function(void)
|
function(void)
|
||||||
{
|
{
|
||||||
printf("\tpush\t%%ebp\n");
|
|
||||||
printf("\tmov\t%%esp,%%ebp\n");
|
|
||||||
|
|
||||||
declare(ARG);
|
declare(ARG);
|
||||||
statement(1);
|
statement(1);
|
||||||
retseq();
|
C_ret(0);
|
||||||
|
C_end(paramsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
global(char *s)
|
global(char *s)
|
||||||
{
|
{
|
||||||
printf("\t.globl\t_%s\n", s);
|
C_exa_dnam(manglename(s, 'b'));
|
||||||
printf("\t.data\n");
|
|
||||||
printf("\t.align %d\n", ALIGN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bsymb(char *s, int und)
|
bsymb(char *s)
|
||||||
{
|
{
|
||||||
printf("\t.section .bsymb; .long %s%s; .data\n", und?"_":"", s);
|
int newpart = C_getid();
|
||||||
|
C_beginpart(newpart);
|
||||||
|
if (bsymb_part != 0)
|
||||||
|
C_insertpart(bsymb_part);
|
||||||
|
C_rom_dlb(isn, 0);
|
||||||
|
C_endpart(newpart);
|
||||||
|
|
||||||
|
bsymb_part = newpart;
|
||||||
|
C_df_dlb(isn++);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -474,6 +517,7 @@ extdef(void)
|
||||||
{
|
{
|
||||||
int o, dim, i;
|
int o, dim, i;
|
||||||
char *bs;
|
char *bs;
|
||||||
|
char *ms;
|
||||||
|
|
||||||
if ((o = symbol()) == EOFC || o == SEMI)
|
if ((o = symbol()) == EOFC || o == SEMI)
|
||||||
return;
|
return;
|
||||||
|
@ -484,7 +528,9 @@ extdef(void)
|
||||||
switch(o = symbol()) {
|
switch(o = symbol()) {
|
||||||
|
|
||||||
case SEMI:
|
case SEMI:
|
||||||
printf("\t.comm\t_%s,%d,%d\n", bs, NCPW, ALIGN);
|
global(bs);
|
||||||
|
C_df_dnam(manglename(bs, 'b'));
|
||||||
|
C_bss_cst(wordsize, 0, 1);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
|
@ -492,8 +538,8 @@ extdef(void)
|
||||||
case STRING:
|
case STRING:
|
||||||
global(bs);
|
global(bs);
|
||||||
if (o == STRING)
|
if (o == STRING)
|
||||||
bsymb(bs,1);
|
bsymb(bs);
|
||||||
printf("_%s:", bs);
|
C_df_dnam(manglename(bs, 'b'));
|
||||||
pushsym(o);
|
pushsym(o);
|
||||||
goto init;
|
goto init;
|
||||||
|
|
||||||
|
@ -507,13 +553,17 @@ extdef(void)
|
||||||
goto syntax;
|
goto syntax;
|
||||||
global(bs);
|
global(bs);
|
||||||
if ((o=symbol()) == SEMI) {
|
if ((o=symbol()) == SEMI) {
|
||||||
printf("\t.comm\tL%d,%d,%d\n", isn, dim*NCPW, ALIGN);
|
bsymb(bs);
|
||||||
bsymb(bs,1);
|
C_df_dnam(manglename(bs, 'b'));
|
||||||
printf("_%s:\t.long L%d\n", bs, isn++);
|
C_con_dlb(isn, 0);
|
||||||
|
C_df_dlb(isn++);
|
||||||
|
C_bss_cst(wordsize*dim, 0, 1);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
bsymb(bs,1);
|
bsymb(bs);
|
||||||
printf("_%s:\t.long 1f\n1:", bs);
|
C_df_dnam(manglename(bs, 'b'));
|
||||||
|
C_con_dlb(isn, 0);
|
||||||
|
C_df_dlb(isn++);
|
||||||
pushsym(o);
|
pushsym(o);
|
||||||
|
|
||||||
init:
|
init:
|
||||||
|
@ -521,15 +571,26 @@ extdef(void)
|
||||||
if ((o=symbol()) != CON && o != STRING && o != NAME)
|
if ((o=symbol()) != CON && o != STRING && o != NAME)
|
||||||
goto syntax;
|
goto syntax;
|
||||||
if (o == NAME) {
|
if (o == NAME) {
|
||||||
bsymb("1f",0);
|
bsymb(NULL);
|
||||||
printf("1:\t.long _%s\n", bsym->name);
|
C_con_dnam(manglename(bsym->name, 'b'), 0);
|
||||||
|
} else {
|
||||||
|
if (o == STRING) {
|
||||||
|
bsymb(NULL);
|
||||||
|
C_con_dlb(cval, 0);
|
||||||
} else
|
} else
|
||||||
printf("\t.long %s%d\n", o==STRING?"L":"",cval);
|
C_con_cst(cval);
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
} while ((o=symbol()) == COMMA);
|
} while ((o=symbol()) == COMMA);
|
||||||
dim = (i > dim) ? i : dim;
|
dim = (i > dim) ? i : dim;
|
||||||
if (dim - i)
|
if (i == 0)
|
||||||
printf("\t.zero %d\n", (dim-i)*NCPW);
|
C_bss_cst((dim-i)*wordsize, 0, 1);
|
||||||
|
else {
|
||||||
|
while (dim -i) {
|
||||||
|
C_con_cst(0);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (o == SEMI)
|
if (o == SEMI)
|
||||||
goto done;
|
goto done;
|
||||||
goto syntax;
|
goto syntax;
|
||||||
|
@ -537,12 +598,15 @@ extdef(void)
|
||||||
/* function */
|
/* function */
|
||||||
case LPARN:
|
case LPARN:
|
||||||
global(bs);
|
global(bs);
|
||||||
bsymb(bs,1);
|
ms = manglename(bs, 'b');
|
||||||
printf("_%s:\t.long 1f\n", bs);
|
bsymb(ms);
|
||||||
printf("\t.text\n\t.align %s\n1:", wordsize);
|
C_df_dnam(ms);
|
||||||
|
ms = manglename(bs, 'i');
|
||||||
|
C_con_pnam(ms);
|
||||||
|
C_inp(ms);
|
||||||
|
C_pro_narg(ms);
|
||||||
function();
|
function();
|
||||||
done:
|
done:
|
||||||
printf("\n");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case EOFC:
|
case EOFC:
|
||||||
|
@ -555,26 +619,6 @@ syntax:
|
||||||
statement(0);
|
statement(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
setstk(int a)
|
|
||||||
{
|
|
||||||
int dif;
|
|
||||||
|
|
||||||
dif = stack-a;
|
|
||||||
stack = a;
|
|
||||||
if (dif)
|
|
||||||
printf("\tsub\t$%d, %%esp\n", dif);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
defvec(void)
|
|
||||||
{
|
|
||||||
stack -= NCPW;
|
|
||||||
printf("\tmov\t%%esp,%%eax\n");
|
|
||||||
printf("\tshr\t$2,%%eax\n");
|
|
||||||
printf("\tpush\t%%eax\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
blkhed(void)
|
blkhed(void)
|
||||||
{
|
{
|
||||||
|
@ -583,27 +627,29 @@ blkhed(void)
|
||||||
|
|
||||||
declist();
|
declist();
|
||||||
stack = al = -wordsize;
|
stack = al = -wordsize;
|
||||||
pl = wordsize*2;
|
pl = 0; /* EM parameters start at offset 0. */
|
||||||
while (paraml) {
|
while (paraml) {
|
||||||
paraml = (bs = paraml)->next;
|
paraml = (bs = paraml)->next;
|
||||||
bs->offset = pl;
|
bs->offset = pl;
|
||||||
pl += NCPW;
|
pl += wordsize;
|
||||||
}
|
}
|
||||||
for (bs = hshtab; bs < &hshtab[HSHSIZ]; bs++)
|
for (bs = hshtab; bs < &hshtab[HSHSIZ]; bs++)
|
||||||
if (bs->name[0]) {
|
if (bs->name[0]) {
|
||||||
if (bs->class == AUTO) {
|
if (bs->class == AUTO) {
|
||||||
bs->offset = al;
|
bs->offset = al;
|
||||||
if (bs->dim) {
|
if (bs->dim) {
|
||||||
al -= bs->dim*NCPW;
|
al -= bs->dim*wordsize;
|
||||||
setstk(al);
|
C_lal(al);
|
||||||
defvec();
|
al -= wordsize;
|
||||||
|
fromnativeaddr();
|
||||||
|
C_stl(al);
|
||||||
bs->offset = al;
|
bs->offset = al;
|
||||||
}
|
}
|
||||||
al -= NCPW;
|
al -= wordsize;
|
||||||
} else if (bs->class == ARG)
|
} else if (bs->class == ARG)
|
||||||
bs->class = AUTO;
|
bs->class = AUTO;
|
||||||
}
|
}
|
||||||
setstk(al);
|
paramsize = -al - wordsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -641,33 +687,23 @@ syntax:
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
label(int l)
|
fnlabel(int l)
|
||||||
{
|
{
|
||||||
printf("L%d:\n", l);
|
C_ilb(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Jump to "lab", if the expression "t" evaluated to 0. */
|
||||||
void
|
void
|
||||||
retseq(void)
|
cbranch(struct tnode *t, int lab)
|
||||||
{
|
|
||||||
printf("\tjmp\tretrn\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Jump to "lab", if the expression "t" evaluated to "val". */
|
|
||||||
void
|
|
||||||
cbranch(struct tnode *t, int lab, int val)
|
|
||||||
{
|
{
|
||||||
rcexpr(t);
|
rcexpr(t);
|
||||||
if (val == 0)
|
C_zeq(lab);
|
||||||
printf("\ttest\t%%eax,%%eax\n");
|
|
||||||
else
|
|
||||||
printf("\tcmp\t%%eax,$%d\n", val);
|
|
||||||
printf("\tje\tL%d\n", lab);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
jump(int lab)
|
jump(int lab)
|
||||||
{
|
{
|
||||||
printf("\tjmp\tL%d\n", lab);
|
C_bra(lab);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -676,26 +712,31 @@ pswitch(void)
|
||||||
struct swtab *sswp;
|
struct swtab *sswp;
|
||||||
int dl, swlab;
|
int dl, swlab;
|
||||||
|
|
||||||
sswp = swp;
|
|
||||||
if (swp == NULL)
|
if (swp == NULL)
|
||||||
swp = swtab;
|
swp = swtab;
|
||||||
|
sswp = swp;
|
||||||
swlab = isn++;
|
swlab = isn++;
|
||||||
printf("\tmov\t$L%d,%%ebx\n", swlab);
|
C_lae_dlb(swlab, 0);
|
||||||
printf("\tjmp\tbswitch\n");
|
C_csb(wordsize);
|
||||||
|
|
||||||
dl = deflab;
|
dl = deflab;
|
||||||
deflab = 0;
|
deflab = 0;
|
||||||
statement(0);
|
statement(0);
|
||||||
if (!deflab) {
|
if (!deflab)
|
||||||
deflab = isn++;
|
deflab = brklab;
|
||||||
label(deflab);
|
|
||||||
}
|
C_df_dlb(swlab);
|
||||||
printf("L%d:\n\t.data\nL%d:", brklab, swlab);
|
C_con_ilb(deflab);
|
||||||
|
C_con_cst(swp - sswp);
|
||||||
|
|
||||||
while (swp > sswp && swp > swtab) {
|
while (swp > sswp && swp > swtab) {
|
||||||
--swp;
|
--swp;
|
||||||
printf("\t.long %d,L%d\n", swp->swval, swp->swlab);
|
C_con_cst(swp->swval);
|
||||||
|
C_con_ilb(swp->swlab);
|
||||||
}
|
}
|
||||||
printf("\t.long L%d,0\n", deflab);
|
|
||||||
printf("\t.text\n");
|
C_df_dlb(brklab);
|
||||||
|
|
||||||
deflab = dl;
|
deflab = dl;
|
||||||
swp = sswp;
|
swp = sswp;
|
||||||
}
|
}
|
||||||
|
@ -742,33 +783,36 @@ stmt:
|
||||||
goto semi;
|
goto semi;
|
||||||
|
|
||||||
case RETURN:
|
case RETURN:
|
||||||
if (pushsym(symbol()) == LPARN)
|
if (pushsym(symbol()) == LPARN) {
|
||||||
rcexpr(pexpr());
|
rcexpr(pexpr());
|
||||||
retseq();
|
C_ret(wordsize);
|
||||||
|
} else {
|
||||||
|
C_ret(0);
|
||||||
|
}
|
||||||
goto semi;
|
goto semi;
|
||||||
|
|
||||||
case IF:
|
case IF:
|
||||||
cbranch(pexpr(), o1=isn++, 0);
|
cbranch(pexpr(), o1=isn++);
|
||||||
statement(0);
|
statement(0);
|
||||||
if ((o = symbol()) == KEYW && cval == ELSE) {
|
if ((o = symbol()) == KEYW && cval == ELSE) {
|
||||||
jump(o2 = isn++);
|
jump(o2 = isn++);
|
||||||
label(o1);
|
fnlabel(o1);
|
||||||
statement(0);
|
statement(0);
|
||||||
label(o2);
|
fnlabel(o2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pushsym(o);
|
pushsym(o);
|
||||||
label(o1);
|
fnlabel(o1);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case WHILE:
|
case WHILE:
|
||||||
o1 = contlab;
|
o1 = contlab;
|
||||||
o2 = brklab;
|
o2 = brklab;
|
||||||
label(contlab = isn++);
|
fnlabel(contlab = isn++);
|
||||||
cbranch(pexpr(), brklab=isn++, 0);
|
cbranch(pexpr(), brklab=isn++);
|
||||||
statement(0);
|
statement(0);
|
||||||
jump(contlab);
|
jump(contlab);
|
||||||
label(brklab);
|
fnlabel(brklab);
|
||||||
contlab = o1;
|
contlab = o1;
|
||||||
brklab = o2;
|
brklab = o2;
|
||||||
return;
|
return;
|
||||||
|
@ -811,7 +855,7 @@ stmt:
|
||||||
else {
|
else {
|
||||||
swp->swlab = isn;
|
swp->swlab = isn;
|
||||||
(swp++)->swval = cval;
|
(swp++)->swval = cval;
|
||||||
label(isn++);
|
fnlabel(isn++);
|
||||||
}
|
}
|
||||||
goto stmt;
|
goto stmt;
|
||||||
|
|
||||||
|
@ -821,7 +865,7 @@ stmt:
|
||||||
if ((o = symbol()) != COLON)
|
if ((o = symbol()) != COLON)
|
||||||
goto syntax;
|
goto syntax;
|
||||||
deflab = isn++;
|
deflab = isn++;
|
||||||
label(deflab);
|
fnlabel(deflab);
|
||||||
goto stmt;
|
goto stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -837,12 +881,13 @@ stmt:
|
||||||
}
|
}
|
||||||
bsym->class = INTERN;
|
bsym->class = INTERN;
|
||||||
bsym->offset = isn++;
|
bsym->offset = isn++;
|
||||||
label(bsym->offset);
|
fnlabel(bsym->offset);
|
||||||
goto stmt;
|
goto stmt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pushsym(o);
|
pushsym(o);
|
||||||
rcexpr(tree());
|
rcexpr(tree());
|
||||||
|
C_asp(wordsize);
|
||||||
goto semi;
|
goto semi;
|
||||||
|
|
||||||
semi:
|
semi:
|
||||||
|
@ -948,6 +993,7 @@ advanc:
|
||||||
switch (o=symbol()) {
|
switch (o=symbol()) {
|
||||||
case NAME:
|
case NAME:
|
||||||
if (pushsym(symbol()) == LPARN) { /* function */
|
if (pushsym(symbol()) == LPARN) { /* function */
|
||||||
|
if (bsym->class == 0)
|
||||||
bsym->class = EXTERN;
|
bsym->class = EXTERN;
|
||||||
} else if (bsym->class == 0) {
|
} else if (bsym->class == 0) {
|
||||||
error("%s undefined", bsym->name);
|
error("%s undefined", bsym->name);
|
||||||
|
|
|
@ -1,26 +1,51 @@
|
||||||
#include "b.h"
|
#include "b.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Code generation (x86 assembly)
|
* Code generation (EM)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
static int
|
||||||
push(void)
|
shiftsize(void)
|
||||||
{
|
{
|
||||||
printf("\tpush\t%%eax\n");
|
switch (wordsize) {
|
||||||
|
case 1: return 0;
|
||||||
|
case 2: return 1;
|
||||||
|
case 4: return 2;
|
||||||
|
case 8: return 3;
|
||||||
|
default:
|
||||||
|
error("unsupported word size");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pop(char *s)
|
tonativeaddr(void)
|
||||||
{
|
{
|
||||||
printf("\tpop\t%%%s\n", s);
|
C_loc(shiftsize());
|
||||||
|
C_slu(wordsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fromnativeaddr(void)
|
||||||
|
{
|
||||||
|
C_loc(shiftsize());
|
||||||
|
C_sru(wordsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
manglename(char* name, char prefix)
|
||||||
|
{
|
||||||
|
static char buffer[NCPS+3];
|
||||||
|
buffer[0] = prefix;
|
||||||
|
buffer[1] = '_';
|
||||||
|
strcpy(buffer+2, name);
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
binary(struct tnode *tr)
|
binary(struct tnode *tr)
|
||||||
{
|
{
|
||||||
rcexpr(tr->tr1);
|
rcexpr(tr->tr1);
|
||||||
push();
|
|
||||||
rcexpr(tr->tr2);
|
rcexpr(tr->tr2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,13 +58,11 @@ pushargs(struct tnode *tr)
|
||||||
return 0;
|
return 0;
|
||||||
if (tr->op == COMMA) {
|
if (tr->op == COMMA) {
|
||||||
rcexpr(tr->tr2);
|
rcexpr(tr->tr2);
|
||||||
push();
|
|
||||||
stk = pushargs(tr->tr1);
|
stk = pushargs(tr->tr1);
|
||||||
return stk+NCPW;
|
return stk+wordsize;
|
||||||
}
|
}
|
||||||
rcexpr(tr);
|
rcexpr(tr);
|
||||||
push();
|
return wordsize;
|
||||||
return NCPW;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -56,42 +79,50 @@ lvalexp(struct tnode *tr)
|
||||||
case INCAFT:
|
case INCAFT:
|
||||||
if (tr->tr1->op == STAR) {
|
if (tr->tr1->op == STAR) {
|
||||||
rcexpr(tr->tr1->tr1);
|
rcexpr(tr->tr1->tr1);
|
||||||
printf("\tmov\t%%eax,%%ebx\n");
|
tonativeaddr();
|
||||||
sprintf(memloc,"(,%%ebx,4)");
|
|
||||||
} else { /* NAME, checked in "build" */
|
} else { /* NAME, checked in "build" */
|
||||||
bs = (struct hshtab *) tr->tr1->tr1;
|
bs = (struct hshtab *) tr->tr1->tr1;
|
||||||
if (bs->class == EXTERN)
|
if (bs->class == EXTERN)
|
||||||
sprintf(memloc,"_%s", bs->name);
|
C_lae_dnam(manglename(bs->name, 'b'), 0);
|
||||||
else if (bs->class == AUTO)
|
else if (bs->class == AUTO)
|
||||||
sprintf(memloc,"%d(%%ebp)", bs->offset);
|
C_lal(bs->offset);
|
||||||
else
|
else
|
||||||
goto classerror;
|
goto classerror;
|
||||||
}
|
}
|
||||||
if (tr->op == DECBEF || tr->op == INCBEF) {
|
if (tr->op == DECBEF || tr->op == INCBEF) {
|
||||||
printf("\t%s\t%s\n", tr->op == DECBEF ? "decl" : "incl",
|
C_dup(wordsize); /* ( addr addr -- ) */
|
||||||
memloc);
|
C_loi(wordsize); /* ( addr val -- ) */
|
||||||
printf("\tmov\t%s,%%eax\n", memloc);
|
C_adp((tr->op == DECBEF) ? -1 : 1); /* ( addr newval -- ) */
|
||||||
|
C_exg(wordsize); /* ( newval addr -- ) */
|
||||||
|
C_dup(wordsize*2); /* ( newval addr newval addr -- ) */
|
||||||
|
C_sti(wordsize); /* ( newval addr -- ) */
|
||||||
|
C_asp(wordsize); /* ( newval -- ) */
|
||||||
} else {
|
} else {
|
||||||
printf("\tmov\t%s,%%eax\n", memloc);
|
C_dup(wordsize); /* ( addr addr -- ) */
|
||||||
printf("\t%s\t%s\n", tr->op == DECAFT ? "decl" : "incl",
|
C_loi(wordsize); /* ( addr val -- ) */
|
||||||
memloc);
|
C_exg(wordsize); /* ( val addr -- ) */
|
||||||
|
C_dup(wordsize*2); /* ( val addr val addr -- ) */
|
||||||
|
C_asp(wordsize); /* ( val addr val -- ) */
|
||||||
|
C_adp((tr->op == DECAFT) ? -1 : 1); /* ( val addr newval -- ) */
|
||||||
|
C_exg(wordsize); /* ( val newval addr -- ) */
|
||||||
|
C_sti(wordsize); /* ( val -- ) */
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case ASSIGN:
|
case ASSIGN:
|
||||||
rcexpr(tr->tr2);
|
rcexpr(tr->tr2);
|
||||||
|
C_dup(wordsize);
|
||||||
if (tr->tr1->op == STAR) {
|
if (tr->tr1->op == STAR) {
|
||||||
push();
|
|
||||||
rcexpr(tr->tr1->tr1);
|
rcexpr(tr->tr1->tr1);
|
||||||
pop("ebx");
|
tonativeaddr();
|
||||||
printf("\tmov\t%%ebx,(,%%eax,4)\n");
|
C_sti(wordsize);
|
||||||
} else { /* NAME */
|
} else { /* NAME */
|
||||||
bs = (struct hshtab *) tr->tr1->tr1;
|
bs = (struct hshtab *) tr->tr1->tr1;
|
||||||
if (bs->class == EXTERN)
|
if (bs->class == EXTERN) {
|
||||||
printf("\tmov\t%%eax,_%s\n", bs->name);
|
C_ste_dnam(bs->name, 0);
|
||||||
else if (bs->class == AUTO)
|
} else if (bs->class == AUTO) {
|
||||||
printf("\tmov\t%%eax,%d(%%ebp)\n", bs->offset);
|
C_stl(bs->offset);
|
||||||
else
|
} else
|
||||||
goto classerror;
|
goto classerror;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -138,20 +169,20 @@ rcexpr(struct tnode *tr)
|
||||||
switch (tr->op) {
|
switch (tr->op) {
|
||||||
|
|
||||||
case CON:
|
case CON:
|
||||||
printf("\tmov\t$%d,%%eax\n", tr->value);
|
C_loc(tr->value);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case STRING:
|
case STRING:
|
||||||
printf("\tmov\t$L%d,%%eax\n", tr->value);
|
C_lae_dlb(tr->value, 0);
|
||||||
printf("\tshr\t$2,%%eax\n");
|
fromnativeaddr();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case NAME: /* only rvalue */
|
case NAME: /* only rvalue */
|
||||||
bs = (struct hshtab *) tr->tr1;
|
bs = (struct hshtab *) tr->tr1;
|
||||||
if (bs->class == EXTERN)
|
if (bs->class == EXTERN)
|
||||||
printf("\tmov\t_%s,%%eax\n", bs->name);
|
C_loe_dnam(manglename(bs->name, 'b'), 0);
|
||||||
else if (bs->class == AUTO)
|
else if (bs->class == AUTO)
|
||||||
printf("\tmov\t%d(%%ebp),%%eax\n", bs->offset);
|
C_lol(bs->offset);
|
||||||
else
|
else
|
||||||
goto classerror;
|
goto classerror;
|
||||||
return;
|
return;
|
||||||
|
@ -159,89 +190,73 @@ rcexpr(struct tnode *tr)
|
||||||
case CALL:
|
case CALL:
|
||||||
stk = pushargs(tr->tr2);
|
stk = pushargs(tr->tr2);
|
||||||
rcexpr(tr->tr1);
|
rcexpr(tr->tr1);
|
||||||
printf("\tshl\t$2,%%eax\n");
|
tonativeaddr();
|
||||||
printf("\tcall\t*%%eax\n");
|
C_cai();
|
||||||
if (stk)
|
if (stk)
|
||||||
printf("\tadd\t$%d,%%esp\n",stk);
|
C_asp(stk);
|
||||||
|
C_lfr(wordsize);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case AMPER:
|
case AMPER:
|
||||||
bs = (struct hshtab *) tr->tr1->tr1;
|
bs = (struct hshtab *) tr->tr1->tr1;
|
||||||
if (bs->class == EXTERN) {
|
if (bs->class == EXTERN) {
|
||||||
printf("\tmov\t$_%s,%%eax\n", bs->name);
|
C_lae_dnam(manglename(bs->name, 'b'), 0);
|
||||||
printf("\tshr\t$2,%%eax\n");
|
|
||||||
} else if (bs->class == AUTO) {
|
} else if (bs->class == AUTO) {
|
||||||
printf("\tlea\t%d(%%ebp),%%eax\n", bs->offset);
|
C_lal(bs->offset);
|
||||||
printf("\tshr\t$2,%%eax\n");
|
|
||||||
} else
|
} else
|
||||||
goto classerror;
|
goto classerror;
|
||||||
|
fromnativeaddr();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case STAR: /* only rvalue */
|
case STAR: /* only rvalue */
|
||||||
rcexpr(tr->tr1);
|
rcexpr(tr->tr1);
|
||||||
printf("\tmov\t(,%%eax,4),%%eax\n");
|
tonativeaddr();
|
||||||
|
C_loi(wordsize);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PLUS:
|
case PLUS:
|
||||||
binary(tr);
|
binary(tr);
|
||||||
pop("ebx");
|
C_adi(wordsize);
|
||||||
printf("\tadd\t%%ebx,%%eax\n");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case MINUS:
|
case MINUS:
|
||||||
binary(tr);
|
binary(tr);
|
||||||
printf("\tmov\t%%eax,%%ebx\n");
|
C_sbi(wordsize);
|
||||||
pop("eax");
|
|
||||||
printf("\tsub\t%%ebx,%%eax\n");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case TIMES:
|
case TIMES:
|
||||||
binary(tr);
|
binary(tr);
|
||||||
pop("ebx");
|
C_mli(wordsize);
|
||||||
printf("\tmul\t%%ebx\n");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case DIVIDE:
|
case DIVIDE:
|
||||||
binary(tr);
|
binary(tr);
|
||||||
printf("\tmov\t%%eax,%%ebx\n");
|
C_dvi(wordsize);
|
||||||
pop("eax");
|
|
||||||
printf("\txor\t%%edx,%%edx\n");
|
|
||||||
printf("\tdiv\t%%ebx\n");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case MOD:
|
case MOD:
|
||||||
binary(tr);
|
binary(tr);
|
||||||
printf("\tmov\t%%eax,%%ebx\n");
|
C_rmi(wordsize);
|
||||||
pop("eax");
|
|
||||||
printf("\txor\t%%edx,%%edx\n");
|
|
||||||
printf("\tdiv\t%%ebx\n");
|
|
||||||
printf("\tmov\t%%edx,%%eax\n");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case AND:
|
case AND:
|
||||||
binary(tr);
|
binary(tr);
|
||||||
pop("ebx");
|
C_and(wordsize);
|
||||||
printf("\tand\t%%ebx,%%eax\n");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case OR:
|
case OR:
|
||||||
binary(tr);
|
binary(tr);
|
||||||
pop("ebx");
|
C_ior(wordsize);
|
||||||
printf("\tor\t%%ebx,%%eax\n");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case LSHIFT:
|
case LSHIFT:
|
||||||
binary(tr);
|
binary(tr);
|
||||||
printf("\tmov\t%%eax,%%ecx\n");
|
C_sli(wordsize);
|
||||||
pop("eax");
|
|
||||||
printf("\tshl\t%%cl,%%eax\n");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case RSHIFT:
|
case RSHIFT:
|
||||||
binary(tr);
|
binary(tr);
|
||||||
printf("\tmov\t%%eax,%%ecx\n");
|
C_sri(wordsize);
|
||||||
pop("eax");
|
|
||||||
printf("\tshr\t%%cl,%%eax\n");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case EQUAL:
|
case EQUAL:
|
||||||
|
@ -251,50 +266,46 @@ rcexpr(struct tnode *tr)
|
||||||
case GREAT:
|
case GREAT:
|
||||||
case GREATEQ:
|
case GREATEQ:
|
||||||
binary(tr);
|
binary(tr);
|
||||||
pop("ebx");
|
C_cmi(wordsize);
|
||||||
printf("\tcmp\t%%eax,%%ebx\n");
|
|
||||||
switch (tr->op) {
|
switch (tr->op) {
|
||||||
case EQUAL:
|
case EQUAL:
|
||||||
printf("\tsete\t%%al\n");
|
C_teq();
|
||||||
break;
|
break;
|
||||||
case NEQUAL:
|
case NEQUAL:
|
||||||
printf("\tsetne\t%%al\n");
|
C_tne();
|
||||||
break;
|
break;
|
||||||
case LESS:
|
case LESS:
|
||||||
printf("\tsetl\t%%al\n");
|
C_tlt();
|
||||||
break;
|
break;
|
||||||
case LESSEQ:
|
case LESSEQ:
|
||||||
printf("\tsetle\t%%al\n");
|
C_tle();
|
||||||
break;
|
break;
|
||||||
case GREAT:
|
case GREAT:
|
||||||
printf("\tsetg\t%%al\n");
|
C_tgt();
|
||||||
break;
|
break;
|
||||||
case GREATEQ:
|
case GREATEQ:
|
||||||
printf("\tsetge\t%%al\n");
|
C_tge();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("\tmovzb\t%%al,%%eax\n");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case EXCLA:
|
case EXCLA:
|
||||||
rcexpr(tr->tr1);
|
rcexpr(tr->tr1);
|
||||||
printf("\ttest\t%%eax,%%eax\n");
|
C_tne();
|
||||||
printf("\tsete\t%%al\n");
|
|
||||||
printf("\tmovzb\t%%al,%%eax\n");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case NEG:
|
case NEG:
|
||||||
rcexpr(tr->tr1);
|
rcexpr(tr->tr1);
|
||||||
printf("\tneg\t%%eax\n");
|
C_ngi(wordsize);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case QUEST:
|
case QUEST:
|
||||||
cbranch(tr->tr1, o1=isn++, 0);
|
cbranch(tr->tr1, o1=isn++);
|
||||||
rcexpr(tr->tr2->tr1);
|
rcexpr(tr->tr2->tr1);
|
||||||
jump(o2 = isn++);
|
jump(o2 = isn++);
|
||||||
label(o1);
|
fnlabel(o1);
|
||||||
rcexpr(tr->tr2->tr2);
|
rcexpr(tr->tr2->tr2);
|
||||||
label(o2);
|
fnlabel(o2);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -5,10 +5,15 @@ cprogram {
|
||||||
"./*.c",
|
"./*.c",
|
||||||
},
|
},
|
||||||
deps = {
|
deps = {
|
||||||
|
"./*.h",
|
||||||
"modules+headers",
|
"modules+headers",
|
||||||
"modules/src/em_code+lib_k",
|
"modules/src/alloc+lib",
|
||||||
|
"modules/src/em_code+lib_e",
|
||||||
"modules/src/em_data+lib",
|
"modules/src/em_data+lib",
|
||||||
"modules/src/em_mes+lib",
|
"modules/src/em_mes+lib",
|
||||||
|
"modules/src/print+lib",
|
||||||
|
"modules/src/string+lib",
|
||||||
|
"modules/src/system+lib",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue