Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a45ca02

Browse files
authoredMar 24, 2024
Rollup merge of #122879 - maurer:callsite-instances, r=workingjubilee
CFI: Strip auto traits off Virtual calls We already use `Instance` at declaration sites when available to glean additional information about possible abstractions of the type in use. This does the same when possible at callsites as well. The primary purpose of this change is to allow CFI to alter how it generates type information for indirect calls through `Virtual` instances. This is needed for the "separate machinery" version of my approach to the vtable issues (#122573), because we need to respond differently to a `Virtual` call to the same type as a non-virtual call, specifically [stripping auto traits off the receiver's `Self`](54b15b0) because there isn't a separate vtable for `Foo` vs `Foo + Send`. This would also make a more general underlying mechanism that could be used by rcvalle's [proposed drop detection / encoding](edcd1e2) if we end up using his approach, as we could condition out on the `def_id` in the CFI code rather than requiring the generating code to explicitly note whether it was calling drop.
2 parents 1190928 + f434c27 commit a45ca02

File tree

14 files changed

+155
-58
lines changed

14 files changed

+155
-58
lines changed
 

‎compiler/rustc_codegen_gcc/src/asm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
541541
let builtin_unreachable: RValue<'gcc> = unsafe {
542542
std::mem::transmute(builtin_unreachable)
543543
};
544-
self.call(self.type_void(), None, None, builtin_unreachable, &[], None);
544+
self.call(self.type_void(), None, None, builtin_unreachable, &[], None, None);
545545
}
546546

547547
// Write results to outputs.

‎compiler/rustc_codegen_gcc/src/builder.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_middle::ty::layout::{
2525
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers,
2626
TyAndLayout,
2727
};
28-
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
28+
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, Instance};
2929
use rustc_span::def_id::DefId;
3030
use rustc_span::Span;
3131
use rustc_target::abi::{
@@ -592,12 +592,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
592592
then: Block<'gcc>,
593593
catch: Block<'gcc>,
594594
_funclet: Option<&Funclet>,
595+
instance: Option<Instance<'tcx>>,
595596
) -> RValue<'gcc> {
596597
let try_block = self.current_func().new_block("try");
597598

598599
let current_block = self.block.clone();
599600
self.block = try_block;
600-
let call = self.call(typ, fn_attrs, None, func, args, None); // TODO(antoyo): use funclet here?
601+
let call = self.call(typ, fn_attrs, None, func, args, None, instance); // TODO(antoyo): use funclet here?
601602
self.block = current_block;
602603

603604
let return_value =
@@ -1667,6 +1668,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
16671668
func: RValue<'gcc>,
16681669
args: &[RValue<'gcc>],
16691670
funclet: Option<&Funclet>,
1671+
_instance: Option<Instance<'tcx>>,
16701672
) -> RValue<'gcc> {
16711673
// FIXME(antoyo): remove when having a proper API.
16721674
let gcc_func = unsafe { std::mem::transmute(func) };

‎compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
133133
func,
134134
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
135135
None,
136+
None,
136137
)
137138
}
138139
sym::likely => self.expect(args[0].immediate(), true),
@@ -401,7 +402,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
401402
fn abort(&mut self) {
402403
let func = self.context.get_builtin_function("abort");
403404
let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
404-
self.call(self.type_void(), None, None, func, &[], None);
405+
self.call(self.type_void(), None, None, func, &[], None, None);
405406
}
406407

407408
fn assume(&mut self, value: Self::Value) {
@@ -1103,7 +1104,7 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(
11031104
dest: RValue<'gcc>,
11041105
) {
11051106
if bx.sess().panic_strategy() == PanicStrategy::Abort {
1106-
bx.call(bx.type_void(), None, None, try_func, &[data], None);
1107+
bx.call(bx.type_void(), None, None, try_func, &[data], None, None);
11071108
// Return 0 unconditionally from the intrinsic call;
11081109
// we can never unwind.
11091110
let ret_align = bx.tcx.data_layout.i32_align.abi;
@@ -1177,21 +1178,21 @@ fn codegen_gnu_try<'gcc>(
11771178
let zero = bx.cx.context.new_rvalue_zero(bx.int_type);
11781179
let ptr = bx.cx.context.new_call(None, eh_pointer_builtin, &[zero]);
11791180
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
1180-
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None);
1181+
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None, None);
11811182
bx.ret(bx.const_i32(1));
11821183

11831184
// NOTE: the blocks must be filled before adding the try/catch, otherwise gcc will not
11841185
// generate a try/catch.
11851186
// FIXME(antoyo): add a check in the libgccjit API to prevent this.
11861187
bx.switch_to_block(current_block);
1187-
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
1188+
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None, None);
11881189
});
11891190

