llvm_scratch/core/function/
function.rs1use fmt::Formatter;
2use std::fmt;
3
4use id_arena::{Arena, Id};
5
6use crate::core::{
7 basic_block::{BasicBlock, BasicBlockId, BasicBlockKind},
8 function::param_attrs::*,
9 instruction::Instruction,
10 llvm_string::*,
11 llvm_type::*,
12};
13
14pub type FunctionId = Id<Function>;
15
16pub struct Function {
19 return_type: ReturnType,
20 name: LLVMString,
21 arg_list: ParameterSet,
22
23 entry_block: BasicBlockId,
24 bb_allocator: Arena<BasicBlock>,
25}
26
27impl fmt::Display for Function {
28 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
29 writeln!(
30 f,
31 "define {} @{} {} {{",
32 self.return_type, self.name, self.arg_list
33 )?;
34
35 let entry_bb = self.bb_allocator.get(self.entry_block).unwrap();
36
37 writeln!(f, "{}", entry_bb)?;
38
39 {
40 entry_bb.print_successors(f, &self.bb_allocator)?;
41 }
42
43 writeln!(f, "}}")?;
44
45 Ok(())
46 }
47}
48
49impl Function {
50 pub fn new(func_name: &str, ret_type: ReturnType) -> Self {
51 let mut bb_alloc = Arena::new();
52 let entry_block_id = bb_alloc.alloc(BasicBlock::new(
53 LLVMString::from("entry"),
54 None,
55 BasicBlockKind::TERMINATED,
56 ));
57 Self {
58 return_type: ret_type,
59 name: LLVMString::from(func_name),
60 arg_list: Default::default(),
61 entry_block: entry_block_id,
62 bb_allocator: bb_alloc,
63 }
64 }
65
66 pub fn entry_bb_is_empty(&self) -> bool {
67 let entry_bb = self.bb_allocator.get(self.entry_block).unwrap();
68 entry_bb.insts_empty()
69 }
70
71 pub fn insert_inst(&mut self, bb: BasicBlockId, inst: Instruction) {
72 if let Some(insert_bb) = self.bb_allocator.get_mut(bb) {
73 insert_bb.new_inst(inst);
74 }
75 }
76
77 pub fn returns_void(&self) -> bool {
78 self.return_type.is_void()
79 }
80
81 pub fn get_name_ref(&self) -> &LLVMString {
82 &self.name
83 }
84
85 pub fn get_entry_bb(&self) -> BasicBlockId {
86 self.entry_block
87 }
88
89 pub fn args_empty(&self) -> bool {
90 self.arg_list.is_empty()
91 }
92
93 pub fn new_argument(&mut self, arg: Parameter) {
94 self.arg_list.add_arg(arg);
95 }
96
97 pub fn new_basic_block(
98 &mut self,
99 l: &str,
100 pred: Option<BasicBlockId>,
101 k: BasicBlockKind,
102 ) -> BasicBlockId {
103 self.bb_allocator
104 .alloc(BasicBlock::new(LLVMString::from(l), pred, k))
105 }
106}
107
108#[derive(Eq, PartialEq, PartialOrd, Ord, Hash)]
110pub struct FunctionType {
111 return_type: ReturnType,
112 arg_list: ParameterSet,
113}
114
115impl FunctionType {
116 pub fn new(ret_type: ReturnType, args: ParameterSet) -> Self {
117 Self {
118 return_type: ret_type,
119 arg_list: args,
120 }
121 }
122}
123
124impl fmt::Display for FunctionType {
125 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
126 write!(f, "{} {}", self.return_type, self.arg_list)
127 }
128}
129
130#[derive(Eq, PartialEq, PartialOrd, Ord, Hash)]
133pub struct ReturnType {
134 return_type: LLVMType,
135 attributes: Option<ParameterAttributes>,
138}
139
140impl ReturnType {
141 pub fn new(ret_type: LLVMType, attrs: Option<ParameterAttributes>) -> Self {
142 Self {
143 return_type: ret_type,
144 attributes: attrs,
145 }
146 }
147
148 fn is_void(&self) -> bool {
149 match &self.return_type.kind {
150 LLVMTypeKind::VOID => true,
151 _ => false,
152 }
153 }
154}
155
156impl fmt::Display for ReturnType {
157 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
158 match &self.attributes {
159 Some(attrs) => write!(f, "{} {}", attrs, self.return_type),
160 None => write!(f, "{}", self.return_type),
161 }
162 }
163}
164
165#[derive(Eq, PartialEq, PartialOrd, Ord, Hash)]
168pub struct ParameterSet {
169 params: Vec<Parameter>,
170}
171
172impl Default for ParameterSet {
173 fn default() -> Self {
174 Self { params: Vec::new() }
175 }
176}
177
178impl ParameterSet {
179 pub fn new(args: Vec<Parameter>) -> Self {
180 Self { params: args }
181 }
182
183 pub fn add_arg(&mut self, arg: Parameter) {
184 self.params.push(arg);
185 }
186
187 fn is_empty(&self) -> bool {
188 self.params.is_empty()
189 }
190}
191
192impl fmt::Display for ParameterSet {
193 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
194 let fmt_string = self
195 .params
196 .iter()
197 .map(|attr| attr.to_string())
198 .collect::<Vec<String>>()
199 .join(", ");
200
201 write!(f, "({})", fmt_string)
202 }
203}
204
205#[derive(Eq, PartialEq, PartialOrd, Ord, Hash)]
207pub struct Parameter {
208 name: LLVMString,
209 attributes: Option<ParameterAttributes>,
210 param_type: LLVMType,
211}
212
213impl Parameter {
214 pub fn new(
215 param_name: LLVMString,
216 attrs: Option<ParameterAttributes>,
217 arg_type: LLVMType,
218 ) -> Self {
219 Self {
220 name: param_name,
221 attributes: attrs,
222 param_type: arg_type,
223 }
224 }
225}
226
227impl fmt::Display for Parameter {
228 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
229 match &self.attributes {
230 Some(attrs) => write!(f, "{} {} {}", self.param_type, attrs, self.name),
231 None => write!(f, "{} {}", self.param_type, self.name),
232 }
233 }
234}