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_derive::{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 /// Supports tail calls, not ABI-stable. 18 // 19 // Currently, this is basically sys-v except that callees pop stack 20 // arguments, rather than callers. Expected to change even more in the 21 // future, however! 22 Tail, 23 /// System V-style convention used on many platforms. 24 SystemV, 25 /// Windows "fastcall" convention, also used for x64 and ARM. 26 WindowsFastcall, 27 /// Mac aarch64 calling convention, which is a tweaked aarch64 ABI. 28 AppleAarch64, 29 /// Specialized convention for the probestack function. 30 Probestack, 31 /// Wasmtime equivalent of SystemV, not ABI-stable. 32 /// 33 /// FIXME: remove this when Wasmtime uses the "tail" calling convention for 34 /// all wasm functions. 35 WasmtimeSystemV, 36 /// The winch calling convention, not ABI-stable. 37 /// 38 /// The main difference to WasmtimeSystemV is that the winch calling 39 /// convention defines no callee-save registers, and restricts the number 40 /// of return registers to one integer, and one floating point. 41 Winch, 42 } 43 44 impl CallConv { 45 /// Return the default calling convention for the given target triple. 46 pub fn triple_default(triple: &Triple) -> Self { 47 match triple.default_calling_convention() { 48 // Default to System V for unknown targets because most everything 49 // uses System V. 50 Ok(CallingConvention::SystemV) | Err(()) => Self::SystemV, 51 Ok(CallingConvention::AppleAarch64) => Self::AppleAarch64, 52 Ok(CallingConvention::WindowsFastcall) => Self::WindowsFastcall, 53 Ok(unimp) => unimplemented!("calling convention: {:?}", unimp), 54 } 55 } 56 57 /// Returns the calling convention used for libcalls according to the current flags. 58 pub fn for_libcall(flags: &settings::Flags, default_call_conv: CallConv) -> Self { 59 match flags.libcall_call_conv() { 60 LibcallCallConv::IsaDefault => default_call_conv, 61 LibcallCallConv::Fast => Self::Fast, 62 LibcallCallConv::Cold => Self::Cold, 63 LibcallCallConv::SystemV => Self::SystemV, 64 LibcallCallConv::WindowsFastcall => Self::WindowsFastcall, 65 LibcallCallConv::AppleAarch64 => Self::AppleAarch64, 66 LibcallCallConv::Probestack => Self::Probestack, 67 } 68 } 69 70 /// Does this calling convention support tail calls? 71 pub fn supports_tail_calls(&self) -> bool { 72 match self { 73 CallConv::Tail => true, 74 _ => false, 75 } 76 } 77 78 /// Is the calling convention extending the Windows Fastcall ABI? 79 pub fn extends_windows_fastcall(self) -> bool { 80 match self { 81 Self::WindowsFastcall => true, 82 _ => false, 83 } 84 } 85 86 /// Is the calling convention extending the Apple aarch64 ABI? 87 pub fn extends_apple_aarch64(self) -> bool { 88 match self { 89 Self::AppleAarch64 => true, 90 _ => false, 91 } 92 } 93 } 94 95 impl fmt::Display for CallConv { 96 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 97 f.write_str(match *self { 98 Self::Fast => "fast", 99 Self::Cold => "cold", 100 Self::Tail => "tail", 101 Self::SystemV => "system_v", 102 Self::WindowsFastcall => "windows_fastcall", 103 Self::AppleAarch64 => "apple_aarch64", 104 Self::Probestack => "probestack", 105 Self::WasmtimeSystemV => "wasmtime_system_v", 106 Self::Winch => "winch", 107 }) 108 } 109 } 110 111 impl str::FromStr for CallConv { 112 type Err = (); 113 fn from_str(s: &str) -> Result<Self, Self::Err> { 114 match s { 115 "fast" => Ok(Self::Fast), 116 "cold" => Ok(Self::Cold), 117 "tail" => Ok(Self::Tail), 118 "system_v" => Ok(Self::SystemV), 119 "windows_fastcall" => Ok(Self::WindowsFastcall), 120 "apple_aarch64" => Ok(Self::AppleAarch64), 121 "probestack" => Ok(Self::Probestack), 122 "wasmtime_system_v" => Ok(Self::WasmtimeSystemV), 123 "winch" => Ok(Self::Winch), 124 _ => Err(()), 125 } 126 } 127 } 128