Skip to content

Commit 2dcd164

Browse files
committed
Move llvm intrinsic call to backend
1 parent 0ab8b95 commit 2dcd164

File tree

4 files changed

+114
-44
lines changed

4 files changed

+114
-44
lines changed

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

Lines changed: 50 additions & 2 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,7 +20,7 @@ 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;
2626
#[cfg(feature = "master")]
@@ -636,6 +636,54 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
636636
Ok(())
637637
}
638638

639+
fn codegen_llvm_intrinsic_call(
640+
&mut self,
641+
instance: ty::Instance<'tcx>,
642+
args: &[OperandRef<'tcx, Self::Value>],
643+
is_cleanup: bool,
644+
) -> Self::Value {
645+
let fn_ptr = self.get_fn_addr(instance);
646+
let fn_ty = fn_ptr.get_type();
647+
648+
let mut llargs = vec![];
649+
650+
for arg in args {
651+
match arg.val {
652+
OperandValue::ZeroSized => {}
653+
OperandValue::Immediate(_) => llargs.push(arg.immediate()),
654+
OperandValue::Pair(a, b) => {
655+
llargs.push(a);
656+
llargs.push(b);
657+
}
658+
OperandValue::Ref(op_place_val) => {
659+
let mut llval = op_place_val.llval;
660+
// We can't use `PlaceRef::load` here because the argument
661+
// may have a type we don't treat as immediate, but the ABI
662+
// used for this call is passing it by-value. In that case,
663+
// the load would just produce `OperandValue::Ref` instead
664+
// of the `OperandValue::Immediate` we need for the call.
665+
llval = self.load(self.backend_type(arg.layout), llval, op_place_val.align);
666+
if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
667+
if scalar.is_bool() {
668+
self.range_metadata(llval, WrappingRange { start: 0, end: 1 });
669+
}
670+
// We store bools as `i8` so we need to truncate to `i1`.
671+
llval = self.to_immediate_scalar(llval, scalar);
672+
}
673+
llargs.push(llval);
674+
}
675+
}
676+
}
677+
678+
// FIXME directly use the llvm intrinsic adjustment functions here
679+
let llret = self.call(fn_ty, None, None, fn_ptr, &llargs, None, None);
680+
if is_cleanup {
681+
self.apply_attrs_to_cleanup_callsite(llret);
682+
}
683+
684+
llret
685+
}
686+
639687
fn abort(&mut self) {
640688
let func = self.context.get_builtin_function("abort");
641689
let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use std::assert_matches::assert_matches;
22
use std::cmp::Ordering;
33

4-
use rustc_abi::{Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size};
4+
use rustc_abi::{
5+
Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size, WrappingRange,
6+
};
57
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
68
use rustc_codegen_ssa::codegen_attrs::autodiff_attrs;
79
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
@@ -609,6 +611,56 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
609611
Ok(())
610612
}
611613

