Skip to content

Commit 2fd66d7

Browse files
committed
Don't depend on FnAbi for intrinsics
Intrinsics are not real functions and as such don't have any calling convention. Trying to compute a calling convention for an intrinsic anyway is a nonsensical operation.
1 parent 3b66c4e commit 2fd66d7

File tree

1 file changed

+42
-32
lines changed
  • compiler/rustc_codegen_ssa/src/mir

1 file changed

+42
-32
lines changed

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_hir::lang_items::LangItem;
88
use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason};
99
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
1010
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
11-
use rustc_middle::ty::{self, Instance, List, Ty};
11+
use rustc_middle::ty::{self, Instance, Ty};
1212
use rustc_middle::{bug, span_bug};
1313
use rustc_session::config::OptLevel;
1414
use rustc_span::Span;
@@ -941,37 +941,55 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
941941
return merging_succ;
942942
}
943943

944-
let fn_abi = bx.fn_abi_of_instance(instance, List::empty());
944+
let result_layout =
945+
self.cx.layout_of(self.monomorphized_place_ty(destination.as_ref()));
945946

946-
let mut llargs = Vec::with_capacity(1);
947-
let ret_dest = self.make_return_dest(
948-
bx,
949-
destination,
950-
&fn_abi.ret,
951-
&mut llargs,
952-
Some(intrinsic),
953-
);
954-
let dest = match ret_dest {
955-
_ if fn_abi.ret.is_indirect() => llargs[0],
956-
ReturnDest::Nothing => bx.const_undef(bx.type_ptr()),
957-
ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => {
958-
dst.val.llval
959-
}
960-
ReturnDest::DirectOperand(_) => {
961-
bug!("Cannot use direct operand with an intrinsic call")
947+
let (result, store_in_local) = if result_layout.is_zst() {
948+
(
949+
PlaceRef::new_sized(bx.const_undef(bx.type_ptr()), result_layout),
950+
None,
951+
)
952+
} else if let Some(local) = destination.as_local() {
953+
match self.locals[local] {
954+
LocalRef::Place(dest) => (dest, None),
955+
LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
956+
LocalRef::PendingOperand => {
957+
// Currently, intrinsics always need a location to store
958+
// the result, so we create a temporary `alloca` for the
959+
// result.
960+
let tmp = PlaceRef::alloca(bx, result_layout);
961+
tmp.storage_live(bx);
962+
(tmp, Some(local))
963+
}
964+
LocalRef::Operand(_) => {
965+
bug!("place local already assigned to");
966+
}
962967
}
968+
} else {
969+
(self.codegen_place(bx, destination.as_ref()), None)
963970
};
964971

972+
if result.val.align < result.layout.align.abi {
973+
// Currently, MIR code generation does not create calls
974+
// that store directly to fields of packed structs (in
975+
// fact, the calls it creates write only to temps).
976+
//
977+
// If someone changes that, please update this code path
978+
// to create a temporary.
979+
span_bug!(self.mir.span, "can't directly store to unaligned value");
980+
}
981+
965982
let args: Vec<_> =
966983
args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect();
967984

968-
let result = PlaceRef::new_sized(dest, fn_abi.ret.layout);
969-
970985
match self.codegen_intrinsic_call(bx, instance, &args, result, source_info)
971986
{
972987
Ok(()) => {
973-
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
974-
self.store_return(bx, ret_dest, &fn_abi.ret, dst.val.llval);
988+
if let Some(local) = store_in_local {
989+
let op = bx.load_operand(result);
990+
result.storage_dead(bx);
991+
self.overwrite_local(local, LocalRef::Operand(op));
992+
self.debug_introduce_local(bx, local);
975993
}
976994

977995
return if let Some(target) = target {
@@ -1026,7 +1044,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10261044
// We still need to call `make_return_dest` even if there's no `target`, since
10271045
// `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited,
10281046
// and `make_return_dest` adds the return-place indirect pointer to `llargs`.
1029-
let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, None);
1047+
let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs);
10301048
let destination = target.map(|target| (return_dest, target));
10311049

10321050
// Split the rust-call tupled arguments off.
@@ -1834,7 +1852,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
18341852
dest: mir::Place<'tcx>,
18351853
fn_ret: &ArgAbi<'tcx, Ty<'tcx>>,
18361854
llargs: &mut Vec<Bx::Value>,
1837-
intrinsic: Option<ty::IntrinsicDef>,
18381855
) -> ReturnDest<'tcx, Bx::Value> {
18391856
// If the return is ignored, we can just return a do-nothing `ReturnDest`.
18401857
if fn_ret.is_ignore() {
@@ -1854,13 +1871,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
18541871
tmp.storage_live(bx);
18551872
llargs.push(tmp.val.llval);
18561873
ReturnDest::IndirectOperand(tmp, index)
1857-
} else if intrinsic.is_some() {
1858-
// Currently, intrinsics always need a location to store
1859-
// the result, so we create a temporary `alloca` for the
1860-
// result.
1861-
let tmp = PlaceRef::alloca(bx, fn_ret.layout);
1862-
tmp.storage_live(bx);
1863-
ReturnDest::IndirectOperand(tmp, index)
18641874
} else {
18651875
ReturnDest::DirectOperand(index)
18661876
};
@@ -1870,7 +1880,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
18701880
}
18711881
}
18721882
} else {
1873-
self.codegen_place(bx, mir::PlaceRef { local: dest.local, projection: dest.projection })
1883+
self.codegen_place(bx, dest.as_ref())
18741884
};
18751885
if fn_ret.is_indirect() {
18761886
if dest.val.align < dest.layout.align.abi {

0 commit comments

Comments
 (0)