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:
parent
6c04c41034
commit
5f3dc8b7b2
@ -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) => {
|
||||
|
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 {} }
|
||||
|
||||
|
||||
// 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*).
|
||||
|
Loading…
x
Reference in New Issue
Block a user