Skip to main content

llvm_assembler/builder/
mod.rs

1use crate::program::LLvmProgram;
2use oak_llvm_ir::ast::{LLirBlock, LLirFunction, LLirGlobal, LLirInstruction, LLirItem, LLirParameter};
3
4/// LLVM 程序构建器
5pub struct LLvmProgramBuilder {
6    program: LLvmProgram,
7}
8
9impl LLvmProgramBuilder {
10    pub fn new() -> Self {
11        Self { program: LLvmProgram::new() }
12    }
13
14    pub fn add_function<F>(mut self, name: impl Into<String>, return_type: impl Into<String>, f: F) -> Self
15    where
16        F: FnOnce(LLvmFunctionBuilder) -> LLvmFunctionBuilder,
17    {
18        let builder = LLvmFunctionBuilder::new(name.into(), return_type.into());
19        let function = f(builder).build();
20        self.program.root.items.push(LLirItem::Function(function));
21        self
22    }
23
24    pub fn add_global(
25        mut self,
26        name: impl Into<String>,
27        ty: impl Into<String>,
28        value: impl Into<String>,
29        is_constant: bool,
30    ) -> Self {
31        self.program.root.items.push(LLirItem::Global(LLirGlobal {
32            name: name.into(),
33            ty: ty.into(),
34            value: value.into(),
35            is_constant,
36        }));
37        self
38    }
39
40    pub fn build(self) -> LLvmProgram {
41        self.program
42    }
43}
44
45/// LLVM 函数构建器
46pub struct LLvmFunctionBuilder {
47    function: LLirFunction,
48}
49
50impl LLvmFunctionBuilder {
51    pub fn new(name: String, return_type: String) -> Self {
52        Self { function: LLirFunction { name, return_type, parameters: Vec::new(), blocks: Vec::new(), span: (0..0).into() } }
53    }
54
55    pub fn add_parameter(mut self, name: impl Into<String>, ty: impl Into<String>) -> Self {
56        self.function.parameters.push(LLirParameter { name: name.into(), ty: ty.into() });
57        self
58    }
59
60    pub fn add_block<F>(mut self, label: impl Into<String>, f: F) -> Self
61    where
62        F: FnOnce(LLvmBlockBuilder) -> LLvmBlockBuilder,
63    {
64        let builder = LLvmBlockBuilder::new(Some(label.into()));
65        let block = f(builder).build();
66        self.function.blocks.push(block);
67        self
68    }
69
70    pub fn build(self) -> LLirFunction {
71        self.function
72    }
73}
74
75/// LLVM 基本块构建器
76pub struct LLvmBlockBuilder {
77    block: LLirBlock,
78}
79
80impl LLvmBlockBuilder {
81    pub fn new(label: Option<String>) -> Self {
82        Self { block: LLirBlock { label, instructions: Vec::new() } }
83    }
84
85    pub fn add_instruction(
86        mut self,
87        opcode: impl Into<String>,
88        operands: Vec<impl Into<String>>,
89        result: Option<impl Into<String>>,
90    ) -> Self {
91        self.block.instructions.push(LLirInstruction {
92            opcode: opcode.into(),
93            operands: operands.into_iter().map(|o| o.into()).collect(),
94            result: result.map(|r| r.into()),
95        });
96        self
97    }
98
99    /// 常用指令的便捷方法
100    pub fn ret(self, ty: impl Into<String>, val: impl Into<String>) -> Self {
101        let ty = ty.into();
102        let val = val.into();
103        self.add_instruction("ret", vec![format!("{} {}", ty, val)], None::<String>)
104    }
105
106    pub fn add(self, result: impl Into<String>, ty: impl Into<String>, lhs: impl Into<String>, rhs: impl Into<String>) -> Self {
107        let ty = ty.into();
108        let lhs = lhs.into();
109        let rhs = rhs.into();
110        self.add_instruction("add", vec![format!("{} {}, {}", ty, lhs, rhs)], Some(result))
111    }
112
113    pub fn sub(self, result: impl Into<String>, ty: impl Into<String>, lhs: impl Into<String>, rhs: impl Into<String>) -> Self {
114        let ty = ty.into();
115        let lhs = lhs.into();
116        let rhs = rhs.into();
117        self.add_instruction("sub", vec![format!("{} {}, {}", ty, lhs, rhs)], Some(result))
118    }
119
120    pub fn mul(self, result: impl Into<String>, ty: impl Into<String>, lhs: impl Into<String>, rhs: impl Into<String>) -> Self {
121        let ty = ty.into();
122        let lhs = lhs.into();
123        let rhs = rhs.into();
124        self.add_instruction("mul", vec![format!("{} {}, {}", ty, lhs, rhs)], Some(result))
125    }
126
127    pub fn call(
128        self,
129        result: Option<impl Into<String>>,
130        ty: impl Into<String>,
131        name: impl Into<String>,
132        args: Vec<impl Into<String>>,
133    ) -> Self {
134        let ty = ty.into();
135        let name = name.into();
136        let mut operands = vec![ty, name];
137        operands.extend(args.into_iter().map(|a| a.into()));
138        self.add_instruction("call", operands, result)
139    }
140
141    pub fn build(self) -> LLirBlock {
142        self.block
143    }
144}