11901191
let func = unsafe { std::mem::transmute(func) };
11911192

11921193
// Note that no invoke is used here because by definition this function
11931194
// can't panic (that's what it's catching).
1194-
let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None);
1195+
let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None, None);
11951196
let i32_align = bx.tcx().data_layout.i32_align.abi;
11961197
bx.store(ret, dest, i32_align);
11971198
}

‎compiler/rustc_codegen_llvm/src/asm.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -466,11 +466,11 @@ pub(crate) fn inline_asm_call<'ll>(
466466

467467
let call = if !labels.is_empty() {
468468
assert!(catch_funclet.is_none());
469-
bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None)
469+
bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None, None)
470470
} else if let Some((catch, funclet)) = catch_funclet {
471-
bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet)
471+
bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet, None)
472472
} else {
473-
bx.call(fty, None, None, v, inputs, None)
473+
bx.call(fty, None, None, v, inputs, None, None)
474474
};
475475

476476
// Store mark in a metadata node so we can map LLVM errors

‎compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
1919
use rustc_middle::ty::layout::{
2020
FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
2121
};
22-
use rustc_middle::ty::{self, Ty, TyCtxt};
22+
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
2323
use rustc_span::Span;
24-
use rustc_symbol_mangling::typeid::{kcfi_typeid_for_fnabi, typeid_for_fnabi, TypeIdOptions};
24+
use rustc_symbol_mangling::typeid::{
25+
kcfi_typeid_for_fnabi, kcfi_typeid_for_instance, typeid_for_fnabi, typeid_for_instance,
26+
TypeIdOptions,
27+
};
2528
use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
2629
use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target};
2730
use smallvec::SmallVec;
@@ -221,6 +224,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
221224
then: &'ll BasicBlock,
222225
catch: &'ll BasicBlock,
223226
funclet: Option<&Funclet<'ll>>,
227+
instance: Option<Instance<'tcx>>,
224228
) -> &'ll Value {
225229
debug!("invoke {:?} with args ({:?})", llfn, args);
226230

@@ -233,10 +237,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
233237
}
234238

235239
// Emit CFI pointer type membership test
236-
self.cfi_type_test(fn_attrs, fn_abi, llfn);
240+
self.cfi_type_test(fn_attrs, fn_abi, instance, llfn);
237241

238242
// Emit KCFI operand bundle
239-
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
243+
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
240244
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
241245
if let Some(kcfi_bundle) = kcfi_bundle {
242246
bundles.push(kcfi_bundle);
@@ -1231,6 +1235,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
12311235
llfn: &'ll Value,
12321236
args: &[&'ll Value],
12331237
funclet: Option<&Funclet<'ll>>,
1238+
instance: Option<Instance<'tcx>>,
12341239
) -> &'ll Value {
12351240
debug!("call {:?} with args ({:?})", llfn, args);
12361241

@@ -1243,10 +1248,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
12431248
}
12441249

12451250
// Emit CFI pointer type membership test
1246-
self.cfi_type_test(fn_attrs, fn_abi, llfn);
1251+
self.cfi_type_test(fn_attrs, fn_abi, instance, llfn);
12471252

