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}
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            // 对于闭包,self.reference 就是结构体值
113            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            // 处理其他参数
131            for i in args.into_iter().flatten() {
132                function_call_args.push(i)
133            }
134            // 将环境指针作为第最后一个参数
135            function_call_args.push(env_ptr);
136            // 调用闭包函数
137            let function_value = function_ptr.as_function().unwrap();
138            builder.build_call(ctx, &function_value, &mut function_call_args, "")
139        } else {
140            // 处理普通函数调用
141            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}