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