rustc: Fix x86 ffi for empty struct arguments
This commit is contained in:
parent
7437995b3e
commit
2d31bcaf16
@ -25,7 +25,9 @@ pub enum ArgKind {
|
||||
/// LLVM type or by coercing to another specified type
|
||||
Direct,
|
||||
/// Pass the argument indirectly via a hidden pointer
|
||||
Indirect
|
||||
Indirect,
|
||||
/// Ignore the argument (useful for empty struct)
|
||||
Ignore,
|
||||
}
|
||||
|
||||
/// Information about how a specific C type
|
||||
@ -68,6 +70,16 @@ impl ArgType {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ignore(ty: Type) -> ArgType {
|
||||
ArgType {
|
||||
kind: Ignore,
|
||||
ty: ty,
|
||||
cast: None,
|
||||
pad: None,
|
||||
attr: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_direct(&self) -> bool {
|
||||
return self.kind == Direct;
|
||||
}
|
||||
@ -75,6 +87,10 @@ impl ArgType {
|
||||
pub fn is_indirect(&self) -> bool {
|
||||
return self.kind == Indirect;
|
||||
}
|
||||
|
||||
pub fn is_ignore(&self) -> bool {
|
||||
return self.kind == Ignore;
|
||||
}
|
||||
}
|
||||
|
||||
/// Metadata describing how the arguments to a native function
|
||||
|
@ -66,7 +66,12 @@ pub fn compute_abi_info(ccx: &CrateContext,
|
||||
for &t in atys.iter() {
|
||||
let ty = match t.kind() {
|
||||
Struct => {
|
||||
ArgType::indirect(t, Some(ByValAttribute))
|
||||
let size = llsize_of_alloc(ccx, t);
|
||||
if size == 0 {
|
||||
ArgType::ignore(t)
|
||||
} else {
|
||||
ArgType::indirect(t, Some(ByValAttribute))
|
||||
}
|
||||
}
|
||||
_ => ArgType::direct(t, None, None, None),
|
||||
};
|
||||
|
@ -325,6 +325,10 @@ pub fn trans_native_call<'a>(
|
||||
for (i, &llarg_rust) in llargs_rust.iter().enumerate() {
|
||||
let mut llarg_rust = llarg_rust;
|
||||
|
||||
if arg_tys[i].is_ignore() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Does Rust pass this argument by pointer?
|
||||
let rust_indirect = type_of::arg_is_indirect(ccx,
|
||||
*passed_arg_tys.get(i));
|
||||
@ -901,6 +905,9 @@ fn lltype_for_fn_from_foreign_types(ccx: &CrateContext, tys: &ForeignTypes) -> T
|
||||
};
|
||||
|
||||
for &arg_ty in tys.fn_ty.arg_tys.iter() {
|
||||
if arg_ty.is_ignore() {
|
||||
continue;
|
||||
}
|
||||
// add padding
|
||||
match arg_ty.pad {
|
||||
Some(ty) => llargument_tys.push(ty),
|
||||
@ -949,6 +956,9 @@ fn add_argument_attributes(tys: &ForeignTypes,
|
||||
}
|
||||
|
||||
for &arg_ty in tys.fn_ty.arg_tys.iter() {
|
||||
if arg_ty.is_ignore() {
|
||||
continue;
|
||||
}
|
||||
// skip padding
|
||||
if arg_ty.pad.is_some() { i += 1; }
|
||||
|
||||
|
@ -126,6 +126,29 @@ rust_dbg_extern_identity_TwoDoubles(struct TwoDoubles u) {
|
||||
return u;
|
||||
}
|
||||
|
||||
struct ManyInts {
|
||||
int8_t arg1;
|
||||
int16_t arg2;
|
||||
int32_t arg3;
|
||||
int16_t arg4;
|
||||
int8_t arg5;
|
||||
struct TwoU8s arg6;
|
||||
};
|
||||
|
||||
struct Empty {
|
||||
};
|
||||
|
||||
void
|
||||
rust_dbg_extern_empty_struct(struct ManyInts v1, struct Empty e, struct ManyInts v2) {
|
||||
assert(v1.arg1 == v2.arg1 + 1);
|
||||
assert(v1.arg2 == v2.arg2 + 1);
|
||||
assert(v1.arg3 == v2.arg3 + 1);
|
||||
assert(v1.arg4 == v2.arg4 + 1);
|
||||
assert(v1.arg5 == v2.arg5 + 1);
|
||||
assert(v1.arg6.one == v2.arg6.one + 1);
|
||||
assert(v1.arg6.two == v2.arg6.two + 1);
|
||||
}
|
||||
|
||||
intptr_t
|
||||
rust_get_test_int() {
|
||||
return 1;
|
||||
|
55
src/test/run-pass/extern-pass-empty.rs
Normal file
55
src/test/run-pass/extern-pass-empty.rs
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test a foreign function that accepts empty struct.
|
||||
|
||||
struct TwoU8s {
|
||||
one: u8,
|
||||
two: u8,
|
||||
}
|
||||
|
||||
struct ManyInts {
|
||||
arg1: i8,
|
||||
arg2: i16,
|
||||
arg3: i32,
|
||||
arg4: i16,
|
||||
arg5: i8,
|
||||
arg6: TwoU8s,
|
||||
}
|
||||
|
||||
struct Empty;
|
||||
|
||||
#[link(name = "rustrt")]
|
||||
extern {
|
||||
fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
let x = ManyInts {
|
||||
arg1: 2,
|
||||
arg2: 3,
|
||||
arg3: 4,
|
||||
arg4: 5,
|
||||
arg5: 6,
|
||||
arg6: TwoU8s { one: 7, two: 8, }
|
||||
};
|
||||
let y = ManyInts {
|
||||
arg1: 1,
|
||||
arg2: 2,
|
||||
arg3: 3,
|
||||
arg4: 4,
|
||||
arg5: 5,
|
||||
arg6: TwoU8s { one: 6, two: 7, }
|
||||
};
|
||||
let empty = Empty;
|
||||
rust_dbg_extern_empty_struct(x, empty, y);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user