Closed ambiguousname closed 1 month ago
This is going to complicate Option code unfortunately.
I'm not convinced this is correct
#[repr(C)]
#[derive(Debug)]
pub struct HasPadding {
first: u8,
second: u32,
}
extern "C" {
fn diplomat_console_log_js(ptr: *const u8, len: usize);
}
fn log(x: &str) {
unsafe { diplomat_console_log_js(x.as_bytes() as *const [u8] as *const u8, x.len()) };
}
#[no_mangle]
pub fn myfn(x: HasPadding) {
log(&format!("{:?}", x))
}
This struct has padding, however myfn
needs to be called as myfn(first, second)
, with no padding bytes.
I'm fine with forbidding 64-bti types in structs for now
Interesting. When I replace u64 with u32 in the test, it does need padding.
This is because LLVM for this struct passes it down as a struct
%"structs::ffi::MyStruct" = type { i8, i8, i8, [1 x i8], i32, i32, i32, i32 }
define dso_local void @MyStruct_assert_value(%"structs::ffi::MyStruct" %0) unnamed_addr #0 !dbg !25583 {
...
whereas for the function above it gets passed in as two parameters, needing no padding
```llvm
define dso_local void @foo(i8 %x.0, i32 %x.1) unnamed_addr #0 {
Okay, this is interesting:
#[repr(C)]
pub struct HasPadding {
first: u8,
second: u32,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct MyStruct {
a: u8,
b: bool,
c: u8,
d: u32,
e: i32,
}
#[no_mangle]
pub extern "C" fn foo(x: HasPadding) {}
#[no_mangle]
pub extern "C" fn bar(x: MyStruct) {}
produces
%MyStruct = type { i8, i8, i8, [1 x i8], i32, i32 }
; Function Attrs: nounwind
define dso_local void @foo(i8 %x.0, i32 %x.1) unnamed_addr #0 {
start:
ret void
}
; Function Attrs: nounwind
define dso_local void @bar(%MyStruct %0) unnamed_addr #0 {
start:
%x = alloca [12 x i8], align 4
store %MyStruct %0, ptr %x, align 4
ret void
}
So what's the threshold for when it decides to introduce padding?
Adding a second u32
field to HasPadding promotes it to a struct with padding.
Trying to see if there's some documentation on this in https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md
Fixes #642