feat add func call and rewrite codes

This commit is contained in:
ZZY
2025-03-07 12:29:53 +08:00
parent 09299e339c
commit 95bf44eb3f
37 changed files with 3369 additions and 1063 deletions

View File

@ -0,0 +1,13 @@
all: ccompiler
run: ccompiler
./ccompiler test.c flat.bin
ccompiler: frontend
gcc -g rv32ima_codegen.c ../../middleend/ir.c -L../../frontend -lfrontend -o ccompiler
frontend:
make -C ../../frontend
clean:
rm -f ccompiler flat.bin

View File

@ -0,0 +1,338 @@
#ifndef __RV32I_GEN_H__
#define __RV32I_GEN_H__
/**
31 25 24 20 19 15 14 12 11 7 6 0
imm[31:12] rd 0110111 U lui
imm[31:12] rd 0010111 U auipc
imm[20|10:1|11|19:12] rd 1101111 J jal
imm[11:0] rs1 000 rd 1100111 I jalr
imm[12|10:5] rs2 rs1 000 imm[4:1|11] 1100011 B beq
imm[12|10:5] rs2 rs1 001 imm[4:1|11] 1100011 B bne
imm[12|10:5] rs2 rs1 100 imm[4:1|11] 1100011 B blt
imm[12|10:5] rs2 rs1 101 imm[4:1|11] 1100011 B bge
imm[12|10:5] rs2 rs1 110 imm[4:1|11] 1100011 B bltu
imm[12|10:5] rs2 rs1 111 imm[4:1|11] 1100011 B bgeu
imm[11:0] rs1 000 rd 0000011 I lb
imm[11:0] rs1 001 rd 0000011 I lh
imm[11:0] rs1 010 rd 0000011 I lw
imm[11:0] rs1 100 rd 0000011 I lbu
imm[11:0] rs1 101 rd 0000011 I lhu
imm[11:5] rs2 rs1 000 imm[4:0] 0100011 S sb
imm[11:5] rs2 rs1 001 imm[4:0] 0100011 S sh
imm[11:5] rs2 rs1 010 imm[4:0] 0100011 S sw
imm[11:0] rs1 000 rd 0010011 I addi
imm[11:0] rs1 010 rd 0010011 I slti
imm[11:0] rs1 011 rd 0010011 I sltiu
imm[11:0] rs1 100 rd 0010011 I xori
imm[11:0] rs1 110 rd 0010011 I ori
imm[11:0] rs1 111 rd 0010011 I andi
0000000 shamt rs1 001 rd 0010011 I slli
0000000 shamt rs1 101 rd 0010011 I srli
0100000 shamt rs1 101 rd 0010011 I srai
0000000 rs2 rs1 000 rd 0110011 R add
0100000 rs2 rs1 000 rd 0110011 R sub
0000000 rs2 rs1 001 rd 0110011 R sll
0000000 rs2 rs1 010 rd 0110011 R slt
0000000 rs2 rs1 011 rd 0110011 R sltu
0000000 rs2 rs1 100 rd 0110011 R xor
0000000 rs2 rs1 101 rd 0110011 R srl
0100000 rs2 rs1 101 rd 0110011 R sra
0000000 rs2 rs1 110 rd 0110011 R or
0000000 rs2 rs1 111 rd 0110011 R and
0000 pred succ 00000 000 00000 0001111 I fence
0000 0000 0000 00000 001 00000 0001111 I fence.i
000000000000 00000 00 00000 1110011 I ecall
000000000000 00000 000 00000 1110011 I ebreak
csr rs1 001 rd 1110011 I csrrw
csr rs1 010 rd 1110011 I csrrs
csr rs1 011 rd 1110011 I csrrc
csr zimm 101 rd 1110011 I csrrwi
csr zimm 110 rd 1110011 I cssrrsi
csr zimm 111 rd 1110011 I csrrci
*/
#include <stdint.h>
// 寄存器枚举定义
typedef enum {
REG_X0, REG_X1, REG_X2, REG_X3, REG_X4, REG_X5, REG_X6, REG_X7,
REG_X8, REG_X9, REG_X10, REG_X11, REG_X12, REG_X13, REG_X14, REG_X15,
REG_X16, REG_X17, REG_X18, REG_X19, REG_X20, REG_X21, REG_X22, REG_X23,
REG_X24, REG_X25, REG_X26, REG_X27, REG_X28, REG_X29, REG_X30, REG_X31,
REG_ZERO = REG_X0, REG_RA = REG_X1, REG_SP = REG_X2, REG_GP = REG_X3,
REG_TP = REG_X4, REG_T0 = REG_X5, REG_T1 = REG_X6, REG_T2 = REG_X7,
REG_S0 = REG_X8, REG_S1 = REG_X9, REG_A0 = REG_X10, REG_A1 = REG_X11,
REG_A2 = REG_X12, REG_A3 = REG_X13, REG_A4 = REG_X14, REG_A5 = REG_X15,
REG_A6 = REG_X16, REG_A7 = REG_X17, REG_S2 = REG_X18, REG_S3 = REG_X19,
REG_S4 = REG_X20, REG_S5 = REG_X21, REG_S6 = REG_X22, REG_S7 = REG_X23,
REG_S8 = REG_X24, REG_S9 = REG_X25, REG_S10 = REG_X26, REG_S11 = REG_X27,
REG_T3 = REG_X28, REG_T4 = REG_X29, REG_T5 = REG_X30, REG_T6 = REG_X31,
} RV32Reg;
/******************** 立即数处理宏 ********************/
#define IMM_12BITS(imm) ((imm) & 0xFFF)
#define IMM_20BITS(imm) ((imm) & 0xFFFFF)
#define SHAMT_VAL(imm) ((imm) & 0x1F)
#define CSR_VAL(csr) ((csr) & 0xFFF)
// B型立即数编码[12|10:5|4:1|11]
#define ENCODE_B_IMM(imm) ( \
(((imm) >> 12) & 0x1) << 31 | /* imm[12:12] -> instr[31:31] */ \
(((imm) >> 5) & 0x3F) << 25 | /* imm[10:5] -> instr[30:25] */ \
(((imm) >> 1) & 0xF) << 8 | /* imm[4:1] -> instr[11:8] */ \
(((imm) >> 11) & 0x1) << 7) /* imm[11:11] -> instr[7:7] */
// J型立即数编码[20|10:1|11|19:12]W
#define ENCODE_J_IMM(imm) ( \
(((imm) >> 20) & 0x1) << 31 | /* imm[20:20] -> instr[31:31] */ \
(((imm) >> 1) & 0x3FF)<< 21 | /* imm[10:1] -> instr[30:21] */ \
(((imm) >> 11) & 0x1) << 20 | /* imm[11:11] -> instr[20:20] */ \
(((imm) >> 12) & 0xFF) << 12) /* imm[19:12] -> instr[19:12] */
/******************** 指令生成宏 ********************/
// R型指令宏
#define RV32_RTYPE(op, f3, f7, rd, rs1, rs2) (uint32_t)( \
(0x33 | ((rd) << 7) | ((f3) << 12) | ((rs1) << 15) | \
((rs2) << 20) | ((f7) << 25)) )
// I型指令宏
#define RV32_ITYPE(op, f3, rd, rs1, imm) (uint32_t)( \
(op | ((rd) << 7) | ((f3) << 12) | ((rs1) << 15) | \
(IMM_12BITS(imm) << 20)) )
// S型指令宏
#define RV32_STYPE(op, f3, rs1, rs2, imm) (uint32_t)( \
(op | ((IMM_12BITS(imm) & 0xFE0) << 20) | ((rs1) << 15) | \
((rs2) << 20) | ((f3) << 12) | ((IMM_12BITS(imm) & 0x1F) << 7)) )
// B型指令宏
#define RV32_BTYPE(op, f3, rs1, rs2, imm) (uint32_t)( \
(op | (ENCODE_B_IMM(imm)) | ((rs1) << 15) | \
((rs2) << 20) | ((f3) << 12)) )
// U型指令宏
#define RV32_UTYPE(op, rd, imm) (uint32_t)( \
(op | ((rd) << 7) | (IMM_20BITS((imm) >> 12) << 12)) )
// J型指令宏
#define RV32_JTYPE(op, rd, imm) (uint32_t)( \
(op | ((rd) << 7) | ENCODE_J_IMM(imm)) )
/******************** U-type ********************/
#define LUI(rd, imm) RV32_UTYPE(0x37, rd, imm)
#define AUIPC(rd, imm) RV32_UTYPE(0x17, rd, imm)
/******************** J-type ********************/
#define JAL(rd, imm) RV32_JTYPE(0x6F, rd, imm)
/******************** I-type ********************/
#define JALR(rd, rs1, imm) RV32_ITYPE(0x67, 0x0, rd, rs1, imm)
// Load instructions
#define LB(rd, rs1, imm) RV32_ITYPE(0x03, 0x0, rd, rs1, imm)
#define LH(rd, rs1, imm) RV32_ITYPE(0x03, 0x1, rd, rs1, imm)
#define LW(rd, rs1, imm) RV32_ITYPE(0x03, 0x2, rd, rs1, imm)
#define LBU(rd, rs1, imm) RV32_ITYPE(0x03, 0x4, rd, rs1, imm)
#define LHU(rd, rs1, imm) RV32_ITYPE(0x03, 0x5, rd, rs1, imm)
// Immediate arithmetic
#define ADDI(rd, rs1, imm) RV32_ITYPE(0x13, 0x0, rd, rs1, imm)
#define SLTI(rd, rs1, imm) RV32_ITYPE(0x13, 0x2, rd, rs1, imm)
#define SLTIU(rd, rs1, imm) RV32_ITYPE(0x13, 0x3, rd, rs1, imm)
#define XORI(rd, rs1, imm) RV32_ITYPE(0x13, 0x4, rd, rs1, imm)
#define ORI(rd, rs1, imm) RV32_ITYPE(0x13, 0x6, rd, rs1, imm)
#define ANDI(rd, rs1, imm) RV32_ITYPE(0x13, 0x7, rd, rs1, imm)
// Shift instructions
#define SLLI(rd, rs1, shamt) RV32_ITYPE(0x13, 0x1, rd, rs1, (0x00000000 | (shamt << 20)))
#define SRLI(rd, rs1, shamt) RV32_ITYPE(0x13, 0x5, rd, rs1, (0x00000000 | (shamt << 20)))
#define SRAI(rd, rs1, shamt) RV32_ITYPE(0x13, 0x5, rd, rs1, (0x40000000 | (shamt << 20)))
/******************** B-type ********************/
#define BEQ(rs1, rs2, imm) RV32_BTYPE(0x63, 0x0, rs1, rs2, imm)
#define BNE(rs1, rs2, imm) RV32_BTYPE(0x63, 0x1, rs1, rs2, imm)
#define BLT(rs1, rs2, imm) RV32_BTYPE(0x63, 0x4, rs1, rs2, imm)
#define BGE(rs1, rs2, imm) RV32_BTYPE(0x63, 0x5, rs1, rs2, imm)
#define BLTU(rs1, rs2, imm) RV32_BTYPE(0x63, 0x6, rs1, rs2, imm)
#define BGEU(rs1, rs2, imm) RV32_BTYPE(0x63, 0x7, rs1, rs2, imm)
/******************** S-type ********************/
#define SB(rs2, rs1, imm) RV32_STYPE(0x23, 0x0, rs1, rs2, imm)
#define SH(rs2, rs1, imm) RV32_STYPE(0x23, 0x1, rs1, rs2, imm)
#define SW(rs2, rs1, imm) RV32_STYPE(0x23, 0x2, rs1, rs2, imm)
/******************** R-type ********************/
#define ADD(rd, rs1, rs2) RV32_RTYPE(0x33, 0x0, 0x00, rd, rs1, rs2)
#define SUB(rd, rs1, rs2) RV32_RTYPE(0x33, 0x0, 0x20, rd, rs1, rs2)
#define SLL(rd, rs1, rs2) RV32_RTYPE(0x33, 0x1, 0x00, rd, rs1, rs2)
#define SLT(rd, rs1, rs2) RV32_RTYPE(0x33, 0x2, 0x00, rd, rs1, rs2)
#define SLTU(rd, rs1, rs2) RV32_RTYPE(0x33, 0x3, 0x00, rd, rs1, rs2)
#define XOR(rd, rs1, rs2) RV32_RTYPE(0x33, 0x4, 0x00, rd, rs1, rs2)
#define SRL(rd, rs1, rs2) RV32_RTYPE(0x33, 0x5, 0x00, rd, rs1, rs2)
#define SRA(rd, rs1, rs2) RV32_RTYPE(0x33, 0x5, 0x20, rd, rs1, rs2)
#define OR(rd, rs1, rs2) RV32_RTYPE(0x33, 0x6, 0x00, rd, rs1, rs2)
#define AND(rd, rs1, rs2) RV32_RTYPE(0x33, 0x7, 0x00, rd, rs1, rs2)
/******************** I-type (system) ********************/
#define FENCE(pred, succ) (uint32_t)( 0x0F | ((pred) << 23) | ((succ) << 27) )
#define FENCE_I() (uint32_t)( 0x100F )
#define ECALL() (uint32_t)( 0x73 )
#define EBREAK() (uint32_t)( 0x100073 )
// CSR instructions
#define CSRRW(rd, csr, rs) RV32_ITYPE(0x73, 0x1, rd, rs, CSR_VAL(csr))
#define CSRRS(rd, csr, rs) RV32_ITYPE(0x73, 0x2, rd, rs, CSR_VAL(csr))
#define CSRRC(rd, csr, rs) RV32_ITYPE(0x73, 0x3, rd, rs, CSR_VAL(csr))
#define CSRRWI(rd, csr, zimm) RV32_ITYPE(0x73, 0x5, rd, 0, (CSR_VAL(csr) | ((zimm) << 15)))
#define CSRRSI(rd, csr, zimm) RV32_ITYPE(0x73, 0x6, rd, 0, (CSR_VAL(csr) | ((zimm) << 15)))
#define CSRRCI(rd, csr, zimm) RV32_ITYPE(0x73, 0x7, rd, 0, (CSR_VAL(csr) | ((zimm) << 15)))
/* M-Extention */
#define MUL(rd, rs1, rs2) RV32_RTYPE(0x33, 0x0, 0x01, rd, rs1, rs2)
#define DIV(rd, rs1, rs2) RV32_RTYPE(0x33, 0x0, 0x05, rd, rs1, rs2)
#define REM(rd, rs1, rs2) RV32_RTYPE(0x33, 0x0, 0x07, rd, rs1, rs2)
/******************** Pseudo-instructions ********************/
// 伪指令
// nop (No operation)
#define NOP() ADDI(REG_X0, REG_X0, 0) // 无操作
// neg rd, rs (Two's complement of rs)
#define NEG(rd, rs) SUB(rd, REG_ZERO, rs) // 补码
// negw rd, rs (Two's complement word of rs)
#define NEGW(rd, rs) SUBW(rd, REG_ZERO, rs) // 字的补码
// snez rd, rs (Set if ≠ zero)
#define SNEZ(rd, rs) SLTU(rd, REG_X0, rs) // 非0则置位
// sltz rd, rs (Set if < zero)
#define SLTZ(rd, rs) SLT(rd, rs, REG_X0) // 小于0则置位
// sgtz rd, rs (Set if > zero)
#define SG TZ(rd, rs) SLT(rd, REG_X0, rs) // 大于0则置位
// beqz rs, offset (Branch if = zero)
#define BEQZ(rs, offset) BEQ(rs, REG_X0, offset) // 为0则转移
// bnez rs, offset (Branch if ≠ zero)
#define BNEZ(rs, offset) BNE(rs, REG_X0, offset) // 非0则转移
// blez rs, offset (Branch if ≤ zero)
#define BLEZ(rs, offset) BGE(REG_X0, rs, offset) // 小于等于0则转移
// bgez rs, offset (Branch if ≥ zero)
#define BGEZ(rs, offset) BGE(rs, REG_X0, offset) // 大于等于0则转移
// bltz rs, offset (Branch if < zero)
#define BLTZ(rs, offset) BLT(rs, REG_X0, offset) // 小于0则转移
// bgtz rs, offset (Branch if > zero)
#define BGTZ(rs, offset) BLT(REG_X0, rs, offset) // 大于0则转移
// j offset (Jump)
#define J(offset) JAL(REG_X0, offset) // 跳转
// jr rs (Jump register)
#define JR(rs) JALR(REG_X0, rs, 0) // 寄存器跳转
// ret (Return from subroutine)
#define RET() JALR(REG_X0, REG_RA, 0) // 从子过程返回
// tail offset (Tail call far-away subroutine)
#define TAIL_2(offset) AUIPC(REG_X6, offset), JAL(REG_X0, REG_X6, offset) // 尾调用远程子过程, 有2条指令
#define TAIL(offset) TAIL_2(offset) // Warning this have 2 instructions
// csrr csr, rd (Read CSR)
#define CSRR(csr, rd) CSRRS(rd, csr, REG_X0) // 读CSR寄存器
// csrw csr, rs (Write CSR)
#define CSR W(csr, rs) CSRRW(csr, REG_X0, rs) // 写CSR寄存器
// csrs csr, rs (Set bits in CSR)
#define CSRS(csr, rs) CSRRS(REG_X0, csr, rs) // CSR寄存器置零位
// csrrc csr, rs (Clear bits in CSR)
#define CSRC(csr, rs) CSRRC(REG_X0, csr, rs) // CSR寄存器清
// csrci csr, imm (Immediate clear bits in CSR)
#define CSRCI(csr, imm) CSRRCI(REG_X0, csr, imm) // 立即数清除CSR
// csrrwi csr, imm (Write CSR immediate)
#define CSRRWI2(csr, imm) CSRRWI(REG_X0, csr, imm) // 立即数写入CSR
// csrrsi csr, imm (Immediate set bits in CSR)
#define CSRRSI2(csr, imm) CSRRSI(REG_X0, csr, imm) // 立即数置位CSR
// csrrci csr, imm (Immediate clear bits in CSR)
#define CSRRCI2(csr, imm) CSRRCI(REG_X0, csr, imm) // 立即数清除CSR
// // frcsr rd (Read FP control/status register)
// #define FRC SR(rd) CSRRS(rd, FCSR, REG_X0) // 读取FP控制/状态寄存器
// // fscsr rs (Write FP control/status register)
// #define FSCSR(rs) CSRRW(REG_X0, FCSR, rs) // 写入FP控制/状态寄存器
// // frrm rd (Read FP rounding mode)
// #define FRRM(rd) CSRRS(rd, FRM, REG_X0) // 读取FP舍入模式
// // fsrm rs (Write FP rounding mode)
// #define FS RM(rs) CSRRW(REG_X0, FRM, rs) // 写入FP舍入模式
// // frflags rd (Read FP exception flags)
// #define FRFLAGS(rd) CSRRS(rd, FFLAGS, REG_X0) // 读取FP例外标志
// // fsflags rs (Write FP exception flags)
// #define FS FLAGS(rs) CSRRW(REG_X0, FFLAGS, rs) // 写入FP例外标志
// Myriad sequences
#define LI(rd, num) \
LUI(rd, num), \
ADDI(rd, rd, num)
#define MV(rd, rs) ADDI(rd, rs, 0)
#define NOT(rd, rs) XORI(rd, rs, -1)
#define CALL(offset) \
AUIPC(REG_X1, offset), \
JALR(REG_X1, REG_X1, offset)
#define CALL_ABS(addr) \
AUIPC(REG_X0, addr), \
JALR(REG_X1, REG_X0, addr)
#ifdef RISCV_VM_BUILDIN_ECALL
#define ECALL_PNT_INT(num) \
ADDI(REG_A0, REG_X0, num), \
ADDI(REG_A7, REG_X0, 0x1), \
ECALL()
#define ECALL_PNT_STR(str) \
ADDI(REG_A0, REG_X0, str), \
ADDI(REG_A7, REG_X0, 0x4), \
ECALL()
#define ECALL_EXIT2() \
ADDI(REG_A7, REG_X0, 93), \
ECALL()
#define ECALL_EXIT_ARG(errno) \
ADDI(REG_A0, REG_X0, errno), \
ECALL_EXIT2()
#define ECALL_EXIT() \
ADDI(REG_A7, REG_X0, 93), \
ECALL()
#define ECALL_SCAN_INT(int) \
ADDI(REG_A7, (1025 + 4)), \
ECALL()
#define ECALL_SCAN_STR(str) \
ADDI(REG_A0, REG_X0, str), \
ADDI(REG_A7, REG_X0, (1025 + 5)), \
ECALL()
#endif
#endif

