#include <limits.h>
#include <assert.h>
-#define MAX_REG 15
-
-/* Register Usage
-
-*/
-
-Type BoolType = {
- .form = FORM_BOOL,
- .size = sizeof(bool)
+static char* RegNames[] = {
+ "%noreg", // invalid register
+ "%rdi", // 1st argument
+ "%rsi", // 2nd argument
+ "%rdx", // 3rd argument
+ "%rcx", // 4th argument
+ "%r8", // 5th argument
+ "%r9", // 6th argument
+ "%rbx", // temp register
+ "%r10", // temp register
+ "%r11", // temp register
+ "%r12", // callee saved register
+ "%r13", // callee saved register
+ "%r14", // callee saved register
+ "%r15", // callee saved register
+// "%rax", // return value
};
-Type IntType = {
- .form = FORM_INT,
- .size = sizeof(long)
-};
+#define MAX_REG (int)(sizeof(RegNames)/sizeof(RegNames[0]))
-Type RealType = {
- .form = FORM_REAL,
- .size = sizeof(double)
-};
-
-Type StringType = {
- .form = FORM_STRING,
- .size = -1
-};
+static char* regname(int reg)
+{
+ return RegNames[reg];
+}
-void codegen_setint(Item* item, Type* type, long long val)
+static char* curr_regname(Parser* p)
{
- item->mode = ITEM_CONST;
- item->type = type;
- item->reg = NOREG;
- item->imm.i = val;
+ return regname(p->curr_reg);
}
-void codegen_setreal(Item* item, double val)
+static void next_reg(Parser* p)
{
- item->mode = ITEM_CONST;
- item->type = &RealType;
- item->reg = NOREG;
- item->imm.f = val;
+ if (p->curr_reg < MAX_REG)
+ {
+ p->curr_reg++;
+ }
+ else
+ {
+ assert(!"register stack overflow");
+ }
}
-void codegen_setstr(Item* item, char* val)
+static void put_immop(char* op, int reg, long long imm)
{
- item->mode = ITEM_CONST;
- item->type = &StringType;
- item->reg = NOREG;
- item->imm.s = val;
+ printf(" %s $%lld, %s\n", op, imm, regname(reg));
}
-static int items_const(Item* a, Item* b)
+static void put_regop(char* op, int rega, int regb)
{
- return ((a->mode == ITEM_CONST) && (b->mode == ITEM_CONST));
+ printf(" %s %s, %s\n", op, regname(regb), regname(rega));
}
-static void const_binop(int op, Item* a, Item* b)
+static void imm_binop(Parser* p, int op, Item* a, Item* b)
{
+ (void)p;
if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
{
switch (op)
{
- case '+': a->imm.i = a->imm.i + b->imm.i; break;
- case '-': a->imm.i = a->imm.i - b->imm.i; break;
- case '*': a->imm.i = a->imm.i * b->imm.i; break;
- case '/': a->imm.i = a->imm.i / b->imm.i; break;
- case '%': a->imm.i = a->imm.i % b->imm.i; break;
- case AND: a->imm.i = a->imm.i && b->imm.i; break;
- case OR: a->imm.i = a->imm.i || b->imm.i; break;
-
- case EQ:
- a->imm.i = a->imm.i == b->imm.i;
- a->type = &BoolType;
- break;
-
- case NEQ:
- a->imm.i = a->imm.i != b->imm.i;
- a->type = &BoolType;
+ case '+':
+ put_immop("addq", a->reg, b->imm.i);
break;
- case '<':
- a->imm.i = a->imm.i < b->imm.i;
- a->type = &BoolType;
+ case '-':
+ put_immop("subq", a->reg, b->imm.i);
break;
- case LTEQ:
- a->imm.i = a->imm.i <= b->imm.i;
- a->type = &BoolType;
+ case '*':
+ put_immop("imulq", a->reg, b->imm.i);
break;
- case '>':
- a->imm.i = a->imm.i > b->imm.i;
- a->type = &BoolType;
- break;
-
- case GTEQ:
- a->imm.i = a->imm.i >= b->imm.i;
- a->type = &BoolType;
- break;
-
-// case IS: break;
-
+// case '/':
+// case '%':
+// case AND:
+// case OR:
+
+// case EQ:
+// cmpq %rax, %rdx
+// setl %al
+// movzbl %al, %eax
+// case NEQ:
+// case '<':
+// case LTEQ:
+// case '>':
+// case GTEQ:
default:
- assert(!"not a valid op");
- break;
+ assert(!"unimplemented immediate op");
}
}
- else if (a->type->form == FORM_REAL)
+ else
+ {
+ assert(!"not implemented");
+ }
+}
+
+static void reg_binop(Parser* p, int op, Item* a, Item* b)
+{
+ if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
{
switch (op)
{
- case '+': a->imm.f = a->imm.f + b->imm.f; break;
- case '-': a->imm.f = a->imm.f - b->imm.f; break;
- case '*': a->imm.f = a->imm.f * b->imm.f; break;
- case '/': a->imm.f = a->imm.f / b->imm.f; break;
-
- case EQ:
- a->imm.f = a->imm.f == b->imm.f;
- a->type = &BoolType;
- break;
-
- case NEQ:
- a->imm.f = a->imm.f != b->imm.f;
- a->type = &BoolType;
+ case '+':
+ put_regop("addq", a->reg, b->reg);
break;
- case '<':
- a->imm.f = a->imm.f < b->imm.f;
- a->type = &BoolType;
+ case '-':
+ put_regop("subq", a->reg, b->reg);
break;
- case LTEQ:
- a->imm.f = a->imm.f <= b->imm.f;
- a->type = &BoolType;
- break;
-
- case '>':
- a->imm.f = a->imm.f > b->imm.f;
- a->type = &BoolType;
- break;
-
- case GTEQ:
- a->imm.f = a->imm.f >= b->imm.f;
- a->type = &BoolType;
+ case '*':
+ put_regop("imulq", a->reg, b->reg);
break;
+// case '/':
+// case '%':
+// case AND:
+// case OR:
+
+// case EQ:
+// case NEQ:
+// case '<':
+// case LTEQ:
+// case '>':
+// case GTEQ:
default:
- assert(!"not a valid op");
- break;
+ assert(!"unimplemented immediate op");
}
- }
- else
- {
- assert(!"not a valid form");
+ p->curr_reg--;
}
}
-static void const_unop(Parser* p, int op, Item* a)
+Type BoolType = {
+ .form = FORM_BOOL,
+ .size = sizeof(bool)
+};
+
+Type IntType = {
+ .form = FORM_INT,
+ .size = sizeof(long)
+};
+
+Type RealType = {
+ .form = FORM_REAL,
+ .size = sizeof(double)
+};
+
+Type StringType = {
+ .form = FORM_STRING,
+ .size = -1
+};
+
+void codegen_setint(Item* item, Type* type, long long val)
{
- (void)p;
- if (a->type->form == FORM_INT)
- {
- switch (op)
- {
- case '+': a->imm.i = +a->imm.i; break;
- case '-': a->imm.i = -a->imm.i; break;
- default: assert(!"not a valid op"); break;
- }
- }
- else if (a->type->form == FORM_REAL)
- {
- switch (op)
- {
- case '+': a->imm.f = +a->imm.f; break;
- case '-': a->imm.f = -a->imm.f; break;
- default: assert(!"not a valid op"); break;
- }
- }
- else if (a->type->form == FORM_BOOL)
- {
- switch (op)
- {
- case NOT: a->imm.i = !a->imm.i; break;
- default: assert(!"not a valid op"); break;
- }
- }
- else
- {
- assert(!"not a valid form");
- }
+ item->mode = ITEM_CONST;
+ item->type = type;
+ item->reg = 0;
+ item->imm.i = val;
}
-static char* regname(int reg)
+void codegen_setreal(Item* item, double val)
{
- static char* names[] = {
- "%noreg", // invalid register
- "%rdi", // 1st argument
- "%rsi", // 2nd argument
- "%rdx", // 3rd argument
- "%rcx", // 4th argument
- "%r8", // 5th argument
- "%r9", // 6th argument
- "%rbx", // temp register
- "%r10", // temp register
- "%r11", // temp register
- "%r12", // callee saved register
- "%r13", // callee saved register
- "%r14", // callee saved register
- "%r15", // callee saved register
- "%rax", // return value
- };
- return names[reg];
+ item->mode = ITEM_CONST;
+ item->type = &RealType;
+ item->reg = 0;
+ item->imm.f = val;
}
-static char* curr_regname(Parser* p)
+void codegen_setstr(Item* item, char* val)
{
- return regname(p->curr_reg);
+ item->mode = ITEM_CONST;
+ item->type = &StringType;
+ item->reg = 0;
+ item->imm.s = val;
}
-static void next_reg(Parser* p)
+static int items_const(Item* a, Item* b)
{
- if (p->curr_reg < MAX_REG)
- {
- p->curr_reg++;
- }
- else
- {
- assert(!"register stack overflow");
- }
+ return ((a->mode == ITEM_CONST) && (b->mode == ITEM_CONST));
}
static void load_var(Parser* p, Item* item)
{
case ITEM_CONST:
/* TODO: range check the constant */
-// // emit instruction
-// item->reg = p->curr_reg;
-
- printf(" movq %s, $%lld\n", curr_regname(p), item->imm.i);
+ put_immop("movq", p->curr_reg, item->imm.i);
item->reg = p->curr_reg;
next_reg(p);
break;
case ITEM_MVAR:
// puts("MVAR");
// printf("movq %s, $%lld\n", curr_regname(p), item->imm.i);
-
// item_dump(item);
-
printf(" movq %s_%s(%%rip), %s\n",
p->name,
item->imm.s,
curr_regname(p)
);
-// b->imm.i, p->name, a->imm.s);
-
item->reg = p->curr_reg;
next_reg(p);
break;
}
}
-static char* ImmOps[] = {
- ['+'] = "addq",
-};
-
-static void imm_binop(Parser* p, int op, Item* a, Item* b)
-{
- if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
- {
- char* opstring = ImmOps[op];
- if (a->mode == ITEM_CONST)
- {
-// printf(" %s $%lld, %s\n",
-// opstring, regname(b->reg), a->imm.i, regname(b->reg));
- printf(" %s $%lld, %s\n",
- opstring, a->imm.i, regname(b->reg));
- a->reg = b->reg;
- }
- else
- {
- printf(" %s $%lld, %s\n",
- opstring, b->imm.i, regname(a->reg));
- }
- }
- else
- {
- assert(!"not implemented");
- }
-}
-
-static void imm_regop(Parser* p, int op, Item* a, Item* b)
-{
- if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
- {
- printf(" addq %s, %s, %s\n",
- regname(a->reg), regname(b->reg), regname(b->reg));
- }
-}
-
void codegen_binop(Parser* p, int op, Item* a, Item* b)
{
if (items_const(a, b))
imm_binop(p, op, a, b);
p->curr_reg--;
}
- else if (a->mode == ITEM_CONST)
- {
- load_var(p, b);
- imm_binop(p, op, a, b);
- p->curr_reg--;
- }
else
{
load_var(p, a);
load_var(p, b);
- item_dump(a);
- item_dump(b);
-
- imm_regop(p, op, a, b);
-
- // emit instruction
- // p->topreg--;
- // a->reg = p->topreg-1;
+ reg_binop(p, op, a, b);
+ p->curr_reg--;
+ a->reg = p->curr_reg;
}
}
-// PROCEDURE Switch*(VAR x: Item);
-// BEGIN Put1(Mov, RH, 0, -60); Put2(Ldw, RH, RH, 0);
-// x.mode := Reg;
-// x.type := intType;
-// x.r := RH;
-// INC(RH)
-// END Switch;
-
-
void codegen_store(Parser* p, Item* a, Item* b)
{
- if (a->mode == ITEM_MVAR && b->reg == NOREG)
+ if (a->mode == ITEM_MVAR && b->reg == 0)
{
printf(" movq $%lld, %s_%s(%%rip)\n",
b->imm.i, p->name, a->imm.s);
--- /dev/null
+#include "cerise.h"
+
+void const_binop(int op, Item* a, Item* b)
+{
+ if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
+ {
+ switch (op)
+ {
+ case '+': a->imm.i = a->imm.i + b->imm.i; break;
+ case '-': a->imm.i = a->imm.i - b->imm.i; break;
+ case '*': a->imm.i = a->imm.i * b->imm.i; break;
+ case '/': a->imm.i = a->imm.i / b->imm.i; break;
+ case '%': a->imm.i = a->imm.i % b->imm.i; break;
+ case AND: a->imm.i = a->imm.i && b->imm.i; break;
+ case OR: a->imm.i = a->imm.i || b->imm.i; break;
+
+ case EQ:
+ a->imm.i = a->imm.i == b->imm.i;
+ a->type = &BoolType;
+ break;
+
+ case NEQ:
+ a->imm.i = a->imm.i != b->imm.i;
+ a->type = &BoolType;
+ break;
+
+ case '<':
+ a->imm.i = a->imm.i < b->imm.i;
+ a->type = &BoolType;
+ break;
+
+ case LTEQ:
+ a->imm.i = a->imm.i <= b->imm.i;
+ a->type = &BoolType;
+ break;
+
+ case '>':
+ a->imm.i = a->imm.i > b->imm.i;
+ a->type = &BoolType;
+ break;
+
+ case GTEQ:
+ a->imm.i = a->imm.i >= b->imm.i;
+ a->type = &BoolType;
+ break;
+
+// case IS: break;
+
+ default:
+ assert(!"not a valid op");
+ break;
+ }
+ }
+ else if (a->type->form == FORM_REAL)
+ {
+ switch (op)
+ {
+ case '+': a->imm.f = a->imm.f + b->imm.f; break;
+ case '-': a->imm.f = a->imm.f - b->imm.f; break;
+ case '*': a->imm.f = a->imm.f * b->imm.f; break;
+ case '/': a->imm.f = a->imm.f / b->imm.f; break;
+
+ case EQ:
+ a->imm.f = a->imm.f == b->imm.f;
+ a->type = &BoolType;
+ break;
+
+ case NEQ:
+ a->imm.f = a->imm.f != b->imm.f;
+ a->type = &BoolType;
+ break;
+
+ case '<':
+ a->imm.f = a->imm.f < b->imm.f;
+ a->type = &BoolType;
+ break;
+
+ case LTEQ:
+ a->imm.f = a->imm.f <= b->imm.f;
+ a->type = &BoolType;
+ break;
+
+ case '>':
+ a->imm.f = a->imm.f > b->imm.f;
+ a->type = &BoolType;
+ break;
+
+ case GTEQ:
+ a->imm.f = a->imm.f >= b->imm.f;
+ a->type = &BoolType;
+ break;
+
+ default:
+ assert(!"not a valid op");
+ break;
+ }
+ }
+ else
+ {
+ assert(!"not a valid form");
+ }
+}
+
+void const_unop(Parser* p, int op, Item* a)
+{
+ (void)p;
+ if (a->type->form == FORM_INT)
+ {
+ switch (op)
+ {
+ case '+': a->imm.i = +a->imm.i; break;
+ case '-': a->imm.i = -a->imm.i; break;
+ default: assert(!"not a valid op"); break;
+ }
+ }
+ else if (a->type->form == FORM_REAL)
+ {
+ switch (op)
+ {
+ case '+': a->imm.f = +a->imm.f; break;
+ case '-': a->imm.f = -a->imm.f; break;
+ default: assert(!"not a valid op"); break;
+ }
+ }
+ else if (a->type->form == FORM_BOOL)
+ {
+ switch (op)
+ {
+ case NOT: a->imm.i = !a->imm.i; break;
+ default: assert(!"not a valid op"); break;
+ }
+ }
+ else
+ {
+ assert(!"not a valid form");
+ }
+}