Skip to content

Commit 407e94a

Browse files
committed
Preserve pointer provenance in the Rust backend.
Use the new `Pointer` and `Length` types in the Rust backend to emit code that uses `*mut c_void` and `usize` instead of `i32` when working with pointers and array lengths. To represent `PointerOrI64`, use a `MaybeUninit<u64>`, since that type can hold any `u64` and is documented to also preserve provenance. This change happens to get the generated Rust code close to supporting memory64, however it isn't complete; the abi code still emits hard-coded `+ 4` offsets for loading the length of a pointer+length pair in memory.
1 parent ec84c8e commit 407e94a

File tree

9 files changed

+254
-105
lines changed

9 files changed

+254
-105
lines changed

Cargo.lock

+32-32
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+5-5
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ clap = { version = "4.3.19", features = ["derive"] }
2929
env_logger = "0.10.0"
3030
indexmap = "2.0.0"
3131

32-
wasmparser = "0.200.0"
33-
wasm-encoder = "0.200.0"
34-
wasm-metadata = "0.200.0"
35-
wit-parser = "0.200.0"
36-
wit-component = "0.200.0"
32+
wasmparser = "0.201.0"
33+
wasm-encoder = "0.201.0"
34+
wasm-metadata = "0.201.0"
35+
wit-parser = "0.201.0"
36+
wit-component = "0.201.0"
3737

3838
wit-bindgen-core = { path = 'crates/core', version = '0.19.2' }
3939
wit-bindgen-c = { path = 'crates/c', version = '0.19.2' }

crates/c/src/lib.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -2205,12 +2205,15 @@ impl Bindgen for FunctionBindgen<'_, '_> {
22052205
op
22062206
));
22072207
}
2208-
Bitcast::I32ToI64 => {
2208+
Bitcast::I32ToI64 | Bitcast::PToP64 => {
22092209
results.push(format!("(int64_t) {}", op));
22102210
}
2211-
Bitcast::I64ToI32 => {
2211+
Bitcast::I64ToI32 | Bitcast::P64ToP => {
22122212
results.push(format!("(int32_t) {}", op));
22132213
}
2214+
Bitcast::I64ToP64 | Bitcast::P64ToI64 => {
2215+
results.push(format!("{}", op));
2216+
}
22142217
Bitcast::None => results.push(op.to_string()),
22152218
}
22162219
}
@@ -2869,11 +2872,17 @@ impl Bindgen for FunctionBindgen<'_, '_> {
28692872
}
28702873
}
28712874

2872-
Instruction::I32Load { offset } => self.load("int32_t", *offset, operands, results),
2875+
Instruction::I32Load { offset }
2876+
| Instruction::PointerLoad { offset }
2877+
| Instruction::LengthLoad { offset } => {
2878+
self.load("int32_t", *offset, operands, results)
2879+
}
28732880
Instruction::I64Load { offset } => self.load("int64_t", *offset, operands, results),
28742881
Instruction::F32Load { offset } => self.load("float", *offset, operands, results),
28752882
Instruction::F64Load { offset } => self.load("double", *offset, operands, results),
2876-
Instruction::I32Store { offset } => self.store("int32_t", *offset, operands),
2883+
Instruction::I32Store { offset }
2884+
| Instruction::PointerStore { offset }
2885+
| Instruction::LengthStore { offset } => self.store("int32_t", *offset, operands),
28772886
Instruction::I64Store { offset } => self.store("int64_t", *offset, operands),
28782887
Instruction::F32Store { offset } => self.store("float", *offset, operands),
28792888
Instruction::F64Store { offset } => self.store("double", *offset, operands),
@@ -3015,6 +3024,9 @@ fn wasm_type(ty: WasmType) -> &'static str {
30153024
WasmType::I64 => "int64_t",
30163025
WasmType::F32 => "float",
30173026
WasmType::F64 => "double",
3027+
WasmType::Pointer => "uintptr_t",
3028+
WasmType::PointerOrI64 => "int64_t",
3029+
WasmType::Length => "size_t",
30183030
}
30193031
}
30203032

crates/core/src/abi.rs

