Skip to content

Fix oversized loads on x86_64 SysV FFI calls #47614

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 1 commit into from
Feb 11, 2018
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
13 changes: 7 additions & 6 deletions src/librustc_trans/cabi_x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,13 @@ fn reg_component(cls: &[Option<Class>], i: &mut usize, size: Size) -> Option<Reg
None => None,
Some(Class::Int) => {
*i += 1;
Some(match size.bytes() {
1 => Reg::i8(),
2 => Reg::i16(),
3 |
4 => Reg::i32(),
_ => Reg::i64()
Some(if size.bytes() < 8 {
Reg {
kind: RegKind::Integer,
size
}
} else {
Reg::i64()
})
}
Some(Class::Sse) => {
Expand Down
39 changes: 39 additions & 0 deletions src/test/codegen/abi-x86_64_sysv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2017 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.

// only-x86_64

// compile-flags: -C no-prepopulate-passes

#![crate_type = "lib"]

pub struct S24 {
a: i8,
b: i8,
c: i8,
}

pub struct S48 {
a: i16,
b: i16,
c: i8,
}

// CHECK: i24 @struct_24_bits(i24
#[no_mangle]
pub extern "sysv64" fn struct_24_bits(a: S24) -> S24 {
a
}

// CHECK: i48 @struct_48_bits(i48
#[no_mangle]
pub extern "sysv64" fn struct_48_bits(a: S48) -> S48 {
a
}
39 changes: 39 additions & 0 deletions src/test/codegen/repr-transparent-sysv64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2017 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.

// only-x86_64

// compile-flags: -C no-prepopulate-passes

#![crate_type="lib"]
#![feature(repr_transparent)]

#[repr(C)]
pub struct Rgb8 { r: u8, g: u8, b: u8 }

#[repr(transparent)]
pub struct Rgb8Wrap(Rgb8);

// CHECK: i24 @test_Rgb8Wrap(i24)
#[no_mangle]
pub extern "sysv64" fn test_Rgb8Wrap(_: Rgb8Wrap) -> Rgb8Wrap { loop {} }

#[repr(C)]
pub union FloatBits {
float: f32,
bits: u32,
}

#[repr(transparent)]
pub struct SmallUnion(FloatBits);

// CHECK: i32 @test_SmallUnion(i32)
#[no_mangle]
pub extern "sysv64" fn test_SmallUnion(_: SmallUnion) -> SmallUnion { loop {} }
60 changes: 9 additions & 51 deletions src/test/codegen/repr-transparent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,55 +123,13 @@ pub struct StructWithProjection(<f32 as Mirror>::It);
pub extern fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }


// The rest of this file tests newtypes around small aggregates on an ABI where small aggregates are
// packed into one register. This is ABI-dependent, so instead we focus on one ABI and supply a
// dummy definition for other ABIs to keep FileCheck happy.
// All that remains to be tested are aggregates. They are tested in separate files called repr-
// transparent-*.rs with `only-*` or `ignore-*` directives, because the expected LLVM IR
// function signatures vary so much that it's not reasonably possible to cover all of them with a
// single CHECK line.
//
// Bigger aggregates are tested in separate files called repr-transparent-aggregate-*.rs because
// there, the expected LLVM IR function signatures vary so much that it's not reasonably possible to
// cover all of them with a single CHECK line. Instead we group ABIs by the general "shape" of the
// signature and have a separate test file for each bin.
//
// PS: You may be wondering why we don't just compare the return types and argument types for
// equality with FileCheck regex captures. Well, rustc doesn't perform newtype unwrapping on
// newtypes containing aggregates. This is OK on all ABIs we support, but because LLVM has not
// gotten rid of pointee types yet, the IR function signature will be syntactically different (%Foo*
// vs %FooWrapper*).

#[repr(C)]
pub struct Rgb8 { r: u8, g: u8, b: u8 }

#[repr(transparent)]
pub struct Rgb8Wrap(Rgb8);

// NB: closing parenthesis is missing because sometimes the argument has a name and sometimes not
// CHECK: define i32 @test_Rgb8Wrap(i32
#[no_mangle]
#[cfg(all(target_arch="x86_64", target_os="linux"))]
pub extern fn test_Rgb8Wrap(_: Rgb8Wrap) -> Rgb8Wrap { loop {} }

#[cfg(not(all(target_arch="x86_64", target_os="linux")))]
#[no_mangle]
pub extern fn test_Rgb8Wrap(_: u32) -> u32 { loop {} }

// Same as with the small struct above: ABI-dependent, we only test the interesting case
// (ABIs that pack the aggregate into a scalar) and stub it out on other ABIs

#[repr(C)]
pub union FloatBits {
float: f32,
bits: u32,
}

#[repr(transparent)]
pub struct SmallUnion(FloatBits);

// NB: closing parenthesis is missing because sometimes the argument has a name and sometimes not
// CHECK: define i32 @test_SmallUnion(i32
#[no_mangle]
#[cfg(all(target_arch="x86_64", target_os="linux"))]
pub extern fn test_SmallUnion(_: SmallUnion) -> SmallUnion { loop {} }

#[cfg(not(all(target_arch="x86_64", target_os="linux")))]
#[no_mangle]
pub extern fn test_SmallUnion(_: u32) -> u32 { loop {} }
// You may be wondering why we don't just compare the return types and argument types for equality
// with FileCheck regex captures. Well, rustc doesn't perform newtype unwrapping on newtypes
// containing aggregates. This is OK on all ABIs we support, but because LLVM has not gotten rid of
// pointee types yet, the IR function signature will be syntactically different (%Foo* vs
// %FooWrapper*).