ITEM_CONST, ITEM_VAR
} mode;
Type* type;
+ int reg;
ImmValue imm;
} Item;
/* Code Generation
*****************************************************************************/
+/* opcodes */
+enum AsmOp {
+ /* Assembly Operations */
+ OP_LOAD = 0, OP_STORE, OP_MOVE,
+ OP_CMP, OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD,
+ OP_EQ, OP_NEQ, OP_LT, OP_GT, OP_LTEQ, OP_GTEQ,
+
+ OP_CALL, OP_RET,
+};
+
+enum Regs {
+ IMM = 0,
+ RAX, RBX, RCX, RDX, RBP, RSP, RSI, RDI,
+ R8, R9, R10, R11, R12, R13, R14, R15,
+};
+
extern Type BoolType, IntType, RealType, StringType;
void codegen_setint(Item* item, Type* type, long long val);
void codegen_setreal(Item* item, double val);
void codegen_setstr(Item* item, char* val);
-void codegen_unop(int op, Item* a);
-void codegen_binop(int op, Item* a, Item* b);
+void codegen_main(char* modname);
void codegen_startproc(char* name, long long localsz);
void codegen_endproc(void);
+void codegen_unop(int op, Item* a);
+void codegen_binop(int op, Item* a, Item* b);
void codegen_store(Item* a, Item* b);
void codegen_setint(Item* item, Type* type, long long val)
{
- item->mode = ITEM_CONST;
- item->type = type;
+ item->mode = ITEM_CONST;
+ item->type = type;
+ item->reg = IMM;
item->imm.i = val;
}
void codegen_setreal(Item* item, double val)
{
- item->mode = ITEM_CONST;
- item->type = &RealType;
+ item->mode = ITEM_CONST;
+ item->type = &RealType;
+ item->reg = IMM;
item->imm.f = val;
}
void codegen_setstr(Item* item, char* val)
{
- item->mode = ITEM_CONST;
- item->type = &StringType;
+ item->mode = ITEM_CONST;
+ item->type = &StringType;
+ item->reg = IMM;
item->imm.s = val;
}
}
}
+void codegen_main(char* modname)
+{
+ codegen_startproc("main", 0);
+// op_l (OP_CALL, modname);
+ printf(" call %s\n", modname);
+ codegen_endproc();
+}
+
+void codegen_startproc(char* name, long long localsz)
+{
+ printf(" .text\n");
+ printf(" .globl %s\n", name);
+ printf("%s:\n", name);
+
+// op_r (OP_PUSH, RBP);
+ printf(" pushq %%rbp\n");
+ if (localsz > 0)
+ {
+// op_rr (OP_MOVE, RSP, RBP);
+ printf(" movq %%rsp, %%rbp\n");
+// op_ri (OP_SUB, localsz, RSP);
+ printf(" sub $%lld, %%rsp\n\n", localsz);
+ }
+ else
+ {
+// op_rr (OP_MOVE, RSP, RBP);
+ printf(" movq %%rsp, %%rbp\n\n");
+ }
+}
+
+void codegen_endproc(void)
+{
+// op_r (OP_POP, RBP);
+// op_0 (OP_RET);
+ printf("\n pop %%rbp\n");
+ printf(" ret\n\n");
+}
+
void codegen_unop(int op, Item* a)
{
if (a->mode == ITEM_CONST)
}
}
-void codegen_startproc(char* name, long long localsz)
-{
- printf(" .text\n");
- printf(" .globl %s\n", name);
- printf("%s:\n", name);
- printf(" pushq %%rbp\n");
- printf(" movq %%rsp, %%rbp\n");
- if (localsz > 0)
- {
- printf(" sub $%lld, %%rsp\n", localsz);
- }
-}
+/*
+ PROCEDURE GetSB;
+ BEGIN
+ IF curSB = 1 THEN
+ Put2(Ldw, SB, 0, pc-fixorgD);
+ fixorgD := pc-1;
+ curSB := 0
+ END
+ END GetSB;
-void codegen_endproc(void)
-{
- printf(" pop %%rbp\n");
- printf(" ret\n");
-}
+ PROCEDURE load(VAR x: Item);
+ BEGIN
+ IF x.mode # Reg THEN
+ IF x.mode = Var THEN
+ IF x.r > 0 THEN (*local*)
+ Put2(Ldw, RH, SP, x.a)
+ ELSE
+ GetSB;
+ Put2(Ldw, RH, SB, x.a)
+ END ;
+ x.r := RH;
+ incR
+ ELSIF x.mode = Par THEN
+ Put2(Ldw, RH, x.r, x.a);
+ Put2(Ldw, RH, RH, 0);
+ x.r := RH;
+ incR
+ ELSIF x.mode = Const THEN
+ IF (x.a >= 10000H) OR (x.a < -10000H) THEN
+ OSS.Mark("const too large")
+ END ;
+ Put1(Mov, RH, 0, x.a);
+ x.r := RH;
+ incR
+ ELSIF x.mode = RegI THEN
+ Put2(Ldw, x.r, x.r, x.a)
+ ELSIF x.mode = Cond THEN
+ Put3(2, negated(x.r), 2);
+ FixLink(x.b);
+ Put1(Mov, RH, 0, 1);
+ Put3(2, 7, 1);
+ FixLink(x.a);
+ Put1(Mov, RH, 0, 0);
+ x.r := RH;
+ incR
+ END ;
+ x.mode := Reg
+ END
+ END load;
+
+ PROCEDURE Store*(VAR x, y: Item); (* x := y *)
+ BEGIN
+ load(y);
+ IF x.mode = Var THEN
+ IF x.r > 0 THEN (*local*)
+ Put2(Stw, y.r, SP, x.a)
+ ELSE
+ GetSB;
+ Put2(Stw, y.r, SB, x.a)
+ END
+ ELSIF x.mode = Par THEN
+ Put2(Ldw, RH, SP, x.a);
+ Put2(Stw, y.r, RH, x.b)
+ ELSIF x.mode = RegI THEN
+ Put2(Stw, y.r, x.r, x.a);
+ DEC(RH)
+ ELSE
+ OSS.Mark("illegal assignment")
+ END ;
+ DEC(RH)
+ END Store;
+
+*/
void codegen_store(Item* a, Item* b)
{
+ if (a->mode == ITEM_VAR && b->reg == IMM)
+ {
+ printf(" movq $%lld, %s(%%rip)\n", b->imm.i, a->imm.s);
+ }
(void)a, (void)b;
}
+
+
+/*
+
+add %r10,%r11 // add r10 and r11, put result in r11
+add $5,%r10 // add 5 to r10, put result in r10
+call label // call a subroutine / function / procedure
+cmp %r10,%r11 // compare register r10 with register r11. The comparison sets flags in the processor status register which affect conditional jumps.
+cmp $99,%r11 // compare the number 99 with register r11. The comparison sets flags in the processor status register which affect conditional jumps.
+div %r10 // divide rax by the given register (r10), places quotient into rax and remainder into rdx (rdx must be zero before this instruction)
+inc %r10 // increment r10
+jmp label // jump to label
+je label // jump to label if equal
+jne label // jump to label if not equal
+jl label // jump to label if less
+jg label // jump to label if greater
+mov %r10,%r11 // move data from r10 to r11
+mov $99,%r10 // put the immediate value 99 into r10
+mov %r10,(%r11) // move data from r10 to address pointed to by r11
+mov (%r10),%r11 // move data from address pointed to by r10 to r10
+mul %r10 // multiplies rax by r10, places result in rax and overflow in rdx
+push %r10 // push r10 onto the stack
+pop %r10 // pop r10 off the stack
+ret // routine from subroutine (counterpart to call)
+syscall // invoke a syscall (in 32-bit mode, use "int $0x80" instead)
+
+*/
+
+//static void emit_op0(AsmOp op)
+//{
+//}
+//
+//static void emit_opreg1(AsmOp op, long long reg)
+//{
+//}
+//
+//static void emit_opimmi(AsmOp op, long long imm)
+//{
+//}
+//
+//static void emit_opimmf(AsmOp op, double imm)
+//{
+//}
+//
+//static void emit_opreg2(AsmOp op, int rega, int regb)
+//{
+//}
+
+
{
check_ints(p, a, b);
}
+ else if (a->type->form == FORM_BOOL)
+ {
+ check_bools(p, a, b);
+ }
else
{
error(p, "type mismatch");
RULE(var_decl)
{
(void)item;
- int nsyms = 0;
- Symbol* sym = NULL;
- Symbol* type = NULL;
- char* name = NULL;
- bool export = false;
-
while (1)
{
+ int nsyms = 0;
+ Symbol* sym = NULL;
+ Symbol* type = NULL;
+ char* name = NULL;
+ bool export = false;
+
+ while (1)
+ {
+ name = expect_text(p, IDENT);
+ export = accept(p, '*');
+ sym = symbol_new(p, name, SYM_VAR, export);
+ nsyms++;
+
+ if (!accept(p, ','))
+ {
+ break;
+ }
+ }
+
+ expect(p, ':');
name = expect_text(p, IDENT);
- export = accept(p, '*');
- sym = symbol_new(p, name, SYM_VAR, export);
- nsyms++;
+ type = symbol_get(p, SYM_TYPE, name);
+
+ /* apply the type to the newly created symbols */
+ for (int i = 0; i < nsyms; i++)
+ {
+ sym->type = type->type;
+ sym = sym->next;
+ }
if (!accept(p, ','))
{
break;
}
}
-
- expect(p, ':');
- name = expect_text(p, IDENT);
- type = symbol_get(p, SYM_TYPE, name);
-
- /* apply the type to the newly created symbols */
- for (int i = 0; i < nsyms; i++)
- {
- sym->type = type->type;
- sym = sym->next;
- }
}
RULE(type_decl)
RULE(statement_seq)
{
- if (matches(p, IDENT))
+ while (1)
{
- Item right = { 0 };
- char* text = expect_text(p, IDENT);
- if (accept(p, '='))
+ if (matches(p, IDENT))
+ {
+ Item right = { 0 };
+ char* text = expect_text(p, IDENT);
+ if (accept(p, '='))
+ {
+ Symbol* sym = symbol_get(p, SYM_VAR, text);
+ init_item(item, sym);
+ item->imm.s = sym->name;
+
+ expression(p, &right);
+ check_types(p, item, &right);
+ codegen_store(item, &right);
+ }
+ else
+ {
+ /* TODO: add function calls and other complex stuff */
+ error(p, "expected assignment");
+ }
+ }
+ else if (matches(p, IF))
{
- Symbol* sym = symbol_get(p, SYM_VAR, text);
- init_item(item, sym);
- expression(p, &right);
- check_types(p, item, &right);
- codegen_store(item, &right);
}
else
{
- /* TODO: add function calls and other complex stuff */
- error(p, "expected assignment");
+ error(p, "expected a statement");
+ }
+ expect(p, ';');
+ if (matches_oneof(p, (int[]){END, 0}))
+ {
+ break;
}
}
- else if (matches(p, IF))
- {
- }
- else
- {
- error(p, "expected a statement");
- }
- expect(p, ';');
}
RULE(declaration_seq)
},
&(Item){0}
);
-
- printf(" .text\n");
- printf(" .globl main\n");
- printf("main:\n");
- printf(" pushq %%rbp\n");
- printf(" movq %%rsp, %%rbp\n");
- printf(" call Module\n");
- printf(" pop %%rbp\n");
- printf(" ret\n");
+ codegen_main("Module");
}
/* Grammar Unit Tests