Skip to content

Preserve pointer provenance in the Rust backend. #870

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 32 additions & 32 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ clap = { version = "4.3.19", features = ["derive"] }
env_logger = "0.10.0"
indexmap = "2.0.0"

wasmparser = "0.200.0"
wasm-encoder = "0.200.0"
wasm-metadata = "0.200.0"
wit-parser = "0.200.0"
wit-component = "0.200.0"
wasmparser = "0.201.0"
wasm-encoder = "0.201.0"
wasm-metadata = "0.201.0"
wit-parser = "0.201.0"
wit-component = "0.201.0"

wit-bindgen-core = { path = 'crates/core', version = '0.19.2' }
wit-bindgen-c = { path = 'crates/c', version = '0.19.2' }
Expand Down
24 changes: 19 additions & 5 deletions crates/c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2205,13 +2205,18 @@ impl Bindgen for FunctionBindgen<'_, '_> {
op
));
}
Bitcast::I32ToI64 => {
Bitcast::I32ToI64 | Bitcast::PToP64 => {
results.push(format!("(int64_t) {}", op));
}
Bitcast::I64ToI32 => {
Bitcast::I64ToI32 | Bitcast::P64ToP => {
results.push(format!("(int32_t) {}", op));
}
Bitcast::None => results.push(op.to_string()),
Bitcast::I64ToP64 | Bitcast::P64ToI64 => {
results.push(format!("{}", op));
}
Bitcast::I32ToP | Bitcast::PToI32 | Bitcast::None => {
results.push(op.to_string())
}
}
}
}
Expand Down Expand Up @@ -2869,11 +2874,17 @@ impl Bindgen for FunctionBindgen<'_, '_> {
}
}

Instruction::I32Load { offset } => self.load("int32_t", *offset, operands, results),
Instruction::I32Load { offset }
| Instruction::PointerLoad { offset }
| Instruction::LengthLoad { offset } => {
self.load("int32_t", *offset, operands, results)
}
Instruction::I64Load { offset } => self.load("int64_t", *offset, operands, results),
Instruction::F32Load { offset } => self.load("float", *offset, operands, results),
Instruction::F64Load { offset } => self.load("double", *offset, operands, results),
Instruction::I32Store { offset } => self.store("int32_t", *offset, operands),
Instruction::I32Store { offset }
| Instruction::PointerStore { offset }
| Instruction::LengthStore { offset } => self.store("int32_t", *offset, operands),
Instruction::I64Store { offset } => self.store("int64_t", *offset, operands),
Instruction::F32Store { offset } => self.store("float", *offset, operands),
Instruction::F64Store { offset } => self.store("double", *offset, operands),
Expand Down Expand Up @@ -3015,6 +3026,9 @@ fn wasm_type(ty: WasmType) -> &'static str {
WasmType::I64 => "int64_t",
WasmType::F32 => "float",
WasmType::F64 => "double",
WasmType::Pointer => "uintptr_t",
WasmType::PointerOrI64 => "int64_t",
WasmType::Length => "size_t",
}
}

