提交 5f3dc8b7 编写于 作者: B Björn Steinbrink

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
上级 6c04c410
......@@ -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) => {
......
// 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
}
// 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 UnitPhantom<T, U> { val: T, unit: PhantomData<U> }
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*).
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册