Skip to content

Commit 2238944

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 d876603 commit 2238944

File tree

7 files changed

+217
-68
lines changed

7 files changed

+217
-68
lines changed

crates/c/src/lib.rs

Lines changed: 16 additions & 4 deletions
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

Lines changed: 43 additions & 10 deletions
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

crates/csharp/src/lib.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,10 +1696,15 @@ impl Bindgen for FunctionBindgen<'_, '_> {
16961696
WasmType::I64 => "0L",
16971697
WasmType::F32 => "0.0F",
16981698
WasmType::F64 => "0.0D",
1699+
WasmType::Pointer => "0",
1700+
WasmType::PointerOrI64 => "0L",
1701+
WasmType::Length => "0",
16991702
}
17001703
.to_owned()
17011704
})),
1702-
Instruction::I32Load { offset } => match self.gen.direction {
1705+
Instruction::I32Load { offset }
1706+
| Instruction::PointerLoad { offset }
1707+
| Instruction::LengthLoad { offset } => match self.gen.direction {
17031708
Direction::Import => results.push(format!("ReturnArea.GetS32(ptr + {offset})")),
17041709
Direction::Export => results.push(format!("returnArea.GetS32({offset})")),
17051710
},
@@ -1723,7 +1728,9 @@ impl Bindgen for FunctionBindgen<'_, '_> {
17231728
}
17241729
Instruction::F64Load { offset } => results.push(format!("ReturnArea.GetF64({offset})")),
17251730

1726-
Instruction::I32Store { offset } => {
1731+
Instruction::I32Store { offset }
1732+
| Instruction::PointerStore { offset }
1733+
| Instruction::LengthStore { offset } => {
17271734
uwriteln!(self.src, "returnArea.SetS32({}, {});", offset, operands[0])
17281735
}
17291736
Instruction::I32Store8 { offset } => {
@@ -2223,6 +2230,9 @@ fn wasm_type(ty: WasmType) -> &'static str {
22232230
WasmType::I64 => "long",
22242231
WasmType::F32 => "float",
22252232
WasmType::F64 => "double",
2233+
WasmType::Pointer => "int",
2234+
WasmType::PointerOrI64 => "long",
2235+
WasmType::Length => "int",
22262236
}
22272237
}
22282238

0 commit comments

Comments
 (0)