Skip to content

Commit 6be93fe

Browse files
committed
Split out ABI handling for LLVM intrinsics
1 parent 66bc5a4 commit 6be93fe

File tree

1 file changed

+85
-1
lines changed
  • compiler/rustc_codegen_ssa/src/mir

1 file changed

+85
-1
lines changed

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_middle::{bug, span_bug};
1414
use rustc_session::config::OptLevel;
1515
use rustc_span::Span;
1616
use rustc_span::source_map::Spanned;
17-
use rustc_target::callconv::{ArgAbi, CastTarget, FnAbi, PassMode};
17+
use rustc_target::callconv::{ArgAbi, ArgAttributes, CastTarget, FnAbi, PassMode};
1818
use tracing::{debug, info};
1919

2020
use super::operand::OperandRef;
@@ -1036,6 +1036,90 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10361036
_ => bug!("{} is not callable", callee.layout.ty),
10371037
};
10381038

1039+
if let Some(instance) = instance
1040+
&& let Some(name) = bx.tcx().codegen_fn_attrs(instance.def_id()).symbol_name
1041+
&& name.as_str().starts_with("llvm.")
1042+
{
1043+
let mut llargs = Vec::with_capacity(args.len());
1044+
1045+
let dest_ty = destination.ty(&self.mir.local_decls, bx.tcx()).ty;
1046+
let return_dest = if dest_ty.is_unit() {
1047+
ReturnDest::Nothing
1048+
} else if let Some(index) = destination.as_local() {
1049+
match self.locals[index] {
1050+
LocalRef::Place(dest) => ReturnDest::Store(dest),
1051+
LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
1052+
LocalRef::PendingOperand => {
1053+
// Handle temporary places, specifically `Operand` ones, as
1054+
// they don't have `alloca`s.
1055+
ReturnDest::DirectOperand(index)
1056+
}
1057+
LocalRef::Operand(_) => bug!("place local already assigned to"),
1058+
}
1059+
} else {
1060+
ReturnDest::Store(self.codegen_place(bx, destination.as_ref()))
1061+
};
1062+
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+
}
1092+
1093+
let fn_ptr = bx.get_fn_addr(instance);
1094+
self.set_debug_loc(bx, source_info);
1095+
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+
}
1105+
1106+
if let Some(target) = target {
1107+
self.store_return(
1108+
bx,
1109+
return_dest,
1110+
&ArgAbi {
1111+
layout: bx.layout_of(dest_ty),
1112+
mode: PassMode::Direct(ArgAttributes::new()),
1113+
},
1114+
llret,
1115+
);
1116+
return helper.funclet_br(self, bx, target, mergeable_succ);
1117+
} else {
1118+
bx.unreachable();
1119+
return MergingSucc::False;
1120+
}
1121+
}
1122+
10391123
// FIXME(eddyb) avoid computing this if possible, when `instance` is
10401124
// available - right now `sig` is only needed for getting the `abi`
10411125
// and figuring out how many extra args were passed to a C-variadic `fn`.

0 commit comments

Comments
 (0)