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