cardinal_codegen/
instbuilder.rs

1//! Provides a trait for building instructions.
2
3use crate::entities::{AbiType, Block, Named, NamedProperty, Type, Value, ValueInfo};
4use crate::instruction::{InstBlock, InstructionInfo, Opcode};
5
6/// A trait for building instructions.
7pub trait InstBuilder {
8
9    /// Defines a value in the InstBuilder's values table, then returning the value.
10    fn create_value(&mut self, value: ValueInfo) -> Value;
11
12    /// Pushes an instruction to the InstBuilder's instruction list.
13    fn create_inst(&mut self, inst: InstructionInfo);
14
15    /// Creates a block and registers it in the InstBuilder's block table, returning a reference
16    /// to said block.
17    fn create_block(&mut self, block: InstBlock) -> Block;
18
19    /// Returns a pointer to the given block.
20    fn use_block(&mut self, block: Block) -> &mut InstBlock;
21
22    /// Adds a required import.
23    fn require_import(&mut self, name: String);
24
25    /// Creates an unsigned 64-bit integer constant.
26    fn iconst_int(&mut self, value: u64) -> Value {
27        self.create_value(ValueInfo::IntegerConstant(value))
28    }
29
30    /// Creates an unsigned 64-bit float constant.
31    fn iconst_float(&mut self, value: f64) -> Value {
32        self.create_value(ValueInfo::FloatConstant(value))
33    }
34
35    /// Creates an unsigned 64-bit double constant.
36    fn iconst_double(&mut self, value: f64) -> Value {
37        self.create_value(ValueInfo::DoubleConstant(value))
38    }
39
40    /// Creates a boolean constant.
41    fn iconst_bool(&mut self, value: bool) -> Value {
42        self.create_value(ValueInfo::BooleanConstant(value))
43    }
44
45    /// Creates a string constant.
46    fn iconst_str(&mut self, value: String) -> Value {
47        self.create_value(ValueInfo::StringConstant(value))
48    }
49
50    /// Creates a named reference constant.
51    fn iconst_named(&mut self, name: String) -> Value {
52        self.create_value(ValueInfo::Named(Named::new(name)))
53    }
54
55    /// Creates a named reference constant including the provided properties.
56    fn iconst_named_props(&mut self, name: String, props: Vec<NamedProperty>) -> Value {
57        self.create_value(ValueInfo::Named(Named::new_props(name, props)))
58    }
59
60    /// Returns a new basic NamedProperty.
61    fn iconst_named_property(&self, name: String) -> NamedProperty {
62        NamedProperty::Basic(name)
63    }
64
65    /// Returns a new static NamedProperty.
66    fn iconst_named_static(&self, name: String) -> NamedProperty {
67        NamedProperty::Static(name)
68    }
69
70    /// Returns a new pointer NamedProperty.
71    fn iconst_named_pointer(&self, name: String) -> NamedProperty {
72        NamedProperty::Pointer(name)
73    }
74
75    /// Returns a new index NamedProperty.
76    fn iconst_named_index(&self, name: Value) -> NamedProperty {
77        NamedProperty::Index(name)
78    }
79
80    /// Creates a C target specific boolean type.  Requires the `stdbool.h` standard library
81    /// to be provided by your C compiler.
82    fn ctype_bool(&mut self) -> AbiType {
83        // The C bool type requires `stdbool.h` to be imported.
84        self.require_import("stdbool.h".into());
85        AbiType("bool".into(), Type::Plain)
86    }
87
88    /// Creates a C target specific 8 bit unsigned integer type.  Requires the `stdint.h`
89    /// standard library to be provided by your C compiler.
90    fn ctype_uint8(&mut self) -> AbiType {
91        self.require_import("stdint.h".into());
92        AbiType("uint8_t".into(), Type::Plain)
93    }
94
95    /// Creates a C target specific 16 bit unsigned integer type.  Requires the `stdint.h`
96    /// standard library to be provided by your C compiler.
97    fn ctype_uint16(&mut self) -> AbiType {
98        self.require_import("stdint.h".into());
99        AbiType("uint16_t".into(), Type::Plain)
100    }
101
102    /// Creates a C target specific 32 bit unsigned integer type.  Requires the `stdint.h`
103    /// standard library to be provided by your C compiler.
104    fn ctype_uint32(&mut self) -> AbiType {
105        self.require_import("stdint.h".into());
106        AbiType("uint32_t".into(), Type::Plain)
107    }
108
109    /// Creates a C target specific 64 bit unsigned integer type.  Requires the `stdint.h`
110    /// standard library to be provided by your C compiler.
111    fn ctype_uint64(&mut self) -> AbiType {
112        self.require_import("stdint.h".into());
113        AbiType("uint64_t".into(), Type::Plain)
114    }
115
116    /// Creates a C target specific size that scales to the target's architecture.  For 32-bit
117    /// processors, this is the same as a `uint32` and for 64-bit architectures this is the
118    /// same as a `uint64`.
119    fn ctype_usize(&mut self) -> AbiType {
120        self.require_import("stdint.h".into());
121        AbiType("uintptr".into(), Type::Plain)
122    }
123
124    /// Creates a C target specific 8 bit integer type.  Requires the `stdint.h`
125    /// standard library to be provided by your C compiler.
126    fn ctype_int8(&mut self) -> AbiType {
127        self.require_import("stdint.h".into());
128        AbiType("int8_t".into(), Type::Plain)
129    }
130
131    /// Creates a C target specific 16 bit integer type.  Requires the `stdint.h`
132    /// standard library to be provided by your C compiler.
133    fn ctype_int16(&mut self) -> AbiType {
134        self.require_import("stdint.h".into());
135        AbiType("uint16_t".into(), Type::Plain)
136    }
137
138    /// Creates a C target specific 32 bit integer type.  Requires the `stdint.h`
139    /// standard library to be provided by your C compiler.
140    fn ctype_int32(&mut self) -> AbiType {
141        self.require_import("stdint.h".into());
142        AbiType("int32_t".into(), Type::Plain)
143    }
144
145    /// Creates a C target specific 64 bit integer type.  Requires the `stdint.h`
146    /// standard library to be provided by your C compiler.
147    fn ctype_int64(&mut self) -> AbiType {
148        self.require_import("stdint.h".into());
149        AbiType("int64_t".into(), Type::Plain)
150    }
151
152    /// Creates a C target specific size that scales to the target's architecture.  For 32-bit
153    /// processors, this is the same as an `int32` and for 64-bit architectures this is the
154    /// same as an `int64`.
155    fn ctype_isize(&mut self) -> AbiType {
156        self.require_import("stdint.h".into());
157        AbiType("intptr".into(), Type::Plain)
158    }
159
160    /// A C-specific character type.
161    fn ctype_char(&mut self) -> AbiType {
162        AbiType("char".into(), Type::Plain)
163    }
164
165    /// Adds two values together and returns the sum of the expression.
166    fn iadd(&mut self, l: Value, r: Value) -> Value {
167        self.create_value(ValueInfo::Instruction(InstructionInfo {
168            opcode: Opcode::Add,
169            arguments: vec![l, r]
170        }))
171    }
172
173    /// Subtracts two values together and returns the sum of the expression.
174    fn isub(&mut self, l: Value, r: Value) -> Value {
175        self.create_value(ValueInfo::Instruction(InstructionInfo {
176            opcode: Opcode::Sub,
177            arguments: vec![l, r]
178        }))
179    }
180
181    /// Multiplies two values together and returns the sum of the expression.
182    fn imul(&mut self, l: Value, r: Value) -> Value {
183        self.create_value(ValueInfo::Instruction(InstructionInfo {
184            opcode: Opcode::Mul,
185            arguments: vec![l, r]
186        }))
187    }
188
189    /// Divides two values together and returns the sum of the expression.
190    fn idiv(&mut self, l: Value, r: Value) -> Value {
191        self.create_value(ValueInfo::Instruction(InstructionInfo {
192            opcode: Opcode::Div,
193            arguments: vec![l, r]
194        }))
195    }
196
197    /// Divides two values together and returns the remainder of the expression.  Equivalent to
198    /// the `%` (modulus) operator.
199    fn imod(&mut self, l: Value, r: Value) -> Value {
200        self.create_value(ValueInfo::Instruction(InstructionInfo {
201            opcode: Opcode::Mod,
202            arguments: vec![l, r]
203        }))
204    }
205
206    /// Returns the results of the Bitwise AND operation.
207    fn ibit_and(&mut self, l: Value, r: Value) -> Value {
208        self.create_value(ValueInfo::Instruction(InstructionInfo {
209            opcode: Opcode::BitAnd,
210            arguments: vec![l, r]
211        }))
212    }
213
214    /// Returns the results of the Bitwise OR operation.
215    fn ibit_or(&mut self, l: Value, r: Value) -> Value {
216        self.create_value(ValueInfo::Instruction(InstructionInfo {
217            opcode: Opcode::BitOr,
218            arguments: vec![l, r]
219        }))
220    }
221
222    /// Returns the results of the Bitwise XOR operation.
223    fn ibit_xor(&mut self, l: Value, r: Value) -> Value {
224        self.create_value(ValueInfo::Instruction(InstructionInfo {
225            opcode: Opcode::BitXor,
226            arguments: vec![l, r]
227        }))
228    }
229
230    /// Returns the results of the Bitwise NOT operation.
231    fn ibit_not(&mut self, l: Value) -> Value {
232        self.create_value(ValueInfo::Instruction(InstructionInfo {
233            opcode: Opcode::BitNot,
234            arguments: vec![l]
235        }))
236    }
237
238    /// Returns the results of the Bitwise left shift operation.
239    fn ibit_left(&mut self, l: Value, r: Value) -> Value {
240        self.create_value(ValueInfo::Instruction(InstructionInfo {
241            opcode: Opcode::BitLeft,
242            arguments: vec![l, r]
243        }))
244    }
245
246    /// Returns the results of the Bitwise right shift operation.
247    fn ibit_right(&mut self, l: Value, r: Value) -> Value {
248        self.create_value(ValueInfo::Instruction(InstructionInfo {
249            opcode: Opcode::BitRight,
250            arguments: vec![l, r]
251        }))
252    }
253
254    /// Tests if two values are equal to eachother.  Returns a boolean value with the result of
255    /// the operation.
256    fn itest_eq(&mut self, l: Value, r: Value) -> Value {
257        self.create_value(ValueInfo::Instruction(InstructionInfo {
258            opcode: Opcode::TestEq,
259            arguments: vec![l, r]
260        }))
261    }
262
263    /// Tests if two values are not equal to eachother.  Returns a boolean value with the result
264    /// of the operation.
265    fn itest_neq(&mut self, l: Value, r: Value) -> Value {
266        self.create_value(ValueInfo::Instruction(InstructionInfo {
267            opcode: Opcode::TestNeq,
268            arguments: vec![l, r]
269        }))
270    }
271
272    /// Tests if the first value is greater than the second.  Returns a boolean value with the
273    /// result of the operation.
274    fn itest_gt(&mut self, l: Value, r: Value) -> Value {
275        self.create_value(ValueInfo::Instruction(InstructionInfo {
276            opcode: Opcode::TestGt,
277            arguments: vec![l, r]
278        }))
279    }
280
281    /// Tests if the first value is greater than or equal to the second.  Returns a boolean
282    /// value with the result of the operation.
283    fn itest_gt_eq(&mut self, l: Value, r: Value) -> Value {
284        self.create_value(ValueInfo::Instruction(InstructionInfo {
285            opcode: Opcode::TestGtEq,
286            arguments: vec![l, r]
287        }))
288    }
289
290    /// Tests if the first value is less than the second.  Returns a boolean value with the
291    /// result of the operation.
292    fn itest_lt(&mut self, l: Value, r: Value) -> Value {
293        self.create_value(ValueInfo::Instruction(InstructionInfo {
294            opcode: Opcode::TestLt,
295            arguments: vec![l, r]
296        }))
297    }
298
299    /// Tests if the first value is less than or equal to the second.  Returns a boolean
300    /// value with the result of the operation.
301    fn itest_lt_eq(&mut self, l: Value, r: Value) -> Value {
302        self.create_value(ValueInfo::Instruction(InstructionInfo {
303            opcode: Opcode::TestLtEq,
304            arguments: vec![l, r]
305        }))
306    }
307
308    /// Negates a boolean value.
309    fn inot(&mut self, l: Value) -> Value {
310        self.create_value(ValueInfo::Instruction(InstructionInfo {
311            opcode: Opcode::Not,
312            arguments: vec![l]
313        }))
314    }
315
316    /// Returns if either value is equal to true.
317    fn ior(&mut self, l: Value, r: Value) -> Value {
318        self.create_value(ValueInfo::Instruction(InstructionInfo {
319            opcode: Opcode::Or,
320            arguments: vec![l, r]
321        }))
322    }
323
324    /// Returns if both values are equal to true.
325    fn iand(&mut self, l: Value, r: Value) -> Value {
326        self.create_value(ValueInfo::Instruction(InstructionInfo {
327            opcode: Opcode::And,
328            arguments: vec![l, r]
329        }))
330    }
331
332    /// Unconditionally jumps to a certain block.
333    fn jmp(&mut self, block: Block) {
334        let b = self.create_value(ValueInfo::Block(block));
335        self.create_inst(InstructionInfo {
336            opcode: Opcode::Jmp,
337            arguments: vec![b]
338        });
339    }
340
341    /// Uses a named reference as a value.
342    fn iuse(&mut self, named: Named) -> Value {
343        self.create_value(ValueInfo::Named(named))
344    }
345
346    /// Sets a value, equivalent to the `=` assignment operator in most programming languages.
347    fn set(&mut self, k: Value, v: Value) {
348        self.create_inst(InstructionInfo {
349            opcode: Opcode::Set,
350            arguments: vec![k, v]
351        });
352    }
353
354    /// Makes a function call with the specified function name and arguments.
355    fn call(&mut self, k: Value, args: Vec<Value>) {
356        let mut v = vec![k];
357        v.append(&mut args.clone());
358        self.create_inst(InstructionInfo {
359            opcode: Opcode::Call,
360            arguments: v
361        });
362    }
363
364    /// Makes a function call and returns the value that the function call returns.
365    fn icall(&mut self, k: Value, args: Vec<Value>) -> Value {
366        let mut v = vec![k];
367        v.append(&mut args.clone());
368        self.create_value(ValueInfo::Instruction(InstructionInfo {
369            opcode: Opcode::Call,
370            arguments: v
371        }))
372    }
373
374    /// Returns a value from the function that this InstBuilder resides in.
375    fn return_(&mut self, v: Value) {
376        self.create_inst(InstructionInfo {
377            opcode: Opcode::Ret,
378            arguments: vec![v]
379        });
380    }
381
382    /// Returns and exits the function, without returning a value.  The function should have a
383    /// return type of `void`.
384    fn return_none(&mut self) {
385        self.create_inst(InstructionInfo {
386            opcode: Opcode::Ret,
387            arguments: vec![]
388        });
389    }
390
391}