1 use crate::settings::{self, LibcallCallConv}; 2 use core::fmt; 3 use core::str; 4 use target_lexicon::{CallingConvention, Triple}; 5 6 #[cfg(feature = "enable-serde")] 7 use serde::{Deserialize, Serialize}; 8 9 /// Calling convention identifiers. 10 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 11 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 12 pub enum CallConv { 13 /// Best performance, not ABI-stable. 14 Fast, 15 /// Smallest caller code size, not ABI-stable. 16 Cold, 17 /// System V-style convention used on many platforms. 18 SystemV, 19 /// Windows "fastcall" convention, also used for x64 and ARM. 20 WindowsFastcall, 21 /// Mac aarch64 calling convention, which is a tweaked aarch64 ABI. 22 AppleAarch64, 23 /// SpiderMonkey WebAssembly convention on systems using natively SystemV. 24 BaldrdashSystemV, 25 /// SpiderMonkey WebAssembly convention on Windows. 26 BaldrdashWindows, 27 /// SpiderMonkey WebAssembly convention for "ABI-2020", with extra TLS 28 /// register slots in the frame. 29 Baldrdash2020, 30 /// Specialized convention for the probestack function. 31 Probestack, 32 /// Wasmtime equivalent of SystemV, not ABI-stable. 33 /// 34 /// Currently only differs in how multiple return values are handled, 35 /// returning the first return value in a register and everything else 36 /// through a return-pointer. 37 WasmtimeSystemV, 38 /// Wasmtime equivalent of WindowsFastcall, not ABI-stable. 39 /// 40 /// Differs from fastcall in the same way as `WasmtimeSystemV`. 41 WasmtimeFastcall, 42 /// Wasmtime equivalent of AppleAarch64, not ABI-stable. 43 /// 44 /// Differs from apple-aarch64 in the same way as `WasmtimeSystemV`. 45 WasmtimeAppleAarch64, 46 } 47 48 impl CallConv { 49 /// Return the default calling convention for the given target triple. 50 pub fn triple_default(triple: &Triple) -> Self { 51 match triple.default_calling_convention() { 52 // Default to System V for unknown targets because most everything 53 // uses System V. 54 Ok(CallingConvention::SystemV) | Err(()) => Self::SystemV, 55 Ok(CallingConvention::AppleAarch64) => Self::AppleAarch64, 56 Ok(CallingConvention::WindowsFastcall) => Self::WindowsFastcall, 57 Ok(unimp) => unimplemented!("calling convention: {:?}", unimp), 58 } 59 } 60 61 /// Returns the calling convention used for libcalls according to the current flags. 62 pub fn for_libcall(flags: &settings::Flags, default_call_conv: CallConv) -> Self { 63 match flags.libcall_call_conv() { 64 LibcallCallConv::IsaDefault => default_call_conv, 65 LibcallCallConv::Fast => Self::Fast, 66 LibcallCallConv::Cold => Self::Cold, 67 LibcallCallConv::SystemV => Self::SystemV, 68 LibcallCallConv::WindowsFastcall => Self::WindowsFastcall, 69 LibcallCallConv::AppleAarch64 => Self::AppleAarch64, 70 LibcallCallConv::BaldrdashSystemV => Self::BaldrdashSystemV, 71 LibcallCallConv::BaldrdashWindows => Self::BaldrdashWindows, 72 LibcallCallConv::Baldrdash2020 => Self::Baldrdash2020, 73 LibcallCallConv::Probestack => Self::Probestack, 74 } 75 } 76 77 /// Is the calling convention extending the Windows Fastcall ABI? 78 pub fn extends_windows_fastcall(self) -> bool { 79 match self { 80 Self::WindowsFastcall | Self::BaldrdashWindows | Self::WasmtimeFastcall => true, 81 _ => false, 82 } 83 } 84 85 /// Is the calling convention extending the Apple aarch64 ABI? 86 pub fn extends_apple_aarch64(self) -> bool { 87 match self { 88 Self::AppleAarch64 | Self::WasmtimeAppleAarch64 => true, 89 _ => false, 90 } 91 } 92 93 /// Is the calling convention extending the Baldrdash ABI? 94 pub fn extends_baldrdash(self) -> bool { 95 match self { 96 Self::BaldrdashSystemV | Self::BaldrdashWindows | Self::Baldrdash2020 => true, 97 _ => false, 98 } 99 } 100 101 /// Is the calling convention extending the Wasmtime ABI? 102 pub fn extends_wasmtime(self) -> bool { 103 match self { 104 Self::WasmtimeSystemV | Self::WasmtimeFastcall | Self::WasmtimeAppleAarch64 => true, 105 _ => false, 106 } 107 } 108 } 109 110 impl fmt::Display for CallConv { 111 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 112 f.write_str(match *self { 113 Self::Fast => "fast", 114 Self::Cold => "cold", 115 Self::SystemV => "system_v", 116 Self::WindowsFastcall => "windows_fastcall", 117 Self::AppleAarch64 => "apple_aarch64", 118 Self::BaldrdashSystemV => "baldrdash_system_v", 119 Self::BaldrdashWindows => "baldrdash_windows", 120 Self::Baldrdash2020 => "baldrdash_2020", 121 Self::Probestack => "probestack", 122 Self::WasmtimeSystemV => "wasmtime_system_v", 123 Self::WasmtimeFastcall => "wasmtime_fastcall", 124 Self::WasmtimeAppleAarch64 => "wasmtime_apple_aarch64", 125 }) 126 } 127 } 128 129 impl str::FromStr for CallConv { 130 type Err = (); 131 fn from_str(s: &str) -> Result<Self, Self::Err> { 132 match s { 133 "fast" => Ok(Self::Fast), 134 "cold" => Ok(Self::Cold), 135 "system_v" => Ok(Self::SystemV), 136 "windows_fastcall" => Ok(Self::WindowsFastcall), 137 "apple_aarch64" => Ok(Self::AppleAarch64), 138 "baldrdash_system_v" => Ok(Self::BaldrdashSystemV), 139 "baldrdash_windows" => Ok(Self::BaldrdashWindows), 140 "baldrdash_2020" => Ok(Self::Baldrdash2020), 141 "probestack" => Ok(Self::Probestack), 142 "wasmtime_system_v" => Ok(Self::WasmtimeSystemV), 143 "wasmtime_fastcall" => Ok(Self::WasmtimeFastcall), 144 "wasmtime_apple_aarch64" => Ok(Self::WasmtimeAppleAarch64), 145 _ => Err(()), 146 } 147 } 148 } 149