Machine IR, support compile llvm module (from MoonLLVM) to different architecture machine code.
Dependencies
moon update
moon add Kaida-Amethyst/MoonMIR{
"imports": [
"Kaida-Amethyst/MoonLLVM/IR",
"Kaida-Amethyst/MoonMIR/riscv64"
]
}{
"imports": [
"Kaida-Amethyst/MoonLLVM/IR",
"Kaida-Amethyst/MoonMIR/riscv64"
]
}fn main_err() -> Unit raise {
// 1. Set up MoonLLVM context, module, and IR builder.
let ctx = @IR.Context::new()
let mod = ctx.addModule("my_module")
let builder = IRBuilder::new()
// 2. Define function signature: i32 add(i32, i32).
let i32_t = ctx.getInt32Ty()
let f_type = ctx.getFunctionType(i32_t, [i32_t, i32_t])
// 3. Add the function and create an entry basic block.
let f = mod.addFunction(f_type, "add")
let bb = f.addBasicBlock("entry")
builder.setInsertPoint(bb)
// 4. Name the function arguments.
let x = f.getArg(0).unwrap()
x.setName("x")
let y = f.getArg(1).unwrap()
y.setName("y")
// 5. Create the add and return instructions.
let sum = builder.createAdd(x, y, "sum")
builder.createRet(sum)
// 6. Compile the LLVM module to RISC-V 64 assembly.
let rv_mod = @riscv64.compile(mod)
// 7. Print the resulting assembly code.
println(rv_mod)
}
fn main {
try main_err() catch {
e => println(e)
} noraise {
_ => ()
}
}moon update
moon add Kaida-Amethyst/MoonMIR{
"imports": [
"Kaida-Amethyst/MoonLLVM/IR",
"Kaida-Amethyst/MoonMIR/riscv64"
]
}{
"imports": [
"Kaida-Amethyst/MoonLLVM/IR",
"Kaida-Amethyst/MoonMIR/riscv64"
]
}fn main_err() -> Unit raise {
// 1. 设置 MoonLLVM 上下文、模块和 IR 构建器。
let ctx = @IR.Context::new()
let mod = ctx.addModule("my_module")
let builder = IRBuilder::new()
// 2. 定义函数签名:i32 add(i32, i32)。
let i32_t = ctx.getInt32Ty()
let f_type = ctx.getFunctionType(i32_t, [i32_t, i32_t])
// 3. 添加函数并创建入口基本块。
let f = mod.addFunction(f_type, "add")
let bb = f.addBasicBlock("entry")
builder.setInsertPoint(bb)
// 4. 命名函数参数。
let x = f.getArg(0).unwrap()
x.setName("x")
let y = f.getArg(1).unwrap()
y.setName("y")
// 5. 创建加法和返回指令。
let sum = builder.createAdd(x, y, "sum")
builder.createRet(sum)
// 6. 将 LLVM 模块编译为 RISC-V 64 汇编。
let rv_mod = @riscv64.compile(mod)
// 7. 打印生成的汇编代码。
println(rv_mod)
}
fn main {
try main_err() catch {
e => println(e)
} noraise {
_ => ()
}
}pub suberror MIRError {
IRTranslateError(String)
LegalizeError(String)
InValidBitWidthError(String)
}pub(all) struct ArchConfig {
arch_name : String
max_num_reg : Int
max_num_freg : Int
num_arg_regs : Int
num_arg_fregs : Int
num_temp_regs : Int
num_temp_fregs : Int
num_saved_regs : Int
num_saved_fregs : Int
support_select : Bool
}pub(all) struct BasicBlock {
llvm_bb : BasicBlock?
label : String
insts : Array[Instruction]
parent : Function
preds : Array[BasicBlock]
succs : Array[BasicBlock]
phi_nodes : Array[(PHINode, Operand)]
live_in : Set[Operand]
live_out : Set[Operand]
}impl Eq for BasicBlockimpl Show for BasicBlockfn BasicBlock::insert_inst_after(self : BasicBlock, inst : Instruction, after~ : Instruction) -> Unit?fn BasicBlock::insert_inst_before(self : BasicBlock, inst : Instruction, before~ : Instruction) -> Unit?fn BasicBlock::rewrite_by_replacement_map(self : BasicBlock, replacement_map : Map[Operand, Operand]) -> Unitfn BasicBlock::translate_llvm_basic_block(self : BasicBlock, llvm_bb : BasicBlock) -> Unit raise MIRErrorpub(all) enum BranchOpCode {
Beq
Bne
Bgt
Bge
Blt
Ble
Bgtu
Bgeu
Bltu
Bleu
Jmp
}pub(all) enum CastOpCode {
Trunc(Int, Int)
ZExt(Int, Int)
SExt(Int, Int)
FPTrunc(Int, Int)
FPExt(Int, Int)
FPToSI(Int, Int)
FPToUI(Int, Int)
SIToFP(Int, Int)
UIToFP(Int, Int)
}pub(all) enum FBinaryOpCode {
FAdd
FSub
FMul
FDiv
FRem
}pub(all) enum FCmpOpCode {
Feq
Fne
Fgt
Fge
Flt
Fle
}pub(all) enum FRegister {
VFReg(Int)
FAReg(Int)
FTReg(Int)
FSReg(Int)
}pub(all) enum FUnaryOpCode {
FNeg
}pub(all) struct Function {
mod : Module
name : String
params : Array[Operand]
body : Array[BasicBlock]
var_stack_size : Int64
reg_stack_size : Int64
terminal_blocks : Array[BasicBlock]
llvm_func : Function?
is_external : Bool
is_variadic : Bool
value_map : Map[&Value, Operand]
bbmap : Map[String, BasicBlock]
vreg_cnt : Int
vfreg_cnt : Int
spilled_count : Int
}#callsite(autofill(loc))
fn Function::append_basic_block(self : Function, label : String, loc~ : SourceLoc) -> BasicBlock#callsite(autofill(loc))
fn Function::traverse_llvm_basic_blocks(self : Function, loc~ : SourceLoc) -> Array[(BasicBlock, BasicBlock)]pub(all) struct GlobalValue {
label : String
content : GlobalValueContent
mod : Module
llvm_gv : &GlobalValue?
}impl Show for GlobalValuepub(all) enum GlobalValueData {
Quad(UInt64)
Word(UInt)
Half(UInt16)
Byte(Byte)
}pub(all) enum IBinaryOpCode {
Add
Sub
Mul
Div
Rem
And
Or
Xor
Shl
LShr
AShr
}pub(all) enum ICmpOpCode {
Eq
Ne
Gt
Ge
Lt
Le
Gtu
Geu
Ltu
Leu
}fn IRBuilder::build_branch(self : IRBuilder, opcode : BranchOpCode, bits : Int, lhs~ : IRegister, rhs~ : IRegister, true_label~ : String, false_label~ : String) -> Instructionfn IRBuilder::build_branch_imm(self : IRBuilder, opcode : BranchOpCode, bits : Int, lhs~ : IRegister, rhs~ : Int64, true_label~ : String, false_label~ : String) -> Instruction#callsite(autofill(loc))
fn IRBuilder::build_fbinary(self : IRBuilder, binop : FBinaryOpCode, bits : Int, dst~ : FRegister, src1~ : FRegister, src2~ : FRegister, loc~ : SourceLoc) -> Instruction raise MIRError#callsite(autofill(loc))
fn IRBuilder::build_fcmp(self : IRBuilder, cmpop : FCmpOpCode, bits : Int, dst~ : IRegister, src1~ : FRegister, src2~ : FRegister, loc~ : SourceLoc) -> Instruction raise MIRErrorfn IRBuilder::build_fp_to_si(self : IRBuilder, from_ty_size~ : Int, to_ty_size~ : Int, dst~ : IRegister, src~ : FRegister) -> Instructionfn IRBuilder::build_fp_to_ui(self : IRBuilder, from_ty_size~ : Int, to_ty_size~ : Int, dst~ : IRegister, src~ : FRegister) -> Instruction#callsite(autofill(loc))
fn IRBuilder::build_funary(self : IRBuilder, unop : FUnaryOpCode, bits : Int, dst~ : FRegister, src~ : FRegister, loc~ : SourceLoc) -> Instruction raise MIRError#callsite(autofill(loc))
fn IRBuilder::build_ibinary(self : IRBuilder, binop : IBinaryOpCode, bits : Int, dst~ : IRegister, src1~ : IRegister, src2~ : IRegister, loc~ : SourceLoc) -> Instruction raise MIRError#callsite(autofill(loc))
fn IRBuilder::build_ibinary_imm(self : IRBuilder, binop : IBinaryOpCode, bits : Int, dst~ : IRegister, src1~ : IRegister, src2~ : Int64, loc~ : SourceLoc) -> Instruction raise MIRError#callsite(autofill(loc))
fn IRBuilder::build_icmp(self : IRBuilder, cmpop : ICmpOpCode, bits : Int, dst~ : IRegister, src1~ : IRegister, src2~ : IRegister, loc~ : SourceLoc) -> Instruction raise MIRError#callsite(autofill(loc))
fn IRBuilder::build_iunary(self : IRBuilder, unop : IUnaryOpCode, bits : Int, dst~ : IRegister, src~ : IRegister, loc~ : SourceLoc) -> Instruction raise MIRErrorfn IRBuilder::build_si_to_fp(self : IRBuilder, from_ty_size~ : Int, to_ty_size~ : Int, dst~ : FRegister, src~ : IRegister) -> Instructionfn IRBuilder::build_ui_to_fp(self : IRBuilder, from_ty_size~ : Int, to_ty_size~ : Int, dst~ : FRegister, src~ : IRegister) -> Instructionpub(all) enum IRegister {
VReg(Int)
AReg(Int)
TReg(Int)
SReg(Int)
StackPtr
FramePtr
FramePtrPrim
ReturnAddr
}pub(all) enum IUnaryOpCode {
Not
}impl Eq for Instructionimpl Show for Instructionfn Instruction::legalize_branch(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_cast(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_cast_fp_to_si(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_cast_fp_to_ui(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_cast_fpext(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_cast_fptrunc(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_cast_sext(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_cast_si_to_fp(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_cast_trunc(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_cast_ui_to_fp(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_cast_zext(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_fbinary(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_fcmp(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_fload(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_fmove(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_fmovei(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_fstore(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_funary(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_icmp(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_iload(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_imove(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_imovef(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_istore(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_iunary(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::legalize_load_addr(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn Instruction::new(opcode : OpCode, defs : Array[Operand], uses : Array[Operand], bb : BasicBlock) -> Instructionfn Instruction::rewrite_by_replacement_map(self : Instruction, replacement_map : Map[Operand, Operand]) -> Unitimpl Show for InterferenceGraphfn InterferenceGraph::coloring(self : InterferenceGraph, preference_list : Map[Operand, Deque[Operand]]) -> (Map[Operand, Operand], Int)fn InterferenceGraph::find_uncolored_vfreg_with_greatest_uncolored_degree(self : InterferenceGraph) -> Operand?fn InterferenceGraph::find_uncolored_vreg_with_greatest_uncolored_degree(self : InterferenceGraph) -> Operand?pub(all) struct Module {
source_file : String
llvm_mod : Module?
arch_config : ArchConfig
functions : Map[String, Function]
all_llvm_functions : Map[String, Function]
external_functions : Map[String, Function]
global_values : Array[GlobalValue]
}fn Module::add_function(self : Module, name : String, arg_patterns : Array[ArgPattern], is_external : Bool, is_variadic? : Bool) -> Functionlet mod = Module::new(ArchConfig::riscv64())
let func = mod.add_function("add", [I, I], false)
let entry_bb = func.append_basic_block("entry")
let builder = IRBuilder::new(func, entry_bb)
let a0 = func.get_param(0).unwrap()
let a1 = func.get_param(1).unwrap()
guard a0 is IRegister(a0)
guard a1 is IRegister(a1)
builder.build_ibinary(Add, 32, dst = AReg(0), src1 = a0, src2 = a1)
|> BasicBlock::push(entry_bb, _)
builder.build_ret()
|> BasicBlock::push(entry_bb, _)
let expected =
#|func add(a0, a1) {
#|entry:
#| a0 = add.i32 a0, a1
#| ret
#|}
#|
inspect(func, content=expected)fn Module::add_global_data(self : Module, label : String, data : Array[GlobalValueData]) -> GlobalValuelet mod = Module::new(ArchConfig::riscv64())
let data : Array[GlobalValueData] = [
Quad(0x1122334455667788),
Word(0x99AABBCC),
Half(0xDDEE),
Byte(0xFF),
]
let gv = mod.add_global_data("data", data)
let expected =
#|global data {
#| .quad 1234605616436508552
#| .word 2578103244
#| .half 56814
#| .byte 255
#|}
#|
inspect(gv, content=expected)let mod = Module::new(ArchConfig::riscv64())
let content = #|Hello, World!\n
let gv = mod.add_global_string(label="msg", content~)
let expected =
#|global msg {
#| "Hello, World!\n"
#|}
#|
inspect(gv, content=expected)let mod = Module::new(ArchConfig::riscv64())
let gv = mod.add_global_zero_data("buffer", 64)
let expected =
#|global buffer {
#| .zero 64
#|}
#|
inspect(gv, content=expected)pub(all) enum OpCode {
IBinary(IBinaryOpCode, Int)
IUnary(IUnaryOpCode, Int)
ICmp(ICmpOpCode, Int)
ILoad(Int)
IStore(Int)
IMove(Int)
Branch(BranchOpCode, Int)
FBinary(FBinaryOpCode, Int)
FUnary(FUnaryOpCode, Int)
FCmp(FCmpOpCode, Int)
FLoad(Int)
FStore(Int)
FMove(Int)
FMoveI(Int)
IMoveF(Int)
LoadAddr
Cast(CastOpCode)
Call
Select
Ret
Nop
Intrinsic(String)
}fn llvm_global_constant_to_data(global_constant : &Constant) -> Array[GlobalValueData] raise MIRErrorfn translate_llvm_binary_inst(llvm_inst : BinaryInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_branch_inst(llvm_inst : BranchInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_cast_inst(llvm_inst : CastInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_conditional_branch(llvm_inst : BranchInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_fcmp_inst(llvm_inst : FCmpInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_float_binary_inst(llvm_inst : BinaryInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_fneg_inst(llvm_inst : FNegInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_gep_inst(llvm_inst : GetElementPtrInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_icmp_inst(llvm_inst : ICmpInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_inst(llvm_inst : &Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRErrorfn translate_llvm_int_binary_inst(llvm_inst : BinaryInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_load_inst(llvm_inst : LoadInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_phi_node(llvm_inst : PHINode, func : Function) -> Array[Instruction] raise MIRErrorfn translate_llvm_return_inst(llvm_inst : ReturnInst, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRErrorfn translate_llvm_select_inst(llvm_inst : SelectInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_store_inst(llvm_inst : StoreInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_switch_inst(llvm_inst : SwitchInst, builder : IRBuilder, func : Function, data_layout : DataLayout) -> Array[Instruction] raise MIRErrorfn translate_llvm_unconditional_branch(llvm_inst : BranchInst, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRErrorMachine IR, support compile llvm module (from MoonLLVM) to different architecture machine code.
Dependencies