mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 11:07:42 +00:00
Auto merge of #47614 - dotdash:x86_64_sysv_ffi, r=eddyb
Fix oversized loads on x86_64 SysV FFI calls The x86_64 SysV ABI should use exact sizes for small structs passed in registers, i.e. a struct that occupies 3 bytes should use an i24, instead of the i32 it currently uses. Refs #45543
This commit is contained in:
commit
0196b20f69
@ -134,12 +134,13 @@ fn reg_component(cls: &[Option<Class>], i: &mut usize, size: Size) -> Option<Reg
|
|||||||
None => None,
|
None => None,
|
||||||
Some(Class::Int) => {
|
Some(Class::Int) => {
|
||||||
*i += 1;
|
*i += 1;
|
||||||
Some(match size.bytes() {
|
Some(if size.bytes() < 8 {
|
||||||
1 => Reg::i8(),
|
Reg {
|
||||||
2 => Reg::i16(),
|
kind: RegKind::Integer,
|
||||||
3 |
|
size
|
||||||
4 => Reg::i32(),
|
}
|
||||||
_ => Reg::i64()
|
} else {
|
||||||
|
Reg::i64()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Some(Class::Sse) => {
|
Some(Class::Sse) => {
|
||||||
|
39
src/test/codegen/abi-x86_64_sysv.rs
Normal file
39
src/test/codegen/abi-x86_64_sysv.rs
Normal file
@ -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
src/test/codegen/repr-transparent-sysv64.rs
Normal file
39
src/test/codegen/repr-transparent-sysv64.rs
Normal file
@ -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 {} }
|
@ -123,55 +123,13 @@ pub struct StructWithProjection(<f32 as Mirror>::It);
|
|||||||
pub extern fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }
|
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
|
// All that remains to be tested are aggregates. They are tested in separate files called repr-
|
||||||
// packed into one register. This is ABI-dependent, so instead we focus on one ABI and supply a
|
// transparent-*.rs with `only-*` or `ignore-*` directives, because the expected LLVM IR
|
||||||
// dummy definition for other ABIs to keep FileCheck happy.
|
// 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
|
// You may be wondering why we don't just compare the return types and argument types for equality
|
||||||
// there, the expected LLVM IR function signatures vary so much that it's not reasonably possible to
|
// with FileCheck regex captures. Well, rustc doesn't perform newtype unwrapping on newtypes
|
||||||
// cover all of them with a single CHECK line. Instead we group ABIs by the general "shape" of the
|
// containing aggregates. This is OK on all ABIs we support, but because LLVM has not gotten rid of
|
||||||
// signature and have a separate test file for each bin.
|
// pointee types yet, the IR function signature will be syntactically different (%Foo* vs
|
||||||
//
|
// %FooWrapper*).
|
||||||
// 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 {} }
|
|
||||||
|
Loading…
Reference in New Issue
Block a user