1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
use std::ffi; use llvm_sys::core::*; use llvm_sys::prelude::*; use llvm_sys::{LLVMAttributeFunctionIndex, LLVMCallConv}; use crate::codegen::mod_gen::ModCtx; use crate::codegen::target_gen::TargetCtx; use crate::libcstr; use crate::mir::ops; pub fn gen_static_symbol_entry_point( tcx: &mut TargetCtx, mcx: &mut ModCtx<'_, '_, '_>, static_symbol: &ops::StaticSymbol, ) -> LLVMValueRef { use crate::codegen::analysis::escape::{infer_param_capture_kind, CaptureKind}; use arret_runtime::abitype::{AbiType, RetAbiType}; let ops::StaticSymbol { abi, impure, symbol, } = static_symbol; let function_type = tcx.fun_abi_to_llvm_type(abi); let function_name = ffi::CString::new(*symbol).unwrap(); unsafe { mcx.get_function_or_insert( function_type, function_name.as_bytes_with_nul(), |function| { let param_attr_offset = abi.takes_task as usize; for (index, param_abi_type) in abi.params.iter().enumerate() { if let AbiType::Boxed(_) = param_abi_type.abi_type { let no_capture = infer_param_capture_kind(&abi.ret, param_abi_type) == CaptureKind::Never; tcx.add_boxed_param_attrs( function, (param_attr_offset + index) as u32, no_capture, ) } } if !impure { let speculatable_attr = tcx.llvm_enum_attr_for_name("speculatable", 0); LLVMAddAttributeAtIndex( function, LLVMAttributeFunctionIndex, speculatable_attr, ); } match abi.ret { RetAbiType::Inhabited(AbiType::Boxed(_)) => { tcx.add_boxed_return_attrs(function); } RetAbiType::Never => { let noreturn_attr = tcx.llvm_enum_attr_for_name("noreturn", 0); LLVMAddAttributeAtIndex( function, LLVMAttributeFunctionIndex, noreturn_attr, ); } _ => {} } }, ) } } pub fn gen_boxed_fun_thunk_entry_point( builder: LLVMBuilderRef, llvm_fun_thunk: LLVMValueRef, ) -> LLVMValueRef { unsafe { let entry_ptr = LLVMBuildStructGEP(builder, llvm_fun_thunk, 2, libcstr!("fun_thunk_entry_ptr")); LLVMBuildLoad(builder, entry_ptr, libcstr!("fun_thunk_entry")) } } pub fn callee_takes_task(callee: &ops::Callee) -> bool { match callee { ops::Callee::BoxedFunThunk(_) => true, ops::Callee::PrivateFun(_) => true, ops::Callee::StaticSymbol(ops::StaticSymbol { abi, .. }) => abi.takes_task, } } pub fn callee_call_conv(mcx: &mut ModCtx<'_, '_, '_>, callee: &ops::Callee) -> u32 { match callee { ops::Callee::BoxedFunThunk(_) | ops::Callee::StaticSymbol(_) => { LLVMCallConv::LLVMCCallConv as u32 } ops::Callee::PrivateFun(private_fun_id) => unsafe { LLVMGetFunctionCallConv(mcx.llvm_private_fun(*private_fun_id)) }, } }