Skip to content

Commit

Permalink
CFI: Support function pointers for trait methods
Browse files Browse the repository at this point in the history
Adds support for both CFI and KCFI for attaching concrete and abstract
types to functions. KCFI does this through generation of `ReifyShim` on
any function pointer that could go in a vtable, and checking the
`ReifyReason` when emitting the instance. CFI does this by attaching
both the concrete and abstract type to every instance.

TypeID codegen tests are switched to be anchored on the left rather than
the right in order to allow emission of additional type attachments.

Fixes #115953
  • Loading branch information
maurer committed Mar 26, 2024
1 parent 2292393 commit 181d861
Show file tree
Hide file tree
Showing 20 changed files with 272 additions and 216 deletions.
27 changes: 13 additions & 14 deletions compiler/rustc_codegen_llvm/src/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::llvm;
use crate::llvm::AttributePlace::Function;
use crate::type_::Type;
use crate::value::Value;
use itertools::Itertools;
use rustc_codegen_ssa::traits::TypeMembershipMethods;
use rustc_middle::ty::{Instance, Ty};
use rustc_symbol_mangling::typeid::{
Expand Down Expand Up @@ -141,20 +142,18 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {

if self.tcx.sess.is_sanitizer_cfi_enabled() {
if let Some(instance) = instance {
let typeid = typeid_for_instance(self.tcx, &instance, TypeIdOptions::empty());
self.set_type_metadata(llfn, typeid);
let typeid =
typeid_for_instance(self.tcx, &instance, TypeIdOptions::GENERALIZE_POINTERS);
self.add_type_metadata(llfn, typeid);
let typeid =
typeid_for_instance(self.tcx, &instance, TypeIdOptions::NORMALIZE_INTEGERS);
self.add_type_metadata(llfn, typeid);
let typeid = typeid_for_instance(
self.tcx,
&instance,
TypeIdOptions::GENERALIZE_POINTERS | TypeIdOptions::NORMALIZE_INTEGERS,
);
self.add_type_metadata(llfn, typeid);
for options in [
TypeIdOptions::GENERALIZE_POINTERS,
TypeIdOptions::NORMALIZE_INTEGERS,
TypeIdOptions::CONCRETE,
]
.into_iter()
.powerset()
.map(TypeIdOptions::from_iter)
{
let typeid = typeid_for_instance(self.tcx, &instance, options);
self.add_type_metadata(llfn, typeid);
}
} else {
let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::empty());
self.set_type_metadata(llfn, typeid);
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,14 @@ impl<'tcx> Instance<'tcx> {
debug!(" => fn pointer created for virtual call");
resolved.def = InstanceDef::ReifyShim(def_id, reason);
}
// FIXME(maurer) only shim it if it is a vtable-safe function
_ if tcx.sess.is_sanitizer_kcfi_enabled()
&& tcx.associated_item(def_id).trait_item_def_id.is_some() =>
{
// If this function could also go in a vtable, we need to `ReifyShim` it with
// KCFI because it can only attach one type per function.
resolved.def = InstanceDef::ReifyShim(resolved.def_id(), reason)
}
_ => {}
}

Expand Down
11 changes: 9 additions & 2 deletions compiler/rustc_symbol_mangling/src/typeid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/// For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler,
/// see design document in the tracking issue #89653.
use bitflags::bitflags;
use rustc_middle::ty::{Instance, Ty, TyCtxt};
use rustc_middle::ty::{Instance, InstanceDef, ReifyReason, Ty, TyCtxt};
use rustc_target::abi::call::FnAbi;
use std::hash::Hasher;
use twox_hash::XxHash64;
Expand All @@ -16,6 +16,8 @@ bitflags! {
const GENERALIZE_POINTERS = 1;
const GENERALIZE_REPR_C = 2;
const NORMALIZE_INTEGERS = 4;
// Only relevant for `typeid_for_instance`
const CONCRETE = 8;
}
}

Expand Down Expand Up @@ -56,8 +58,13 @@ pub fn kcfi_typeid_for_fnabi<'tcx>(
pub fn kcfi_typeid_for_instance<'tcx>(
tcx: TyCtxt<'tcx>,
instance: &Instance<'tcx>,
options: TypeIdOptions,
mut options: TypeIdOptions,
) -> u32 {
// If we receive a `ReifyShim` intended to produce a function pointer, we need to remain
// concrete - abstraction is for vtables.
if matches!(instance.def, InstanceDef::ReifyShim(_, Some(ReifyReason::FnPtr))) {
options |= TypeIdOptions::CONCRETE
}
// A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the
// xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
let mut hash: XxHash64 = Default::default();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,8 @@ pub fn typeid_for_instance<'tcx>(
instance.args = strip_receiver_auto(tcx, instance.args)
}