614+
fn codegen_llvm_intrinsic_call(
615+
&mut self,
616+
instance: ty::Instance<'tcx>,
617+
args: &[OperandRef<'tcx, Self::Value>],
618+
is_cleanup: bool,
619+
) -> Self::Value {
620+
let fn_ptr = self.get_fn_addr(instance);
621+
// FIXME remove usage of fn_abi
622+
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
623+
assert!(!fn_abi.ret.is_indirect());
624+
let fn_ty = self.fn_decl_backend_type(fn_abi);
625+
626+
let mut llargs = vec![];
627+
628+
for arg in args {
629+
match arg.val {
630+
OperandValue::ZeroSized => {}
631+
OperandValue::Immediate(_) => llargs.push(arg.immediate()),
632+
OperandValue::Pair(a, b) => {
633+
llargs.push(a);
634+
llargs.push(b);
635+
}
636+
OperandValue::Ref(op_place_val) => {
637+
let mut llval = op_place_val.llval;
638+
// We can't use `PlaceRef::load` here because the argument
639+
// may have a type we don't treat as immediate, but the ABI
640+
// used for this call is passing it by-value. In that case,
641+
// the load would just produce `OperandValue::Ref` instead
642+
// of the `OperandValue::Immediate` we need for the call.
643+
llval = self.load(self.backend_type(arg.layout), llval, op_place_val.align);
644+
if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
645+
if scalar.is_bool() {
646+
self.range_metadata(llval, WrappingRange { start: 0, end: 1 });
647+
}
648+
// We store bools as `i8` so we need to truncate to `i1`.
649+
llval = self.to_immediate_scalar(llval, scalar);
650+
}
651+
llargs.push(llval);
652+
}
653+
}
654+
}
655+
656+
let llret = self.call(fn_ty, None, None, fn_ptr, &llargs, None, None);
657+
if is_cleanup {
658+
self.apply_attrs_to_cleanup_callsite(llret);
659+
}
660+
661+
llret
662+
}
663+
612664
fn abort(&mut self) {
613665
self.call_intrinsic("llvm.trap", &[], &[]);
614666
}

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,8 +1040,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10401040
&& let Some(name) = bx.tcx().codegen_fn_attrs(instance.def_id()).symbol_name
10411041
&& name.as_str().starts_with("llvm.")
10421042
{
1043-
let mut llargs = Vec::with_capacity(args.len());
1044-
10451043
let dest_ty = destination.ty(&self.mir.local_decls, bx.tcx()).ty;
10461044
let return_dest = if dest_ty.is_unit() {
10471045
ReturnDest::Nothing
@@ -1060,48 +1058,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10601058
ReturnDest::Store(self.codegen_place(bx, destination.as_ref()))
10611059
};
10621060

1063-
for arg in args {
1064-
let op = self.codegen_operand(bx, &arg.node);
1065-
1066-
match op.val {
1067-
ZeroSized => {}
1068-
Immediate(_) => llargs.push(op.immediate()),
1069-
Pair(a, b) => {
1070-
llargs.push(a);
1071-
llargs.push(b);
1072-
}
1073-
Ref(op_place_val) => {
1074-
let mut llval = op_place_val.llval;
1075-
// We can't use `PlaceRef::load` here because the argument
1076-
// may have a type we don't treat as immediate, but the ABI
1077-
// used for this call is passing it by-value. In that case,
1078-
// the load would just produce `OperandValue::Ref` instead
1079-
// of the `OperandValue::Immediate` we need for the call.
1080-
llval = bx.load(bx.backend_type(op.layout), llval, op_place_val.align);
1081-
if let BackendRepr::Scalar(scalar) = op.layout.backend_repr {
1082-
if scalar.is_bool() {
1083-
bx.range_metadata(llval, WrappingRange { start: 0, end: 1 });
1084-
}
1085-
// We store bools as `i8` so we need to truncate to `i1`.
1086-
llval = bx.to_immediate_scalar(llval, scalar);
1087-
}
1088-
llargs.push(llval);
1089-
}
1090-
}
1091-
}
1061+
let args =
1062+
args.into_iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect::<Vec<_>>();
10921063

1093-
let fn_ptr = bx.get_fn_addr(instance);
10941064
self.set_debug_loc(bx, source_info);
10951065

1096-
// FIXME remove usage of fn_abi
1097-
let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
1098-
assert!(!fn_abi.ret.is_indirect());
1099-
let fn_ty = bx.fn_decl_backend_type(fn_abi);
1100-
1101-
let llret = bx.call(fn_ty, None, None, fn_ptr, &llargs, None, None);
1102-
if self.mir[helper.bb].is_cleanup {
1103-
bx.apply_attrs_to_cleanup_callsite(llret);
1104-
}
1066+
let llret =
1067+
bx.codegen_llvm_intrinsic_call(instance, &args, self.mir[helper.bb].is_cleanup);
11051068

11061069
if let Some(target) = target {
11071070
self.store_return(

compiler/rustc_codegen_ssa/src/traits/intrinsic.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes {
2525
span: Span,
2626
) -> Result<(), ty::Instance<'tcx>>;
2727

28+
fn codegen_llvm_intrinsic_call(
29+
&mut self,
30+
instance: ty::Instance<'tcx>,
31+
args: &[OperandRef<'tcx, Self::Value>],
32+
is_cleanup: bool,
33+
) -> Self::Value;
34+
2835
fn abort(&mut self);
2936
fn assume(&mut self, val: Self::Value);
3037
fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value;

0 commit comments

Comments
 (0)