Skip to content

Commit 23d01cd

Browse files
committed
Auto merge of #150448 - matthiaskrgr:rollup-d52y317, r=matthiaskrgr
Rollup of 3 pull requests Successful merges: - #148533 (Split LLVM intrinsic abi handling from the rest of the abi handling) - #150358 (fix rustfmt on `const impl Ty {}`) - #150434 (Add test for never type fallback in try blocks with `Into<!>`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 7b5cde7 + 05287d1 commit 23d01cd

14 files changed

Lines changed: 338 additions & 43 deletions

File tree

compiler/rustc_codegen_gcc/src/builder.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -314,14 +314,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
314314
self.block.get_function()
315315
}
316316

317-
fn function_call(
317+
pub fn function_call(
318318
&mut self,
319-
func: RValue<'gcc>,
319+
func: Function<'gcc>,
320320
args: &[RValue<'gcc>],
321321
_funclet: Option<&Funclet>,
322322
) -> RValue<'gcc> {
323-
// TODO(antoyo): remove when the API supports a different type for functions.
324-
let func: Function<'gcc> = self.cx.rvalue_as_function(func);
325323
let args = self.check_call("call", func, args);
326324

327325
// gccjit requires to use the result of functions, even when it's not used.
@@ -514,6 +512,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
514512
type CodegenCx = CodegenCx<'gcc, 'tcx>;
515513

516514
fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Builder<'a, 'gcc, 'tcx> {
515+
*cx.current_func.borrow_mut() = Some(block.get_function());
517516
Builder::with_cx(cx, block)
518517
}
519518

@@ -1765,6 +1764,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
17651764
// FIXME(antoyo): remove when having a proper API.
17661765
let gcc_func = unsafe { std::mem::transmute::<RValue<'gcc>, Function<'gcc>>(func) };
17671766
let call = if self.functions.borrow().values().any(|value| *value == gcc_func) {
1767+
// TODO(antoyo): remove when the API supports a different type for functions.
1768+
let func: Function<'gcc> = self.cx.rvalue_as_function(func);
17681769
self.function_call(func, args, funclet)
17691770
} else {
17701771
// If it's a not function that was defined, it's a function pointer.

compiler/rustc_codegen_gcc/src/context.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ pub struct CodegenCx<'gcc, 'tcx> {
9292
pub instances: RefCell<FxHashMap<Instance<'tcx>, LValue<'gcc>>>,
9393
/// Cache function instances of monomorphic and polymorphic items
9494
pub function_instances: RefCell<FxHashMap<Instance<'tcx>, Function<'gcc>>>,
95+
/// Cache function instances of intrinsics
96+
pub intrinsic_instances: RefCell<FxHashMap<Instance<'tcx>, Function<'gcc>>>,
9597
/// Cache generated vtables
9698
pub vtables:
9799
RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
@@ -280,6 +282,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
280282
linkage: Cell::new(FunctionType::Internal),
281283
instances: Default::default(),
282284
function_instances: Default::default(),
285+
intrinsic_instances: Default::default(),
283286
on_stack_params: Default::default(),
284287
on_stack_function_params: Default::default(),
285288
vtables: Default::default(),
@@ -391,17 +394,13 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
391394
}
392395

393396
fn get_fn(&self, instance: Instance<'tcx>) -> Function<'gcc> {
394-
let func = get_fn(self, instance);
395-
*self.current_func.borrow_mut() = Some(func);
396-
func
397+
get_fn(self, instance)
397398
}
398399

399400
fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> {
400401
let func_name = self.tcx.symbol_name(instance).name;
401402

402-
let func = if self.intrinsics.borrow().contains_key(func_name) {
403-
self.intrinsics.borrow()[func_name]
404-
} else if let Some(variable) = self.get_declared_value(func_name) {
403+
let func = if let Some(variable) = self.get_declared_value(func_name) {
405404
return variable;
406405
} else {
407406
get_fn(self, instance)

compiler/rustc_codegen_gcc/src/declare.rs

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use rustc_target::callconv::FnAbi;
88

99
use crate::abi::{FnAbiGcc, FnAbiGccExt};
1010
use crate::context::CodegenCx;
11-
use crate::intrinsic::llvm;
1211

1312
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
1413
pub fn get_or_insert_global(
@@ -100,18 +99,14 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
10099
let return_type = self.type_i32();
101100
let variadic = false;
102101
self.linkage.set(FunctionType::Exported);
103-
let func = declare_raw_fn(
102+
declare_raw_fn(
104103
self,
105104
name,
106105
callconv,
107106
return_type,
108107
&[self.type_i32(), const_string],
109108
variadic,
110-
);
111-
// NOTE: it is needed to set the current_func here as well, because get_fn() is not called
112-
// for the main function.
113-
*self.current_func.borrow_mut() = Some(func);
114-
func
109+
)
115110
}
116111

117112
pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> {
@@ -166,19 +161,6 @@ fn declare_raw_fn<'gcc>(
166161
param_types: &[Type<'gcc>],
167162
variadic: bool,
168163
) -> Function<'gcc> {
169-
if name.starts_with("llvm.") {
170-
let intrinsic = match name {
171-
"llvm.fma.f16" => {
172-
// fma is not a target builtin, but a normal builtin, so we handle it differently
173-
// here.
174-
cx.context.get_builtin_function("fma")
175-
}
176-
_ => llvm::intrinsic(name, cx),
177-
};
178-
179-
cx.intrinsics.borrow_mut().insert(name.to_string(), intrinsic);
180-
return intrinsic;
181-
}
182164
let func = if cx.functions.borrow().contains_key(name) {
183165
cx.functions.borrow()[name]
184166
} else {

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

Lines changed: 92 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use gccjit::Type;
99
use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp};
1010
#[cfg(feature = "master")]
1111
use rustc_abi::ExternAbi;
12-
use rustc_abi::{BackendRepr, HasDataLayout};
12+
use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange};
1313
use rustc_codegen_ssa::MemFlags;
1414
use rustc_codegen_ssa::base::wants_msvc_seh;
1515
use rustc_codegen_ssa::common::IntPredicate;
@@ -20,19 +20,15 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
2020
use rustc_codegen_ssa::traits::MiscCodegenMethods;
2121
use rustc_codegen_ssa::traits::{
2222
ArgAbiBuilderMethods, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods,
23-
IntrinsicCallBuilderMethods,
23+
IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods,
2424
};
2525
use rustc_middle::bug;
26-
#[cfg(feature = "master")]
27-
use rustc_middle::ty::layout::FnAbiOf;
28-
use rustc_middle::ty::layout::LayoutOf;
26+
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
2927
use rustc_middle::ty::{self, Instance, Ty};
3028
use rustc_span::{Span, Symbol, sym};
3129
use rustc_target::callconv::{ArgAbi, PassMode};
3230

33-
#[cfg(feature = "master")]
34-
use crate::abi::FnAbiGccExt;
35-
use crate::abi::GccType;
31+
use crate::abi::{FnAbiGccExt, GccType};
3632
use crate::builder::Builder;
3733
use crate::common::{SignType, TypeReflection};
3834
use crate::context::CodegenCx;
@@ -609,6 +605,94 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
609605
Ok(())
610606
}
611607

608+
fn codegen_llvm_intrinsic_call(
609+
&mut self,
610+
instance: ty::Instance<'tcx>,
611+
args: &[OperandRef<'tcx, Self::Value>],
612+
is_cleanup: bool,
613+
) -> Self::Value {
614+
let func = if let Some(&func) = self.intrinsic_instances.borrow().get(&instance) {
615+
func
616+
} else {
617+
let sym = self.tcx.symbol_name(instance).name;
618+
619+
let func = if let Some(func) = self.intrinsics.borrow().get(sym) {
620+
*func
621+
} else {
622+
self.linkage.set(FunctionType::Extern);
623+
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
624+
let fn_ty = fn_abi.gcc_type(self);
625+
626+
let func = match sym {
627+
"llvm.fma.f16" => {
628+
// fma is not a target builtin, but a normal builtin, so we handle it differently
629+
// here.
630+
self.context.get_builtin_function("fma")
631+
}
632+
_ => llvm::intrinsic(sym, self),
633+
};
634+
635+
self.intrinsics.borrow_mut().insert(sym.to_string(), func);
636+
637+
self.on_stack_function_params
638+
.borrow_mut()
639+
.insert(func, fn_ty.on_stack_param_indices);
640+
#[cfg(feature = "master")]
641+
for fn_attr in fn_ty.fn_attributes {
642+
func.add_attribute(fn_attr);
643+
}
644+
645+
crate::attributes::from_fn_attrs(self, func, instance);
646+
647+
func
648+
};
649+
650+
self.intrinsic_instances.borrow_mut().insert(instance, func);
651+
652+
func
653+
};
654+
let fn_ptr = func.get_address(None);
655+
let fn_ty = fn_ptr.get_type();
656+
657+
let mut llargs = vec![];
658+
659+
for arg in args {
660+
match arg.val {
661+
OperandValue::ZeroSized => {}
662+
OperandValue::Immediate(_) => llargs.push(arg.immediate()),
663+
OperandValue::Pair(a, b) => {
664+
llargs.push(a);
665+
llargs.push(b);
666+
}
667+
OperandValue::Ref(op_place_val) => {
668+
let mut llval = op_place_val.llval;
669+
// We can't use `PlaceRef::load` here because the argument
670+
// may have a type we don't treat as immediate, but the ABI
671+
// used for this call is passing it by-value. In that case,
672+
// the load would just produce `OperandValue::Ref` instead
673+
// of the `OperandValue::Immediate` we need for the call.
674+
llval = self.load(self.backend_type(arg.layout), llval, op_place_val.align);
675+
if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
676+
if scalar.is_bool() {
677+
self.range_metadata(llval, WrappingRange { start: 0, end: 1 });
678+
}
679+
// We store bools as `i8` so we need to truncate to `i1`.
680+
llval = self.to_immediate_scalar(llval, scalar);
681+
}
682+
llargs.push(llval);
683+
}
684+
}
685+
}
686+
687+
// FIXME directly use the llvm intrinsic adjustment functions here
688+
let llret = self.call(fn_ty, None, None, fn_ptr, &llargs, None, None);
689+
if is_cleanup {
690+
self.apply_attrs_to_cleanup_callsite(llret);
691+
}
692+
693+
llret
694+
}
695+
612696
fn abort(&mut self) {
613697
let func = self.context.get_builtin_function("abort");
614698
let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1705,7 +1705,7 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
17051705
ret.expect("LLVM does not have support for catchret")
17061706
}
17071707

1708-
fn check_call<'b>(
1708+
pub(crate) fn check_call<'b>(
17091709
&mut self,
17101710
typ: &str,
17111711
fn_ty: &'ll Type,

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ pub(crate) struct FullCx<'ll, 'tcx> {
101101

102102
/// Cache instances of monomorphic and polymorphic items
103103
pub instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>,
104+
/// Cache instances of intrinsics
105+
pub intrinsic_instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>,
104106
/// Cache generated vtables
105107
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), &'ll Value>>,
106108
/// Cache of constant strings,
@@ -627,6 +629,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
627629
tls_model,
628630
codegen_unit,
629631
instances: Default::default(),
632+
intrinsic_instances: Default::default(),
630633
vtables: Default::default(),
631634
const_str_cache: Default::default(),
632635
const_globals: Default::default(),

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
use std::assert_matches::assert_matches;
22
use std::cmp::Ordering;
3+
use std::ffi::c_uint;
4+
use std::ptr;
35

4-
use rustc_abi::{Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size};
6+
use rustc_abi::{
7+
Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size, WrappingRange,
8+
};
59
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
610
use rustc_codegen_ssa::codegen_attrs::autodiff_attrs;
711
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
@@ -28,6 +32,7 @@ use crate::builder::Builder;
2832
use crate::builder::autodiff::{adjust_activity_to_abi, generate_enzyme_call};
2933
use crate::builder::gpu_offload::{gen_call_handling, gen_define_handling};
3034
use crate::context::CodegenCx;
35+
use crate::declare::declare_raw_fn;
3136
use crate::errors::{
3237
AutoDiffWithoutEnable, AutoDiffWithoutLto, OffloadWithoutEnable, OffloadWithoutFatLTO,
3338
};
@@ -633,6 +638,99 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
633638
Ok(())
634639
}
635640

641+
fn codegen_llvm_intrinsic_call(
642+
&mut self,
643+
instance: ty::Instance<'tcx>,
644+
args: &[OperandRef<'tcx, Self::Value>],
645+
is_cleanup: bool,
646+
) -> Self::Value {
647+
let tcx = self.tcx();
648+
649+
// FIXME remove usage of fn_abi
650+
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
651+
assert!(!fn_abi.ret.is_indirect());
652+
let fn_ty = fn_abi.llvm_type(self);
653+
654+
let fn_ptr = if let Some(&llfn) = self.intrinsic_instances.borrow().get(&instance) {
655+
llfn
656+
} else {
657+
let sym = tcx.symbol_name(instance).name;
658+
659+
// FIXME use get_intrinsic
660+
let llfn = if let Some(llfn) = self.get_declared_value(sym) {
661+
llfn
662+
} else {
663+
// Function addresses in Rust are never significant, allowing functions to
664+
// be merged.
665+
let llfn = declare_raw_fn(
666+
self,
667+
sym,
668+
fn_abi.llvm_cconv(self),
669+
llvm::UnnamedAddr::Global,
670+
llvm::Visibility::Default,
671+
fn_ty,
672+
);
673+
fn_abi.apply_attrs_llfn(self, llfn, Some(instance));
674+
675+
llfn
676+
};
677+
678+
self.intrinsic_instances.borrow_mut().insert(instance, llfn);
679+
680+
llfn
681+
};
682+
683+
let mut llargs = vec![];
684+
685+
for arg in args {
686+
match arg.val {
687+
OperandValue::ZeroSized => {}
688+
OperandValue::Immediate(_) => llargs.push(arg.immediate()),
689+
OperandValue::Pair(a, b) => {
690+
llargs.push(a);
691+
llargs.push(b);
692+
}
693+
OperandValue::Ref(op_place_val) => {
694+
let mut llval = op_place_val.llval;
695+
// We can't use `PlaceRef::load` here because the argument
696+
// may have a type we don't treat as immediate, but the ABI
697+
// used for this call is passing it by-value. In that case,
698+
// the load would just produce `OperandValue::Ref` instead
699+
// of the `OperandValue::Immediate` we need for the call.
700+
llval = self.load(self.backend_type(arg.layout), llval, op_place_val.align);
701+
if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
702+
if scalar.is_bool() {
703+
self.range_metadata(llval, WrappingRange { start: 0, end: 1 });
704+
}
705+
// We store bools as `i8` so we need to truncate to `i1`.
706+
llval = self.to_immediate_scalar(llval, scalar);
707+
}
708+
llargs.push(llval);
709+
}
710+
}
711+
}
712+
713+
debug!("call intrinsic {:?} with args ({:?})", instance, llargs);
714+
let args = self.check_call("call", fn_ty, fn_ptr, &llargs);
715+
let llret = unsafe {
716+
llvm::LLVMBuildCallWithOperandBundles(
717+
self.llbuilder,
718+
fn_ty,
719+
fn_ptr,
720+
args.as_ptr() as *const &llvm::Value,
721+
args.len() as c_uint,
722+
ptr::dangling(),
723+
0,
724+
c"".as_ptr(),
725+
)
726+
};
727+
if is_cleanup {
728+
self.apply_attrs_to_cleanup_callsite(llret);
729+
}
730+
731+
llret
732+
}
733+
636734
fn abort(&mut self) {
637735
self.call_intrinsic("llvm.trap", &[], &[]);
638736
}

0 commit comments

Comments
 (0)