Expand Down
68 changes: 58 additions & 10 deletions crates/core/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ def_instruction! {
/// it, using the specified constant offset.
F64Load { offset: i32 } : [1] => [1],

/// Like `I32Load` or `I64Load`, but for loading pointer values.
PointerLoad { offset: i32 } : [1] => [1],
/// Like `I32Load` or `I64Load`, but for loading array length values.
LengthLoad { offset: i32 } : [1] => [1],

/// Pops an `i32` address from the stack and then an `i32` value.
/// Stores the value in little-endian at the pointer specified plus the
/// constant `offset`.
Expand All @@ -138,6 +143,11 @@ def_instruction! {
/// constant `offset`.
F64Store { offset: i32 } : [2] => [0],

/// Like `I32Store` or `I64Store`, but for storing pointer values.
PointerStore { offset: i32 } : [2] => [0],
/// Like `I32Store` or `I64Store`, but for storing array length values.
LengthStore { offset: i32 } : [2] => [0],

// Scalar lifting/lowering

/// Converts an interface type `char` value to a 32-bit integer
Expand Down Expand Up @@ -526,6 +536,24 @@ pub enum Bitcast {
I64ToI32,
I64ToF32,

// PointerOrI64<->Pointer conversions. These preserve provenance.
//
// These are used when pointer values are being stored in
// (PToP64) and loaded out of (P64ToP) PointerOrI64 values, so they
// always have to preserve provenance.
P64ToP,
PToP64,

// Pointer<->integer conversions. These do not preserve provenance.
//
// These are used when integer values are being stored in
// (I64ToP64 and I32ToP) and loaded out of (P64ToI64 and PToI32) pointer
// or PointerOrI64 values, so they never have any provenance to preserve.
P64ToI64,
I64ToP64,
I32ToP,
PToI32,

None,
}

Expand Down Expand Up @@ -1517,9 +1545,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
// and the length into the high address.
self.lower(ty);
self.stack.push(addr.clone());
self.emit(&Instruction::I32Store { offset: offset + 4 });
self.emit(&Instruction::LengthStore { offset: offset + 4 });
self.stack.push(addr);
self.emit(&Instruction::I32Store { offset });
self.emit(&Instruction::PointerStore { offset });
}

fn write_fields_to_memory<'b>(
Expand Down Expand Up @@ -1689,9 +1717,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
// Read the pointer/len and then perform the standard lifting
// proceses.
self.stack.push(addr.clone());
self.emit(&Instruction::I32Load { offset });
self.emit(&Instruction::PointerLoad { offset });
self.stack.push(addr);
self.emit(&Instruction::I32Load { offset: offset + 4 });
self.emit(&Instruction::LengthLoad { offset: offset + 4 });
self.lift(ty);
}

Expand Down Expand Up @@ -1742,9 +1770,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
match *ty {
Type::String => {
self.stack.push(addr.clone());
self.emit(&Instruction::I32Load { offset });
self.emit(&Instruction::PointerLoad { offset });
self.stack.push(addr);
self.emit(&Instruction::I32Load { offset: offset + 4 });
self.emit(&Instruction::LengthLoad { offset: offset + 4 });
self.emit(&Instruction::GuestDeallocateString);
}

Expand Down Expand Up @@ -1772,9 +1800,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
self.finish_block(0);

self.stack.push(addr.clone());
self.emit(&Instruction::I32Load { offset });
self.emit(&Instruction::PointerLoad { offset });
self.stack.push(addr);
self.emit(&Instruction::I32Load { offset: offset + 4 });
self.emit(&Instruction::LengthLoad { offset: offset + 4 });
self.emit(&Instruction::GuestDeallocateList { element });
}

Expand Down Expand Up @@ -1862,7 +1890,12 @@ fn cast(from: WasmType, to: WasmType) -> Bitcast {
use WasmType::*;

match (from, to) {
(I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => Bitcast::None,
(I32, I32)
| (I64, I64)
| (F32, F32)
| (F64, F64)
| (Pointer, Pointer)
| (Length, Length) => Bitcast::None,

(I32, I64) => Bitcast::I32ToI64,
(F32, I32) => Bitcast::F32ToI32,
Expand All @@ -1875,7 +1908,22 @@ fn cast(from: WasmType, to: WasmType) -> Bitcast {
(F32, I64) => Bitcast::F32ToI64,
(I64, F32) => Bitcast::I64ToF32,

(F32, F64) | (F64, F32) | (F64, I32) | (I32, F64) => unreachable!(),
(I64, PointerOrI64) => Bitcast::I64ToP64,
(PointerOrI64, I64) => Bitcast::P64ToI64,
(Pointer, PointerOrI64) => Bitcast::PToP64,
(PointerOrI64, Pointer) => Bitcast::P64ToP,

(I32, Pointer) => Bitcast::I32ToP,
(Pointer, I32) => Bitcast::PToI32,

(Pointer | PointerOrI64 | Length, _)
| (_, Pointer | PointerOrI64 | Length)
| (F32, F64)
| (F64, F32)
| (F64, I32)
| (I32, F64) => {
unreachable!("Don't know how to bitcast from {:?} to {:?}", from, to);
}
}
}

Expand Down
Loading