Manually set dso_local when its valid to do so
This should have no real effect in most cases, as e.g. `hidden`
visibility already implies `dso_local` (or at least LLVM IR does not
preserve the `dso_local` setting if the item is already `hidden`), but
it should fix `-Crelocation-model=static` and improve codegen in
executables.
Note that this PR does not exhaustively port the logic in [clang]. Only
the obviously correct portion and what is necessary to fix a regression
from LLVM 12 that relates to `-Crelocation_model=static`.
Fixes #83335
[clang]: 3001d080c8/clang/lib/CodeGen/CodeGenModule.cpp (L945-L1039)
This commit is contained in:
parent
9b0edb7fdd
commit
2f000a78bf
30 changed files with 221 additions and 122 deletions
|
@ -254,6 +254,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
|
|||
attributes::emit_uwtable(llfn, true);
|
||||
}
|
||||
|
||||
// FIXME: none of these three functions interact with source level attributes.
|
||||
set_frame_pointer_elimination(cx, llfn);
|
||||
set_instrument_function(cx, llfn);
|
||||
set_probestack(cx, llfn);
|
||||
|
|
|
@ -14,6 +14,7 @@ use tracing::debug;
|
|||
|
||||
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
|
||||
use rustc_middle::ty::{self, Instance, TypeFoldable};
|
||||
use rustc_target::spec::RelocModel;
|
||||
|
||||
/// Codegens a reference to a fn/method item, monomorphizing and
|
||||
/// inlining as it goes.
|
||||
|
@ -170,17 +171,19 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MinGW: For backward compatibility we rely on the linker to decide whether it
|
||||
// should use dllimport for functions.
|
||||
if cx.use_dll_storage_attrs
|
||||
&& tcx.is_dllimport_foreign_item(instance_def_id)
|
||||
&& tcx.sess.target.env != "gnu"
|
||||
{
|
||||
unsafe {
|
||||
// MinGW: For backward compatibility we rely on the linker to decide whether it
|
||||
// should use dllimport for functions.
|
||||
if cx.use_dll_storage_attrs
|
||||
&& tcx.is_dllimport_foreign_item(instance_def_id)
|
||||
&& tcx.sess.target.env != "gnu"
|
||||
{
|
||||
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
|
||||
}
|
||||
|
||||
if cx.tcx.sess.relocation_model() == RelocModel::Static {
|
||||
llvm::LLVMRustSetDSOLocal(llfn, true);
|
||||
}
|
||||
}
|
||||
|
||||
llfn
|
||||
|
|
|
@ -1031,6 +1031,7 @@ extern "C" {
|
|||
pub fn LLVMSetSection(Global: &Value, Section: *const c_char);
|
||||
pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility;
|
||||
pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility);
|
||||
pub fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool);
|
||||
pub fn LLVMGetAlignment(Global: &Value) -> c_uint;
|
||||
pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint);
|
||||
pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass);
|
||||
|
|
|
@ -10,7 +10,9 @@ pub use rustc_middle::mir::mono::MonoItem;
|
|||
use rustc_middle::mir::mono::{Linkage, Visibility};
|
||||
use rustc_middle::ty::layout::FnAbiExt;
|
||||
use rustc_middle::ty::{self, Instance, TypeFoldable};
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_target::abi::LayoutOf;
|
||||
use rustc_target::spec::RelocModel;
|
||||
use tracing::debug;
|
||||
|
||||
impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
|
@ -35,6 +37,9 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
unsafe {
|
||||
llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage));
|
||||
llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility));
|
||||
if self.should_assume_dso_local(linkage, visibility) {
|
||||
llvm::LLVMRustSetDSOLocal(g, true);
|
||||
}
|
||||
}
|
||||
|
||||
self.instances.borrow_mut().insert(instance, g);
|
||||
|
@ -79,6 +84,42 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
|
||||
attributes::from_fn_attrs(self, lldecl, instance);
|
||||
|
||||
unsafe {
|
||||
if self.should_assume_dso_local(linkage, visibility) {
|
||||
llvm::LLVMRustSetDSOLocal(lldecl, true);
|
||||
}
|
||||
}
|
||||
|
||||
self.instances.borrow_mut().insert(instance, lldecl);
|
||||
}
|
||||
}
|
||||
|
||||
impl CodegenCx<'ll, 'tcx> {
|
||||
/// Whether a definition (NB: not declaration!) can be assumed to be local to a group of
|
||||
/// libraries that form a single DSO or executable.
|
||||
pub(crate) unsafe fn should_assume_dso_local(
|
||||
&self,
|
||||
linkage: Linkage,
|
||||
visibility: Visibility,
|
||||
) -> bool {
|
||||
if matches!(linkage, Linkage::Internal | Linkage::Private) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if visibility != Visibility::Default && linkage != Linkage::ExternalWeak {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Static relocation model should force copy relocations everywhere.
|
||||
if self.tcx.sess.relocation_model() == RelocModel::Static {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Symbols from executables can't really be imported any further.
|
||||
if self.tcx.sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1636,6 +1636,10 @@ extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
|
|||
LLVMSetVisibility(V, fromRust(RustVisibility));
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
|
||||
unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
|
||||
}
|
||||
|
||||
struct LLVMRustModuleBuffer {
|
||||
std::string data;
|
||||
};
|
||||
|
|
44
src/test/assembly/static-relocation-model.rs
Normal file
44
src/test/assembly/static-relocation-model.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
// min-llvm-version: 12.0.0
|
||||
// needs-llvm-components: aarch64 x86
|
||||
// revisions:X64 A64
|
||||
// assembly-output: emit-asm
|
||||
// [X64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=static
|
||||
// [A64] compile-flags: --target aarch64-unknown-linux-gnu -Crelocation-model=static
|
||||
|
||||
#![feature(no_core, lang_items)]
|
||||
#![no_core]
|
||||
#![crate_type="rlib"]
|
||||
|
||||
#[lang="sized"]
|
||||
trait Sized {}
|
||||
|
||||
#[lang="copy"]
|
||||
trait Copy {}
|
||||
|
||||
impl Copy for u8 {}
|
||||
|
||||
extern "C" {
|
||||
fn chaenomeles();
|
||||
}
|
||||
|
||||
// CHECK-LABEL: banana:
|
||||
// x64: movb chaenomeles, %{{[a,z]+}}
|
||||
// A64: adrp [[REG:[a-z0-9]+]], chaenomeles
|
||||
// A64-NEXT: ldrb {{[a-z0-9]+}}, {{\[}}[[REG]], :lo12:chaenomeles]
|
||||
#[no_mangle]
|
||||
pub fn banana() -> u8 {
|
||||
unsafe {
|
||||
*(chaenomeles as *mut u8)
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: peach:
|
||||
// x64: movb banana, %{{[a,z]+}}
|
||||
// A64: adrp [[REG2:[a-z0-9]+]], banana
|
||||
// A64-NEXT: ldrb {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:banana]
|
||||
#[no_mangle]
|
||||
pub fn peach() -> u8 {
|
||||
unsafe {
|
||||
*(banana as *mut u8)
|
||||
}
|
||||
}
|
|
@ -23,8 +23,8 @@ trait Copy { }
|
|||
|
||||
//x86_64: define win64cc void @has_efiapi
|
||||
//i686: define void @has_efiapi
|
||||
//aarch64: define void @has_efiapi
|
||||
//arm: define void @has_efiapi
|
||||
//riscv: define void @has_efiapi
|
||||
//aarch64: define dso_local void @has_efiapi
|
||||
//arm: define dso_local void @has_efiapi
|
||||
//riscv: define dso_local void @has_efiapi
|
||||
#[no_mangle]
|
||||
pub extern "efiapi" fn has_efiapi() {}
|
||||
|
|
|
@ -6,7 +6,7 @@ pub enum Type {
|
|||
Type2 = 1
|
||||
}
|
||||
|
||||
// CHECK: define signext i8 @test()
|
||||
// CHECK: define{{( dso_local)?}} signext i8 @test()
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test() -> Type {
|
||||
Type::Type1
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
// Checks if the correct annotation for the sysv64 ABI is passed to
|
||||
// llvm. Also checks that the abi-sysv64 feature gate allows usage
|
||||
// of the sysv64 abi.
|
||||
|
||||
// ignore-arm
|
||||
// ignore-aarch64
|
||||
// ignore-riscv64 sysv64 not supported
|
||||
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
//
|
||||
// needs-llvm-components: x86
|
||||
// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![no_core]
|
||||
#![feature(abi_x86_interrupt, no_core, lang_items)]
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
// CHECK: define x86_64_sysvcc i64 @has_sysv64_abi
|
||||
#[no_mangle]
|
||||
pub extern "sysv64" fn has_sysv64_abi(a: i64) -> i64 {
|
||||
a * 2
|
||||
a
|
||||
}
|
||||
|
|
|
@ -2,17 +2,20 @@
|
|||
// llvm. Also checks that the abi_x86_interrupt feature gate allows usage
|
||||
// of the x86-interrupt abi.
|
||||
|
||||
// ignore-arm
|
||||
// ignore-aarch64
|
||||
// ignore-riscv64 x86-interrupt is not supported
|
||||
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
// needs-llvm-components: x86
|
||||
// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(abi_x86_interrupt)]
|
||||
#![no_core]
|
||||
#![feature(abi_x86_interrupt, no_core, lang_items)]
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
// CHECK: define x86_intrcc i64 @has_x86_interrupt_abi
|
||||
#[no_mangle]
|
||||
pub extern "x86-interrupt" fn has_x86_interrupt_abi(a: i64) -> i64 {
|
||||
a * 2
|
||||
a
|
||||
}
|
||||
|
|
|
@ -2,42 +2,42 @@
|
|||
|
||||
#![crate_type = "cdylib"]
|
||||
|
||||
// CHECK: define void @a()
|
||||
// CHECK: define{{( dso_local)?}} void @a()
|
||||
#[no_mangle]
|
||||
#[inline]
|
||||
pub extern "C" fn a() {}
|
||||
|
||||
// CHECK: define void @b()
|
||||
// CHECK: define{{( dso_local)?}} void @b()
|
||||
#[export_name = "b"]
|
||||
#[inline]
|
||||
pub extern "C" fn b() {}
|
||||
|
||||
// CHECK: define void @c()
|
||||
// CHECK: define{{( dso_local)?}} void @c()
|
||||
#[no_mangle]
|
||||
#[inline]
|
||||
extern "C" fn c() {}
|
||||
|
||||
// CHECK: define void @d()
|
||||
// CHECK: define{{( dso_local)?}} void @d()
|
||||
#[export_name = "d"]
|
||||
#[inline]
|
||||
extern "C" fn d() {}
|
||||
|
||||
// CHECK: define void @e()
|
||||
// CHECK: define{{( dso_local)?}} void @e()
|
||||
#[no_mangle]
|
||||
#[inline(always)]
|
||||
pub extern "C" fn e() {}
|
||||
|
||||
// CHECK: define void @f()
|
||||
// CHECK: define{{( dso_local)?}} void @f()
|
||||
#[export_name = "f"]
|
||||
#[inline(always)]
|
||||
pub extern "C" fn f() {}
|
||||
|
||||
// CHECK: define void @g()
|
||||
// CHECK: define{{( dso_local)?}} void @g()
|
||||
#[no_mangle]
|
||||
#[inline(always)]
|
||||
extern "C" fn g() {}
|
||||
|
||||
// CHECK: define void @h()
|
||||
// CHECK: define{{( dso_local)?}} void @h()
|
||||
#[export_name = "h"]
|
||||
#[inline(always)]
|
||||
extern "C" fn h() {}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//
|
||||
// no-system-llvm
|
||||
// compile-flags: -O
|
||||
|
||||
|
@ -15,7 +14,7 @@ impl Drop for A {
|
|||
|
||||
#[no_mangle]
|
||||
pub fn a(a: Box<i32>) {
|
||||
// CHECK-LABEL: define void @a
|
||||
// CHECK-LABEL: define{{.*}}void @a
|
||||
// CHECK: call void @__rust_dealloc
|
||||
// CHECK-NEXT: call void @foo
|
||||
let _a = A;
|
||||
|
|
|
@ -4,30 +4,30 @@
|
|||
#![crate_type = "lib"]
|
||||
#![no_std]
|
||||
|
||||
// CHECK: define void @a()
|
||||
// CHECK: define{{( dso_local)?}} void @a()
|
||||
#[no_mangle]
|
||||
fn a() {}
|
||||
|
||||
// CHECK: define void @b()
|
||||
// CHECK: define{{( dso_local)?}} void @b()
|
||||
#[no_mangle]
|
||||
pub fn b() {}
|
||||
|
||||
mod private {
|
||||
// CHECK: define void @c()
|
||||
// CHECK: define{{( dso_local)?}} void @c()
|
||||
#[no_mangle]
|
||||
fn c() {}
|
||||
|
||||
// CHECK: define void @d()
|
||||
// CHECK: define{{( dso_local)?}} void @d()
|
||||
#[no_mangle]
|
||||
pub fn d() {}
|
||||
}
|
||||
|
||||
const HIDDEN: () = {
|
||||
// CHECK: define void @e()
|
||||
// CHECK: define{{( dso_local)?}} void @e()
|
||||
#[no_mangle]
|
||||
fn e() {}
|
||||
|
||||
// CHECK: define void @f()
|
||||
// CHECK: define{{( dso_local)?}} void @f()
|
||||
#[no_mangle]
|
||||
pub fn f() {}
|
||||
};
|
||||
|
@ -38,13 +38,13 @@ const HIDDEN: () = {
|
|||
// CHECK-NEXT: define internal
|
||||
#[inline(never)]
|
||||
fn x() {
|
||||
// CHECK: define void @g()
|
||||
// CHECK: define{{( dso_local)?}} void @g()
|
||||
#[no_mangle]
|
||||
fn g() {
|
||||
x();
|
||||
}
|
||||
|
||||
// CHECK: define void @h()
|
||||
// CHECK: define{{( dso_local)?}} void @h()
|
||||
#[no_mangle]
|
||||
pub fn h() {}
|
||||
|
||||
|
@ -54,22 +54,22 @@ fn x() {
|
|||
}
|
||||
}
|
||||
|
||||
// CHECK: define void @i()
|
||||
// CHECK: define{{( dso_local)?}} void @i()
|
||||
#[no_mangle]
|
||||
#[inline]
|
||||
fn i() {}
|
||||
|
||||
// CHECK: define void @j()
|
||||
// CHECK: define{{( dso_local)?}} void @j()
|
||||
#[no_mangle]
|
||||
#[inline]
|
||||
pub fn j() {}
|
||||
|
||||
// CHECK: define void @k()
|
||||
// CHECK: define{{( dso_local)?}} void @k()
|
||||
#[no_mangle]
|
||||
#[inline(always)]
|
||||
fn k() {}
|
||||
|
||||
// CHECK: define void @l()
|
||||
// CHECK: define{{( dso_local)?}} void @l()
|
||||
#[no_mangle]
|
||||
#[inline(always)]
|
||||
pub fn l() {}
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
|
||||
#[no_mangle]
|
||||
pub fn sum(x: u32, y: u32) -> u32 {
|
||||
// YES-LABEL: define i32 @sum(i32 %0, i32 %1)
|
||||
// YES-LABEL: define{{.*}}i32 @sum(i32 %0, i32 %1)
|
||||
// YES-NEXT: %3 = add i32 %1, %0
|
||||
// YES-NEXT: ret i32 %3
|
||||
|
||||
// NO-LABEL: define i32 @sum(i32 %x, i32 %y)
|
||||
// NO-LABEL: define{{.*}}i32 @sum(i32 %x, i32 %y)
|
||||
// NO-NEXT: start:
|
||||
// NO-NEXT: %z = add i32 %y, %x
|
||||
// NO-NEXT: ret i32 %z
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
pub fn bar() { unsafe { foo() } }
|
||||
|
||||
extern "C" {
|
||||
// CHECK-LABEL: declare void @foo()
|
||||
// CHECK-LABEL: declare{{.*}}void @foo()
|
||||
// CHECK-SAME: [[ATTRS:#[0-9]+]]
|
||||
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readnone{{.*}} }
|
||||
#[ffi_const] pub fn foo();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
pub fn bar() { unsafe { foo() } }
|
||||
|
||||
extern "C" {
|
||||
// CHECK-LABEL: declare void @foo()
|
||||
// CHECK-LABEL: declare{{.*}}void @foo()
|
||||
// CHECK-SAME: [[ATTRS:#[0-9]+]]
|
||||
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readonly{{.*}} }
|
||||
#[ffi_pure] pub fn foo();
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
pub fn bar() { unsafe { foo() } }
|
||||
|
||||
extern "C" {
|
||||
// CHECK-LABEL: declare void @foo()
|
||||
// CHECK-SAME: [[ATTRS:#[0-9]+]]
|
||||
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}returns_twice{{.*}} }
|
||||
// CHECK: declare{{( dso_local)?}} void @foo(){{.*}}[[ATTRS:#[0-9]+]]
|
||||
// CHECK: attributes [[ATTRS]] = { {{.*}}returns_twice{{.*}} }
|
||||
#[ffi_returns_twice] pub fn foo();
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#[no_mangle]
|
||||
pub fn a(a: &mut u32, b: u32) {
|
||||
// CHECK-LABEL: define void @a
|
||||
// CHECK-LABEL: define{{.*}}void @a
|
||||
// CHECK: store i32 %b, i32* %a, align 4, !nontemporal
|
||||
unsafe {
|
||||
std::intrinsics::nontemporal_store(a, b);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#[no_mangle]
|
||||
pub struct F32(f32);
|
||||
|
||||
// CHECK: define float @add_newtype_f32(float %a, float %b)
|
||||
// CHECK: define{{.*}}float @add_newtype_f32(float %a, float %b)
|
||||
#[inline(never)]
|
||||
#[no_mangle]
|
||||
pub fn add_newtype_f32(a: F32, b: F32) -> F32 {
|
||||
|
@ -15,7 +15,7 @@ pub fn add_newtype_f32(a: F32, b: F32) -> F32 {
|
|||
#[no_mangle]
|
||||
pub struct F64(f64);
|
||||
|
||||
// CHECK: define double @add_newtype_f64(double %a, double %b)
|
||||
// CHECK: define{{.*}}double @add_newtype_f64(double %a, double %b)
|
||||
#[inline(never)]
|
||||
#[no_mangle]
|
||||
pub fn add_newtype_f64(a: F64, b: F64) -> F64 {
|
||||
|
|
|
@ -10,7 +10,7 @@ fn main() {
|
|||
fn foo() {
|
||||
let _a = Box::new(3);
|
||||
bar();
|
||||
// CHECK-LABEL: define void @foo
|
||||
// CHECK-LABEL: define dso_local void @foo
|
||||
// CHECK: call void @bar
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#![feature(naked_functions)]
|
||||
|
||||
// CHECK: Function Attrs: naked
|
||||
// CHECK-NEXT: define void @naked_empty()
|
||||
// CHECK-NEXT: define{{.*}}void @naked_empty()
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
pub fn naked_empty() {
|
||||
|
@ -15,14 +15,14 @@ pub fn naked_empty() {
|
|||
// CHECK: Function Attrs: naked
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %a)?}})
|
||||
// CHECK-NEXT: define{{.*}}void @naked_with_args(i{{[0-9]+( %a)?}})
|
||||
pub fn naked_with_args(a: isize) {
|
||||
// CHECK-NEXT: {{.+}}:
|
||||
// CHECK: ret void
|
||||
}
|
||||
|
||||
// CHECK: Function Attrs: naked
|
||||
// CHECK-NEXT: define i{{[0-9]+}} @naked_with_return()
|
||||
// CHECK-NEXT: define{{.*}}i{{[0-9]+}} @naked_with_return()
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
pub fn naked_with_return() -> isize {
|
||||
|
@ -32,7 +32,7 @@ pub fn naked_with_return() -> isize {
|
|||
}
|
||||
|
||||
// CHECK: Function Attrs: naked
|
||||
// CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+( %a)?}})
|
||||
// CHECK-NEXT: define{{.*}}i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+( %a)?}})
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
pub fn naked_with_args_and_return(a: isize) -> isize {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#![feature(optimize_attribute)]
|
||||
#![crate_type="rlib"]
|
||||
|
||||
// CHECK-LABEL: define i32 @nothing
|
||||
// CHECK-LABEL: define{{.*}}i32 @nothing
|
||||
// CHECK-SAME: [[NOTHING_ATTRS:#[0-9]+]]
|
||||
// NO-OPT: ret i32 4
|
||||
// SIZE-OPT: ret i32 4
|
||||
|
@ -16,7 +16,7 @@ pub fn nothing() -> i32 {
|
|||
2 + 2
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define i32 @size
|
||||
// CHECK-LABEL: define{{.*}}i32 @size
|
||||
// CHECK-SAME: [[SIZE_ATTRS:#[0-9]+]]
|
||||
// NO-OPT: ret i32 6
|
||||
// SIZE-OPT: ret i32 6
|
||||
|
@ -27,7 +27,7 @@ pub fn size() -> i32 {
|
|||
3 + 3
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define i32 @speed
|
||||
// CHECK-LABEL: define{{.*}}i32 @speed
|
||||
// NO-OPT-SAME: [[NOTHING_ATTRS]]
|
||||
// SPEED-OPT-SAME: [[NOTHING_ATTRS]]
|
||||
// SIZE-OPT-SAME: [[SPEED_ATTRS:#[0-9]+]]
|
||||
|
|
|
@ -34,19 +34,19 @@ pub enum TeBigS {
|
|||
Variant(BigS),
|
||||
}
|
||||
|
||||
// CHECK: define void @test_BigS(%BigS* [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], %BigS* [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]])
|
||||
// CHECK: define{{.*}}void @test_BigS(%BigS* [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], %BigS* [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]])
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} }
|
||||
|
||||
// CHECK: define void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], %TsBigS* [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]])
|
||||
// CHECK: define{{.*}}void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], %TsBigS* [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]])
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
|
||||
|
||||
// CHECK: define void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], %TuBigS* [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]])
|
||||
// CHECK: define{{.*}}void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], %TuBigS* [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]])
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
|
||||
|
||||
// CHECK: define void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], %"TeBigS::Variant"* [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]])
|
||||
// CHECK: define{{.*}}void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], %"TeBigS::Variant"* [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]])
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
|
||||
|
||||
|
@ -70,18 +70,18 @@ pub enum TeBigU {
|
|||
Variant(BigU),
|
||||
}
|
||||
|
||||
// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], %BigU* [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]])
|
||||
// CHECK: define{{.*}}void @test_BigU(%BigU* [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], %BigU* [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]])
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} }
|
||||
|
||||
// CHECK: define void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS1:.*]] sret(%TsBigU) [[BIGU_RET_ATTRS2:.*]], %TsBigU* [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]])
|
||||
// CHECK: define{{.*}}void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS1:.*]] sret(%TsBigU) [[BIGU_RET_ATTRS2:.*]], %TsBigU* [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]])
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
|
||||
|
||||
// CHECK: define void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2:.*]], %TuBigU* [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]])
|
||||
// CHECK: define{{.*}}void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2:.*]], %TuBigU* [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]])
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
|
||||
|
||||
// CHECK: define void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2:.*]], %"TeBigU::Variant"* [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]])
|
||||
// CHECK: define{{.*}}void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2:.*]], %"TeBigU::Variant"* [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]])
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
|
||||
|
|
|
@ -17,21 +17,21 @@ pub struct Zst2(());
|
|||
#[repr(transparent)]
|
||||
pub struct F32(f32);
|
||||
|
||||
// CHECK: define float @test_F32(float %_1)
|
||||
// CHECK: define{{.*}}float @test_F32(float %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_F32(_: F32) -> F32 { loop {} }
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Ptr(*mut u8);
|
||||
|
||||
// CHECK: define i8* @test_Ptr(i8* %_1)
|
||||
// CHECK: define{{.*}}i8* @test_Ptr(i8* %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_Ptr(_: Ptr) -> Ptr { loop {} }
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct WithZst(u64, Zst1);
|
||||
|
||||
// CHECK: define i64 @test_WithZst(i64 %_1)
|
||||
// CHECK: define{{.*}}i64 @test_WithZst(i64 %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} }
|
||||
|
||||
|
@ -39,14 +39,14 @@ pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} }
|
|||
pub struct WithZeroSizedArray(*const f32, [i8; 0]);
|
||||
|
||||
// Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever.
|
||||
// CHECK: define i32* @test_WithZeroSizedArray(i32* %_1)
|
||||
// CHECK: define{{.*}}i32* @test_WithZeroSizedArray(i32* %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} }
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Generic<T>(T);
|
||||
|
||||
// CHECK: define double @test_Generic(double %_1)
|
||||
// CHECK: define{{.*}}double @test_Generic(double %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} }
|
||||
|
||||
|
@ -56,14 +56,14 @@ pub struct GenericPlusZst<T>(T, Zst2);
|
|||
#[repr(u8)]
|
||||
pub enum Bool { True, False, FileNotFound }
|
||||
|
||||
// CHECK: define{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %_1)
|
||||
// CHECK: define{{( dso_local)?}}{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} }
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>);
|
||||
|
||||
// CHECK: define i16* @test_LifetimePhantom(i16* %_1)
|
||||
// CHECK: define{{.*}}i16* @test_LifetimePhantom(i16* %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} }
|
||||
|
||||
|
@ -73,28 +73,28 @@ pub struct UnitPhantom<T, U> { val: T, unit: PhantomData<U> }
|
|||
|
||||
pub struct Px;
|
||||
|
||||
// CHECK: define float @test_UnitPhantom(float %_1)
|
||||
// CHECK: define{{.*}}float @test_UnitPhantom(float %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { loop {} }
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct TwoZsts(Zst1, i8, Zst2);
|
||||
|
||||
// CHECK: define{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %_1)
|
||||
// CHECK: define{{( dso_local)?}}{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} }
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Nested1(Zst2, Generic<f64>);
|
||||
|
||||
// CHECK: define double @test_Nested1(double %_1)
|
||||
// CHECK: define{{.*}}double @test_Nested1(double %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_Nested1(_: Nested1) -> Nested1 { loop {} }
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Nested2(Nested1, Zst1);
|
||||
|
||||
// CHECK: define double @test_Nested2(double %_1)
|
||||
// CHECK: define{{.*}}double @test_Nested2(double %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_Nested2(_: Nested2) -> Nested2 { loop {} }
|
||||
|
||||
|
@ -104,7 +104,7 @@ struct f32x4(f32, f32, f32, f32);
|
|||
#[repr(transparent)]
|
||||
pub struct Vector(f32x4);
|
||||
|
||||
// CHECK: define <4 x float> @test_Vector(<4 x float> %_1)
|
||||
// CHECK: define{{.*}}<4 x float> @test_Vector(<4 x float> %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_Vector(_: Vector) -> Vector { loop {} }
|
||||
|
||||
|
@ -114,7 +114,7 @@ impl<T: ?Sized> Mirror for T { type It = Self; }
|
|||
#[repr(transparent)]
|
||||
pub struct StructWithProjection(<f32 as Mirror>::It);
|
||||
|
||||
// CHECK: define float @test_Projection(float %_1)
|
||||
// CHECK: define{{.*}}float @test_Projection(float %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }
|
||||
|
||||
|
@ -123,7 +123,7 @@ pub enum EnumF32 {
|
|||
Variant(F32)
|
||||
}
|
||||
|
||||
// CHECK: define float @test_EnumF32(float %_1)
|
||||
// CHECK: define{{.*}}float @test_EnumF32(float %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} }
|
||||
|
||||
|
@ -132,7 +132,7 @@ pub enum EnumF32WithZsts {
|
|||
Variant(Zst1, F32, Zst2)
|
||||
}
|
||||
|
||||
// CHECK: define float @test_EnumF32WithZsts(float %_1)
|
||||
// CHECK: define{{.*}}float @test_EnumF32WithZsts(float %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} }
|
||||
|
||||
|
@ -141,7 +141,7 @@ pub union UnionF32 {
|
|||
field: F32,
|
||||
}
|
||||
|
||||
// CHECK: define float @test_UnionF32(float %_1)
|
||||
// CHECK: define{{.*}}float @test_UnionF32(float %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
|
||||
|
||||
|
@ -152,7 +152,7 @@ pub union UnionF32WithZsts {
|
|||
zst2: Zst2,
|
||||
}
|
||||
|
||||
// CHECK: define float @test_UnionF32WithZsts(float %_1)
|
||||
// CHECK: define{{.*}}float @test_UnionF32WithZsts(float %_1)
|
||||
#[no_mangle]
|
||||
pub extern "C" fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} }
|
||||
|
||||
|
|
|
@ -16,27 +16,27 @@
|
|||
// MSAN-RECOVER: @__msan_keep_going = weak_odr {{.*}}constant i32 1
|
||||
// MSAN-RECOVER-LTO: @__msan_keep_going = weak_odr {{.*}}constant i32 1
|
||||
|
||||
// ASAN-LABEL: define i32 @penguin(
|
||||
// ASAN-LABEL: define dso_local i32 @penguin(
|
||||
// ASAN: call void @__asan_report_load4(i64 %0)
|
||||
// ASAN: unreachable
|
||||
// ASAN: }
|
||||
//
|
||||
// ASAN-RECOVER-LABEL: define i32 @penguin(
|
||||
// ASAN-RECOVER-LABEL: define dso_local i32 @penguin(
|
||||
// ASAN-RECOVER: call void @__asan_report_load4_noabort(
|
||||
// ASAN-RECOVER-NOT: unreachable
|
||||
// ASAN: }
|
||||
//
|
||||
// MSAN-LABEL: define i32 @penguin(
|
||||
// MSAN-LABEL: define dso_local i32 @penguin(
|
||||
// MSAN: call void @__msan_warning{{(_with_origin_noreturn\(i32 0\)|_noreturn\(\))}}
|
||||
// MSAN: unreachable
|
||||
// MSAN: }
|
||||
//
|
||||
// MSAN-RECOVER-LABEL: define i32 @penguin(
|
||||
// MSAN-RECOVER-LABEL: define dso_local i32 @penguin(
|
||||
// MSAN-RECOVER: call void @__msan_warning{{(_with_origin\(i32 0\)|\(\))}}
|
||||
// MSAN-RECOVER-NOT: unreachable
|
||||
// MSAN-RECOVER: }
|
||||
//
|
||||
// MSAN-RECOVER-LTO-LABEL: define i32 @penguin(
|
||||
// MSAN-RECOVER-LTO-LABEL: define dso_local i32 @penguin(
|
||||
// MSAN-RECOVER-LTO: call void @__msan_warning{{(_with_origin\(i32 0\)|\(\))}}
|
||||
// MSAN-RECOVER-LTO-NOT: unreachable
|
||||
// MSAN-RECOVER-LTO: }
|
||||
|
|
|
@ -2,25 +2,25 @@
|
|||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// CHECK: define { i8, i8 } @pair_bool_bool(i1 zeroext %pair.0, i1 zeroext %pair.1)
|
||||
// CHECK: define{{.*}}{ i8, i8 } @pair_bool_bool(i1 zeroext %pair.0, i1 zeroext %pair.1)
|
||||
#[no_mangle]
|
||||
pub fn pair_bool_bool(pair: (bool, bool)) -> (bool, bool) {
|
||||
pair
|
||||
}
|
||||
|
||||
// CHECK: define { i8, i32 } @pair_bool_i32(i1 zeroext %pair.0, i32 %pair.1)
|
||||
// CHECK: define{{.*}}{ i8, i32 } @pair_bool_i32(i1 zeroext %pair.0, i32 %pair.1)
|
||||
#[no_mangle]
|
||||
pub fn pair_bool_i32(pair: (bool, i32)) -> (bool, i32) {
|
||||
pair
|
||||
}
|
||||
|
||||
// CHECK: define { i32, i8 } @pair_i32_bool(i32 %pair.0, i1 zeroext %pair.1)
|
||||
// CHECK: define{{.*}}{ i32, i8 } @pair_i32_bool(i32 %pair.0, i1 zeroext %pair.1)
|
||||
#[no_mangle]
|
||||
pub fn pair_i32_bool(pair: (i32, bool)) -> (i32, bool) {
|
||||
pair
|
||||
}
|
||||
|
||||
// CHECK: define { i8, i8 } @pair_and_or(i1 zeroext %_1.0, i1 zeroext %_1.1)
|
||||
// CHECK: define{{.*}}{ i8, i8 } @pair_and_or(i1 zeroext %_1.0, i1 zeroext %_1.1)
|
||||
#[no_mangle]
|
||||
pub fn pair_and_or((a, b): (bool, bool)) -> (bool, bool) {
|
||||
// Make sure it can operate directly on the unpacked args
|
||||
|
@ -30,7 +30,7 @@ pub fn pair_and_or((a, b): (bool, bool)) -> (bool, bool) {
|
|||
(a && b, a || b)
|
||||
}
|
||||
|
||||
// CHECK: define void @pair_branches(i1 zeroext %_1.0, i1 zeroext %_1.1)
|
||||
// CHECK: define{{.*}}void @pair_branches(i1 zeroext %_1.0, i1 zeroext %_1.1)
|
||||
#[no_mangle]
|
||||
pub fn pair_branches((a, b): (bool, bool)) {
|
||||
// Make sure it can branch directly on the unpacked bool args
|
||||
|
|
|
@ -2,42 +2,42 @@
|
|||
|
||||
#![crate_type = "staticlib"]
|
||||
|
||||
// CHECK: define void @a()
|
||||
// CHECK: define{{.*}}void @a()
|
||||
#[no_mangle]
|
||||
#[inline]
|
||||
pub extern "C" fn a() {}
|
||||
|
||||
// CHECK: define void @b()
|
||||
// CHECK: define{{.*}}void @b()
|
||||
#[export_name = "b"]
|
||||
#[inline]
|
||||
pub extern "C" fn b() {}
|
||||
|
||||
// CHECK: define void @c()
|
||||
// CHECK: define{{.*}}void @c()
|
||||
#[no_mangle]
|
||||
#[inline]
|
||||
extern "C" fn c() {}
|
||||
|
||||
// CHECK: define void @d()
|
||||
// CHECK: define{{.*}}void @d()
|
||||
#[export_name = "d"]
|
||||
#[inline]
|
||||
extern "C" fn d() {}
|
||||
|
||||
// CHECK: define void @e()
|
||||
// CHECK: define{{.*}}void @e()
|
||||
#[no_mangle]
|
||||
#[inline(always)]
|
||||
pub extern "C" fn e() {}
|
||||
|
||||
// CHECK: define void @f()
|
||||
// CHECK: define{{.*}}void @f()
|
||||
#[export_name = "f"]
|
||||
#[inline(always)]
|
||||
pub extern "C" fn f() {}
|
||||
|
||||
// CHECK: define void @g()
|
||||
// CHECK: define{{.*}}void @g()
|
||||
#[no_mangle]
|
||||
#[inline(always)]
|
||||
extern "C" fn g() {}
|
||||
|
||||
// CHECK: define void @h()
|
||||
// CHECK: define{{.*}}void @h()
|
||||
#[export_name = "h"]
|
||||
#[inline(always)]
|
||||
extern "C" fn h() {}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// FIXME(eddyb) all of these tests show memory stores and loads, even after a
|
||||
// scalar `bitcast`, more special-casing is required to remove `alloca` usage.
|
||||
|
||||
// CHECK: define i32 @f32_to_bits(float %x)
|
||||
// CHECK-LABEL: define{{.*}}i32 @f32_to_bits(float %x)
|
||||
// CHECK: %2 = bitcast float %x to i32
|
||||
// CHECK-NEXT: store i32 %2, i32* %0
|
||||
// CHECK-NEXT: %3 = load i32, i32* %0
|
||||
|
@ -15,7 +15,7 @@ pub fn f32_to_bits(x: f32) -> u32 {
|
|||
unsafe { std::mem::transmute(x) }
|
||||
}
|
||||
|
||||
// CHECK: define i8 @bool_to_byte(i1 zeroext %b)
|
||||
// CHECK-LABEL: define{{.*}}i8 @bool_to_byte(i1 zeroext %b)
|
||||
// CHECK: %1 = zext i1 %b to i8
|
||||
// CHECK-NEXT: store i8 %1, i8* %0
|
||||
// CHECK-NEXT: %2 = load i8, i8* %0
|
||||
|
@ -25,7 +25,7 @@ pub fn bool_to_byte(b: bool) -> u8 {
|
|||
unsafe { std::mem::transmute(b) }
|
||||
}
|
||||
|
||||
// CHECK: define zeroext i1 @byte_to_bool(i8 %byte)
|
||||
// CHECK-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8 %byte)
|
||||
// CHECK: %1 = trunc i8 %byte to i1
|
||||
// CHECK-NEXT: %2 = zext i1 %1 to i8
|
||||
// CHECK-NEXT: store i8 %2, i8* %0
|
||||
|
@ -37,7 +37,7 @@ pub unsafe fn byte_to_bool(byte: u8) -> bool {
|
|||
std::mem::transmute(byte)
|
||||
}
|
||||
|
||||
// CHECK: define i8* @ptr_to_ptr(i16* %p)
|
||||
// CHECK-LABEL: define{{.*}}i8* @ptr_to_ptr(i16* %p)
|
||||
// CHECK: %2 = bitcast i16* %p to i8*
|
||||
// CHECK-NEXT: store i8* %2, i8** %0
|
||||
// CHECK-NEXT: %3 = load i8*, i8** %0
|
||||
|
@ -54,7 +54,7 @@ pub fn ptr_to_ptr(p: *mut u16) -> *mut u8 {
|
|||
// Tests below show the non-special-cased behavior (with the possible
|
||||
// future special-cased instructions in the "NOTE(eddyb)" comments).
|
||||
|
||||
// CHECK: define [[USIZE:i[0-9]+]] @ptr_to_int(i16* %p)
|
||||
// CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int(i16* %p)
|
||||
|
||||
// NOTE(eddyb) see above, the following two CHECK lines should ideally be this:
|
||||
// %2 = ptrtoint i16* %p to [[USIZE]]
|
||||
|
@ -69,7 +69,7 @@ pub fn ptr_to_int(p: *mut u16) -> usize {
|
|||
unsafe { std::mem::transmute(p) }
|
||||
}
|
||||
|
||||
// CHECK: define i16* @int_to_ptr([[USIZE]] %i)
|
||||
// CHECK: define{{.*}}i16* @int_to_ptr([[USIZE]] %i)
|
||||
|
||||
// NOTE(eddyb) see above, the following two CHECK lines should ideally be this:
|
||||
// %2 = inttoptr [[USIZE]] %i to i16*
|
||||
|
|
|
@ -6,28 +6,28 @@
|
|||
|
||||
extern "C" {
|
||||
// CHECK: Function Attrs:{{.*}}nounwind
|
||||
// CHECK-NEXT: declare void @extern_fn
|
||||
// CHECK-NEXT: declare{{.*}}void @extern_fn
|
||||
fn extern_fn();
|
||||
// CHECK-NOT: Function Attrs:{{.*}}nounwind
|
||||
// CHECK: declare void @unwinding_extern_fn
|
||||
// CHECK: declare{{.*}}void @unwinding_extern_fn
|
||||
#[unwind(allowed)]
|
||||
fn unwinding_extern_fn();
|
||||
// CHECK-NOT: nounwind
|
||||
// CHECK: declare void @aborting_extern_fn
|
||||
// CHECK: declare{{.*}}void @aborting_extern_fn
|
||||
#[unwind(aborts)]
|
||||
fn aborting_extern_fn(); // FIXME: we want to have the attribute here
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
// CHECK-NOT: nounwind
|
||||
// CHECK: declare void @rust_extern_fn
|
||||
// CHECK: declare{{.*}}void @rust_extern_fn
|
||||
fn rust_extern_fn();
|
||||
// CHECK-NOT: nounwind
|
||||
// CHECK: declare void @rust_unwinding_extern_fn
|
||||
// CHECK: declare{{.*}}void @rust_unwinding_extern_fn
|
||||
#[unwind(allowed)]
|
||||
fn rust_unwinding_extern_fn();
|
||||
// CHECK-NOT: nounwind
|
||||
// CHECK: declare void @rust_aborting_extern_fn
|
||||
// CHECK: declare{{.*}}void @rust_aborting_extern_fn
|
||||
#[unwind(aborts)]
|
||||
fn rust_aborting_extern_fn(); // FIXME: we want to have the attribute here
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// CHECK-LABEL: define i32 @test(i32 %a, i32 %b)
|
||||
// CHECK-LABEL: define{{.*}}i32 @test(i32 %a, i32 %b)
|
||||
#[no_mangle]
|
||||
pub fn test(a: u32, b: u32) -> u32 {
|
||||
let c = a + b;
|
||||
|
|
Loading…
Add table
Reference in a new issue