Skip to content

Commit cd204e5

Browse files
committed
Split out ABI handling for LLVM intrinsics
1 parent c0ff72f commit cd204e5

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;
@@ -1034,6 +1034,90 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10341034
_ => bug!("{} is not callable", callee.layout.ty),
10351035
};
10361036

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

0 commit comments

Comments
 (0)