RISC-V code generator (binary-encoding, hooked into ir_match/ir_ra/ir_emit_code)#174
RISC-V code generator (binary-encoding, hooked into ir_match/ir_ra/ir_emit_code)#174steven-studio wants to merge 15 commits into
Conversation
…loat params/return)
…runc, if/else; 29 tests pass
… from pool; matmul verified
…_emit_code for START/PARAM/ADD/RETURN Hand-written encoder (no DynAsm), verified end-to-end against riscv64-linux-gnu-objdump. Also fixes target-detection fallthrough bugs in ir.h/ir_ra.c/ir_dump.c/ir_gdb.c that were silently treating IR_TARGET_RISCV64 as x86_64, plus an ir_disasm.c objdump fallback since this system's libcapstone lacks CS_ARCH_RISCV.
dstogov
left a comment
There was a problem hiding this comment.
Please, remove binary libir.a.
This looks like a good start. Go forward!
I made only a quick look over the sources.
| int32_t rd = riscv_reg_of(ctx, ref, 0); | ||
| int32_t rs1 = riscv_reg_of(ctx, ref, 1); | ||
| int32_t rs2 = riscv_reg_of(ctx, ref, 2); | ||
| emit32(ctx, rv_add((uint32_t)rd, (uint32_t)rs1, (uint32_t)rs2)); | ||
| break; |
There was a problem hiding this comment.
Live ranges might be spilled, and then register might need to be loaded and stored.
ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]);
ir_ref op1 = insn->op1;
if (op1_reg != IR_REG_NONE) {
if (IR_REG_SPILLED(op1_reg)) {
op1_reg = IR_REG_NUM(op1_reg);
ir_emit_load(ctx, insn->type, insn->op1_reg, op1);
}
}
....
if (IR_REG_SPILLED(ctx->regs[def][0])) {
ir_emit_store(ctx, type, def, def_reg);
}Also operands might be constants (IR_IS_CONST_REF(insn->op`)).
I guess, RISC should load them into registers first. This may be done allocating temporary register in ir_get_target_constraints().
case IR_RISCV_RULE_ADD
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_MUST_BE_IN_REG | IR_OP2_MUST_BE_IN_REG;
insn = &ctx->ir_base[ref];
if (IR_IS_CONST_REF(insn->op1)) {
constraints->tmp_regs[n] = IR_TMP_REG(1, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
n = 1;
}
if (IR_IS_CONST_REF(insn->op2)) {
constraints->tmp_regs[n] = IR_TMP_REG(2, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
n = 1;
}
break;This should lead to generation of necessary spill-load(s).
| echo "" | ||
| echo "Results: $PASS passed, $FAIL failed" |
There was a problem hiding this comment.
Why do we need this file? Why not to use make test?
Removed |
Description
Follow-up to #169 — implementing the direction we landed on there: hand-written
binary encoding hooked into ir_match()/ir_ra.c/ir_emit_code(), skipping DynAsm
entirely.
What's here
ir_riscv.h— register definitions (x0-x31, f0-f31), ABI aliases, regsetmacros, mirroring ir_x86.h's structure
ir_riscv_enc.h— R/I/S/B/U/J-type instruction encoders per the RISC-V baseISA spec
ir_emit_riscv.c—ir_match(),ir_get_target_constraints(),ir_emit_code(), calling convention (lp64d: a0-a7 int args, a0/a1 intreturn, s0-s11 callee-saved), plus the debug/dump helpers (
ir_reg_name,ir_dump_reg,ir_rule_name)ir.h,ir_ra.c,ir_dump.c,ir_gdb.c— thesefiles were silently falling through to x86_64 handling when
IR_TARGET_RISCV64was defined, which took a while to track down (registerallocator was picking
x0as a scratch register before this was fixed)ir_disasm.c—-Sshells out toriscv64-linux-gnu-objdumpfor RISC-V;this system's libcapstone (4.0.2) has no
CS_ARCH_RISCV, so the existingcapstone path was segfaulting on an uninitialized handle. Open to
reverting this once capstone has real RISC-V support — wasn't sure if this
belongs upstream or as a local workaround, your call.
Scope
IR_START,IR_PARAM,IR_ADD,IR_RETURN— enough for a leaf functionwith two int params and one addition. Everything in the pipeline is real
(register allocation, constraints, encoding) — nothing stubbed in this path.
The handful of functions not exercised yet (thunks,
ir_call_proto) arestubbed and marked
TODO, since they're only needed once CALL/LLVM-emitpaths are in scope.
Verified
./ir add.ir -O2 -S:Cross-checked independently against
riscv64-linux-gnu-objdump— matches.Next
Planning SUB/MUL next (same shape as ADD, different funct7/funct3), then
comparisons and branches (B-type encoder is already in
ir_riscv_enc.h,just not wired to any rule yet). Let me know if you'd rather look at the
current shape before I keep going.