MoonMIR

Machine IR, support compile llvm module (from MoonLLVM) to different architecture machine code.

llvm
Compiler
riscv64
aarch64
moon add Kaida-Amethyst/MoonMIR@0.1.2
Download zip
Version
0.1.2
License
Apache-2.0
Last updated
8 months ago
Downloads
25
README

#MoonMIR

MoonMIR is a compiler backend for MoonLLVM, designed to translate MoonLLVM's intermediate representation (IR) into assembly code. The entire project is written in MoonBit, ensuring seamless integration with the MoonBit ecosystem. Currently, MoonMIR supports riscv64 and aarch64 as compilation targets.

#Features

  • Pure MoonBit: Developed entirely in MoonBit for excellent compatibility and performance within the MoonBit environment.
  • MoonLLVM Backend: Acts as a compiler backend, transforming MoonLLVM IR into human-readable assembly code.
  • Cross-Architecture Support: Currently supports riscv64 and aarch64 architectures, with plans to expand.

#Getting Started

#Prerequisites

Before using MoonMIR, you need a MoonBit project that already utilizes Kaida-Amethyst/MoonLLVM.

#Installation

First, update your package index and then add MoonMIR to your project by running the following commands in your project's root directory:

moon update moon add Kaida-Amethyst/MoonMIR

#Configuration

To enable a specific target architecture, you must add its corresponding package to your moon.pkg.json file. For example, to compile to riscv64, modify your imports section as follows:

{ "imports": [ "Kaida-Amethyst/MoonLLVM/IR", "Kaida-Amethyst/MoonMIR/riscv64" ] }

If you need to target aarch64, simply replace riscv64 with aarch64.

#Usage Example

Here is a complete example demonstrating how to generate riscv64 assembly from MoonLLVM IR.

  1. Configure moon.pkg.json:

    { "imports": [ "Kaida-Amethyst/MoonLLVM/IR", "Kaida-Amethyst/MoonMIR/riscv64" ] }

  2. Write the MoonBit code:

    The following code snippet creates a simple add function using MoonLLVM and then compiles it to riscv64 assembly using MoonMIR.

    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 {
    _ => ()
    }
    }

#Future Plans

  • Expanded Architecture Support: Add more backends, with x86_64 as a priority.
  • Assembler and Linker: Develop a custom assembler (MoonAs) and linker (MoonLD) to create a complete toolchain.
  • Debugging Support: Integrate debugging capabilities.


#MoonMIR

MoonMIR 是一个为 MoonLLVM 设计的编译器后端,用于将 MoonLLVM 的中间表示(IR)转换为汇编代码。整个项目完全由 MoonBit 语言编写,确保了与 MoonBit 生态系统的无缝集成。目前,MoonMIR 支持 riscv64aarch64 作为编译目标。

#特性

  • 纯 MoonBit 实现: 完全使用 MoonBit 开发,在 MoonBit 环境中具有出色的兼容性和性能。
  • MoonLLVM 后端: 作为编译器后端,将 MoonLLVM IR 转换为人类可读的汇编代码。
  • 跨架构支持: 目前支持 riscv64aarch64 架构,并计划在未来扩展。

#快速上手

#先决条件

在使用 MoonMIR 之前,您需要一个已经使用 Kaida-Amethyst/MoonLLVM 的 MoonBit 项目。

#安装

首先,更新您的包索引,然后在项目根目录中运行以下命令,将 MoonMIR 添加到您的项目中:

moon update moon add Kaida-Amethyst/MoonMIR

#配置

要启用特定的目标架构,您必须将其对应的包添加到您的 moon.pkg.json 文件中。例如,要编译到 riscv64,请按如下方式修改您的 imports 部分:

{ "imports": [ "Kaida-Amethyst/MoonLLVM/IR", "Kaida-Amethyst/MoonMIR/riscv64" ] }

如果您需要针对 aarch64,只需将 riscv64 替换为 aarch64

#使用示例

以下是一个完整的示例,演示了如何从 MoonLLVM IR 生成 riscv64 汇编代码。

  1. 配置 moon.pkg.json:

    { "imports": [ "Kaida-Amethyst/MoonLLVM/IR", "Kaida-Amethyst/MoonMIR/riscv64" ] }

  2. 编写 MoonBit 代码:

    以下代码片段使用 MoonLLVM 创建一个简单的 add 函数,然后使用 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 {
    _ => ()
    }
    }

