Skip to content

Commit 84af47c

Browse files
committed
CFI: Use Instance at callsites
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.
1 parent 0b49e3c commit 84af47c

File tree

9 files changed

+106
-45
lines changed

9 files changed

+106
-45
lines changed

compiler/rustc_codegen_gcc/src/builder.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,7 @@ 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

@@ -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_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

0 commit comments

Comments
 (0)