if let Some(impl_id) = tcx.impl_of_method(instance.def_id())
if !options.contains(TypeIdOptions::CONCRETE)
&& let Some(impl_id) = tcx.impl_of_method(instance.def_id())
&& let Some(trait_ref) = tcx.impl_trait_ref(impl_id)
{
let impl_method = tcx.associated_item(instance.def_id());
Expand Down
30 changes: 15 additions & 15 deletions tests/codegen/sanitizer/cfi/emit-type-metadata-attr-cfi-encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,35 +26,35 @@ pub struct Type4(i32);
pub struct Type5(u32);

pub fn foo0(_: Type1) { }
// CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo0{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE0:[0-9]+]]
pub fn foo1(_: Type1, _: Type1) { }
// CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo1{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE1:[0-9]+]]
pub fn foo2(_: Type1, _: Type1, _: Type1) { }
// CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo2{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE2:[0-9]+]]
pub fn foo3(_: *mut Type2) { }
// CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo3{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE3:[0-9]+]]
pub fn foo4(_: *mut Type2, _: *mut Type2) { }
// CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo4{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE4:[0-9]+]]
pub fn foo5(_: *mut Type2, _: *mut Type2, _: *mut Type2) { }
// CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo5{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE5:[0-9]+]]
pub fn foo6(_: *mut Type3) { }
// CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo6{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE6:[0-9]+]]
pub fn foo7(_: *mut Type3, _: *mut Type3) { }
// CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo7{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE7:[0-9]+]]
pub fn foo8(_: *mut Type3, _: *mut Type3, _: *mut Type3) { }
// CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo8{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE8:[0-9]+]]
pub fn foo9(_: Type4) { }
// CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo9{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE9:[0-9]+]]
pub fn foo10(_: Type4, _: Type4) { }
// CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo10{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE10:[0-9]+]]
pub fn foo11(_: Type4, _: Type4, _: Type4) { }
// CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo11{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE11:[0-9]+]]
pub fn foo12(_: Type5) { }
// CHECK: define{{.*}}foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo12{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE12:[0-9]+]]
pub fn foo13(_: Type5, _: Type5) { }
// CHECK: define{{.*}}foo13{{.*}}!type ![[TYPE13:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo13{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE13:[0-9]+]]
pub fn foo14(_: Type5, _: Type5, _: Type5) { }
// CHECK: define{{.*}}foo14{{.*}}!type ![[TYPE14:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}foo14{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE14:[0-9]+]]

// CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFv3FooE"}
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFv3FooS_E"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ pub fn foo() where
}

pub fn foo1(_: Type1) { }
// CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo1{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE1:[0-9]+]]
pub fn foo2(_: Type1, _: Type1) { }
// CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo2{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE2:[0-9]+]]
pub fn foo3(_: Type1, _: Type1, _: Type1) { }
// CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo3{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE3:[0-9]+]]

// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooIu3i32Lu5usize32EEE"}
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooIu3i32Lu5usize32EES2_E"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,29 @@
#![crate_type="lib"]

