cardinal_codegen/
function.rs

1//! Exposes types for function declarations and definitions.
2
3use crate::entities::{AbiParam, AbiType, Block, Type, Variable};
4use crate::instruction::{InstBlock, BlockType};
5use std::collections::HashMap;
6
7// A function that allows Cardinal to create instructions, variables and SSA values.
8pub struct Function {
9
10    // A list of variables declared in the function.
11    pub variables: HashMap<String, AbiType>,
12
13    /// A list of that blocks that may store instructions.
14    pub blocks: Vec<InstBlock>,
15
16    /// The name of the Function, used at compile time to generate correct code.
17    pub name: String,
18
19    /// The signature that the function uses.
20    pub signature: FunctionSignature,
21
22}
23
24/// A function signature that allows the code generator to verify function calls and references.
25pub struct FunctionSignature {
26
27    /// A list of arguments in the function signature, which are checked at compile time to
28    /// verify their validity.
29    pub arguments: Vec<AbiParam>,
30
31    /// A return value of the function.  Defaults to `void`.
32    pub returns: AbiType,
33
34}
35
36impl FunctionSignature {
37
38    pub fn new() -> Self {
39        Self {
40            arguments: vec![],
41            returns: AbiType("void".into(), Type::Plain)
42        }
43    }
44
45}
46
47impl Function {
48
49    /// Creates a new function from the given name and signature.
50    pub fn new(name: String, sig: FunctionSignature) -> Self {
51        Self {
52            name,
53            signature: sig,
54            variables: HashMap::new(),
55            blocks: vec![],
56        }
57    }
58
59    /// Declares a variable at the start of the function.
60    pub fn declare_var(&mut self, name: String, var_type: AbiType) -> Variable {
61        let val = Variable(name.to_string());
62        self.variables.insert(name, var_type);
63
64        val
65    }
66
67    /// Uses a block.
68    pub fn use_block(&mut self, block: Block) -> &mut InstBlock {
69        self.blocks.get_mut(block.0 as usize).unwrap()
70    }
71
72    /// Creates a new empty block.
73    pub fn create_block(&mut self) -> Block {
74        let block = InstBlock {
75            block_type: BlockType::Basic,
76            blocks: vec![],
77            else_block: None,
78            elses: vec![],
79            imports: vec![],
80            insts: vec![],
81            values: vec![],
82        };
83
84        let val = Block(self.blocks.len() as u32);
85        self.blocks.push(block);
86
87        val
88    }
89
90}