Skip to content

Commit 716134e

Browse files
committed
pulley: Ungate memory64 feature
This commit is similar to #9779 in that it's removing a proposal from the "known list of panicking features" for Pulley to allow more tests to run on Pulley. This then fills out a few miscellaneous instructions to get a full suite of tests passing in Pulley related to memory64 and other instructions. prtest:full
1 parent de7fcc3 commit 716134e

File tree

7 files changed

+132
-42
lines changed

7 files changed

+132
-42
lines changed

cranelift/codegen/src/isa/pulley_shared/lower.isle

+29
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,30 @@
186186
(rule (lower (has_type $I32 (sdiv a b)))
187187
(pulley_xdiv32_s a b))
188188

189+
;;;; Rules for `ishl` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
190+
191+
(rule (lower (has_type $I32 (ishl a b)))
192+
(pulley_xshl32 a b))
193+
194+
(rule (lower (has_type $I64 (ishl a b)))
195+
(pulley_xshl64 a b))
196+
197+
;;;; Rules for `ushr` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
198+
199+
(rule (lower (has_type $I32 (ushr a b)))
200+
(pulley_xshr32_u a b))
201+
202+
(rule (lower (has_type $I64 (ushr a b)))
203+
(pulley_xshr64_u a b))
204+
205+
;;;; Rules for `sshr` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
206+
207+
(rule (lower (has_type $I32 (sshr a b)))
208+
(pulley_xshr32_s a b))
209+
210+
(rule (lower (has_type $I64 (sshr a b)))
211+
(pulley_xshr64_s a b))
212+
189213
;;;; Rules for `band` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
190214