12481253
// Emit KCFI operand bundle
1249-
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
1254+
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
12501255
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
12511256
if let Some(kcfi_bundle) = kcfi_bundle {
12521257
bundles.push(kcfi_bundle);
@@ -1468,7 +1473,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
14681473

14691474
pub(crate) fn call_intrinsic(&mut self, intrinsic: &str, args: &[&'ll Value]) -> &'ll Value {
14701475
let (ty, f) = self.cx.get_intrinsic(intrinsic);
1471-
self.call(ty, None, None, f, args, None)
1476+
self.call(ty, None, None, f, args, None, None)
14721477
}
14731478

14741479
fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Size) {
@@ -1526,7 +1531,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
15261531
format!("llvm.{instr}.sat.i{int_width}.f{float_width}")
15271532
};
15281533
let f = self.declare_cfn(&name, llvm::UnnamedAddr::No, self.type_func(&[src_ty], dest_ty));
1529-
self.call(self.type_func(&[src_ty], dest_ty), None, None, f, &[val], None)
1534+
self.call(self.type_func(&[src_ty], dest_ty), None, None, f, &[val], None, None)
15301535
}
15311536

15321537
pub(crate) fn landing_pad(
@@ -1554,6 +1559,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
15541559
default_dest: &'ll BasicBlock,
15551560
indirect_dest: &[&'ll BasicBlock],
15561561
funclet: Option<&Funclet<'ll>>,
1562+
instance: Option<Instance<'tcx>>,
15571563
) -> &'ll Value {
15581564
debug!("invoke {:?} with args ({:?})", llfn, args);
15591565

@@ -1566,10 +1572,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
15661572
}
15671573

15681574
// Emit CFI pointer type membership test
1569-
self.cfi_type_test(fn_attrs, fn_abi, llfn);
1575+
self.cfi_type_test(fn_attrs, fn_abi, instance, llfn);
15701576

15711577
// Emit KCFI operand bundle
1572-
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
1578+
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
15731579
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
15741580
if let Some(kcfi_bundle) = kcfi_bundle {
15751581
bundles.push(kcfi_bundle);
@@ -1601,6 +1607,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
16011607
&mut self,
16021608
fn_attrs: Option<&CodegenFnAttrs>,
16031609
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
1610+
instance: Option<Instance<'tcx>>,
16041611
llfn: &'ll Value,
16051612
) {
16061613
let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) };
@@ -1622,7 +1629,11 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
16221629
options.insert(TypeIdOptions::NORMALIZE_INTEGERS);
16231630
}
16241631

1625-
let typeid = typeid_for_fnabi(self.tcx, fn_abi, options);
1632+
let typeid = if let Some(instance) = instance {
1633+
typeid_for_instance(self.tcx, &instance, options)
1634+
} else {
1635+
typeid_for_fnabi(self.tcx, fn_abi, options)
1636+
};
16261637
let typeid_metadata = self.cx.typeid_metadata(typeid).unwrap();
16271638

16281639
// Test whether the function pointer is associated with the type identifier.
@@ -1644,6 +1655,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
16441655
&mut self,
16451656
fn_attrs: Option<&CodegenFnAttrs>,
16461657
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
1658+
instance: Option<Instance<'tcx>>,
16471659
llfn: &'ll Value,
16481660
) -> Option<llvm::OperandBundleDef<'ll>> {
16491661
let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) };
@@ -1665,7 +1677,12 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
16651677
options.insert(TypeIdOptions::NORMALIZE_INTEGERS);
16661678
}
16671679

1668-
let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi, options);
1680+
let kcfi_typeid = if let Some(instance) = instance {
1681+
kcfi_typeid_for_instance(self.tcx, &instance, options)
1682+
} else {
1683+
kcfi_typeid_for_fnabi(self.tcx, fn_abi, options)
1684+
};
1685+
16691686
Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
16701687
} else {
16711688
None

‎compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
181181
simple_fn,
182182
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
183183
None,
184+
Some(instance),
184185
)
185186
}
186187
sym::likely => {
@@ -539,7 +540,7 @@ fn catch_unwind_intrinsic<'ll>(
539540
) {
540541
if bx.sess().panic_strategy() == PanicStrategy::Abort {
541542
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
542-
bx.call(try_func_ty, None, None, try_func, &[data], None);
543+
bx.call(try_func_ty, None, None, try_func, &[data], None, None);
543544
// Return 0 unconditionally from the intrinsic call;
544545
// we can never unwind.
545546
let ret_align = bx.tcx().data_layout.i32_align.abi;
@@ -640,7 +641,7 @@ fn codegen_msvc_try<'ll>(
640641
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
641642
let slot = bx.alloca(bx.type_ptr(), ptr_align);
642643
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
643-
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None);
644+
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None, None);
644645

