Skip to content

Commit

Permalink
rustc: Fix x86 ffi for empty struct arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
klutzy committed Mar 19, 2014
1 parent 7437995 commit 2d31bca
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 2 deletions.
18 changes: 17 additions & 1 deletion src/librustc/middle/trans/cabi.rs
Expand Up @@ -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
Expand Down Expand Up @@ -68,13 +70,27 @@ 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;
}

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
Expand Down
7 changes: 6 additions & 1 deletion src/librustc/middle/trans/cabi_x86.rs
Expand Up @@ -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),
};
Expand Down
10 changes: 10 additions & 0 deletions src/librustc/middle/trans/foreign.rs
Expand Up @@ -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));
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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; }

Expand Down
23 changes: 23 additions & 0 deletions src/rt/rust_test_helpers.c
Expand Up @@ -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;
Expand Down
55 changes: 55 additions & 0 deletions src/test/run-pass/extern-pass-empty.rs
@@ -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);
}
}

5 comments on commit 2d31bca

@bors
Copy link
Contributor

@bors bors commented on 2d31bca Mar 19, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from alexcrichton
at klutzy@2d31bca

@bors
Copy link
Contributor

@bors bors commented on 2d31bca Mar 19, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging klutzy/rust/win-struct-abi = 2d31bca into auto

@bors
Copy link
Contributor

@bors bors commented on 2d31bca Mar 19, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

klutzy/rust/win-struct-abi = 2d31bca merged ok, testing candidate = 61d5bc5

@bors
Copy link
Contributor

@bors bors commented on 2d31bca Mar 19, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on 2d31bca Mar 19, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 61d5bc5

Please sign in to comment.