+43-10
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ def_instruction! {
113113
/// it, using the specified constant offset.
114114
F64Load { offset: i32 } : [1] => [1],
115115

116+
/// Like `I32Load` or `I64Load`, but for loading pointer values.
117+
PointerLoad { offset: i32 } : [1] => [1],
118+
/// Like `I32Load` or `I64Load`, but for loading array length values.
119+
LengthLoad { offset: i32 } : [1] => [1],
120+
116121
/// Pops an `i32` address from the stack and then an `i32` value.
117122
/// Stores the value in little-endian at the pointer specified plus the
118123
/// constant `offset`.
@@ -138,6 +143,11 @@ def_instruction! {
138143
/// constant `offset`.
139144
F64Store { offset: i32 } : [2] => [0],
140145

146+
/// Like `I32Store` or `I64Store`, but for storing pointer values.
147+
PointerStore { offset: i32 } : [2] => [0],
148+
/// Like `I32Store` or `I64Store`, but for storing array length values.
149+
LengthStore { offset: i32 } : [2] => [0],
150+
141151
// Scalar lifting/lowering
142152

143153
/// Converts an interface type `char` value to a 32-bit integer
@@ -526,6 +536,12 @@ pub enum Bitcast {
526536
I64ToI32,
527537
I64ToF32,
528538

539+
// Pointers
540+
P64ToI64,
541+
I64ToP64,
542+
P64ToP,
543+
PToP64,
544+
529545
None,
530546
}
531547

@@ -1517,9 +1533,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
15171533
// and the length into the high address.
15181534
self.lower(ty);
15191535
self.stack.push(addr.clone());
1520-
self.emit(&Instruction::I32Store { offset: offset + 4 });
1536+
self.emit(&Instruction::LengthStore { offset: offset + 4 });
15211537
self.stack.push(addr);
1522-
self.emit(&Instruction::I32Store { offset });
1538+
self.emit(&Instruction::PointerStore { offset });
15231539
}
15241540

15251541
fn write_fields_to_memory<'b>(
@@ -1689,9 +1705,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
16891705
// Read the pointer/len and then perform the standard lifting
16901706
// proceses.
16911707
self.stack.push(addr.clone());
1692-
self.emit(&Instruction::I32Load { offset });
1708+
self.emit(&Instruction::PointerLoad { offset });
16931709
self.stack.push(addr);
1694-
self.emit(&Instruction::I32Load { offset: offset + 4 });
1710+
self.emit(&Instruction::LengthLoad { offset: offset + 4 });
16951711
self.lift(ty);
16961712
}
16971713

@@ -1742,9 +1758,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
17421758
match *ty {
17431759
Type::String => {
17441760
self.stack.push(addr.clone());
1745-
self.emit(&Instruction::I32Load { offset });
1761+
self.emit(&Instruction::PointerLoad { offset });
17461762
self.stack.push(addr);
1747-
self.emit(&Instruction::I32Load { offset: offset + 4 });
1763+
self.emit(&Instruction::LengthLoad { offset: offset + 4 });
17481764
self.emit(&Instruction::GuestDeallocateString);
17491765
}
17501766

@@ -1772,9 +1788,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
17721788
self.finish_block(0);
17731789

17741790
self.stack.push(addr.clone());
1775-
self.emit(&Instruction::I32Load { offset });
1791+
self.emit(&Instruction::PointerLoad { offset });
17761792
self.stack.push(addr);
1777-
self.emit(&Instruction::I32Load { offset: offset + 4 });
1793+
self.emit(&Instruction::LengthLoad { offset: offset + 4 });
17781794
self.emit(&Instruction::GuestDeallocateList { element });
17791795
}
17801796

@@ -1862,7 +1878,12 @@ fn cast(from: WasmType, to: WasmType) -> Bitcast {
18621878
use WasmType::*;
18631879

18641880
match (from, to) {
1865-
(I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => Bitcast::None,
1881+
(I32, I32)
1882+
| (I64, I64)
1883+
| (F32, F32)
1884+
| (F64, F64)
1885+
| (Pointer, Pointer)
1886+
| (Length, Length) => Bitcast::None,
18661887

18671888
(I32, I64) => Bitcast::I32ToI64,
18681889
(F32, I32) => Bitcast::F32ToI32,
@@ -1875,7 +1896,19 @@ fn cast(from: WasmType, to: WasmType) -> Bitcast {
18751896
(F32, I64) => Bitcast::F32ToI64,
18761897
(I64, F32) => Bitcast::I64ToF32,
18771898

1878-
(F32, F64) | (F64, F32) | (F64, I32) | (I32, F64) => unreachable!(),
1899+
(I64, PointerOrI64) => Bitcast::I64ToP64,
1900+
(PointerOrI64, I64) => Bitcast::P64ToI64,
1901+
(Pointer, PointerOrI64) => Bitcast::PToP64,
1902+
(PointerOrI64, Pointer) => Bitcast::P64ToP,
1903+
1904+
(Pointer | PointerOrI64 | Length, _)
1905+
| (_, Pointer | PointerOrI64 | Length)
1906+
| (F32, F64)
1907+
| (F64, F32)
1908+
| (F64, I32)
1909+
| (I32, F64) => {
1910+
unreachable!()
1911+
}
18791912
}
18801913
}
18811914

0 commit comments

Comments
 (0)