645646
bx.switch_to_block(normal);
646647
bx.ret(bx.const_i32(0));
@@ -684,15 +685,15 @@ fn codegen_msvc_try<'ll>(
684685
let funclet = bx.catch_pad(cs, &[tydesc, flags, slot]);
685686
let ptr = bx.load(bx.type_ptr(), slot, ptr_align);
686687
let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
687-
bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet));
688+
bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet), None);
688689
bx.catch_ret(&funclet, caught);
689690

690691
// The flag value of 64 indicates a "catch-all".
691692
bx.switch_to_block(catchpad_foreign);
692693
let flags = bx.const_i32(64);
693694
let null = bx.const_null(bx.type_ptr());
694695
let funclet = bx.catch_pad(cs, &[null, flags, null]);
695-
bx.call(catch_ty, None, None, catch_func, &[data, null], Some(&funclet));
696+
bx.call(catch_ty, None, None, catch_func, &[data, null], Some(&funclet), None);
696697
bx.catch_ret(&funclet, caught);
697698

698699
bx.switch_to_block(caught);
@@ -701,7 +702,7 @@ fn codegen_msvc_try<'ll>(
701702

702703
// Note that no invoke is used here because by definition this function
703704
// can't panic (that's what it's catching).
704-
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None);
705+
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
705706
let i32_align = bx.tcx().data_layout.i32_align.abi;
706707
bx.store(ret, dest, i32_align);
707708
}
@@ -750,7 +751,7 @@ fn codegen_wasm_try<'ll>(
750751
// }
751752
//
752753
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
753-
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None);
754+
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None, None);
754755

755756
bx.switch_to_block(normal);
756757
bx.ret(bx.const_i32(0));
@@ -766,7 +767,7 @@ fn codegen_wasm_try<'ll>(
766767
let _sel = bx.call_intrinsic("llvm.wasm.get.ehselector", &[funclet.cleanuppad()]);
767768

768769
let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
769-
bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet));
770+
bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet), None);
770771
bx.catch_ret(&funclet, caught);
771772

772773
bx.switch_to_block(caught);
@@ -775,7 +776,7 @@ fn codegen_wasm_try<'ll>(
775776

776777
// Note that no invoke is used here because by definition this function
777778
// can't panic (that's what it's catching).
778-
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None);
779+
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
779780
let i32_align = bx.tcx().data_layout.i32_align.abi;
780781
bx.store(ret, dest, i32_align);
781782
}
@@ -818,7 +819,7 @@ fn codegen_gnu_try<'ll>(
818819
let data = llvm::get_param(bx.llfn(), 1);
819820
let catch_func = llvm::get_param(bx.llfn(), 2);
820821
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
821-
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
822+
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None, None);
822823

823824
bx.switch_to_block(then);
824825
bx.ret(bx.const_i32(0));
@@ -836,13 +837,13 @@ fn codegen_gnu_try<'ll>(
836837
bx.add_clause(vals, tydesc);
837838
let ptr = bx.extract_value(vals, 0);
838839
let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
839-
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None);
840+
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None, None);
840841
bx.ret(bx.const_i32(1));
841842
});
842843

843844
// Note that no invoke is used here because by definition this function
844845
// can't panic (that's what it's catching).
845-
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None);
846+
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
846847
let i32_align = bx.tcx().data_layout.i32_align.abi;
847848
bx.store(ret, dest, i32_align);
848849
}
@@ -882,7 +883,7 @@ fn codegen_emcc_try<'ll>(
882883
let data = llvm::get_param(bx.llfn(), 1);
883884
let catch_func = llvm::get_param(bx.llfn(), 2);
884885
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
885-
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
886+
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None, None);
886887

887888
bx.switch_to_block(then);
888889
bx.ret(bx.const_i32(0));
@@ -920,13 +921,13 @@ fn codegen_emcc_try<'ll>(
920921
bx.store(is_rust_panic, catch_data_1, i8_align);
921922

922923
let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
923-
bx.call(catch_ty, None, None, catch_func, &[data, catch_data], None);
924+
bx.call(catch_ty, None, None, catch_func, &[data, catch_data], None, None);
924925
bx.ret(bx.const_i32(1));
925926
});
926927