#未来计划

  • 扩展架构支持: 添加更多后端,优先支持 x86_64
  • 汇编器和链接器: 开发自定义的汇编器(MoonAs)和链接器(MoonLD),以构建完整的工具链。
  • 调试支持: 集成调试功能。

#
MIRError

pub suberror MIRError {
IRTranslateError(String)
LegalizeError(String)
InValidBitWidthError(String)
}

impl Show for MIRError

#
ArchConfig

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
}

Architecture Configuration

#
ArchConfig::aarch64

fn ArchConfig::aarch64() -> ArchConfig

#
ArchConfig::debug

fn ArchConfig::debug() -> ArchConfig

#
ArchConfig::is_valid_imm

fn ArchConfig::is_valid_imm(self : ArchConfig, imm : Int64) -> Bool

Check if an immediate value is valid for arithmetic instructions

#
ArchConfig::riscv64

fn ArchConfig::riscv64() -> ArchConfig

#
ArgPattern

pub(all) enum ArgPattern {
I
F
}

#
BasicBlock

impl Eq for BasicBlock
impl Show for BasicBlock

#
BasicBlock::compute_live_out_from_succs

fn BasicBlock::compute_live_out_from_succs(self : BasicBlock) ->
Set
[Operand]

#
BasicBlock::contains_virtual_reg

fn BasicBlock::contains_virtual_reg(self : BasicBlock) -> Bool

#
BasicBlock::insert_inst_after

fn BasicBlock::insert_inst_after(self : BasicBlock, inst : Instruction, after~ : Instruction) -> Unit?

#
BasicBlock::insert_inst_before

fn BasicBlock::insert_inst_before(self : BasicBlock, inst : Instruction, before~ : Instruction) -> Unit?

#
BasicBlock::legalize

fn BasicBlock::legalize(self : BasicBlock) -> Unit raise MIRError

#
BasicBlock::live_analysis

fn BasicBlock::live_analysis(self : BasicBlock) -> Bool

return if is changed

#
BasicBlock::new

fn BasicBlock::new(func : Function, label : String) -> BasicBlock

#
BasicBlock::phi_elimination

fn BasicBlock::phi_elimination(self : BasicBlock) -> Unit raise MIRError

#
BasicBlock::push

fn BasicBlock::push(self : BasicBlock, inst : Instruction) -> Unit

#
BasicBlock::push_inst_before_terminator

fn BasicBlock::push_inst_before_terminator(self : BasicBlock, inst : Instruction) -> Unit

#
BasicBlock::rewrite_by_replacement_map

fn BasicBlock::rewrite_by_replacement_map(self : BasicBlock, replacement_map : Map[Operand, Operand]) -> Unit

#
BasicBlock::translate_llvm_basic_block

fn BasicBlock::translate_llvm_basic_block(self : BasicBlock, llvm_bb :
BasicBlock
) -> Unit raise MIRError

#
BasicBlock::update_live_in

fn BasicBlock::update_live_in(self : BasicBlock, live_in :
Set
[Operand]) -> Bool

#
BasicBlock::update_live_out

fn BasicBlock::update_live_out(self : BasicBlock, live_out :
Set
[Operand]) -> Bool

Return True is the live_out set was changed

#
BranchOpCode

pub(all) enum BranchOpCode {
Beq
Bne
Bgt
Bge
Blt
Ble
Bgtu
Bgeu
Bltu
Bleu
Jmp
}

impl Eq for BranchOpCode

#
CastOpCode

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)
}

impl Eq for CastOpCode
impl Show for CastOpCode

#
FBinaryOpCode

pub(all) enum FBinaryOpCode {
FAdd
FSub
FMul
FDiv
FRem
}

impl Eq for FBinaryOpCode

#
FBinaryOpCode::is_commutative

fn FBinaryOpCode::is_commutative(self : FBinaryOpCode) -> Bool

#
FCmpOpCode

pub(all) enum FCmpOpCode {
Feq
Fne
Fgt
Fge
Flt
Fle
}

impl Eq for FCmpOpCode
impl Show for FCmpOpCode

#
FRegister

pub(all) enum FRegister {
VFReg(Int)
FAReg(Int)
FTReg(Int)
FSReg(Int)
}

