pipeline_script/llvm/value/
fucntion.rs

1use 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            // 对于闭包,self.reference 就是结构体值
125            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            // 处理其他参数
143            for i in args.into_iter().flatten() {
144                function_call_args.push(i)
145            }
146            // 将环境指针作为第最后一个参数
147            function_call_args.push(env_ptr);
148            // 调用闭包函数
149            let function_value = function_ptr.as_function().unwrap();
150            builder.build_call(ctx, &function_value, &mut function_call_args, "")
151        } else {
152            // 处理普通函数调用
153            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}