927928
// Note that no invoke is used here because by definition this function
928929
// can't panic (that's what it's catching).
929-
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None);
930+
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
930931
let i32_align = bx.tcx().data_layout.i32_align.abi;
931932
bx.store(ret, dest, i32_align);
932933
}
@@ -1439,6 +1440,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
14391440
f,
14401441
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
14411442
None,
1443+
None,
14421444
);
14431445
Ok(c)
14441446
}
@@ -1607,6 +1609,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
16071609
f,
16081610
&[args[1].immediate(), alignment, mask, args[0].immediate()],
16091611
None,
1612+
None,
16101613
);
16111614
return Ok(v);
16121615
}
@@ -1706,6 +1709,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
17061709
f,
17071710
&[args[1].immediate(), alignment, mask, args[2].immediate()],
17081711
None,
1712+
None,
17091713
);
17101714
return Ok(v);
17111715
}
@@ -1799,6 +1803,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
17991803
f,
18001804
&[args[2].immediate(), args[1].immediate(), alignment, mask],
18011805
None,
1806+
None,
18021807
);
18031808
return Ok(v);
18041809
}
@@ -1904,6 +1909,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
19041909
f,
19051910
&[args[0].immediate(), args[1].immediate(), alignment, mask],
19061911
None,
1912+
None,
19071913
);
19081914
return Ok(v);
19091915
}
@@ -2352,11 +2358,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
23522358
f,
23532359
&[args[0].immediate(), bx.const_int(bx.type_i1(), 0)],
23542360
None,
2361+
None,
23552362
))
23562363
} else {
23572364
let fn_ty = bx.type_func(&[vec_ty], vec_ty);
23582365
let f = bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
2359-
Ok(bx.call(fn_ty, None, None, f, &[args[0].immediate()], None))
2366+
Ok(bx.call(fn_ty, None, None, f, &[args[0].immediate()], None, None))
23602367
};
23612368
}
23622369

@@ -2409,7 +2416,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
24092416

24102417
let fn_ty = bx.type_func(&[vec_ty, vec_ty], vec_ty);
24112418
let f = bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
2412-
let v = bx.call(fn_ty, None, None, f, &[lhs, rhs], None);
2419+
let v = bx.call(fn_ty, None, None, f, &[lhs, rhs], None, None);
24132420
return Ok(v);
24142421
}
24152422

‎compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -462,27 +462,34 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
462462
let ptr_ty = cx.type_ptr();
463463
let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx);
464464

465-
let (start_fn, start_ty, args) = if let EntryFnType::Main { sigpipe } = entry_type {
465+
let (start_fn, start_ty, args, instance) = if let EntryFnType::Main { sigpipe } = entry_type
466+
{
466467
let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None);
467-
let start_fn = cx.get_fn_addr(ty::Instance::expect_resolve(
468+
let start_instance = ty::Instance::expect_resolve(
468469
cx.tcx(),
469470
ty::ParamEnv::reveal_all(),
470471
start_def_id,
471472
cx.tcx().mk_args(&[main_ret_ty.into()]),
472-
));
473+
);
474+
let start_fn = cx.get_fn_addr(start_instance);
473475

474476
let i8_ty = cx.type_i8();
475477
let arg_sigpipe = bx.const_u8(sigpipe);
476478

477479
let start_ty = cx.type_func(&[cx.val_ty(rust_main), isize_ty, ptr_ty, i8_ty], isize_ty);
478-
(start_fn, start_ty, vec![rust_main, arg_argc, arg_argv, arg_sigpipe])
480+
(
481+
start_fn,
482+
start_ty,
483+
vec![rust_main, arg_argc, arg_argv, arg_sigpipe],
484+
Some(start_instance),
485+
)
479486
} else {
480487
debug!("using user-defined start fn");
481488
let start_ty = cx.type_func(&[isize_ty, ptr_ty], isize_ty);
482-
(rust_main, start_ty, vec![arg_argc, arg_argv])
489+
(rust_main, start_ty, vec![arg_argc, arg_argv], None)
483490
};
484491