impl Eq for FRegister
impl Hash for FRegister
impl Show for FRegister

#
FUnaryOpCode

pub(all) enum FUnaryOpCode {
FNeg
}

impl Eq for FUnaryOpCode

#
Function

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
}

{args passed in stack } ---------- fp reg_stack { callee-saved registers } { spilled registers } { temporary space for registers } { ra, fp saved by callee } ---------- fp' var_stack { local variables } { function parameters passed on stack } ---------- sp
impl Show for Function

#
Function::adjust_mem_operands

fn Function::adjust_mem_operands(self : Function) -> Unit

#
Function::alloc_register

fn Function::alloc_register(self : Function) -> Unit raise MIRError

#
Function::append_basic_block

#callsite(autofill(loc))
fn Function::append_basic_block(self : Function, label : String, loc~ : SourceLoc) -> BasicBlock

#
Function::bind_llvm_value_to_fregister

fn Function::bind_llvm_value_to_fregister(self : Function, val : &
Value
, freg : FRegister) -> Unit

#
Function::bind_llvm_value_to_mem

fn Function::bind_llvm_value_to_mem(self : Function, val : &
Value
, base : IRegister, offset : Int64) -> Unit

#
Function::bind_llvm_value_to_register

fn Function::bind_llvm_value_to_register(self : Function, val : &
Value
, reg : IRegister) -> Unit

#
Function::build_interference_graph

fn Function::build_interference_graph(self : Function) -> InterferenceGraph

#
Function::build_preference_list

fn Function::build_preference_list(self : Function) -> Map[Operand,
Deque
[Operand]]

Move Bias

#
Function::collect_blocks_with_opcode

fn Function::collect_blocks_with_opcode(self : Function, opcode : OpCode) -> Array[BasicBlock]

#
Function::collect_insts_with_opcode

fn Function::collect_insts_with_opcode(self : Function, opcode : OpCode) -> Array[Instruction]

#
Function::contains_virtual_reg

fn Function::contains_virtual_reg(self : Function) -> Bool

#
Function::get_entry_block

fn Function::get_entry_block(self : Function) -> BasicBlock?

#
Function::get_operand_from_llvm_value

fn Function::get_operand_from_llvm_value(self : Function, val : &
Value
) -> Operand?

#
Function::get_param

fn Function::get_param(self : Function, idx : Int) -> Operand?

#
Function::has_inst_with_opcode

fn Function::has_inst_with_opcode(self : Function, opcode : OpCode) -> Bool

#
Function::inst_iter

fn Function::inst_iter(self : Function) -> Iter[Instruction]

#
Function::keeped_ftreg1

fn Function::keeped_ftreg1(self : Function) -> FRegister

#
Function::keeped_ftreg2

fn Function::keeped_ftreg2(self : Function) -> (FRegister, FRegister)

#
Function::keeped_treg1

fn Function::keeped_treg1(self : Function) -> IRegister

#
Function::keeped_treg2

fn Function::keeped_treg2(self : Function) -> (IRegister, IRegister)

#
Function::legalize

fn Function::legalize(func : Function) -> Unit raise MIRError

#
Function::live_analysis

fn Function::live_analysis(self : Function) -> Unit

Perform live variable analysis on the function.

#
Function::new

fn Function::new(mod : Module, name : String, is_external : Bool, is_variadic? : Bool) -> Function

#
Function::new_virtual_freg

fn Function::new_virtual_freg(self : Function) -> FRegister

#
Function::new_virtual_reg

fn Function::new_virtual_reg(self : Function) -> IRegister

#
Function::phi_elimination

fn Function::phi_elimination(func : Function) -> Unit raise MIRError

#
Function::post_ra

fn Function::post_ra(self : Function) -> Unit

#
Function::rewrite_by_replacement_map

fn Function::rewrite_by_replacement_map(self : Function, replacement_map : Map[Operand, Operand]) -> Unit

#
Function::translate_llvm_function

fn Function::translate_llvm_function(self : Function, llvm_func :
Function
) -> Unit raise MIRError

#
Function::translate_params

#callsite(autofill(loc))
fn Function::translate_params(self : Function, loc~ : SourceLoc) -> Unit

#
Function::traverse_llvm_basic_blocks

#callsite(autofill(loc))
fn Function::traverse_llvm_basic_blocks(self : Function, loc~ : SourceLoc) -> Array[(
BasicBlock
, BasicBlock)]

