Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/codegen/src/isa/s390x/mod.rs
3092 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::string::String;
16
use alloc::{boxed::Box, vec::Vec};
17
use core::fmt;
18
use cranelift_control::ControlPlane;
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 value_labels_ranges = emit_result.value_labels_ranges;
78
let buffer = emit_result.buffer;
79
80
if let Some(disasm) = emit_result.disasm.as_ref() {
81
log::debug!("disassembly:\n{disasm}");
82
}
83
84
Ok(CompiledCodeStencil {
85
buffer,
86
vcode: emit_result.disasm,
87
value_labels_ranges,
88
bb_starts: emit_result.bb_offsets,
89
bb_edges: emit_result.bb_edges,
90
})
91
}
92
93
fn name(&self) -> &'static str {
94
"s390x"
95
}
96
97
fn triple(&self) -> &Triple {
98
&self.triple
99
}
100
101
fn flags(&self) -> &shared_settings::Flags {
102
&self.flags
103
}
104
105
fn isa_flags(&self) -> Vec<shared_settings::Value> {
106
self.isa_flags.iter().collect()
107
}
108
109
fn isa_flags_hash_key(&self) -> IsaFlagsHashKey<'_> {
110
IsaFlagsHashKey(self.isa_flags.hash_key())
111
}
112
113
fn dynamic_vector_bytes(&self, _dyn_ty: Type) -> u32 {
114
16
115
}
116
117
#[cfg(feature = "unwind")]
118
fn emit_unwind_info(
119
&self,
120
result: &CompiledCode,
121
kind: crate::isa::unwind::UnwindInfoKind,
122
) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>> {
123
use crate::isa::unwind::UnwindInfo;
124
use crate::isa::unwind::UnwindInfoKind;
125
Ok(match kind {
126
UnwindInfoKind::SystemV => {
127
let mapper = self::inst::unwind::systemv::RegisterMapper;
128
Some(UnwindInfo::SystemV(
129
crate::isa::unwind::systemv::create_unwind_info_from_insts(
130
&result.buffer.unwind_info[..],
131
result.buffer.data().len(),
132
&mapper,
133
)?,
134
))
135
}
136
_ => None,
137
})
138
}
139
140
#[cfg(feature = "unwind")]
141
fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> {
142
Some(inst::unwind::systemv::create_cie())
143
}
144
145
#[cfg(feature = "unwind")]
146
fn map_regalloc_reg_to_dwarf(&self, reg: Reg) -> Result<u16, RegisterMappingError> {
147
inst::unwind::systemv::map_reg(reg).map(|reg| reg.0)
148
}
149
150
fn text_section_builder(&self, num_funcs: usize) -> Box<dyn TextSectionBuilder> {
151
Box::new(MachTextSectionBuilder::<inst::Inst>::new(num_funcs))
152
}
153
154
fn function_alignment(&self) -> FunctionAlignment {
155
inst::Inst::function_alignment()
156
}
157
158
fn page_size_align_log2(&self) -> u8 {
159
debug_assert_eq!(1 << 12, 0x1000);
160
12
161
}
162
163
#[cfg(feature = "disas")]
164
fn to_capstone(&self) -> Result<capstone::Capstone, capstone::Error> {
165
use capstone::prelude::*;
166
let mut cs = Capstone::new()
167
.sysz()
168
.mode(arch::sysz::ArchMode::Default)
169
.build()?;
170
171
cs.set_skipdata(true)?;
172
173
Ok(cs)
174
}
175
176
fn pretty_print_reg(&self, reg: Reg, _size: u8) -> String {
177
inst::regs::pretty_print_reg(reg)
178
}
179
180
fn has_native_fma(&self) -> bool {
181
true
182
}
183
184
fn has_round(&self) -> bool {
185
true
186
}
187
188
fn has_blendv_lowering(&self, _: Type) -> bool {
189
self.isa_flags.has_vxrs_ext3()
190
}
191
192
fn has_x86_pshufb_lowering(&self) -> bool {
193
false
194
}
195
196
fn has_x86_pmulhrsw_lowering(&self) -> bool {
197
false
198
}
199
200
fn has_x86_pmaddubsw_lowering(&self) -> bool {
201
false
202
}
203
204
fn default_argument_extension(&self) -> ir::ArgumentExtension {
205
// This is copied/carried over from a historical piece of code in
206
// Wasmtime:
207
//
208
// https://github.com/bytecodealliance/wasmtime/blob/a018a5a9addb77d5998021a0150192aa955c71bf/crates/cranelift/src/lib.rs#L366-L374
209
//
210
// Whether or not it is still applicable here is unsure, but it's left
211
// the same as-is for now to reduce the likelihood of problems arising.
212
ir::ArgumentExtension::Uext
213
}
214
}
215
216
impl fmt::Display for S390xBackend {
217
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
218
f.debug_struct("MachBackend")
219
.field("name", &self.name())
220
.field("triple", &self.triple())
221
.field("flags", &format!("{}", self.flags()))
222
.finish()
223
}
224
}
225
226
/// Create a new `isa::Builder`.
227
pub fn isa_builder(triple: Triple) -> IsaBuilder {
228
assert!(triple.architecture == Architecture::S390x);
229
IsaBuilder {
230
triple,
231
setup: s390x_settings::builder(),
232
constructor: |triple, shared_flags, builder| {
233
let isa_flags = s390x_settings::Flags::new(&shared_flags, builder);
234
let backend = S390xBackend::new_with_flags(triple, shared_flags, isa_flags);
235
Ok(backend.wrapped())
236
},
237
}
238
}
239
240