485-
let result = bx.call(start_ty, None, None, start_fn, &args, None);
492+
let result = bx.call(start_ty, None, None, start_fn, &args, None, instance);
486493
if cx.sess().target.os.contains("uefi") {
487494
bx.ret(result);
488495
} else {

‎compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
232232
ret_llbb,
233233
unwind_block,
234234
self.funclet(fx),
235+
instance,
235236
);
236237
if fx.mir[self.bb].is_cleanup {
237238
bx.apply_attrs_to_cleanup_callsite(invokeret);
@@ -247,7 +248,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
247248
}
248249
MergingSucc::False
249250
} else {
250-
let llret = bx.call(fn_ty, fn_attrs, Some(fn_abi), fn_ptr, llargs, self.funclet(fx));
251+
let llret =
252+
bx.call(fn_ty, fn_attrs, Some(fn_abi), fn_ptr, llargs, self.funclet(fx), instance);
251253
if fx.mir[self.bb].is_cleanup {
252254
bx.apply_attrs_to_cleanup_callsite(llret);
253255
}
@@ -502,7 +504,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
502504
let ty = location.ty(self.mir, bx.tcx()).ty;
503505
let ty = self.monomorphize(ty);
504506
let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty);
505-
let instance = drop_fn.clone();
506507

507508
if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
508509
// we don't actually need to drop anything.
@@ -518,7 +519,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
518519
args1 = [place.llval];
519520
&args1[..]
520521
};
521-
let (drop_fn, fn_abi) =
522+
let (drop_fn, fn_abi, drop_instance) =
522523
match ty.kind() {
523524
// FIXME(eddyb) perhaps move some of this logic into
524525
// `Instance::resolve_drop_in_place`?
@@ -550,6 +551,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
550551
meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
551552
.get_fn(bx, vtable, ty, fn_abi),
552553
fn_abi,
554+
virtual_drop,
553555
)
554556
}
555557
ty::Dynamic(_, _, ty::DynStar) => {
@@ -592,9 +594,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
592594
meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
593595
.get_fn(bx, meta.immediate(), ty, fn_abi),
594596
fn_abi,
597+
virtual_drop,
595598
)
596599
}
597-
_ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())),
600+
_ => (
601+
bx.get_fn_addr(drop_fn),
602+
bx.fn_abi_of_instance(drop_fn, ty::List::empty()),
603+
drop_fn,
604+
),
598605
};
599606
helper.do_call(
600607
self,
@@ -605,7 +612,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
605612
Some((ReturnDest::Nothing, target)),
606613
unwind,
607614
&[],
608-
Some(instance),
615+
Some(drop_instance),
609616
mergeable_succ,
610617
)
611618
}
@@ -1699,7 +1706,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
16991706
} else {
17001707
let fn_ty = bx.fn_decl_backend_type(fn_abi);
17011708

1702-
let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref());
1709+
let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref(), None);
17031710
bx.apply_attrs_to_cleanup_callsite(llret);
17041711
}
17051712

‎compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
709709
} else {
710710
None
711711
};
712-
bx.call(fn_ty, fn_attrs, Some(fn_abi), fn_ptr, &[], None)
712+
bx.call(fn_ty, fn_attrs, Some(fn_abi), fn_ptr, &[], None, Some(instance))
713713
} else {
714714
bx.get_static(def_id)
715715
};

‎compiler/rustc_codegen_ssa/src/size_of_val.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,15 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
7070
// (But we are in good company, this code is duplicated plenty of times.)
7171
let fn_ty = bx.fn_decl_backend_type(fn_abi);
7272

73-
bx.call(fn_ty, /* fn_attrs */ None, Some(fn_abi), llfn, &[msg.0, msg.1], None);
73+
bx.call(
74+
fn_ty,
75+
/* fn_attrs */ None,
76+
Some(fn_abi),
77+
llfn,
78+
&[msg.0, msg.1],
79+
None,
80+
None,
81+
);
7482

7583
// This function does not return so we can now return whatever we want.
7684
let size = bx.const_usize(layout.size.bytes());

‎compiler/rustc_codegen_ssa/src/traits/builder.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::MemFlags;
1717

1818
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
1919
use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout};
20-
use rustc_middle::ty::Ty;
20+
use rustc_middle::ty::{Instance, Ty};
2121
use rustc_session::config::OptLevel;
2222
use rustc_span::Span;
2323
use rustc_target::abi::call::FnAbi;
@@ -82,6 +82,7 @@ pub trait BuilderMethods<'a, 'tcx>:
8282
then: Self::BasicBlock,
8383
catch: Self::BasicBlock,
8484
funclet: Option<&Self::Funclet>,
85+
instance: Option<Instance<'tcx>>,
8586
) -> Self::Value;
8687
fn unreachable(&mut self);
8788