#
GlobalValue

pub(all) struct GlobalValue {
label : String
content : GlobalValueContent
mod : Module
llvm_gv : &
GlobalValue
?
}

impl Show for GlobalValue

#
GlobalValueContent

pub(all) enum GlobalValueContent {
String(String)
Zero(UInt)
Data(Array[GlobalValueData])
}

#
GlobalValueData

pub(all) enum GlobalValueData {
Quad(UInt64)
Word(UInt)
Half(UInt16)
Byte(Byte)
}

#
IBinaryOpCode

pub(all) enum IBinaryOpCode {
Add
Sub
Mul
Div
Rem
And
Or
Xor
Shl
LShr
AShr
}

impl Eq for IBinaryOpCode

#
IBinaryOpCode::is_commutative

fn IBinaryOpCode::is_commutative(self : IBinaryOpCode) -> Bool

#
ICmpOpCode

pub(all) enum ICmpOpCode {
Eq
Ne
Gt
Ge
Lt
Le
Gtu
Geu
Ltu
Leu
}

impl Eq for ICmpOpCode
impl Show for ICmpOpCode

#
IRBuilder

pub struct IRBuilder {
func : Function
bb : BasicBlock
}

#
IRBuilder::build_branch

fn IRBuilder::build_branch(self : IRBuilder, opcode : BranchOpCode, bits : Int, lhs~ : IRegister, rhs~ : IRegister, true_label~ : String, false_label~ : String) -> Instruction

#
IRBuilder::build_branch_imm

fn IRBuilder::build_branch_imm(self : IRBuilder, opcode : BranchOpCode, bits : Int, lhs~ : IRegister, rhs~ : Int64, true_label~ : String, false_label~ : String) -> Instruction

#
IRBuilder::build_call

fn IRBuilder::build_call(self : IRBuilder, func_name : String) -> Instruction

#
IRBuilder::build_fbinary

