sfinae687 / SysYust

SysY2022编译器项目
GNU General Public License v3.0
0 stars 2 forks source link

后端代码生成 #63

Open l3773l opened 3 months ago

l3773l commented 3 months ago

TASK

架构

中端 IR

l3773l commented 3 months ago

IR 和 MIR:一些需求

l3773l commented 3 months ago
enum RiscVInst {
    BEGIN_RV64IM,
    MV,
    NOP,

    // 64:
    NEG,
    ADD,
    ADDI,
    SUB,
    MUL,
    DIV,
    REM,

    // 32:
    NEGW,

    // BITWISE 按位逻辑运算
    AND,
    ANDI,
    XOR,
    XORI,
    NOT,
    OR,
    ORI,

    // SHIFT 移位指令
    // S{L/R}{L/A} 第一个 {L/R} 表示左右,第个 {L/A}
    // (LOGICAL/ARITHMETIC)表示逻辑和算数(算数保持符号) 没有 SLA 是因为它和
    // SLL 是等价的
    SLL,
    SLLI,
    SRL,
    SRLI,
    SRA,
    SRAI,

    // BRANCH
    BEQ,
    // BGE,
    // BGT,
    // BLE,
    // BLT,
    BNE,

    // CMP
    // 无符号比较跟有符号一样
    // 没有 SEQ, 它等价于 XOR A, A, B; SEQZ DST, A
    SLT,
    SLTI,

    // 处理 PC 高位偏移
    /**
     * 在 RISC-V 里,由于指令长度的问题(64
     * 位指令可能存有多个参数/立即数,指令中提供给立即数的长度有限),偏移有时无法完全加载(比如
     * 63 位长的偏移),这时要分为高位和低位分开加载。 比如 JALR
     * DST,OFFSET(SRC) OFFSET 只能是 12 位立即数
     * 在加载地址类偏移时,理想的状况是 DST = PC + OFFSET 得到偏移后的地址
     * 加载高位和低位情况时 DST = PC + OFFSETHI + OFFSETLO (OFFSET = OFFSETHI +
     * OFFSETLO) 可以使用 DST1 = PC + OFFSETHI; JALR DST, OFFSETLO(DST1) 来解决
     * 但是由于 RISC-V 的设计,你不能直接访问 PC
     * 那么(PC + OFFSETHI)部分就产生了一个指令 AUIPC(ADD UI TO PC)
     * AUIPC RD, OFFSET <=> RD = PC + (OFFSET << 12)
     */
    AUIPC,

    // JUMP
    // L 指 LINK(把下一条指令的地址加载到寄存器里用做返回地址),R 指寄存器跳转
    // JAL,
    // JALR,
    J,
    // JR,

    // 函数调用/返回
    CALL,
    TAIL,
    RET,

    // LOAD & STORE
    // LA 和 LLA 都是加载符号地址,LLA RD, SYMBOL <=> RD = &SYMBOL
    // 特别地 当编译位置无关代码时,LA 会去加载 GOT(全局偏移表中的地址),而
    // LLA 始终如上(LLA 的第二个 L 指 LOCAL)。 (PIC)LA RD, SYMBOL <=> RD =
    // GOT[PC + SYMBOL_GOT_OFFSET] (NON-PIC) 非 PIC 时 LA 和 LLA 一样。
    LA,
    // LLA,

    // 加载,没有 U 则符号扩展,32/64 位没有 LWU/LDU 因为 LW/LD
    // 在对应位架构直接一整个全加载了
    LW,
    SW,

    // 加载立即数
    // 对 LI,汇编器会根据 立即数的大小 自动生成对应加载指令
    LI,
    LUI,

    // SYSTEM CALL
    // ECALL,   // 环境调用异常
    // EBREAK,  // 调试器断点异常

    END_RV64IM,

    BEGIN_RV64FD,
    // FLOAT
    FNEG_S,
    FADD_S,
    FSUB_S,
    FMUL_S,
    FDIV_S,

    // 浮点转换 S 单精度 D 双精度 W 字 L 64 位整数(指 LP64 LONG)
    FCVT_S_W,
    FCVT_W_S,

    // LOAD & STORE
    FLW,
    FSW,

    // CMP
    FEQ_S,
    FLE_S,
    FLT_S,

    // FLOAT MV, X 指整数寄存器
    FMV_S,
    FMV_W_X,
    FMV_X_W,

    END_RV64FD,
};

// i 指 整数寄存器
// f 值 浮点数寄存器
// 12-bits im/20-bits im 指 12/20 位长的(有符号/无符号)立即数
// symbol 指汇编中类似 .main(函数符号) .L1(跳转地址符号),可能有替换的需求(变量)

#define DECL(...)

// i32

// i -> i
#define DECL1(name)
DECL1(NEG)
DECL1(NEGW)
DECL1(NOT)

// (i, i) -> i
#define DECLR(name)
DECLR(ADD)
DECLR(SUB)
DECLR(MUL)
DECLR(DIV)
DECLR(REM)

DECLR(AND)
DECLR(XOR)
DECLR(OR)

DECLR(SLL)
DECLR(SRL)
DECLR(SRA)

DECLR(SLT)

// (i, 12bits signed imm) -> i
#define DECLI(name)
DECLI(ADDI)

DECLI(ANDI)
DECLI(XORI)
DECLI(ORI)

DECLI(SLLI)
DECLI(SRLI)
DECLI(SRAI)

DECLI(SLTI)

// (i, symbol) -> void
#define DECLB(name)
DECLB(BEQ)
DECLB(BNE)

// 不定型的指令

DECL(i, AUIPC, 20-bits im)

DECL(void, J, symbol)

DECL(void, CALL, symbol)
DECL(void, TAIL, symbol)
DECL(void, RET)

DECL(i, LA, symbol) 

// lw rd, offset(rs)
DECL(i, LW, 12-bits im, i)
// sw rs2, offset(rs1)
DECL(void, SW, i, 12-bits im, i)

DECL(i, LI, 12-bits im)
DECL(i, LUI, 20-bits im)

// float
// f -> f
#define DECL1F(name) 
DECL1F(FNEG_S)
// (f, f) -> f
#define DECLRF(name)
DECLRF(FADD_S)
DECLRF(FSUB_S)
DECLRF(FMUL_S)
DECLRF(FDIV_S)

// 浮点转换 S 单精度 D 双精度 W 字 L 64 位整数(指 LP64 LONG)
DECL(i, FCVT_S_W, f)
DECL(f, FCVT_W_S, i)

// LOAD & STORE
DECL(f, FLW, 12-bits im, i)
DECL(void, FSW, f, 12-bits im, i)

// CMP
DECL(i, FEQ_S, f, f)
DECL(i, FLE_S, f, f)
DECL(i, FLT_S, f, f)

// FLOAT MV, X 指整数寄存器
DECL(f, FMV_S, f)
DECL(i, FMV_W_X, f)
DECL(f, FMV_X_W, i)

// END_RV64FD,
ll06printf commented 3 months ago

68

IR 和 MIR:一些需求

* [x]  IR 的 Inst 加入 RISCVInst

* [x]  var_symbol 加入 x0~x31 和 f0~f31 寄存器(有可能不满足 SSA 性质)

未测试版本 509ab59423bdea887968cd8bccab9f1969f8ee22 已完成。