191215
(rule (lower (has_type $I32 (band a b)))
@@ -338,6 +362,11 @@
338362
(rule (lower (has_type (fits_in_64 _) (sextend val @ (value_type $I32))))
339363
(pulley_sext32 val))
340364

365+
;;;; Rules for `ireduce` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
366+
367+
(rule (lower (has_type (fits_in_64 _ty) (ireduce src)))
368+
src)
369+
341370
;;;; Rules for `uadd_overflow_trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
342371

343372
(rule (lower (has_type $I32 (uadd_overflow_trap a b tc)))

crates/cranelift/src/translate/code_translator/bounds_checks.rs

+19-5
Original file line numberDiff line numberDiff line change
@@ -491,11 +491,25 @@ fn cast_index_to_pointer_ty(
491491
if index_ty == pointer_ty {
492492
return index;
493493
}
494-
// Note that using 64-bit heaps on a 32-bit host is not currently supported,
495-
// would require at least a bounds check here to ensure that the truncation
496-
// from 64-to-32 bits doesn't lose any upper bits. For now though we're
497-
// mostly interested in the 32-bit-heaps-on-64-bit-hosts cast.
498-
assert!(index_ty.bits() < pointer_ty.bits());
494+
495+
// If the index size is larger than the pointer, that means that this is a
496+
// 32-bit host platform with a 64-bit wasm linear memory. If the index is
497+
// larger than 2**32 then that's guranteed to be out-of-bounds, otherwise we
498+
// `ireduce` the index.
499+
//
500+
// Also note that at this time this branch doesn't support pcc nor the
501+
// value-label-ranges of the below path.
502+
if index_ty.bits() > pointer_ty.bits() {
503+
assert_eq!(index_ty, ir::types::I64);
504+
assert_eq!(pointer_ty, ir::types::I32);
505+
let low_bits = pos.ins().ireduce(pointer_ty, index);
506+
let c32 = pos.ins().iconst(pointer_ty, 32);
507+
let high_bits = pos.ins().ushr(index, c32);
508+
let high_bits = pos.ins().ireduce(pointer_ty, high_bits);
509+
pos.ins()
510+
.trapnz(high_bits, ir::TrapCode::HEAP_OUT_OF_BOUNDS);
511+
return low_bits;
512+
}
499513

500514
// Convert `index` to `addr_ty`.
501515
let extended_index = pos.ins().uextend(pointer_ty, index);

crates/wasmtime/src/config.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1932,9 +1932,7 @@ impl Config {
19321932
// errors are panics though due to unimplemented bits in ABI
19331933
// code and those causes are listed here.
19341934
if self.compiler_target().is_pulley() {
1935-
return WasmFeatures::TAIL_CALL
1936-
| WasmFeatures::MEMORY64
1937-
| WasmFeatures::GC_TYPES;
1935+
return WasmFeatures::TAIL_CALL | WasmFeatures::GC_TYPES;
19381936
}
19391937

19401938
// Other Cranelift backends are either 100% missing or complete

crates/wasmtime/src/runtime/vm/memory.rs

-16
Original file line numberDiff line numberDiff line change
@@ -290,22 +290,6 @@ impl Memory {
290290
// overkill for this purpose.
291291
let absolute_max = 0usize.wrapping_sub(page_size);
292292

293-
// Sanity-check what should already be true from wasm module validation.
294-
// Note that for 32-bit targets the absolute maximum is `1<<32` during
295-
// compilation, not one-page-less-than-u32::MAX, so need to handle that
296-
// specially here.
297-
let absolute_max64 = if cfg!(target_pointer_width = "32") {
298-
1 << 32
299-
} else {
300-
u64::try_from(absolute_max).unwrap()
301-
};
302-
if let Ok(size) = ty.minimum_byte_size() {
303-
assert!(size <= absolute_max64);
304-
}
305-
if let Ok(max) = ty.maximum_byte_size() {
306-
assert!(max <= absolute_max64);
307-
}
308-
309293
// If the minimum memory size overflows the size of our own address
310294
// space, then we can't satisfy this request, but defer the error to
311295
// later so the `store` can be informed that an effective oom is

crates/wast-util/src/lib.rs

+28-18
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ impl WastTest {
415415
"misc_testsuite/component-model/nested.wast",
416416
"misc_testsuite/component-model/types.wast",
417417
"misc_testsuite/control-flow.wast",
418+
"misc_testsuite/custom-page-sizes/custom-page-sizes.wast",
418419
"misc_testsuite/elem-ref-null.wast",
419420
"misc_testsuite/elem_drop.wast",
420421
"misc_testsuite/empty.wast",
@@ -426,12 +427,23 @@ impl WastTest {
426427
"misc_testsuite/imported-memory-copy.wast",
427428
"misc_testsuite/issue4857.wast",
428429
"misc_testsuite/memory-copy.wast",
430+
"misc_testsuite/memory64/bounds.wast",
431+
"misc_testsuite/memory64/linking-errors.wast",
432+
"misc_testsuite/memory64/linking.wast",
433+
"misc_testsuite/memory64/multi-memory.wast",
434+
"misc_testsuite/memory64/offsets.wast",
435+
"misc_testsuite/multi-memory/simple.wast",
429436
"misc_testsuite/partial-init-memory-segment.wast",
430437
"misc_testsuite/rs2wasm-add-func.wast",
431438
"misc_testsuite/stack_overflow.wast",
439+
"misc_testsuite/table_grow_with_funcref.wast",
440+
"misc_testsuite/threads/atomics_notify.wast",
441+
"misc_testsuite/threads/atomics_wait_address.wast",
442+
"misc_testsuite/threads/wait_notify.wast",
432443
"misc_testsuite/winch/_simd_linking.wast",
433444
"misc_testsuite/winch/misc.wast",
434445
"misc_testsuite/winch/oob.wast",
446+
"misc_testsuite/winch/table_grow.wast",
435447
"spec_testsuite/address.wast",
436448
"spec_testsuite/binary-leb128.wast",
437449
"spec_testsuite/binary.wast",
@@ -445,11 +457,14 @@ impl WastTest {
445457
"spec_testsuite/memory_copy.wast",
446458
"spec_testsuite/memory_fill.wast",
447459
"spec_testsuite/memory_init.wast",
460+
"spec_testsuite/memory_size.wast",
461+
"spec_testsuite/memory_trap.wast",
448462
"spec_testsuite/names.wast",
449463
"spec_testsuite/obsolete-keywords.wast",
450464
"spec_testsuite/proposals/annotations/annotations.wast",
451465
"spec_testsuite/proposals/annotations/id.wast",
452466
"spec_testsuite/proposals/annotations/token.wast",
467+
"spec_testsuite/proposals/custom-page-sizes/custom-page-sizes.wast",
453468
"spec_testsuite/proposals/exception-handling/binary.wast",
454469
"spec_testsuite/proposals/multi-memory/address0.wast",
455470
"spec_testsuite/proposals/multi-memory/address1.wast",
@@ -462,21 +477,33 @@ impl WastTest {
462477
"spec_testsuite/proposals/multi-memory/exports0.wast",
463478
"spec_testsuite/proposals/multi-memory/imports1.wast",
464479
"spec_testsuite/proposals/multi-memory/imports2.wast",
480+
"spec_testsuite/proposals/multi-memory/imports4.wast",
465481
"spec_testsuite/proposals/multi-memory/linking1.wast",
482+
"spec_testsuite/proposals/multi-memory/linking2.wast",
466483
"spec_testsuite/proposals/multi-memory/load0.wast",
467484
"spec_testsuite/proposals/multi-memory/load1.wast",
468485
"spec_testsuite/proposals/multi-memory/memory-multi.wast",
469486
"spec_testsuite/proposals/multi-memory/memory_copy0.wast",
470487
"spec_testsuite/proposals/multi-memory/memory_copy1.wast",
471488
"spec_testsuite/proposals/multi-memory/memory_fill0.wast",
472489
"spec_testsuite/proposals/multi-memory/memory_init0.wast",
490+
"spec_testsuite/proposals/multi-memory/memory_size.wast",
491+
"spec_testsuite/proposals/multi-memory/memory_size0.wast",
492+
"spec_testsuite/proposals/multi-memory/memory_size1.wast",
493+
"spec_testsuite/proposals/multi-memory/memory_size2.wast",
473494
"spec_testsuite/proposals/multi-memory/memory_size3.wast",
495+
"spec_testsuite/proposals/multi-memory/memory_trap0.wast",
474496
"spec_testsuite/proposals/multi-memory/memory_trap1.wast",
475497
"spec_testsuite/proposals/multi-memory/start0.wast",
476498
"spec_testsuite/proposals/multi-memory/store.wast",
477499
"spec_testsuite/proposals/multi-memory/store0.wast",
478500
"spec_testsuite/proposals/multi-memory/store1.wast",
501+
"spec_testsuite/proposals/multi-memory/trap0.wast",
479502
"spec_testsuite/proposals/multi-memory/traps0.wast",
503+
"spec_testsuite/proposals/threads/atomics_notify.wast",
504+
"spec_testsuite/proposals/threads/atomics_wait_address.wast",
505+
"spec_testsuite/proposals/threads/exports.wast",
506+
"spec_testsuite/proposals/threads/wait_notify.wast",
480507
"spec_testsuite/simd_linking.wast",
481508
"spec_testsuite/skip-stack-guard-page.wast",
482509
"spec_testsuite/start.wast",
@@ -493,30 +520,13 @@ impl WastTest {
493520
"spec_testsuite/utf8-import-field.wast",
494521
"spec_testsuite/utf8-import-module.wast",
495522
"spec_testsuite/utf8-invalid-encoding.wast",
496-
"threads/exports.wast",
523+
"misc_testsuite/memory64/more-than-4gb.wast",
497524
];
498525

499526
if supported.iter().any(|part| self.path.ends_with(part)) {
500527
return false;
501528
}
502529

503-
// FIXME: once the backend has enough instruction support move these
504-
// into the above tests since they should pass on 64-bit platforms
505-
// as well.
506-
let supported32bit = [
507-
"misc_testsuite/winch/table_grow.wast",
508-
"misc_testsuite/table_grow_with_funcref.wast",
509-
"spec_testsuite/proposals/multi-memory/trap0.wast",
510-
"spec_testsuite/proposals/multi-memory/memory_trap0.wast",
511-
"spec_testsuite/proposals/multi-memory/linking2.wast",
512-
"spec_testsuite/memory_trap.wast",
513-
];
514-
if cfg!(target_pointer_width = "32") {
515-
if supported32bit.iter().any(|part| self.path.ends_with(part)) {
516-
return false;
517-
}
518-
}
519-
520530
return true;
521531
}
522532

pulley/src/interp.rs

+42
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,48 @@ impl OpVisitor for Interpreter<'_> {
11311131
ControlFlow::Continue(())
11321132
}
11331133

1134+
fn xshl32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1135+
let a = self.state[operands.src1].get_u32();
1136+
let b = self.state[operands.src2].get_u32();
1137+
self.state[operands.dst].set_u32(a.wrapping_shl(b));
1138+
ControlFlow::Continue(())
1139+
}
1140+
1141+
fn xshr32_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1142+
let a = self.state[operands.src1].get_u32();
1143+
let b = self.state[operands.src2].get_u32();
1144+
self.state[operands.dst].set_u32(a.wrapping_shr(b));
1145+
ControlFlow::Continue(())
1146+
}
1147+
1148+
fn xshr32_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1149+
let a = self.state[operands.src1].get_i32();
1150+
let b = self.state[operands.src2].get_u32();
1151+
self.state[operands.dst].set_i32(a.wrapping_shr(b));
1152+
ControlFlow::Continue(())
1153+
}
1154+
1155+
fn xshl64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1156+
let a = self.state[operands.src1].get_u64();
1157+
let b = self.state[operands.src2].get_u32();
1158+
self.state[operands.dst].set_u64(a.wrapping_shl(b));
1159+
ControlFlow::Continue(())
1160+
}
1161+
1162+
fn xshr64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1163+
let a = self.state[operands.src1].get_u64();
1164+
let b = self.state[operands.src2].get_u32();
1165+
self.state[operands.dst].set_u64(a.wrapping_shr(b));
1166+
ControlFlow::Continue(())
1167+
}
1168+
1169+
fn xshr64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1170+
let a = self.state[operands.src1].get_i64();
1171+
let b = self.state[operands.src2].get_u32();
1172+
self.state[operands.dst].set_i64(a.wrapping_shr(b));
1173+
ControlFlow::Continue(())
1174+
}
1175+
11341176
fn xeq64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
11351177
let a = self.state[operands.src1].get_u64();
11361178
let b = self.state[operands.src2].get_u64();

pulley/src/lib.rs

+13
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,19 @@ macro_rules! for_each_op {
184184
/// 64-bit wrapping subtraction: `dst = src1 - src2`.
185185
xsub64 = Xsub64 { operands: BinaryOperands<XReg> };
186186

187+
/// `low32(dst) = low32(src1) << low5(src2)`
188+
xshl32 = Xshl32 { operands: BinaryOperands<XReg> };
189+
/// `low32(dst) = low32(src1) >> low5(src2)`
190+
xshr32_s = Xshr32S { operands: BinaryOperands<XReg> };
191+
/// `low32(dst) = low32(src1) >> low5(src2)`
192+
xshr32_u = Xshr32U { operands: BinaryOperands<XReg> };
193+
/// `dst = src1 << low5(src2)`
194+
xshl64 = Xshl64 { operands: BinaryOperands<XReg> };
195+
/// `dst = src1 >> low6(src2)`
196+
xshr64_s = Xshr64S { operands: BinaryOperands<XReg> };
197+
/// `dst = src1 >> low6(src2)`
198+
xshr64_u = Xshr64U { operands: BinaryOperands<XReg> };
199+
187200
/// 64-bit equality.
188201
xeq64 = Xeq64 { operands: BinaryOperands<XReg> };
189202
/// 64-bit inequality.

0 commit comments

Comments
 (0)