wasmer_compiler_llvm/abi/
mod.rs

1// LLVM implements part of the ABI lowering internally, but also requires that
2// the user pack and unpack values themselves sometimes. This can help the LLVM
3// optimizer by exposing operations to the optimizer, but it requires that the
4// frontend know exactly what IR to produce in order to get the right ABI.
5
6#![deny(dead_code, missing_docs)]
7
8use crate::translator::intrinsics::Intrinsics;
9use inkwell::{
10    attributes::{Attribute, AttributeLoc},
11    builder::Builder,
12    context::Context,
13    targets::TargetMachine,
14    types::FunctionType,
15    values::{BasicValueEnum, CallSiteValue, FunctionValue, IntValue, PointerValue},
16};
17use wasmer_types::CompileError;
18use wasmer_types::FunctionType as FuncSig;
19use wasmer_vm::VMOffsets;
20
21mod aarch64_systemv;
22mod x86_64_systemv;
23
24use aarch64_systemv::Aarch64SystemV;
25use x86_64_systemv::X86_64SystemV;
26
27pub fn get_abi(target_machine: &TargetMachine) -> Box<dyn Abi> {
28    if target_machine
29        .get_triple()
30        .as_str()
31        .to_string_lossy()
32        .starts_with("aarch64")
33    {
34        Box::new(Aarch64SystemV {})
35    } else {
36        Box::new(X86_64SystemV {})
37    }
38}
39
40#[derive(Debug)]
41pub(crate) enum G0M0FunctionKind {
42    Local,
43    Imported,
44}
45
46impl G0M0FunctionKind {
47    /// Returns `true` if the function kind is [`Local`].
48    ///
49    /// [`Local`]: FunctionKind::Local
50    #[must_use]
51    pub(crate) fn is_local(&self) -> bool {
52        matches!(self, Self::Local)
53    }
54}
55
56/// The two additional parameters needed for g0m0 optimization.
57pub(crate) type LocalFunctionG0M0params<'ctx> = Option<(IntValue<'ctx>, PointerValue<'ctx>)>;
58
59/// We need to produce different LLVM IR for different platforms. (Contrary to
60/// popular knowledge LLVM IR is not intended to be portable in that way.) This
61/// trait deals with differences between function signatures on different
62/// targets.
63pub trait Abi {
64    /// Given a function definition, retrieve the parameter that is the vmctx pointer.
65    fn get_vmctx_ptr_param<'ctx>(&self, func_value: &FunctionValue<'ctx>) -> PointerValue<'ctx>;
66
67    /// Given a function definition, retrieve the parameter that is the pointer to the first --
68    /// number 0 -- local global.
69    #[allow(unused)]
70    fn get_g0_ptr_param<'ctx>(&self, func_value: &FunctionValue<'ctx>) -> IntValue<'ctx>;
71
72    /// Given a function definition, retrieve the parameter that is the pointer to the first --
73    /// number 0 -- local memory.
74    ///
75    /// # Notes
76    /// This function assumes that g0m0 is enabled.
77    fn get_m0_ptr_param<'ctx>(&self, func_value: &FunctionValue<'ctx>) -> PointerValue<'ctx>;
78
79    /// Given a wasm function type, produce an llvm function declaration.
80    ///
81    /// # Notes
82    /// This function assumes that g0m0 is enabled.
83    fn func_type_to_llvm<'ctx>(
84        &self,
85        context: &'ctx Context,
86        intrinsics: &Intrinsics<'ctx>,
87        offsets: Option<&VMOffsets>,
88        sig: &FuncSig,
89        function_kind: Option<G0M0FunctionKind>,
90    ) -> Result<(FunctionType<'ctx>, Vec<(Attribute, AttributeLoc)>), CompileError>;
91
92    /// Marshall wasm stack values into function parameters.
93    #[allow(clippy::too_many_arguments)]
94    fn args_to_call<'ctx>(
95        &self,
96        alloca_builder: &Builder<'ctx>,
97        func_sig: &FuncSig,
98        llvm_fn_ty: &FunctionType<'ctx>,
99        ctx_ptr: PointerValue<'ctx>,
100        values: &[BasicValueEnum<'ctx>],
101        intrinsics: &Intrinsics<'ctx>,
102        g0m0: LocalFunctionG0M0params<'ctx>,
103    ) -> Result<Vec<BasicValueEnum<'ctx>>, CompileError>;
104
105    /// Given a CallSite, extract the returned values and return them in a Vec.
106    fn rets_from_call<'ctx>(
107        &self,
108        builder: &Builder<'ctx>,
109        intrinsics: &Intrinsics<'ctx>,
110        call_site: CallSiteValue<'ctx>,
111        func_sig: &FuncSig,
112    ) -> Result<Vec<BasicValueEnum<'ctx>>, CompileError>;
113
114    /// Whether the llvm equivalent of this wasm function has an `sret` attribute.
115    fn is_sret(&self, func_sig: &FuncSig) -> Result<bool, CompileError>;
116
117    /// Pack LLVM IR values representing individual wasm values into the return type for the function.
118    fn pack_values_for_register_return<'ctx>(
119        &self,
120        intrinsics: &Intrinsics<'ctx>,
121        builder: &Builder<'ctx>,
122        values: &[BasicValueEnum<'ctx>],
123        func_type: &FunctionType<'ctx>,
124    ) -> Result<BasicValueEnum<'ctx>, CompileError>;
125}