Move llvm intrinsic call to backend
This commit is contained in:
parent
4f7086a629
commit
62e17e920c
4 changed files with 114 additions and 44 deletions
|
|
@ -9,7 +9,7 @@ use gccjit::Type;
|
|||
use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp};
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_abi::{BackendRepr, HasDataLayout};
|
||||
use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange};
|
||||
use rustc_codegen_ssa::MemFlags;
|
||||
use rustc_codegen_ssa::base::wants_msvc_seh;
|
||||
use rustc_codegen_ssa::common::IntPredicate;
|
||||
|
|
@ -20,7 +20,7 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
|
|||
use rustc_codegen_ssa::traits::MiscCodegenMethods;
|
||||
use rustc_codegen_ssa::traits::{
|
||||
ArgAbiBuilderMethods, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods,
|
||||
IntrinsicCallBuilderMethods,
|
||||
IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods,
|
||||
};
|
||||
use rustc_middle::bug;
|
||||
#[cfg(feature = "master")]
|
||||
|
|
@ -609,6 +609,54 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn codegen_llvm_intrinsic_call(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OperandRef<'tcx, Self::Value>],
|
||||
is_cleanup: bool,
|
||||
) -> Self::Value {
|
||||
let fn_ptr = self.get_fn_addr(instance);
|
||||
let fn_ty = fn_ptr.get_type();
|
||||
|
||||
let mut llargs = vec![];
|
||||
|
||||
for arg in args {
|
||||
match arg.val {
|
||||
OperandValue::ZeroSized => {}
|
||||
OperandValue::Immediate(_) => llargs.push(arg.immediate()),
|
||||
OperandValue::Pair(a, b) => {
|
||||
llargs.push(a);
|
||||
llargs.push(b);
|
||||
}
|
||||
OperandValue::Ref(op_place_val) => {
|
||||
let mut llval = op_place_val.llval;
|
||||
// We can't use `PlaceRef::load` here because the argument
|
||||
// may have a type we don't treat as immediate, but the ABI
|
||||
// used for this call is passing it by-value. In that case,
|
||||
// the load would just produce `OperandValue::Ref` instead
|
||||
// of the `OperandValue::Immediate` we need for the call.
|
||||
llval = self.load(self.backend_type(arg.layout), llval, op_place_val.align);
|
||||
if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
|
||||
if scalar.is_bool() {
|
||||
self.range_metadata(llval, WrappingRange { start: 0, end: 1 });
|
||||
}
|
||||
// We store bools as `i8` so we need to truncate to `i1`.
|
||||
llval = self.to_immediate_scalar(llval, scalar);
|
||||
}
|
||||
llargs.push(llval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME directly use the llvm intrinsic adjustment functions here
|
||||
let llret = self.call(fn_ty, None, None, fn_ptr, &llargs, None, None);
|
||||
if is_cleanup {
|
||||
self.apply_attrs_to_cleanup_callsite(llret);
|
||||
}
|
||||
|
||||
llret
|
||||
}
|
||||
|
||||
fn abort(&mut self) {
|
||||
let func = self.context.get_builtin_function("abort");
|
||||
let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use rustc_abi::{Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size};
|
||||
use rustc_abi::{
|
||||
Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size, WrappingRange,
|
||||
};
|
||||
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
|
||||
use rustc_codegen_ssa::codegen_attrs::autodiff_attrs;
|
||||
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||
|
|
@ -633,6 +635,56 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn codegen_llvm_intrinsic_call(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OperandRef<'tcx, Self::Value>],
|
||||
is_cleanup: bool,
|
||||
) -> Self::Value {
|
||||
let fn_ptr = self.get_fn_addr(instance);
|
||||
// FIXME remove usage of fn_abi
|
||||
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
|
||||
assert!(!fn_abi.ret.is_indirect());
|
||||
let fn_ty = self.fn_decl_backend_type(fn_abi);
|
||||
|
||||
let mut llargs = vec![];
|
||||
|
||||
for arg in args {
|
||||
match arg.val {
|
||||
OperandValue::ZeroSized => {}
|
||||
OperandValue::Immediate(_) => llargs.push(arg.immediate()),
|
||||
OperandValue::Pair(a, b) => {
|
||||
llargs.push(a);
|
||||
llargs.push(b);
|
||||
}
|
||||
OperandValue::Ref(op_place_val) => {
|
||||
let mut llval = op_place_val.llval;
|
||||
// We can't use `PlaceRef::load` here because the argument
|
||||
// may have a type we don't treat as immediate, but the ABI
|
||||
// used for this call is passing it by-value. In that case,
|
||||
// the load would just produce `OperandValue::Ref` instead
|
||||
// of the `OperandValue::Immediate` we need for the call.
|
||||
llval = self.load(self.backend_type(arg.layout), llval, op_place_val.align);
|
||||
if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
|
||||
if scalar.is_bool() {
|
||||
self.range_metadata(llval, WrappingRange { start: 0, end: 1 });
|
||||
}
|
||||
// We store bools as `i8` so we need to truncate to `i1`.
|
||||
llval = self.to_immediate_scalar(llval, scalar);
|
||||
}
|
||||
llargs.push(llval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let llret = self.call(fn_ty, None, None, fn_ptr, &llargs, None, None);
|
||||
if is_cleanup {
|
||||
self.apply_attrs_to_cleanup_callsite(llret);
|
||||
}
|
||||
|
||||
llret
|
||||
}
|
||||
|
||||
fn abort(&mut self) {
|
||||
self.call_intrinsic("llvm.trap", &[], &[]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1040,8 +1040,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
&& let Some(name) = bx.tcx().codegen_fn_attrs(instance.def_id()).symbol_name
|
||||
&& name.as_str().starts_with("llvm.")
|
||||
{
|
||||
let mut llargs = Vec::with_capacity(args.len());
|
||||
|
||||
let dest_ty = destination.ty(&self.mir.local_decls, bx.tcx()).ty;
|
||||
let return_dest = if dest_ty.is_unit() {
|
||||
ReturnDest::Nothing
|
||||
|
|
@ -1060,48 +1058,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
ReturnDest::Store(self.codegen_place(bx, destination.as_ref()))
|
||||
};
|
||||
|
||||
for arg in args {
|
||||
let op = self.codegen_operand(bx, &arg.node);
|
||||
let args =
|
||||
args.into_iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect::<Vec<_>>();
|
||||
|
||||
match op.val {
|
||||
ZeroSized => {}
|
||||
Immediate(_) => llargs.push(op.immediate()),
|
||||
Pair(a, b) => {
|
||||
llargs.push(a);
|
||||
llargs.push(b);
|
||||
}
|
||||
Ref(op_place_val) => {
|
||||
let mut llval = op_place_val.llval;
|
||||
// We can't use `PlaceRef::load` here because the argument
|
||||
// may have a type we don't treat as immediate, but the ABI
|
||||
// used for this call is passing it by-value. In that case,
|
||||
// the load would just produce `OperandValue::Ref` instead
|
||||
// of the `OperandValue::Immediate` we need for the call.
|
||||
llval = bx.load(bx.backend_type(op.layout), llval, op_place_val.align);
|
||||
if let BackendRepr::Scalar(scalar) = op.layout.backend_repr {
|
||||
if scalar.is_bool() {
|
||||
bx.range_metadata(llval, WrappingRange { start: 0, end: 1 });
|
||||
}
|
||||
// We store bools as `i8` so we need to truncate to `i1`.
|
||||
llval = bx.to_immediate_scalar(llval, scalar);
|
||||
}
|
||||
llargs.push(llval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let fn_ptr = bx.get_fn_addr(instance);
|
||||
self.set_debug_loc(bx, source_info);
|
||||
|
||||
// FIXME remove usage of fn_abi
|
||||
let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
|
||||
assert!(!fn_abi.ret.is_indirect());
|
||||
let fn_ty = bx.fn_decl_backend_type(fn_abi);
|
||||
|
||||
let llret = bx.call(fn_ty, None, None, fn_ptr, &llargs, None, None);
|
||||
if self.mir[helper.bb].is_cleanup {
|
||||
bx.apply_attrs_to_cleanup_callsite(llret);
|
||||
}
|
||||
let llret =
|
||||
bx.codegen_llvm_intrinsic_call(instance, &args, self.mir[helper.bb].is_cleanup);
|
||||
|
||||
if let Some(target) = target {
|
||||
self.store_return(
|
||||
|
|
|
|||
|
|
@ -25,6 +25,13 @@ pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes {
|
|||
span: Span,
|
||||
) -> Result<(), ty::Instance<'tcx>>;
|
||||
|
||||
fn codegen_llvm_intrinsic_call(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OperandRef<'tcx, Self::Value>],
|
||||
is_cleanup: bool,
|
||||
) -> Self::Value;
|
||||
|
||||
fn abort(&mut self);
|
||||
fn assume(&mut self, val: Self::Value);
|
||||
fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue