Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/codegen/src/isa/call_conv.rs
3050 views
1
use crate::ir::Type;
2
use crate::ir::types;
3
use crate::settings::{self, LibcallCallConv};
4
use core::fmt;
5
use core::str;
6
use target_lexicon::{CallingConvention, Triple};
7
8
#[cfg(feature = "enable-serde")]
9
use serde_derive::{Deserialize, Serialize};
10
11
/// Calling convention identifiers.
12
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
13
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
14
pub enum CallConv {
15
/// Best performance, not ABI-stable.
16
Fast,
17
/// Supports tail calls, not ABI-stable except for exception
18
/// payload registers.
19
///
20
/// On exception resume, a caller to a `tail`-convention function
21
/// assumes that the exception payload values are in the following
22
/// registers (per platform):
23
/// - x86-64: rax, rdx
24
/// - aarch64: x0, x1
25
/// - riscv64: a0, a1
26
/// - pulley{32,64}: x0, x1
27
//
28
// Currently, this is basically sys-v except that callees pop stack
29
// arguments, rather than callers. Expected to change even more in the
30
// future, however!
31
Tail,
32
/// System V-style convention used on many platforms.
33
SystemV,
34
/// Windows "fastcall" convention, also used for x64 and ARM.
35
WindowsFastcall,
36
/// Mac aarch64 calling convention, which is a tweaked aarch64 ABI.
37
AppleAarch64,
38
/// Specialized convention for the probestack function.
39
Probestack,
40
/// The winch calling convention, not ABI-stable.
41
///
42
/// The main difference to SystemV is that the winch calling convention
43
/// defines no callee-save registers, and restricts the number of return
44
/// registers to one integer, and one floating point.
45
Winch,
46
/// Calling convention optimized for callsite efficiency, at the
47
/// cost of the callee. It does so by not clobbering any
48
/// registers.
49
///
50
/// This is designed for a very specific need: we want callsites
51
/// that we can insert as instrumentation (perhaps patchable)
52
/// while affecting surrounding instructions' register allocation
53
/// as little as possible.
54
///
55
/// The ABI is based on the native register-argument ABI on each
56
/// respective platform. It does not support tail-calls. It also
57
/// does not support return values.
58
PreserveAll,
59
}
60
61
impl CallConv {
62
/// Return the default calling convention for the given target triple.
63
pub fn triple_default(triple: &Triple) -> Self {
64
match triple.default_calling_convention() {
65
// Default to System V for unknown targets because most everything
66
// uses System V.
67
Ok(CallingConvention::SystemV) | Err(()) => Self::SystemV,
68
Ok(CallingConvention::AppleAarch64) => Self::AppleAarch64,
69
Ok(CallingConvention::WindowsFastcall) => Self::WindowsFastcall,
70
Ok(unimp) => unimplemented!("calling convention: {:?}", unimp),
71
}
72
}
73
74
/// Returns the calling convention used for libcalls according to the current flags.
75
pub fn for_libcall(flags: &settings::Flags, default_call_conv: CallConv) -> Self {
76
match flags.libcall_call_conv() {
77
LibcallCallConv::IsaDefault => default_call_conv,
78
LibcallCallConv::Fast => Self::Fast,
79
LibcallCallConv::SystemV => Self::SystemV,
80
LibcallCallConv::WindowsFastcall => Self::WindowsFastcall,
81
LibcallCallConv::AppleAarch64 => Self::AppleAarch64,
82
LibcallCallConv::PreserveAll => Self::PreserveAll,
83
LibcallCallConv::Probestack => Self::Probestack,
84
}
85
}
86
87
/// Does this calling convention support tail calls?
88
pub fn supports_tail_calls(&self) -> bool {
89
match self {
90
CallConv::Tail => true,
91
_ => false,
92
}
93
}
94
95
/// Does this calling convention support exceptions?
96
pub fn supports_exceptions(&self) -> bool {
97
match self {
98
CallConv::Tail | CallConv::SystemV | CallConv::Winch | CallConv::PreserveAll => true,
99
_ => false,
100
}
101
}
102
103
/// What types do the exception payload value(s) have?
104
///
105
/// Note that this function applies to the *callee* of a `try_call`
106
/// instruction. The calling convention of the callee may differ from the
107
/// caller, but the exceptional payload types available are defined by the
108
/// callee calling convention.
109
///
110
/// Also note that individual backends are responsible for reporting
111
/// register destinations for exceptional types. Internally Cranelift
112
/// asserts that the backend supports the exact same number of register
113
/// destinations as this return value.
114
pub fn exception_payload_types(&self, pointer_ty: Type) -> &[Type] {
115
match self {
116
CallConv::Tail | CallConv::SystemV | CallConv::PreserveAll => match pointer_ty {
117
types::I32 => &[types::I32, types::I32],
118
types::I64 => &[types::I64, types::I64],
119
_ => unreachable!(),
120
},
121
_ => &[],
122
}
123
}
124
}
125
126
impl fmt::Display for CallConv {
127
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
128
f.write_str(match *self {
129
Self::Fast => "fast",
130
Self::Tail => "tail",
131
Self::SystemV => "system_v",
132
Self::WindowsFastcall => "windows_fastcall",
133
Self::AppleAarch64 => "apple_aarch64",
134
Self::Probestack => "probestack",
135
Self::Winch => "winch",
136
Self::PreserveAll => "preserve_all",
137
})
138
}
139
}
140
141
impl str::FromStr for CallConv {
142
type Err = ();
143
fn from_str(s: &str) -> Result<Self, Self::Err> {
144
match s {
145
"fast" => Ok(Self::Fast),
146
"tail" => Ok(Self::Tail),
147
"system_v" => Ok(Self::SystemV),
148
"windows_fastcall" => Ok(Self::WindowsFastcall),
149
"apple_aarch64" => Ok(Self::AppleAarch64),
150
"probestack" => Ok(Self::Probestack),
151
"winch" => Ok(Self::Winch),
152
"preserve_all" => Ok(Self::PreserveAll),
153
_ => Err(()),
154
}
155
}
156
}
157
158