Skip to content

Commit 209d94a

Browse files
committed
Move llvm intrinsic call to backend
1 parent cd204e5 commit 209d94a

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")]
@@ -640,6 +640,54 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
640640
Ok(())
641641
}
642642

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

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

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,8 +1038,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10381038
&& let Some(name) = bx.tcx().codegen_fn_attrs(instance.def_id()).symbol_name
10391039
&& name.as_str().starts_with("llvm.")
10401040
{
1041-
let mut llargs = Vec::with_capacity(args.len());
1042-
10431041
let dest_ty = destination.ty(&self.mir.local_decls, bx.tcx()).ty;
10441042
let return_dest = if dest_ty.is_unit() {
10451043
ReturnDest::Nothing
@@ -1058,48 +1056,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10581056
ReturnDest::Store(self.codegen_place(bx, destination.as_ref()))
10591057
};
10601058

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

1091-
let fn_ptr = bx.get_fn_addr(instance);
10921062
self.set_debug_loc(bx, source_info);
10931063

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

11041067
if let Some(target) = target {
11051068
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)