Skip to content

Commit 8be22dd

Browse files
authored
pulley: Fix big-endian results in a spillslot (#11597)
This commit fixes an issue for Pulley on big-endian targets where if a call's result was mapped to a spillslot it was loaded with a too-wide load when moving from the return location to the storage location. This only affects the shared `CallInfo::emit_retval_loads` implementation which is unused on s390x. All other targets, with the exception of big-endian Pulley targets, using this are little-endian where the width won't matter since slots are always integer-register-in-size. The fix here is to perform a load with the exact type of the return value as opposed to a full machine word width. This fixes the big-endian behavior for Pulley and fixes the attached test cases which reproduce the issue. I've also expanded some of the many-results tests to also have many parameters to try to exercise more parts of the ABI pipeline too.
1 parent 3b85d83 commit 8be22dd

File tree

5 files changed

+272
-2
lines changed

5 files changed

+272
-2
lines changed

cranelift/codegen/src/machinst/abi.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2477,11 +2477,14 @@ impl<T> CallInfo<T> {
24772477
// returns), we use the integer temp register in
24782478
// steps.
24792479
let parts = (ty.bytes() + M::word_bytes() - 1) / M::word_bytes();
2480+
let one_part_load_ty =
2481+
Type::int_with_byte_size(M::word_bytes().min(ty.bytes()) as u16)
2482+
.unwrap();
24802483
for part in 0..parts {
24812484
emit(M::gen_load_stack(
24822485
amode.offset_by(part * M::word_bytes()),
24832486
temp,
2484-
M::word_type(),
2487+
one_part_load_ty,
24852488
));
24862489
emit(M::gen_store_stack(
24872490
StackAMode::Slot(

crates/test-util/src/wast.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,13 @@ impl Compiler {
293293
/// `Config::compiler_panicking_wasm_features`.
294294
pub fn should_fail(&self, config: &TestConfig) -> bool {
295295
match self {
296-
Compiler::CraneliftNative => config.legacy_exceptions(),
296+
Compiler::CraneliftNative => {
297+
// FIXME(#11602) temporarily disabled
298+
if cfg!(target_arch = "s390x") && config.exceptions() {
299+
return true;
300+
}
301+
config.legacy_exceptions()
302+
}
297303

298304
Compiler::Winch => {
299305
let unsupported_base = config.gc()

crates/wasmtime/src/config.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,6 +2087,11 @@ impl Config {
20872087
unsupported |= WasmFeatures::STACK_SWITCHING;
20882088
}
20892089

2090+
// FIXME(#11602) temporarily disabled
2091+
if self.compiler_target().architecture == target_lexicon::Architecture::S390x {
2092+
unsupported |= WasmFeatures::EXCEPTIONS;
2093+
}
2094+
20902095
use target_lexicon::*;
20912096
match self.compiler_target() {
20922097
Triple {
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
;;! exceptions = true
2+
3+
(module
4+
(func (export "f")
5+
(result
6+
i32 i32 i32 i32
7+
i32 i32 i32 i32
8+
i32 i32 i32 i32
9+
i32 i32 i32 i32
10+
i32
11+
)
12+
13+
(block $h
14+
(try_table (catch_all $h)
15+
call $f_callee
16+
return
17+
)
18+
)
19+
unreachable
20+
)
21+
(func $f_callee
22+
(result
23+
i32 i32 i32 i32
24+
i32 i32 i32 i32
25+
i32 i32 i32 i32
26+
i32 i32 i32 i32
27+
i32
28+
)
29+
30+
i32.const 0
31+
i32.const 1
32+
i32.const 2
33+
i32.const 3
34+
i32.const 4
35+
i32.const 5
36+
i32.const 6
37+
i32.const 7
38+
i32.const 8
39+
i32.const 9
40+
i32.const 10
41+
i32.const 11
42+
i32.const 12
43+
i32.const 13
44+
i32.const 14
45+
i32.const 15
46+
i32.const 16
47+
)
48+
49+
(func (export "f2")
50+
(param
51+
i32 i32 i32 i32
52+
i32 i32 i32 i32
53+
i32 i32 i32 i32
54+
i32 i32 i32 i32
55+
i32
56+
)
57+
(result
58+
i32 i32 i32 i32
59+
i32 i32 i32 i32
60+
i32 i32 i32 i32
61+
i32 i32 i32 i32
62+
i32
63+
)
64+
65+
(block $h
66+
(try_table (catch_all $h)
67+
local.get 0
68+
local.get 1
69+
local.get 2
70+
local.get 3
71+
local.get 4
72+
local.get 5
73+
local.get 6
74+
local.get 7
75+
local.get 8
76+
local.get 9
77+
local.get 10
78+
local.get 11
79+
local.get 12
80+
local.get 13
81+
local.get 14
82+
local.get 15
83+
local.get 16
84+
85+
call $f2_callee
86+
return
87+
)
88+
)
89+
unreachable
90+
)
91+
(func $f2_callee
92+
(param
93+
i32 i32 i32 i32
94+
i32 i32 i32 i32
95+
i32 i32 i32 i32
96+
i32 i32 i32 i32
97+
i32
98+
)
99+
(result
100+
i32 i32 i32 i32
101+
i32 i32 i32 i32
102+
i32 i32 i32 i32
103+
i32 i32 i32 i32
104+
i32
105+
)
106+
107+
local.get 0
108+
local.get 1
109+
local.get 2
110+
local.get 3
111+
local.get 4
112+
local.get 5
113+
local.get 6
114+
local.get 7
115+
local.get 8
116+
local.get 9
117+
local.get 10
118+
local.get 11
119+
local.get 12
120+
local.get 13
121+
local.get 14
122+
local.get 15
123+
local.get 16
124+
)
125+
)
126+
127+
(assert_return (invoke "f")
128+
(i32.const 0)
129+
(i32.const 1)
130+
(i32.const 2)
131+
(i32.const 3)
132+
(i32.const 4)
133+
(i32.const 5)
134+
(i32.const 6)
135+
(i32.const 7)
136+
(i32.const 8)
137+
(i32.const 9)
138+
(i32.const 10)
139+
(i32.const 11)
140+
(i32.const 12)
141+
(i32.const 13)
142+
(i32.const 14)
143+
(i32.const 15)
144+
(i32.const 16)
145+
)
146+
147+
(assert_return (invoke "f2"
148+
(i32.const 0)
149+
(i32.const 1)
150+
(i32.const 2)
151+
(i32.const 3)
152+
(i32.const 4)
153+
(i32.const 5)
154+
(i32.const 6)
155+
(i32.const 7)
156+
(i32.const 8)
157+
(i32.const 9)
158+
(i32.const 10)
159+
(i32.const 11)
160+
(i32.const 12)
161+
(i32.const 13)
162+
(i32.const 14)
163+
(i32.const 15)
164+
(i32.const 16)
165+
)
166+
(i32.const 0)
167+
(i32.const 1)
168+
(i32.const 2)
169+
(i32.const 3)
170+
(i32.const 4)
171+
(i32.const 5)
172+
(i32.const 6)
173+
(i32.const 7)
174+
(i32.const 8)
175+
(i32.const 9)
176+
(i32.const 10)
177+
(i32.const 11)
178+
(i32.const 12)
179+
(i32.const 13)
180+
(i32.const 14)
181+
(i32.const 15)
182+
(i32.const 16)
183+
)

tests/misc_testsuite/many-results.wast

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,41 @@
2626
i32.const 15
2727
i32.const 16
2828
)
29+
30+
(func (export "f2")
31+
(param
32+
i32 i32 i32 i32
33+
i32 i32 i32 i32
34+
i32 i32 i32 i32
35+
i32 i32 i32 i32
36+
i32
37+
)
38+
(result
39+
i32 i32 i32 i32
40+
i32 i32 i32 i32
41+
i32 i32 i32 i32
42+
i32 i32 i32 i32
43+
i32
44+
)
45+
46+
local.get 0
47+
local.get 1
48+
local.get 2
49+
local.get 3
50+
local.get 4
51+
local.get 5
52+
local.get 6
53+
local.get 7
54+
local.get 8
55+
local.get 9
56+
local.get 10
57+
local.get 11
58+
local.get 12
59+
local.get 13
60+
local.get 14
61+
local.get 15
62+
local.get 16
63+
)
2964
)
3065

3166
(assert_return (invoke "f")
@@ -47,3 +82,41 @@
4782
(i32.const 15)
4883
(i32.const 16)
4984
)
85+
86+
(assert_return (invoke "f2"
87+
(i32.const 0)
88+
(i32.const 1)
89+
(i32.const 2)
90+
(i32.const 3)
91+
(i32.const 4)
92+
(i32.const 5)
93+
(i32.const 6)
94+
(i32.const 7)
95+
(i32.const 8)
96+
(i32.const 9)
97+
(i32.const 10)
98+
(i32.const 11)
99+
(i32.const 12)
100+
(i32.const 13)
101+
(i32.const 14)
102+
(i32.const 15)
103+
(i32.const 16)
104+
)
105+
(i32.const 0)
106+
(i32.const 1)
107+
(i32.const 2)
108+
(i32.const 3)
109+
(i32.const 4)
110+
(i32.const 5)
111+
(i32.const 6)
112+
(i32.const 7)
113+
(i32.const 8)
114+
(i32.const 9)
115+
(i32.const 10)
116+
(i32.const 11)
117+
(i32.const 12)
118+
(i32.const 13)
119+
(i32.const 14)
120+
(i32.const 15)
121+
(i32.const 16)
122+
)

0 commit comments

Comments
 (0)