pub fn foo1(_: fn(i32) -> i32) { }
// CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo1{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE1:[0-9]+]]
pub fn foo2(_: fn(i32) -> i32, _: fn(i32) -> i32) { }
// CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo2{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE2:[0-9]+]]
pub fn foo3(_: fn(i32) -> i32, _: fn(i32) -> i32, _: fn(i32) -> i32) { }
// CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo3{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE3:[0-9]+]]
pub fn foo4(_: &dyn Fn(i32) -> i32) { }
// CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo4{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE4:[0-9]+]]
pub fn foo5(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { }
// CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo5{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE5:[0-9]+]]
pub fn foo6(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { }
// CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo6{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE6:[0-9]+]]
pub fn foo7(_: &dyn FnMut(i32) -> i32) { }
// CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo7{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE7:[0-9]+]]
pub fn foo8(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { }
// CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo8{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE8:[0-9]+]]
pub fn foo9(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { }
// CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo9{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE9:[0-9]+]]
pub fn foo10(_: &dyn FnOnce(i32) -> i32) { }
// CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}5foo10{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE10:[0-9]+]]
pub fn foo11(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) { }
// CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}5foo11{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE11:[0-9]+]]
pub fn foo12(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) {}
// CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}5foo12{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE12:[0-9]+]]

// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvPFu3i32S_EE"}
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_E"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ pub fn foo<'a>() where
}

pub fn foo1(_: Type1) { }
// CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo1{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE1:[0-9]+]]
pub fn foo2(_: Type1, _: Type1) { }
// CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo2{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE2:[0-9]+]]
pub fn foo3(_: Type1, _: Type1, _: Type1) { }
// CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo3{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE3:[0-9]+]]
Original file line number Diff line number Diff line change
Expand Up @@ -50,29 +50,29 @@ pub fn foo() where
// Force arguments to be passed by using a reference. Otherwise, they may end up PassMode::Ignore

pub fn foo1(_: &Type1) { }
// CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo1{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE1:[0-9]+]]
pub fn foo2(_: &Type1, _: &Type1) { }
// CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo2{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE2:[0-9]+]]
pub fn foo3(_: &Type1, _: &Type1, _: &Type1) { }
// CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo3{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE3:[0-9]+]]
pub fn foo4(_: &Type2) { }
// CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo4{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE4:[0-9]+]]
pub fn foo5(_: &Type2, _: &Type2) { }
// CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo5{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE5:[0-9]+]]
pub fn foo6(_: &Type2, _: &Type2, _: &Type2) { }
// CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo6{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE6:[0-9]+]]
pub fn foo7(_: &Type3) { }
// CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo7{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE7:[0-9]+]]
pub fn foo8(_: &Type3, _: &Type3) { }
// CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo8{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE8:[0-9]+]]
pub fn foo9(_: &Type3, _: &Type3, _: &Type3) { }
// CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo9{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE9:[0-9]+]]
pub fn foo10(_: &Type4) { }
// CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}5foo10{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE10:[0-9]+]]
pub fn foo11(_: &Type4, _: &Type4) { }
// CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}5foo11{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE11:[0-9]+]]
pub fn foo12(_: &Type4, _: &Type4, _: &Type4) { }
// CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}5foo12{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE12:[0-9]+]]

// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barEE"}
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_E"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,35 @@
#![crate_type="lib"]

pub fn foo1(_: &mut i32) { }
// CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo1{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE1:[0-9]+]]
pub fn foo2(_: &mut i32, _: &i32) { }
// CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo2{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE2:[0-9]+]]
pub fn foo3(_: &mut i32, _: &i32, _: &i32) { }
// CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo3{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE3:[0-9]+]]
pub fn foo4(_: &i32) { }
// CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo4{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE4:[0-9]+]]
pub fn foo5(_: &i32, _: &mut i32) { }
// CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo5{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE5:[0-9]+]]
pub fn foo6(_: &i32, _: &mut i32, _: &mut i32) { }
// CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo6{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE6:[0-9]+]]
pub fn foo7(_: *mut i32) { }
// CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo7{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE7:[0-9]+]]
pub fn foo8(_: *mut i32, _: *const i32) { }
// CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo8{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE8:[0-9]+]]
pub fn foo9(_: *mut i32, _: *const i32, _: *const i32) { }
// CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}4foo9{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE9:[0-9]+]]
pub fn foo10(_: *const i32) { }
// CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}5foo10{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE10:[0-9]+]]
pub fn foo11(_: *const i32, _: *mut i32) { }
// CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}5foo11{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE11:[0-9]+]]
pub fn foo12(_: *const i32, _: *mut i32, _: *mut i32) { }
// CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}5foo12{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE12:[0-9]+]]
pub fn foo13(_: fn(i32) -> i32) { }
// CHECK: define{{.*}}5foo13{{.*}}!type ![[TYPE13:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}5foo13{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE13:[0-9]+]]
pub fn foo14(_: fn(i32) -> i32, _: fn(i32) -> i32) { }
// CHECK: define{{.*}}5foo14{{.*}}!type ![[TYPE14:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}5foo14{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE14:[0-9]+]]
pub fn foo15(_: fn(i32) -> i32, _: fn(i32) -> i32, _: fn(i32) -> i32) { }
// CHECK: define{{.*}}5foo15{{.*}}!type ![[TYPE15:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: define{{.*}}5foo15{{.*}}unnamed_addr #{{[0-9]+}} !type ![[TYPE15:[0-9]+]]

// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvU3mutu3refIu3i32EE"}
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvU3mutu3refIu3i32ES0_E"}
Expand Down
Loading

0 comments on commit 181d861

Please sign in to comment.