pipeline_script/llvm/value/
fucntion.rs1use crate::context::Context;
2use crate::llvm::global::Global;
3use crate::llvm::types::LLVMType;
4use crate::llvm::value::pointer::PointerValue;
5use crate::llvm::value::pstruct::StructValue;
6use crate::llvm::value::LLVMValue;
7use llvm_sys::core::{LLVMAppendBasicBlock, LLVMGetParam};
8use llvm_sys::prelude::{LLVMBasicBlockRef, LLVMValueRef};
9use std::collections::HashMap;
10use std::ffi::c_char;
11
12#[derive(Clone, Debug)]
13pub struct FunctionValue {
14 reference: LLVMValueRef,
15 name: String,
16 return_type: Box<LLVMValue>,
17 args: Vec<(String, LLVMValue)>,
18 is_closure: bool,
19 is_vararg: bool,
20}
21
22impl FunctionValue {
23 pub fn new(
24 reference: LLVMValueRef,
25 name: String,
26 return_type: Box<LLVMValue>,
27 args: Vec<(String, LLVMValue)>,
28 ) -> Self {
29 Self {
30 reference,
31 name,
32 return_type,
33 args,
34 is_closure: false,
35 is_vararg: false,
36 }
37 }
38 pub fn get_reference(&self) -> LLVMValueRef {
39 self.reference
40 }
41
42 pub fn append_basic_block(&self, name: impl Into<String>) -> LLVMBasicBlockRef {
43 unsafe { LLVMAppendBasicBlock(self.reference, name.into().as_mut_ptr() as *mut c_char) }
44 }
45 pub fn get_param(&self, name: impl AsRef<str>) -> Option<LLVMValue> {
46 let name_ref = name.as_ref();
47 for (index, (arg_name, v)) in self.args.iter().enumerate() {
48 if arg_name == name_ref {
49 let param = unsafe { LLVMGetParam(self.reference, index as u32) };
50 return match v {
51 LLVMValue::Struct(v) => {
52 return Some(LLVMValue::Struct(StructValue::new(
53 param,
54 v.get_name(),
55 v.field_index.clone(),
56 v.field_values.borrow().clone(),
57 )))
58 }
59 LLVMValue::String(_) => Some(LLVMValue::String(param)),
60 LLVMValue::Function(function_value) => {
61 let mut function_value = function_value.clone();
62 function_value.set_reference(param);
63 Some(LLVMValue::Function(function_value))
64 }
65 LLVMValue::Pointer(p) => {
66 let mut p = p.clone();
67 p.set_reference(param);
68 Some(LLVMValue::Pointer(p))
69 }
70 LLVMValue::Reference(r) => {
71 let mut r = r.clone();
72 r.set_reference(param);
73 Some(LLVMValue::Reference(r))
74 }
75 _ => Some(param.into()),
76 };
77 }
78 }
79 None
80 }
81 pub fn set_reference(&mut self, reference: LLVMValueRef) {
82 self.reference = reference;
83 }
84 pub fn get_param_index(&self, name: impl AsRef<str>) -> Option<usize> {
85 let name_ref = name.as_ref();
86 for (i, (arg_name, _)) in self.args.iter().enumerate() {
87 if arg_name == name_ref {
88 return Some(i);
89 }
90 }
91 None
92 }
93 pub fn get_llvm_type(&self, ctx: &Context) -> LLVMType {
94 let mut args_type = vec![];
95 for (name, v) in &self.args {
96 args_type.push((name.clone(), v.get_llvm_type(ctx)))
97 }
98 let return_type = self.return_type.get_llvm_type(ctx);
99 Global::pointer_type(Global::function_type(return_type, args_type))
100 }
101 pub fn get_param_index_map(&self) -> HashMap<String, usize> {
102 let mut map = HashMap::new();
103 for (i, (name, _)) in self.args.iter().enumerate() {
104 map.insert(name.clone(), i);
105 }
106 map
107 }
108 pub fn call(&self, ctx: &Context, args: Vec<Option<LLVMValue>>) -> LLVMValue {
109 let builder = ctx.get_builder();
110 let mut function_call_args = vec![];
111 let r = if self.is_closure {
112 let mut field_index = HashMap::new();
114 field_index.insert("ptr".to_string(), 0);
115 field_index.insert("env".to_string(), 1);
116
117 let closure_struct = StructValue::new(
118 self.reference,
119 "Closure".into(),
120 field_index,
121 vec![
122 LLVMValue::Function(self.clone()),
123 LLVMValue::Pointer(PointerValue::new(self.reference, LLVMValue::Unit)),
124 ],
125 );
126
127 let function_ptr = builder.build_extract_value(ctx, &closure_struct, 0);
128 let env_ptr = builder.build_extract_value(ctx, &closure_struct, 1);
129
130 for i in args.into_iter().flatten() {
132 function_call_args.push(i)
133 }
134 function_call_args.push(env_ptr);
136 let function_value = function_ptr.as_function().unwrap();
138 builder.build_call(ctx, &function_value, &mut function_call_args, "")
139 } else {
140 for i in args.into_iter().flatten() {
142 function_call_args.push(i)
143 }
144 builder.build_call(ctx, self, &mut function_call_args, "")
145 };
146 if self.name == "panic" || self.name == "exit" {
147 builder.build_unreachable();
148 }
149 r
150 }
151 pub fn get_return_value(&self) -> LLVMValue {
152 *self.return_type.clone()
153 }
154 pub fn get_args_count(&self) -> usize {
155 self.args.len()
156 }
157 pub fn get_arg_name(&self, index: usize) -> Option<String> {
158 self.args.get(index).map(|(name, _)| name.clone())
159 }
160 pub fn get_param_by_index(&self, index: usize) -> Option<LLVMValue> {
161 self.args.get(index).map(|(_, ty)| ty.clone())
162 }
163 pub fn is_undef(&self) -> bool {
164 unsafe { llvm_sys::core::LLVMIsUndef(self.reference) == 1 }
165 }
166 pub fn is_vararg(&self) -> bool {
167 self.is_vararg
168 }
169 pub fn set_vararg(&mut self) {
170 self.is_vararg = true;
171 }
172 pub fn is_arg_undef(&self, index: usize) -> bool {
173 if let Some((_, arg_value)) = self.args.get(index) {
174 arg_value.is_undef()
175 } else {
176 false
177 }
178 }
179 pub fn set_closure(&mut self) {
180 self.is_closure = true;
181 }
182 pub fn is_closure(&self) -> bool {
183 self.is_closure
184 }
185 pub fn get_function_arg_count(&self) -> usize {
186 self.args.len()
187 }
188 pub fn get_function_arg(&self, index: usize) -> Option<LLVMValue> {
189 self.args.get(index).map(|(_, ty)| ty.clone())
190 }
191 pub fn is_vararg_function(&self) -> bool {
192 self.is_vararg
193 }
194}
195
196impl From<FunctionValue> for LLVMValue {
197 fn from(value: FunctionValue) -> Self {
198 LLVMValue::Function(value)
199 }
200}