@@ -389,6 +390,7 @@ pub trait BuilderMethods<'a, 'tcx>:
389390
llfn: Self::Value,
390391
args: &[Self::Value],
391392
funclet: Option<&Self::Funclet>,
393+
instance: Option<Instance<'tcx>>,
392394
) -> Self::Value;
393395
fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
394396

‎compiler/rustc_symbol_mangling/src/typeid.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub fn typeid_for_instance<'tcx>(
3636
instance: &Instance<'tcx>,
3737
options: TypeIdOptions,
3838
) -> String {
39-
typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options)
39+
typeid_itanium_cxx_abi::typeid_for_instance(tcx, *instance, options)
4040
}
4141

4242
/// Returns a KCFI type metadata identifier for the specified FnAbi.
@@ -61,6 +61,6 @@ pub fn kcfi_typeid_for_instance<'tcx>(
6161
// A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the
6262
// xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
6363
let mut hash: XxHash64 = Default::default();
64-
hash.write(typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options).as_bytes());
64+
hash.write(typeid_itanium_cxx_abi::typeid_for_instance(tcx, *instance, options).as_bytes());
6565
hash.finish() as u32
6666
}

‎compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,11 +1108,15 @@ pub fn typeid_for_fnabi<'tcx>(
11081108
/// vendor extended type qualifiers and types for Rust types that are not used at the FFI boundary.
11091109
pub fn typeid_for_instance<'tcx>(
11101110
tcx: TyCtxt<'tcx>,
1111-
instance: &Instance<'tcx>,
1111+
mut instance: Instance<'tcx>,
11121112
options: TypeIdOptions,
11131113
) -> String {
1114+
if matches!(instance.def, ty::InstanceDef::Virtual(..)) {
1115+
instance.args = strip_receiver_auto(tcx, instance.args)
1116+
}
1117+
11141118
let fn_abi = tcx
1115-
.fn_abi_of_instance(tcx.param_env(instance.def_id()).and((*instance, ty::List::empty())))
1119+
.fn_abi_of_instance(tcx.param_env(instance.def_id()).and((instance, ty::List::empty())))
11161120
.unwrap_or_else(|instance| {
11171121
bug!("typeid_for_instance: couldn't get fn_abi of instance {:?}", instance)
11181122
});
@@ -1158,3 +1162,23 @@ pub fn typeid_for_instance<'tcx>(
11581162

11591163
typeid_for_fnabi(tcx, fn_abi, options)
11601164
}
1165+
1166+
fn strip_receiver_auto<'tcx>(
1167+
tcx: TyCtxt<'tcx>,
1168+
args: ty::GenericArgsRef<'tcx>,
1169+
) -> ty::GenericArgsRef<'tcx> {
1170+
let ty = args.type_at(0);
1171+
let ty::Dynamic(preds, lifetime, kind) = ty.kind() else {
1172+
bug!("Tried to strip auto traits from non-dynamic type {ty}");
1173+
};
1174+
let filtered_preds =
1175+
if preds.principal().is_some() {
1176+
tcx.mk_poly_existential_predicates_from_iter(preds.into_iter().filter(|pred| {
1177+
!matches!(pred.skip_binder(), ty::ExistentialPredicate::AutoTrait(..))
1178+
}))
1179+
} else {
1180+
ty::List::empty()
1181+
};
1182+
let new_rcvr = Ty::new_dynamic(tcx, filtered_preds, *lifetime, *kind);
1183+
tcx.mk_args_trait(new_rcvr, args.into_iter().skip(1))
1184+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Tests that calling a trait object method on a trait object with additional auto traits works.
2+
3+
//@ needs-sanitizer-cfi
4+
// FIXME(#122848) Remove only-linux once OSX CFI binaries work
5+
//@ only-linux
6+
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
7+
//@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0
8+
//@ run-pass
9+
10+
trait Foo {
11+
fn foo(&self);
12+
}
13+
14+
struct Bar;
15+
impl Foo for Bar {
16+
fn foo(&self) {}
17+
}
18+
19+
pub fn main() {
20+
let x: &(dyn Foo + Send) = &Bar;
21+
x.foo();
22+
}

0 commit comments

Comments
 (0)
Please sign in to comment.