Skip to content

Commit 9a07437

Browse files
committed
Teach llvm backend how to fall back to default bodies
1 parent 432635a commit 9a07437

File tree

11 files changed

+109
-103
lines changed

11 files changed

+109
-103
lines changed

compiler/rustc_codegen_cranelift/src/abi/mod.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -396,9 +396,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
396396
source_info,
397397
) {
398398
Ok(()) => return,
399-
// Unimplemented intrinsics must have a fallback body. The fallback body is obtained
400-
// by converting the `InstanceDef::Intrinsic` to an `InstanceDef::Item`.
401-
Err(()) => Some(Instance::new(instance.def_id(), instance.args)),
399+
Err(instance) => Some(instance),
402400
}
403401
}
404402
InstanceDef::DropGlue(_, None) => {

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
268268
destination: CPlace<'tcx>,
269269
target: Option<BasicBlock>,
270270
source_info: mir::SourceInfo,
271-
) -> Result<(), ()> {
271+
) -> Result<(), Instance<'tcx>> {
272272
let intrinsic = fx.tcx.item_name(instance.def_id());
273273
let instance_args = instance.args;
274274

@@ -431,7 +431,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
431431
ret: CPlace<'tcx>,
432432
destination: Option<BasicBlock>,
433433
source_info: mir::SourceInfo,
434-
) -> Result<(), ()> {
434+
) -> Result<(), Instance<'tcx>> {
435435
assert_eq!(generic_args, instance.args);
436436
let usize_layout = fx.layout_of(fx.tcx.types.usize);
437437

@@ -1229,14 +1229,6 @@ fn codegen_regular_intrinsic_call<'tcx>(
12291229
ret.write_cvalue(fx, CValue::by_val(cmp, ret.layout()));
12301230
}
12311231

1232-
sym::const_allocate => {
1233-
intrinsic_args!(fx, args => (_size, _align); intrinsic);
1234-
1235-
// returns a null pointer at runtime.
1236-
let null = fx.bcx.ins().iconst(fx.pointer_type, 0);
1237-
ret.write_cvalue(fx, CValue::by_val(null, ret.layout()));
1238-
}
1239-
12401232
sym::const_deallocate => {
12411233
intrinsic_args!(fx, args => (_ptr, _size, _align); intrinsic);
12421234
// nop at runtime.
@@ -1257,7 +1249,9 @@ fn codegen_regular_intrinsic_call<'tcx>(
12571249
);
12581250
}
12591251

1260-
_ => return Err(()),
1252+
// Unimplemented intrinsics must have a fallback body. The fallback body is obtained
1253+
// by converting the `InstanceDef::Intrinsic` to an `InstanceDef::Item`.
1254+
_ => return Err(Instance::new(instance.def_id(), instance.args)),
12611255
}
12621256

12631257
let ret_block = fx.get_block(destination.unwrap());

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ fn get_simple_intrinsic<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, name: Symbol) ->
9090
}
9191

9292
impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
93-
fn codegen_intrinsic_call(&mut self, instance: Instance<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, RValue<'gcc>>], llresult: RValue<'gcc>, span: Span) {
93+
fn codegen_intrinsic_call(&mut self, instance: Instance<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, RValue<'gcc>>], llresult: RValue<'gcc>, span: Span) -> Result<(), Instance<'tcx>> {
9494
let tcx = self.tcx;
9595
let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
9696

@@ -137,7 +137,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
137137
args[2].immediate(),
138138
llresult,
139139
);
140-
return;
140+
return Ok(());
141141
}
142142
sym::breakpoint => {
143143
unimplemented!();
@@ -166,12 +166,12 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
166166
sym::volatile_store => {
167167
let dst = args[0].deref(self.cx());
168168
args[1].val.volatile_store(self, dst);
169-
return;
169+
return Ok(());
170170
}
171171
sym::unaligned_volatile_store => {
172172
let dst = args[0].deref(self.cx());
173173
args[1].val.unaligned_volatile_store(self, dst);
174-
return;
174+
return Ok(());
175175
}
176176
sym::prefetch_read_data
177177
| sym::prefetch_write_data
@@ -269,7 +269,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
269269
},
270270
None => {
271271
tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty });
272-
return;
272+
return Ok(());
273273
}
274274
}
275275
}
@@ -339,7 +339,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
339339
extended_asm.set_volatile_flag(true);
340340

341341
// We have copied the value to `result` already.
342-
return;
342+
return Ok(());
343343
}
344344

345345
sym::ptr_mask => {
@@ -357,11 +357,12 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
357357
_ if name_str.starts_with("simd_") => {
358358
match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
359359
Ok(llval) => llval,
360-
Err(()) => return,
360+
Err(()) => return Ok(()),
361361
}
362362
}
363363

