#include #include "bind.h" #include "tree.h" #include "qc.h" /* stringf.c で定義 */ char *Stringf(char *fmt, ...); /* 文字列を生成して返す (malloc 使用) */ /* bind.h でマクロ定義 */ /* isLocal(obj) */ /* isGlobal(obj) */ /* isScalar(obj) */ /* isArray(obj) */ /* asm.c で定義 */ char *newLabel(char prefix); /* ラベルの生成 */ void L(char *label); /* ラベルをを追加する */ void I(char *op, char *arg1, char *arg2); /* 命令を追加する */ void C(char *comment); /* 直前の命令にコメントをつける */ char *getStrLabel(char *str); /* 文字列定数のラベルを得る */ /* プロトタイプ宣言 */ void codeExp(Node exp); /* 式のコード生成 */ void codeAsgn(Node dst, Node src); /* 代入式のコード生成 */ void codeLogOp(char *code, Node l, Node r); /* 論理演算のコード生成 */ void codeRelOp(char *code, Node l, Node r); /* 比較演算のコード生成 */ void codeBinOp(char *code, Node l, Node r); /* 四則演算のコード生成 */ int codeFunArg(Node exps); /* 関数引数のコード生成 */ /********************************/ /* 式のコード生成 */ /********************************/ /* 式のコード生成 */ void codeExp(Node t) { Node u; Obj o; char *op, *loc; int argc; switch (t->type) { case '=': codeAsgn(t->left, t->right); return; case BRBR: codeLogOp("jnz", t->left, t->right); return; case AMAM: codeLogOp("jz", t->left, t->right); return; case EQEQ: codeRelOp("jne", t->left, t->right); return; case EXEQ: codeRelOp("je" , t->left, t->right); return; case '<': codeRelOp("jge", t->left, t->right); return; case LTEQ: codeRelOp("jg", t->left, t->right); return; case '>': codeRelOp("jle", t->left, t->right); return; case GTEQ: codeRelOp("jl", t->left, t->right); return; case '+': codeBinOp("add", t->left, t->right); return; case '-': codeBinOp("sub", t->left, t->right); return; case '*': codeBinOp("imul", t->left, t->right); return; case '/': codeBinOp("mdiv", t->left, t->right); return; case '!': codeExp(t->left); I("or", "%eax", "%eax"); I("jz", loc = newLabel('E'), NUL); I("mov", "%eax", "1"); L(loc); I("dec", "%eax", NUL); return; case UMINUS: codeExp(t->left); I("neg", "%eax", NUL); return; case Func: o = (Obj)t->left->right; argc = codeFunArg(t->right); switch (o->type) { case objFUNC: I("call", o->name, NUL); break; /* 以下裏仕様 */ case objGVAR: I("call", Stringf("[%s]", o->name), NUL); break; case objLVAR: I("call", Stringf("[%%ebp%+d]", o->offset * 4), NUL); } I("add", "%esp", Stringf("%d", argc*4)); return; case Arry: o = (Obj)t->left->right; codeExp(t->right); if (isArray(o)) { if (isGlobal(o)) I("mov", "%eax", Stringf("[%%eax*4+%s]", o->name)); else I("mov", "%eax", Stringf("[%%ebp+%%eax*4%+d]", o->offset * 4)); } else /* isScalar(o) */ { /* 裏仕様 */ if (isGlobal(o)) I("mov", "%ebx", o->name); else I("mov", "%ebx", Stringf("[%%ebp%+d]", o->offset * 4)); C(Stringf("base of %s", o->name)); I("mov", "%eax", "[%ebx+%eax*4]"); } C(Stringf("%s[...]", o->name)); return; case Sclr: o = (Obj)t->left->right; if (isGlobal(o)) loc = o->name; else /* isLocal(o) */ loc = Stringf("[%%ebp%+d]", o->offset * 4); if (isScalar(o)) op = "mov"; else /* isArray(o) */ op = "lea"; /* 裏仕様 */ I(op, "%eax", loc); C(o->name); return; case NUM: I("mov", "%eax", Stringf("%d", (long int)t->left)); return; case STR: I("lea", "%eax", getStrLabel((char *)t->left)); C((char *)t->left); } } /* 代入式のコード生成 */ void codeAsgn(Node dst, Node src) { Obj o = (Obj)dst->left->right; char *op, *loc; if (isGlobal(o)) loc = o->name; else /* isLocal(o) */ loc = Stringf("[%%ebp%+d]", o->offset * 4); switch (dst->type) { case Sclr: codeExp(src); I("mov", loc, "%eax"); C(o->name); break; case Arry: if (isArray(o)) op = "lea"; else /* isScalar(o) */ op = "mov"; /* 裏仕様 */ codeExp(dst->right); I("push", "%eax", NUL); codeExp(src); I(op, "%ebx", loc); C(Stringf("base of %s", o->name)); I("pop", "%edx", NUL); I("mov", "[%ebx+%edx*4]", "%eax"); C(Stringf("%s[...]", o->name)); } } /* 論理演算のコード生成 */ void codeLogOp(char *op, Node left, Node right) { char *l = newLabel('E'); codeExp(left); I("or", "%eax", "%eax"); I(op, l, NUL); codeExp(right); L(l); } /* 比較演算のコード生成 */ void codeRelOp(char *op, Node left, Node right) { char *loc = newLabel('E'); codeExp(right); I("push", "%eax", NUL); codeExp(left); I("pop", "%ebx", NUL); I("cmp", "%eax", "%ebx"); I("mov", "%eax", "0"); I(op, loc, NUL); I("dec", "%eax", NUL); L(loc); } /* 四則演算のコード生成 */ void codeBinOp(char *op, Node left, Node right) { codeExp(right); I("push", "%eax", NUL); codeExp(left); I("pop", "%ebx", NUL); I(op, "%eax", "%ebx"); } /* 関数引数のコード生成 */ int codeFunArg(Node t) { int argc; if (t==NUL) return 0; argc = codeFunArg(t->right); codeExp(t->left); I("push", "%eax", NUL); return argc+1; }