Skip to content

Commit 3c2e043

Browse files
authored
fix(rustc_codegen_nvvm): Check function signatures before overriding libm functions. (#206)
libm 0.2.13 refactored some of its implementations to use generic functions. The monomorphized function names clashed with the function names the codegen would override, causing it the codegen to override the function to a libdevice call that did not match the function signature. It then tries to patch this with a bitcast betwen floating point types, which are invalid casts. This change adds an additional check before overriding. The libm function signature must match the libdevice intrinsic signature of the same name. Note that this prevents overrides even if bitcasts between the two argument types would be valid, which is likely another bug anyways.
1 parent 290d711 commit 3c2e043

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

crates/rustc_codegen_nvvm/src/override_fns.rs

+23-6
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22
//! codegen-builtin methods. Currently the only use for this is overriding libm functions
33
//! with libdevice intrinsics (which are much faster and smaller).
44
5-
use crate::{builder::Builder, context::CodegenCx, llvm};
5+
use crate::abi::FnAbiLlvmExt;
6+
use crate::builder::Builder;
7+
use crate::context::CodegenCx;
8+
use crate::llvm;
69
use rustc_codegen_ssa::mono_item::MonoItemExt;
7-
use rustc_codegen_ssa::traits::BuilderMethods;
10+
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods};
811
use rustc_hir::def_id::LOCAL_CRATE;
9-
use rustc_middle::{mir::mono::MonoItem, ty::Instance};
12+
use rustc_middle::mir::mono::MonoItem;
13+
use rustc_middle::ty::layout::FnAbiOf;
14+
use rustc_middle::ty::{self, Instance};
1015

1116
/// Either override or define a function.
1217
pub(crate) fn define_or_override_fn<'tcx>(func: Instance<'tcx>, cx: &CodegenCx<'_, 'tcx>) {
@@ -27,12 +32,24 @@ fn should_override<'tcx>(func: Instance<'tcx>, cx: &CodegenCx<'_, 'tcx>) -> bool
2732
if !is_libm {
2833
return false;
2934
}
35+
3036
let sym = cx.tcx.item_name(func.def_id());
3137
let name = sym.as_str();
32-
let intrinsics = cx.intrinsics_map.borrow();
33-
let is_known_intrinsic = intrinsics.contains_key(format!("__nv_{}", name).as_str());
3438

35-
!is_unsupported_libdevice_fn(name) && is_known_intrinsic
39+
if is_unsupported_libdevice_fn(name) {
40+
return false;
41+
}
42+
43+
let libdevice_name = format!("__nv_{}", name);
44+
let ld_fn = if let Some((args, ret)) = cx.intrinsics_map.borrow().get(libdevice_name.as_str()) {
45+
cx.type_func(args, ret)
46+
} else {
47+
return false;
48+
};
49+
50+
// Check the function signatures match.
51+
let lm_fn = cx.fn_abi_of_instance(func, ty::List::empty()).llvm_type(cx);
52+
lm_fn == ld_fn
3653
}
3754

3855
fn is_unsupported_libdevice_fn(name: &str) -> bool {

0 commit comments

Comments
 (0)