#callsite(autofill(loc))
fn IRBuilder::build_fbinary(self : IRBuilder, binop : FBinaryOpCode, bits : Int, dst~ : FRegister, src1~ : FRegister, src2~ : FRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_fcmp

#callsite(autofill(loc))
fn IRBuilder::build_fcmp(self : IRBuilder, cmpop : FCmpOpCode, bits : Int, dst~ : IRegister, src1~ : FRegister, src2~ : FRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_fmove

#callsite(autofill(loc))
fn IRBuilder::build_fmove(self : IRBuilder, bits : Int, dst~ : FRegister, src~ : FRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_fmove_from_ireg

#callsite(autofill(loc))
fn IRBuilder::build_fmove_from_ireg(self : IRBuilder, bits : Int, dst~ : FRegister, src~ : IRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_fmove_imm

#callsite(autofill(loc))
fn IRBuilder::build_fmove_imm(self : IRBuilder, bits : Int, dst~ : FRegister, src~ : Double, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_fmove_to_ireg

#callsite(autofill(loc))
fn IRBuilder::build_fmove_to_ireg(self : IRBuilder, bits : Int, dst~ : IRegister, src~ : FRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_fneg

#callsite(autofill(loc))
fn IRBuilder::build_fneg(self : IRBuilder, bits : Int, dst~ : FRegister, src~ : FRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_fp_to_si

fn IRBuilder::build_fp_to_si(self : IRBuilder, from_ty_size~ : Int, to_ty_size~ : Int, dst~ : IRegister, src~ : FRegister) -> Instruction

#
IRBuilder::build_fp_to_ui

fn IRBuilder::build_fp_to_ui(self : IRBuilder, from_ty_size~ : Int, to_ty_size~ : Int, dst~ : IRegister, src~ : FRegister) -> Instruction

#
IRBuilder::build_fpext

#callsite(autofill(loc))
fn IRBuilder::build_fpext(self : IRBuilder, from_ty_size~ : Int, to_ty_size~ : Int, dst~ : FRegister, src~ : FRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_fptrunc

#callsite(autofill(loc))
fn IRBuilder::build_fptrunc(self : IRBuilder, from_ty_size~ : Int, to_ty_size~ : Int, dst~ : FRegister, src~ : FRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_funary

#callsite(autofill(loc))
fn IRBuilder::build_funary(self : IRBuilder, unop : FUnaryOpCode, bits : Int, dst~ : FRegister, src~ : FRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_ibinary

#callsite(autofill(loc))
fn IRBuilder::build_ibinary(self : IRBuilder, binop : IBinaryOpCode, bits : Int, dst~ : IRegister, src1~ : IRegister, src2~ : IRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_ibinary_imm

#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

#
IRBuilder::build_icmp

#callsite(autofill(loc))
fn IRBuilder::build_icmp(self : IRBuilder, cmpop : ICmpOpCode, bits : Int, dst~ : IRegister, src1~ : IRegister, src2~ : IRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_imove

#callsite(autofill(loc))
fn IRBuilder::build_imove(self : IRBuilder, bits : Int, dst~ : IRegister, src~ : IRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_imove_imm

#callsite(autofill(loc))
fn IRBuilder::build_imove_imm(self : IRBuilder, bits : Int, dst~ : IRegister, src~ : Int64, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_iunary

#callsite(autofill(loc))
fn IRBuilder::build_iunary(self : IRBuilder, unop : IUnaryOpCode, bits : Int, dst~ : IRegister, src~ : IRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_jmp

fn IRBuilder::build_jmp(self : IRBuilder, target_label~ : String) -> Instruction

#
IRBuilder::build_load_addr

fn IRBuilder::build_load_addr(self : IRBuilder, dst : IRegister, label : String) -> Instruction

#
IRBuilder::build_loadf

#callsite(autofill(loc))
fn IRBuilder::build_loadf(self : IRBuilder, bits : Int, dst~ : FRegister, base~ : IRegister, offset~ : Int64, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_loadi

#callsite(autofill(loc))
fn IRBuilder::build_loadi(self : IRBuilder, bits : Int, dst~ : IRegister, base~ : IRegister, offset~ : Int64, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_ret

fn IRBuilder::build_ret(self : IRBuilder) -> Instruction

#
IRBuilder::build_sext

#callsite(autofill(loc))
fn IRBuilder::build_sext(self : IRBuilder, from_ty_size~ : Int, to_ty_size~ : Int, dst~ : IRegister, src~ : IRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_si_to_fp

fn IRBuilder::build_si_to_fp(self : IRBuilder, from_ty_size~ : Int, to_ty_size~ : Int, dst~ : FRegister, src~ : IRegister) -> Instruction

#
IRBuilder::build_storef

#callsite(autofill(loc))
fn IRBuilder::build_storef(self : IRBuilder, bits : Int, src~ : FRegister, base~ : IRegister, offset~ : Int64, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_storei

#callsite(autofill(loc))
fn IRBuilder::build_storei(self : IRBuilder, bits : Int, src~ : IRegister, base~ : IRegister, offset~ : Int64, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_trunc

#callsite(autofill(loc))
fn IRBuilder::build_trunc(self : IRBuilder, from_ty_size~ : Int, to_ty_size~ : Int, dst~ : IRegister, src~ : IRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::build_ui_to_fp

fn IRBuilder::build_ui_to_fp(self : IRBuilder, from_ty_size~ : Int, to_ty_size~ : Int, dst~ : FRegister, src~ : IRegister) -> Instruction

#
IRBuilder::build_zext

#callsite(autofill(loc))
fn IRBuilder::build_zext(self : IRBuilder, from_ty_size~ : Int, to_ty_size~ : Int, dst~ : IRegister, src~ : IRegister, loc~ : SourceLoc) -> Instruction raise MIRError

#
IRBuilder::new

fn IRBuilder::new(func : Function, bb : BasicBlock) -> IRBuilder

#
IRegister

pub(all) enum IRegister {
VReg(Int)
AReg(Int)
TReg(Int)
SReg(Int)
StackPtr
FramePtr
FramePtrPrim
ReturnAddr
}

impl Eq for IRegister
impl Hash for IRegister
impl Show for IRegister

#
IUnaryOpCode

pub(all) enum IUnaryOpCode {
Not
}

impl Eq for IUnaryOpCode

#
Instruction

pub(all) struct Instruction {
id : Int
opcode : OpCode
defs : Array[Operand]
uses : Array[Operand]
bb : BasicBlock
func : Function
live_in :
Set
[Operand]
live_out :
Set
[Operand]
}

impl Eq for Instruction
impl Show for Instruction

#
Instruction::contains_virtual_reg

fn Instruction::contains_virtual_reg(self : Instruction) -> Bool

#
Instruction::legalize

fn Instruction::legalize(self : Instruction) -> Array[Instruction] raise MIRError

#
Instruction::legalize_branch

fn Instruction::legalize_branch(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_cast

fn Instruction::legalize_cast(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_cast_fp_to_si

fn Instruction::legalize_cast_fp_to_si(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRError

#
Instruction::legalize_cast_fp_to_ui

fn Instruction::legalize_cast_fp_to_ui(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRError

#
Instruction::legalize_cast_fpext

fn Instruction::legalize_cast_fpext(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRError

#
Instruction::legalize_cast_fptrunc

fn Instruction::legalize_cast_fptrunc(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRError

#
Instruction::legalize_cast_sext

fn Instruction::legalize_cast_sext(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRError

#
Instruction::legalize_cast_si_to_fp

fn Instruction::legalize_cast_si_to_fp(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRError

#
Instruction::legalize_cast_trunc

fn Instruction::legalize_cast_trunc(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRError

#
Instruction::legalize_cast_ui_to_fp

fn Instruction::legalize_cast_ui_to_fp(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRError

#
Instruction::legalize_cast_zext

fn Instruction::legalize_cast_zext(self : Instruction, builder : IRBuilder, func : Function, cast_op : CastOpCode) -> Array[Instruction] raise MIRError

#
Instruction::legalize_fbinary

fn Instruction::legalize_fbinary(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_fcmp

fn Instruction::legalize_fcmp(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_fload

fn Instruction::legalize_fload(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_fmove

fn Instruction::legalize_fmove(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_fmovei

fn Instruction::legalize_fmovei(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_fstore

fn Instruction::legalize_fstore(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_funary

fn Instruction::legalize_funary(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_icmp

fn Instruction::legalize_icmp(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_iload

fn Instruction::legalize_iload(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_imove

fn Instruction::legalize_imove(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_imovef

fn Instruction::legalize_imovef(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

imovef means move from freg to ireg

#
Instruction::legalize_istore

fn Instruction::legalize_istore(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_iunary

fn Instruction::legalize_iunary(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
Instruction::legalize_load_addr

fn Instruction::legalize_load_addr(self : Instruction, builder : IRBuilder) -> Array[Instruction] raise MIRError

loadaddr means load address of a variable (in memory) into a register def must be IRegister, use must be label

#
Instruction::live_analysis

fn Instruction::live_analysis(self : Instruction) -> Bool

#
Instruction::new

fn Instruction::new(opcode : OpCode, defs : Array[Operand], uses : Array[Operand], bb : BasicBlock) -> Instruction

#
Instruction::rewrite_by_replacement_map

fn Instruction::rewrite_by_replacement_map(self : Instruction, replacement_map : Map[Operand, Operand]) -> Unit

#
Instruction::update_live_in

fn Instruction::update_live_in(self : Instruction, live_in :
Set
[Operand]) -> Bool

Returns true if live_out changed.

#
Instruction::update_live_out

fn Instruction::update_live_out(self : Instruction, live_out :
Set
[Operand]) -> Bool

Returns true if live_in changed.

#
InterferenceGraph

pub struct InterferenceGraph {
nodes :
Set
[Operand]
edges : Map[Operand,
Set
[Operand]]
color_map : Map[Operand, Operand]
available_int_colors :
Set
[Operand]
available_fp_colors :
Set
[Operand]
spilled_count : Int
}

#
InterferenceGraph::add_edge

fn InterferenceGraph::add_edge(self : InterferenceGraph, node1 : Operand, node2 : Operand) -> Unit

#
InterferenceGraph::add_node

fn InterferenceGraph::add_node(self : InterferenceGraph, node : Operand) -> Unit

#
InterferenceGraph::coloring

#
InterferenceGraph::find_uncolored_vfreg_with_greatest_uncolored_degree

fn InterferenceGraph::find_uncolored_vfreg_with_greatest_uncolored_degree(self : InterferenceGraph) -> Operand?

#
InterferenceGraph::find_uncolored_vreg_with_greatest_uncolored_degree

fn InterferenceGraph::find_uncolored_vreg_with_greatest_uncolored_degree(self : InterferenceGraph) -> Operand?

#
InterferenceGraph::new

fn InterferenceGraph::new(config : ArchConfig, spilled_count : Int) -> InterferenceGraph

#
Module

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]
}

impl Show for Module

#
Module::add_function

fn Module::add_function(self : Module, name : String, arg_patterns : Array[ArgPattern], is_external : Bool, is_variadic? : Bool) -> Function

let 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)

#
Module::add_global_data

fn Module::add_global_data(self : Module, label : String, data : Array[GlobalValueData]) -> GlobalValue

let 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)

#
Module::add_global_string

fn Module::add_global_string(self : Module, label~ : String, content~ : String) -> GlobalValue

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)

#
Module::add_global_zero_data

fn Module::add_global_zero_data(self : Module, label : String, size : UInt) -> GlobalValue

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)

#
Module::alloc_register

fn Module::alloc_register(self : Module) -> Unit raise MIRError

#
Module::get_function

fn Module::get_function(self : Module, name : String) -> Function?

#
Module::legalize

fn Module::legalize(self : Module) -> Unit raise MIRError

#
Module::new

fn Module::new(arch_config : ArchConfig, source_file? : String) -> Module

#
Module::post_ra

fn Module::post_ra(self : Module) -> Unit

#
Module::translate_global_values

fn Module::translate_global_values(self : Module, llvm_mod :
Module
) -> Unit raise MIRError

#
Module::translate_llvm_global_constant

fn Module::translate_llvm_global_constant(self : Module, global_name : String, global_constant : &
Constant
) -> Unit raise MIRError

#
Module::translate_llvm_module

fn Module::translate_llvm_module(self : Module, llvm_mod :
Module
) -> Unit raise MIRError

#
OpCode

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)
}

impl Eq for OpCode
impl Show for OpCode

#
OpCode::is_terminator

fn OpCode::is_terminator(self : OpCode) -> Bool

#
Operand

pub(all) enum Operand {
IRegister(IRegister)
FRegister(FRegister)
Mem(IRegister, Int64)
MemLoc(IRegister, Int64)
MemGroup(IRegister, Array[Int64])
Imm(Int64)
FImm(Double)
Label(String)
}

impl Eq for Operand
impl Hash for Operand
impl Show for Operand

#
get_constant_size

fn get_constant_size(constant : &
Constant
) -> UInt

Get the size of a constant in bytes

#
get_type_size

fn get_type_size(ty : &
Type
) -> UInt

Get the size of a type in bytes

#
is_zero_initializer

fn is_zero_initializer(constant : &
Constant
) -> Bool

Check if a constant is a zeroinitializer

#
llvm_global_constant_to_data

fn llvm_global_constant_to_data(global_constant : &
Constant
) -> Array[GlobalValueData] raise MIRError

#
translate_bitcast

fn translate_bitcast(data_size : Int, from_op : Operand, dst_op : Operand, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRError

#
translate_fpext

fn translate_fpext(from_ty_size : Int, to_ty_size : Int, from_op : Operand, dst_op : Operand, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRError

#
translate_fptosi

fn translate_fptosi(from_ty_size : Int, to_ty_size : Int, from_op : Operand, dst_op : Operand, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRError

#
translate_fptoui

fn translate_fptoui(from_ty_size : Int, to_ty_size : Int, from_op : Operand, dst_op : Operand, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRError

#
translate_fptrunc

fn translate_fptrunc(from_ty_size : Int, to_ty_size : Int, from_op : Operand, dst_op : Operand, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRError

#
translate_llvm_binary_inst

fn translate_llvm_binary_inst(llvm_inst :
BinaryInst
, builder : IRBuilder, func : Function, data_layout :
DataLayout
) -> Array[Instruction] raise MIRError

IRTranslate from LLVM IR to MoonMIR for Int or Float binary instructions.

#
translate_llvm_branch_inst

fn translate_llvm_branch_inst(llvm_inst :
BranchInst
, builder : IRBuilder, func : Function, data_layout :
DataLayout
) -> Array[Instruction] raise MIRError

#
translate_llvm_call_inst

fn translate_llvm_call_inst(llvm_inst :
CallInst
, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRError

IRTranslate from LLVM IR to MoonMIR for CallInst.

#
translate_llvm_cast_inst

fn translate_llvm_cast_inst(llvm_inst :
CastInst
, builder : IRBuilder, func : Function, data_layout :
DataLayout
) -> Array[Instruction] raise MIRError

#
translate_llvm_conditional_branch

fn translate_llvm_conditional_branch(llvm_inst :
BranchInst
, builder : IRBuilder, func : Function, data_layout :
DataLayout
) -> Array[Instruction] raise MIRError

IRTranslate from LLVM IR to MoonMIR for conditional BranchInst.

#
translate_llvm_fcmp_inst

fn translate_llvm_fcmp_inst(llvm_inst :
FCmpInst
, builder : IRBuilder, func : Function, data_layout :
DataLayout
) -> Array[Instruction] raise MIRError

#
translate_llvm_float_binary_inst

fn translate_llvm_float_binary_inst(llvm_inst :
BinaryInst
, builder : IRBuilder, func : Function, data_layout :
DataLayout
) -> Array[Instruction] raise MIRError

IRTranslate from LLVM IR to MIR for floating-point BinaryInst

#
translate_llvm_fneg_inst

fn translate_llvm_fneg_inst(llvm_inst :
FNegInst
, builder : IRBuilder, func : Function, data_layout :
DataLayout
) -> Array[Instruction] raise MIRError

IRTranslate from LLVM IR to MoonMIR for FNegInst

#
translate_llvm_gep_inst

#
translate_llvm_icmp_inst

fn translate_llvm_icmp_inst(llvm_inst :
ICmpInst
, builder : IRBuilder, func : Function, data_layout :
DataLayout
) -> Array[Instruction] raise MIRError

IRTranslate from LLVM IR to MoonMIR for ICmpInst.

#
translate_llvm_inst

fn translate_llvm_inst(llvm_inst : &
Instruction
, builder : IRBuilder) -> Array[Instruction] raise MIRError

#
translate_llvm_int_binary_inst

fn translate_llvm_int_binary_inst(llvm_inst :
BinaryInst
, builder : IRBuilder, func : Function, data_layout :
DataLayout
) -> Array[Instruction] raise MIRError

IRTranslate from LLVM IR to MIR for Int BinaryInst

#
translate_llvm_load_inst

fn translate_llvm_load_inst(llvm_inst :
LoadInst
, builder : IRBuilder, func : Function, data_layout :
DataLayout
) -> Array[Instruction] raise MIRError

#
translate_llvm_phi_node

fn translate_llvm_phi_node(llvm_inst :
PHINode
, func : Function) -> Array[Instruction] raise MIRError

#
translate_llvm_return_inst

fn translate_llvm_return_inst(llvm_inst :
ReturnInst
, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRError

#
translate_llvm_select_inst

fn translate_llvm_select_inst(llvm_inst :
SelectInst
, builder : IRBuilder, func : Function, data_layout :
DataLayout
) -> Array[Instruction] raise MIRError

#
translate_llvm_store_inst

fn translate_llvm_store_inst(llvm_inst :
StoreInst
, builder : IRBuilder, func : Function, data_layout :
DataLayout
) -> Array[Instruction] raise MIRError

IRTranslate from LLVM IR to MoonMIR for StoreInst.

#
translate_llvm_switch_inst

fn translate_llvm_switch_inst(llvm_inst :
SwitchInst
, builder : IRBuilder, func : Function, data_layout :
DataLayout
) -> Array[Instruction] raise MIRError

#
translate_llvm_unconditional_branch

fn translate_llvm_unconditional_branch(llvm_inst :
BranchInst
, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRError

IRTranslate from LLVM IR to MoonMIR for unconditional BranchInst.

#
translate_sext

fn translate_sext(from_ty_size : Int, to_ty_size : Int, from_op : Operand, dst_op : Operand, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRError

#
translate_sitofp

fn translate_sitofp(from_ty_size : Int, to_ty_size : Int, from_op : Operand, dst_op : Operand, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRError

#
translate_trunc

fn translate_trunc(from_ty_size : Int, to_ty_size : Int, from_op : Operand, dst_op : Operand, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRError

#
translate_uitofp

fn translate_uitofp(from_ty_size : Int, to_ty_size : Int, from_op : Operand, dst_op : Operand, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRError

#
translate_zext

fn translate_zext(from_ty_size : Int, to_ty_size : Int, from_op : Operand, dst_op : Operand, builder : IRBuilder, func : Function) -> Array[Instruction] raise MIRError