364-
_ => bug!("unknown intrinsic '{}'", name),
364+
// Fall back to default body
365+
_ => return Err(Instance::new(instance.def_id(), instance.args)),
365366
};
366367

367368
if !fn_abi.ret.is_ignore() {
@@ -376,6 +377,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
376377
.store(self, result);
377378
}
378379
}
380+
Ok(())
379381
}
380382

381383
fn abort(&mut self) {

compiler/rustc_codegen_llvm/src/intrinsic.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
8686
args: &[OperandRef<'tcx, &'ll Value>],
8787
llresult: &'ll Value,
8888
span: Span,
89-
) {
89+
) -> Result<(), ty::Instance<'tcx>> {
9090
let tcx = self.tcx;
9191
let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
9292

@@ -141,7 +141,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
141141
args[2].immediate(),
142142
llresult,
143143
);
144-
return;
144+
return Ok(());
145145
}
146146
sym::breakpoint => self.call_intrinsic("llvm.debugtrap", &[]),
147147
sym::va_copy => {
@@ -194,17 +194,17 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
194194
if !result.layout.is_zst() {
195195
self.store(load, result.llval, result.align);
196196
}
197-
return;
197+
return Ok(());
198198
}
199199
sym::volatile_store => {
200200
let dst = args[0].deref(self.cx());
201201
args[1].val.volatile_store(self, dst);
202-
return;
202+
return Ok(());
203203
}
204204
sym::unaligned_volatile_store => {
205205
let dst = args[0].deref(self.cx());
206206
args[1].val.unaligned_volatile_store(self, dst);
207-
return;
207+
return Ok(());
208208
}
209209
sym::prefetch_read_data
210210
| sym::prefetch_write_data
@@ -305,7 +305,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
305305
name,
306306
ty,
307307
});
308-
return;
308+
return Ok(());
309309
}
310310
}
311311
}
@@ -387,19 +387,23 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
387387
.unwrap_or_else(|| bug!("failed to generate inline asm call for `black_box`"));
388388

389389
// We have copied the value to `result` already.
390-
return;
390+
return Ok(());
391391
}
392392

393393
_ if name.as_str().starts_with("simd_") => {
394394
match generic_simd_intrinsic(
395395
self, name, callee_ty, fn_args, args, ret_ty, llret_ty, span,
396396
) {
397397
Ok(llval) => llval,
398-
Err(()) => return,
398+
Err(()) => return Ok(()),
399399
}
400400
}
401401

402-
_ => bug!("unknown intrinsic '{}' -- should it have been lowered earlier?", name),
402+
_ => {
403+
debug!("unknown intrinsic '{}' -- falling back to default body", name);
404+
// Call the fallback body instead of generating the intrinsic code
405+
return Err(ty::Instance::new(instance.def_id(), instance.args));
406+
}
403407
};
404408

405409
if !fn_abi.ret.is_ignore() {
@@ -411,6 +415,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
411415
.store(self, result);
412416
}
413417
}
418+
Ok(())
414419
}
415420

416421
fn abort(&mut self) {

compiler/rustc_codegen_ssa/src/mir/block.rs

+17-20
Original file line numberDiff line numberDiff line change
@@ -837,8 +837,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
837837
};
838838
}
839839

840-
match intrinsic {
841-
None | Some(sym::drop_in_place) => {}
840+
let instance = match intrinsic {
841+
None | Some(sym::drop_in_place) => instance,
842842
Some(intrinsic) => {
843843
let mut llargs = Vec::with_capacity(1);
844844
let ret_dest = self.make_return_dest(
@@ -882,27 +882,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
882882
})
883883
.collect();
884884

885-
Self::codegen_intrinsic_call(
886-
bx,
887-
*instance.as_ref().unwrap(),
888-
fn_abi,
889-
&args,
890-
dest,
891-
span,
892-
);
885+
let instance = *instance.as_ref().unwrap();
886+
match Self::codegen_intrinsic_call(bx, instance, fn_abi, &args, dest, span) {
887+
Ok(()) => {
888+
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
889+
self.store_return(bx, ret_dest, &fn_abi.ret, dst.llval);
890+
}
893891

894-
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
895-
self.store_return(bx, ret_dest, &fn_abi.ret, dst.llval);
892+
return if let Some(target) = target {
893+
helper.funclet_br(self, bx, target, mergeable_succ)
894+
} else {
895+
bx.unreachable();
896+
MergingSucc::False
897+
};
898+
}
899+
Err(instance) => Some(instance),
896900
}
897-
898-
return if let Some(target) = target {
899-
helper.funclet_br(self, bx, target, mergeable_succ)
900-
} else {
901-
bx.unreachable();
902-
MergingSucc::False
903-
};
904901
}
905-
}
902+
};
906903

907904
let mut llargs = Vec::with_capacity(arg_count);
908905
let destination = target.as_ref().map(|&target| {

0 commit comments

Comments
 (0)