Change:
I prepared some files that should illustrate the problem: Struct Color is passed incorrectly to function in C library. I pass {1,2,3,4} but receive {1,0,0,0}. It happens on Windows 7 64bit, but not on Linux Mint 64bit. Using external LLVM to compile bitcode (on Windows) works too.
Can you provide a slightly more minimized test case? It would also be useful to have content hosted in a github gist instead of a 7z archive that's much more easily accessible.
Sure:
Thanks! cc
It appears that gcc treats the struct as an immediate 32-bit value (one register), and our call to the function generate a function call with 4 arguments. I would copy-paste more assembly, but I'm not sure how to copy out of a windows VM...
These parts are probably relevant: was generated by LLVM integrated with rust was generated by my own LLVM build and it works OK Are there some parameters passed to integrated LLVM that could cause this?
I wrote a small utility to bypass the problem: It worked with rsfml, though I guess rust uses LLVM fork for a reason.

Discussion:
/// LLVM type or by coercing to another specified type Direct, /// Pass the argument indirectly via a hidden pointer <del> Indirect </del> <ins> Indirect, /// Ignore the argument (useful for empty struct) Ignore, </ins> } /// Information about how a specific C type

} } <ins> pub fn ignore(ty: Type) -> ArgType { ArgType { kind: Ignore, ty: ty, cast: None, pad: None, attr: None, } } </ins> pub fn is_direct(&self) -> bool { return self.kind == Direct; }

pub fn is_indirect(&self) -> bool { return self.kind == Indirect; } <ins> pub fn is_ignore(&self) -> bool { return self.kind == Ignore; } </ins> } /// Metadata describing how the arguments to a native function

for &t in atys.iter() { let ty = match t.kind() { Struct => { <del> ArgType::indirect(t, Some(ByValAttribute)) </del> <ins> let size = llsize_of_alloc(ccx, t); if size == 0 { ArgType::ignore(t) } else { ArgType::indirect(t, Some(ByValAttribute)) } </ins> } _ => ArgType::direct(t, None, None, None), };

for (i, &llarg_rust) in llargs_rust.iter().enumerate() { let mut llarg_rust = llarg_rust; <ins> if arg_tys[i].is_ignore() { continue; } </ins> // Does Rust pass this argument by pointer? let rust_indirect = type_of::arg_is_indirect(ccx, *passed_arg_tys.get(i));

}; for &arg_ty in tys.fn_ty.arg_tys.iter() { <ins> if arg_ty.is_ignore() { continue; } </ins> // add padding match arg_ty.pad { Some(ty) => llargument_tys.push(ty),

} for &arg_ty in tys.fn_ty.arg_tys.iter() { <ins> if arg_ty.is_ignore() { continue; } </ins> // skip padding if arg_ty.pad.is_some() { i += 1; }

return u; } <ins> 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); } </ins> intptr_t rust_get_test_int() { return 1;

<ins> // 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); } } </ins>