Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/codegen/src/isa/s390x/mod.rs
1693 views
1
//! IBM Z 64-bit Instruction Set Architecture.
2
3
use crate::dominator_tree::DominatorTree;
4
use crate::ir::{self, Function, Type};
5
use crate::isa::s390x::settings as s390x_settings;
6
#[cfg(feature = "unwind")]
7
use crate::isa::unwind::systemv::RegisterMappingError;
8
use crate::isa::{Builder as IsaBuilder, FunctionAlignment, IsaFlagsHashKey, TargetIsa};
9
use crate::machinst::{
10
CompiledCode, CompiledCodeStencil, MachInst, MachTextSectionBuilder, Reg, SigSet,
11
TextSectionBuilder, VCode, compile,
12
};
13
use crate::result::CodegenResult;
14
use crate::settings as shared_settings;
15
use alloc::{boxed::Box, vec::Vec};
16
use core::fmt;
17
use cranelift_control::ControlPlane;
18
use std::string::String;
19
use target_lexicon::{Architecture, Triple};
20
21
// New backend:
22
mod abi;
23
pub(crate) mod inst;
24
mod lower;
25
mod settings;
26
27
use self::inst::EmitInfo;
28
29
/// A IBM Z backend.
30
pub struct S390xBackend {
31
triple: Triple,
32
flags: shared_settings::Flags,
33
isa_flags: s390x_settings::Flags,
34
}
35
36
impl S390xBackend {
37
/// Create a new IBM Z backend with the given (shared) flags.
38
pub fn new_with_flags(
39
triple: Triple,
40
flags: shared_settings::Flags,
41
isa_flags: s390x_settings::Flags,
42
) -> S390xBackend {
43
S390xBackend {
44
triple,
45
flags,
46
isa_flags,
47
}
48
}
49
50
/// This performs lowering to VCode, register-allocates the code, computes block layout and
51
/// finalizes branches. The result is ready for binary emission.
52
fn compile_vcode(
53
&self,
54
func: &Function,
55
domtree: &DominatorTree,
56
ctrl_plane: &mut ControlPlane,
57
) -> CodegenResult<(VCode<inst::Inst>, regalloc2::Output)> {
58
let emit_info = EmitInfo::new(self.isa_flags.clone());
59
let sigs = SigSet::new::<abi::S390xMachineDeps>(func, &self.flags)?;
60
let abi = abi::S390xCallee::new(func, self, &self.isa_flags, &sigs)?;
61
compile::compile::<S390xBackend>(func, domtree, self, abi, emit_info, sigs, ctrl_plane)
62
}
63
}
64
65
impl TargetIsa for S390xBackend {
66
fn compile_function(
67
&self,
68
func: &Function,
69
domtree: &DominatorTree,
70
want_disasm: bool,
71
ctrl_plane: &mut ControlPlane,
72
) -> CodegenResult<CompiledCodeStencil> {
73
let flags = self.flags();
74
let (vcode, regalloc_result) = self.compile_vcode(func, domtree, ctrl_plane)?;
75
76
let emit_result = vcode.emit(&regalloc_result, want_disasm, flags, ctrl_plane);
77
let frame_size = emit_result.frame_size;
78
let value_labels_ranges = emit_result.value_labels_ranges;
79
let buffer = emit_result.buffer;
80
let sized_stackslot_offsets = emit_result.sized_stackslot_offsets;
81
let dynamic_stackslot_offsets = emit_result.dynamic_stackslot_offsets;
82
83
if let Some(disasm) = emit_result.disasm.as_ref() {
84
log::debug!("disassembly:\n{disasm}");
85
}
86
87
Ok(CompiledCodeStencil {
88
buffer,
89
frame_size,
90
vcode: emit_result.disasm,
91
value_labels_ranges,
92
sized_stackslot_offsets,
93
dynamic_stackslot_offsets,
94
bb_starts: emit_result.bb_offsets,
95
bb_edges: emit_result.bb_edges,
96
})
97
}
98
99
fn name(&self) -> &'static str {
100
"s390x"
101
}
102
103
fn triple(&self) -> &Triple {
104
&self.triple
105
}
106
107
fn flags(&self) -> &shared_settings::Flags {
108
&self.flags
109
}
110
111
fn isa_flags(&self) -> Vec<shared_settings::Value> {
112
self.isa_flags.iter().collect()
113
}
114
115
fn isa_flags_hash_key(&self) -> IsaFlagsHashKey<'_> {
116
IsaFlagsHashKey(self.isa_flags.hash_key())
117
}
118
119
fn dynamic_vector_bytes(&self, _dyn_ty: Type) -> u32 {
120
16
121
}
122
123
#[cfg(feature = "unwind")]
124
fn emit_unwind_info(
125
&self,
126
result: &CompiledCode,
127
kind: crate::isa::unwind::UnwindInfoKind,
128
) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>> {
129
use crate::isa::unwind::UnwindInfo;
130
use crate::isa::unwind::UnwindInfoKind;
131
Ok(match kind {
132
UnwindInfoKind::SystemV => {
133
let mapper = self::inst::unwind::systemv::RegisterMapper;
134
Some(UnwindInfo::SystemV(
135
crate::isa::unwind::systemv::create_unwind_info_from_insts(
136
&result.buffer.unwind_info[..],
137
result.buffer.data().len(),
138
&mapper,
139
)?,
140
))
141
}
142
_ => None,
143
})
144
}
145
146
#[cfg(feature = "unwind")]
147
fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> {
148
Some(inst::unwind::systemv::create_cie())
149
}
150
151
#[cfg(feature = "unwind")]
152
fn map_regalloc_reg_to_dwarf(&self, reg: Reg) -> Result<u16, RegisterMappingError> {
153
inst::unwind::systemv::map_reg(reg).map(|reg| reg.0)
154
}
155
156
fn text_section_builder(&self, num_funcs: usize) -> Box<dyn TextSectionBuilder> {
157
Box::new(MachTextSectionBuilder::<inst::Inst>::new(num_funcs))
158
}
159
160
fn function_alignment(&self) -> FunctionAlignment {
161
inst::Inst::function_alignment()
162
}
163
164
fn page_size_align_log2(&self) -> u8 {
165
debug_assert_eq!(1 << 12, 0x1000);
166
12
167
}
168
169
#[cfg(feature = "disas")]
170
fn to_capstone(&self) -> Result<capstone::Capstone, capstone::Error> {
171
use capstone::prelude::*;
172
let mut cs = Capstone::new()
173
.sysz()
174
.mode(arch::sysz::ArchMode::Default)
175
.build()?;
176
177
cs.set_skipdata(true)?;
178
179
Ok(cs)
180
}
181
182
fn pretty_print_reg(&self, reg: Reg, _size: u8) -> String {
183
inst::regs::pretty_print_reg(reg)
184
}
185
186
fn has_native_fma(&self) -> bool {
187
true
188
}
189
190
fn has_round(&self) -> bool {
191
true
192
}
193
194
fn has_x86_blendv_lowering(&self, _: Type) -> bool {
195
false
196
}
197
198
fn has_x86_pshufb_lowering(&self) -> bool {
199
false
200
}
201
202
fn has_x86_pmulhrsw_lowering(&self) -> bool {
203
false
204
}
205
206
fn has_x86_pmaddubsw_lowering(&self) -> bool {
207
false
208
}
209
210
fn default_argument_extension(&self) -> ir::ArgumentExtension {
211
// This is copied/carried over from a historical piece of code in
212
// Wasmtime:
213
//
214
// https://github.com/bytecodealliance/wasmtime/blob/a018a5a9addb77d5998021a0150192aa955c71bf/crates/cranelift/src/lib.rs#L366-L374
215
//
216
// Whether or not it is still applicable here is unsure, but it's left
217
// the same as-is for now to reduce the likelihood of problems arising.
218
ir::ArgumentExtension::Uext
219
}
220
}
221
222
impl fmt::Display for S390xBackend {
223
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
224
f.debug_struct("MachBackend")
225
.field("name", &self.name())
226
.field("triple", &self.triple())
227
.field("flags", &format!("{}", self.flags()))
228
.finish()
229
}
230
}
231
232
/// Create a new `isa::Builder`.
233
pub fn isa_builder(triple: Triple) -> IsaBuilder {
234
assert!(triple.architecture == Architecture::S390x);
235
IsaBuilder {
236
triple,
237
setup: s390x_settings::builder(),
238
constructor: |triple, shared_flags, builder| {
239
let isa_flags = s390x_settings::Flags::new(&shared_flags, builder);
240
let backend = S390xBackend::new_with_flags(triple, shared_flags, isa_flags);
241
Ok(backend.wrapped())
242
},
243
}
244
}
245
246