#pragma once #include // IR uses an unlimited number of registers. This will later be fixed by a regalloc. enum instype { INS_ADD, // r0 = r1 + r2 INS_SUB, // r0 = r1 - r2 INS_MUL, // r0 = r1 * r2 INS_DIV, // r0 = r1 / r2 INS_MOD, // r0 = r1 % r2 INS_NEG, // r0 = -r1 INS_NOT, // r0 = !r1 INS_TEST, // r1 & r2 (flags) INS_PUSH, // push r1 INS_POP, // r0 = pop INS_CMP, // r1 - r2 (flags) INS_LBL, // label name INS_JMP, // jmp name INS_JCC, // if condcode, jmp name INS_CALL, // call name INS_RET, // return INS_RETV, // return r1 INS_MOV, // r0 = r1 }; enum condcode { CCZ, CCNZ, CCL, CCG, CCLE, CCGE }; enum reftype { REF_REG, // reg REF_MEM, // [reg + offset + (rel_heap ? heap_base : 0)] REF_IMM, // imm }; struct ref { enum reftype type; int reg; // if -1 in a REF_MEM, unused int offset; bool rel_heap; // whether the heap base address should be added to the offset int imm; }; struct irins { enum instype type; struct ref r0, r1, r2; char *name; enum condcode condcode; }; struct ir { int cap, len; struct irins **inss; int globspace; }; struct ir* ir_make(void); void ir_delete(struct ir *ir); // returns offset struct ref ir_reserve_global(struct ir *ir, int size); void ir_append(struct ir *ir, struct irins *ins); struct irins* irins_make(enum instype type); struct irins* irins_make_name(enum instype type, char *name); struct irins* irins_make_01(enum instype type, struct ref r0, struct ref r1); struct irins* irins_make_012(enum instype type, struct ref r0, struct ref r1, struct ref r2); struct irins* irins_make_1(enum instype type, struct ref r1); struct irins* irins_make_12(enum instype type, struct ref r1, struct ref r2); struct irins* irins_make_jcc(char *name, enum condcode condcode); void irins_delete(struct irins *ins); char* gen_label_name(void); struct ref ref_reg(int reg); struct ref ref_mem(int reg, int offset, bool rel_heap); struct ref ref_imm(int imm); struct ref ref_next_register(void);