View File

@ -0,0 +1,413 @@
#define RISCV_VM_BUILDIN_ECALL
#include "rv32gen.h"
#include <stdio.h>
#include <assert.h>
// 指令编码联合体(自动处理小端序)
typedef union rv32code {
uint32_t code;
uint8_t bytes[4];
} rv32code_t;
#define CRT_CODE_SIZE 16
// 使用示例
rv32code_t gcodes[] = {
LI(REG_SP, 0x1000),
LI(REG_RA, 0x0),
CALL_ABS(CRT_CODE_SIZE << 2),
// Exit
ECALL_EXIT2(),
};
void test_raw_gen(FILE* out) {
fwrite(gcodes, sizeof(rv32code_t), sizeof(gcodes)/sizeof(gcodes[0]), out);
}
#include "../../frontend/frontend.h"
#include "../../middleend/ir.h"
typedef struct {
int code_pos;
int to_idx;
int cur_idx;
int base_offset;
enum {
JMP_BRANCH,
JMP_JUMP,
JMP_CALL,
} type;
} jmp_t;
static struct {
vector_header(codes, rv32code_t);
int stack_offset;
int stack_base;
int tmp_reg;
ir_bblock_t* cur_block;
ir_func_t* cur_func;
ir_prog_t* prog;
vector_header(jmp, jmp_t*);
vector_header(call, jmp_t*);
int cur_func_offset;
int cur_block_offset;
} ctx;
int write_inst(union rv32code ins, FILE* fp) {
return fwrite(&ins, sizeof(union rv32code), 1, fp);
}
#define GENCODE(code) vector_push(ctx.codes, (rv32code_t)(code)); len += 4
#define GENCODES(code) do { \
rv32code_t codes[] = { \
code \
}; \
for (int i = 0; i < sizeof(codes) / sizeof(codes[0]); i ++) { \
GENCODE(codes[i]); \
} \
} while (0)
static int stack_offset(ir_node_t* ptr) {
int offset = ctx.stack_base;
for (int i = 0; i < ctx.cur_func->bblocks.size; i ++) {
ir_bblock_t* block = vector_at(ctx.cur_func->bblocks, i);
for (int i = 0; i < block->instrs.size; i++) {
if (vector_at(block->instrs, i) == ptr) {
offset += i * 4;
assert(offset >= 0 && offset < ctx.stack_offset);
return offset;
}
}
offset += block->instrs.size * 4;
}
assert(0);
}
static int block_idx(ir_bblock_t* toblock) {
for (int i = 0; i < ctx.cur_func->bblocks.size; i ++) {
ir_bblock_t* block = vector_at(ctx.cur_func->bblocks, i);
if (toblock == block) {
return i;
}
}
assert(0);
}
static int func_idx(ir_func_t* tofunc) {
for (int i = 0; i < ctx.prog->funcs.size; i ++) {
ir_func_t* func = vector_at(ctx.prog->funcs, i);
if (tofunc == func) {
return i;
}
}
assert(0);
}
static int system_func(const char* name) {
static const char defined_func[][16] = {
"ecall_pnt_int",
};
for (int j = 0; j < sizeof(defined_func)/sizeof(defined_func[0]); j++) {
if (strcmp(name, defined_func[j]) == 0) {
return j;
}
}
return -1;
}
static int get_node_val(ir_node_t* ptr, int reg) {
int len = 0;
if (ptr->tag == IR_NODE_CONST_INT) {
GENCODES(LI(reg, ptr->data.const_int.val));
} else {
int offset = stack_offset(ptr);
GENCODE(LW(reg, REG_SP, offset));
}
return len;
}
static int gen_instr(ir_bblock_t* block, ir_node_t* instr) {
int len = 0;
int offset;
switch (instr->tag) {
case IR_NODE_ALLOC: {
break;
}
case IR_NODE_LOAD: {
// S1 = *(S0 + imm)
offset = stack_offset(instr->data.load.target);
GENCODE(LW(REG_T0, REG_SP, offset));
// offset = STACK_OFFSET(instr);
// GENCODE(SW(REG_T0, REG_SP, offset));
break;
}
case IR_NODE_STORE: {
// *(S0 + imm) = S1
len += get_node_val(instr->data.store.value, REG_T0);
offset = stack_offset(instr->data.store.target);
GENCODE(SW(REG_T0, REG_SP, offset));
break;
}
case IR_NODE_RET: {
// A0 = S0
if (instr->data.ret.ret_val != NULL) {
len += get_node_val(instr->data.ret.ret_val, REG_A0);
}
GENCODE(LW(REG_RA, REG_SP, 0));
GENCODE(ADDI(REG_SP, REG_SP, ctx.stack_offset));
GENCODE(RET());
break;
}
case IR_NODE_OP: {
len += get_node_val(instr->data.op.lhs, REG_T1);
len += get_node_val(instr->data.op.rhs, REG_T2);
switch (instr->data.op.op) {
case IR_OP_ADD:
GENCODE(ADD(REG_T0, REG_T1, REG_T2));
break;
case IR_OP_SUB:
GENCODE(SUB(REG_T0, REG_T1, REG_T2));
break;
case IR_OP_MUL:
GENCODE(MUL(REG_T0, REG_T1, REG_T2));
break;
case IR_OP_DIV:
GENCODE(DIV(REG_T0, REG_T1, REG_T2));
break;
case IR_OP_MOD:
GENCODE(REM(REG_T0, REG_T1, REG_T2));
break;
default:
error("ERROR gen_instr op in riscv");
break;
}
offset = stack_offset(instr);
GENCODE(SW(REG_T0, REG_SP, offset));
break;
}
case IR_NODE_BRANCH: {
len += get_node_val(instr->data.branch.cond, REG_T0);
int tidx = block_idx(instr->data.branch.true_bblock);
int fidx = block_idx(instr->data.branch.false_bblock);
int cidx = block_idx(ctx.cur_block);
jmp_t* jmp;
jmp = xmalloc(sizeof(jmp_t));
*jmp = (jmp_t) {
.base_offset = 8,
.code_pos = ctx.codes.size,
.type = JMP_BRANCH,
.to_idx = tidx,
.cur_idx=cidx,
};
vector_push(ctx.jmp, jmp);
GENCODE(BNEZ(REG_T0, 0));
jmp = xmalloc(sizeof(jmp_t));
*jmp = (jmp_t) {
.base_offset = 4,
.code_pos = ctx.codes.size,
.type = JMP_JUMP,
.to_idx = fidx,
.cur_idx=cidx,
};
vector_push(ctx.jmp, jmp);
GENCODE(J(0));
break;
}
case IR_NODE_JUMP: {
int idx = block_idx(instr->data.jump.target_bblock);
jmp_t* jmp = xmalloc(sizeof(jmp_t));
*jmp = (jmp_t) {
.base_offset = 4,
.code_pos = ctx.codes.size,
.type = JMP_JUMP,
.to_idx = idx,
.cur_idx=block_idx(ctx.cur_block),
};
vector_push(ctx.jmp, jmp);
GENCODE(J(0));
break;
}
case IR_NODE_CALL: {
if (instr->data.call.args.size > 8) {
error("can't add so much params");
}
int param_regs[8] = {
REG_A0, REG_A1, REG_A2, REG_A3,
REG_A4, REG_A5, REG_A6, REG_A7
};
for (int i = 0; i < instr->data.call.args.size; i++) {
ir_node_t* param = vector_at(instr->data.call.args, i);
len += get_node_val(param, param_regs[i]);
}
int system_func_idx = system_func(instr->data.call.callee->name);
if (system_func_idx == 0) {
// ecall_pnt_int
GENCODE(ADDI(REG_A7, REG_X0, 0x1));
GENCODE(ECALL());
break;
}
jmp_t* jmp = xmalloc(sizeof(jmp_t));
*jmp = (jmp_t) {
.base_offset = ctx.cur_func_offset + ctx.cur_block_offset + len,
.code_pos = ctx.codes.size,
.type = JMP_CALL,
.to_idx = func_idx(instr->data.call.callee),
.cur_idx = func_idx(ctx.cur_func),
};
vector_push(ctx.call, jmp);
GENCODES((
CALL(0)
));
break;
}
default:
error("ERROR gen_instr in riscv");
}
return len;
}
static int gen_block(ir_bblock_t* block) {
int len = 0;
ctx.cur_block = block;
for (int i = 0; i < block->instrs.size; i ++) {
ctx.cur_block_offset = len;
len += gen_instr(block, vector_at(block->instrs, i));
}
return len;
}
static int gen_func(ir_func_t* func) {
int len = 0;
ctx.cur_func = func;
ctx.stack_base = 16;
ctx.stack_offset = ctx.stack_base;
for (int i = 0; i < func->bblocks.size; i++) {
ctx.stack_offset += 4 * (*vector_at(func->bblocks, i)).instrs.size;
}
GENCODE(ADDI(REG_SP, REG_SP, -ctx.stack_offset));
GENCODE(SW(REG_RA, REG_SP, 0));
int param_regs[8] = {
REG_A0, REG_A1, REG_A2, REG_A3,
REG_A4, REG_A5, REG_A6, REG_A7
};
if (func->params.size > 8) {
error("can't add so much params");
}
for (int i = 0; i < func->params.size; i++) {
int offset = stack_offset(vector_at(func->params, i));
GENCODE(SW(param_regs[i], REG_SP, offset));
}
int jmp_cache[func->bblocks.size + 1];
if (ctx.jmp.data != NULL) vector_free(ctx.jmp);
vector_init(ctx.jmp);
jmp_cache[0] = 0;
for(int i = 0; i < func->bblocks.size; i ++) {
ctx.cur_func_offset = len;
jmp_cache[i + 1] = jmp_cache[i];
int ret = gen_block(vector_at(func->bblocks, i));
jmp_cache[i + 1] += ret;
len += ret;
}
for (int i = 0; i < ctx.jmp.size; i++) {
jmp_t* jmp = vector_at(ctx.jmp, i);
int32_t code = 0;
int offset = jmp_cache[jmp->to_idx] - (jmp_cache[jmp->cur_idx + 1] - jmp->base_offset);
if (jmp->type == JMP_JUMP) {
code = J(offset);
} else {
code = BNEZ(REG_T0, offset);
}
ctx.codes.data[jmp->code_pos] = (rv32code_t) {
.code = code,
};
}
return len;
}
static void gen_code(ir_prog_t* prog) {
ctx.prog = prog;
for (int i = 0; i < prog->extern_funcs.size; i++) {
if (system_func(prog->extern_funcs.data[i]->name) == -1) {
error("func %s not defined and not a system func", prog->extern_funcs.data[i]->name);
}
}
int len = 0;
int jmp_cache[prog->funcs.size + 1];
for(int i = 0; i < prog->funcs.size; i ++) {
jmp_cache[i + 1] = jmp_cache[i];
int ret = gen_func(vector_at(prog->funcs, i));
jmp_cache[i + 1] += ret;
len += ret;
}
for (int i = 0; i < ctx.call.size; i++) {
jmp_t* jmp = vector_at(ctx.call, i);
int32_t code = 0;
// FIXME ERROR
int offset = jmp_cache[jmp->to_idx] - (jmp_cache[jmp->cur_idx] + jmp->base_offset);
int32_t codes[2] = {
CALL(offset)
};
for (int i = 0; i < 2; i++) {
ctx.codes.data[jmp->code_pos + i] = (rv32code_t) {
.code = codes[i],
};
}
}
}
int main(int argc, char** argv) {
// gcc rv32ima_codegen.c -o rv32gen.exe
const char* infilename = "test.c";
const char* outfilename = "flat.bin";
if (argc >= 2) {
infilename = argv[1];
}
if (argc >= 3) {
outfilename = argv[2];
}
FILE* in = fopen(infilename, "r");
FILE* out = fopen(outfilename, "wb");
if (in == NULL || out == NULL) {
printf("Failed to open file\n");
return 1;
}
struct ASTNode* root = frontend(infilename, in, (sread_fn)fread_s);
gen_ir_from_ast(root);
gen_code(&prog);
for (int i = 0; i < CRT_CODE_SIZE; i++) {
write_inst((union rv32code) {
.code = NOP(),
}, out);
}
fflush(out);
assert(CRT_CODE_SIZE >= sizeof(gcodes) / sizeof(gcodes[0]));
fseek(out, 0, SEEK_SET);
fwrite(gcodes, sizeof(gcodes), 1, out);
fflush(out);
fseek(out, CRT_CODE_SIZE * 4, SEEK_SET);
fwrite(ctx.codes.data, sizeof(ctx.codes.data[0]), ctx.codes.size, out);
fflush(out);
fclose(in);
fclose(out);
// printf("comiler end out: %s\n", outfilename);
return 0;
}