Skip to content

Commit 9bf6cf9

Browse files
committed
Check for AutoUpgraded intrinsics, and emit a hard error for unknown intrinsics
1 parent 9bf2867 commit 9bf6cf9

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

compiler/rustc_codegen_llvm/src/declare.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,27 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
177177
fn_abi.apply_attrs_llfn(self, llfn, instance);
178178
}
179179

180-
// todo: check for upgrades, and emit error if not upgradable
180+
if let FunctionSignature::MaybeInvalidIntrinsic(..) = signature {
181+
let mut new_llfn = None;
182+
let can_upgrade =
183+
unsafe { llvm::LLVMRustUpgradeIntrinsicFunction(llfn, &mut new_llfn, false) };
184+
185+
if can_upgrade {
186+
// not all intrinsics are upgraded to some other intrinsics, most are upgraded to instruction sequences
187+
if let Some(new_llfn) = new_llfn {
188+
self.tcx.dcx().note(format!(
189+
"Using deprecated intrinsic `{name}`, `{}` can be used instead",
190+
str::from_utf8(llvm::get_value_name(new_llfn)).unwrap()
191+
));
192+
} else if self.tcx.sess.opts.verbose {
193+
self.tcx.dcx().note(format!(
194+
"Using deprecated intrinsic `{name}`, consider using other intrinsics/instructions"
195+
));
196+
}
197+
} else {
198+
self.tcx.dcx().fatal(format!("Invalid LLVM intrinsic: `{name}`"))
199+
}
200+
}
181201

182202
if self.tcx.sess.is_sanitizer_cfi_enabled() {
183203
if let Some(instance) = instance {

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,8 @@ unsafe extern "C" {
11951195

11961196
// Operations on functions
11971197
pub(crate) fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint);
1198+
1199+
// Operations about llvm intrinsics
11981200
pub(crate) fn LLVMLookupIntrinsicID(Name: *const c_char, NameLen: size_t) -> c_uint;
11991201
pub(crate) fn LLVMIntrinsicGetType<'a>(
12001202
C: &'a Context,
@@ -1203,6 +1205,11 @@ unsafe extern "C" {
12031205
ParamCount: size_t,
12041206
) -> &'a Type;
12051207
pub(crate) fn LLVMIntrinsicIsOverloaded(ID: c_uint) -> Bool;
1208+
pub(crate) fn LLVMRustUpgradeIntrinsicFunction<'a>(
1209+
Fn: &'a Value,
1210+
NewFn: &mut Option<&'a Value>,
1211+
CanUpgradeDebugIntrinsicsToRecords: bool,
1212+
) -> bool;
12061213

12071214
// Operations on parameters
12081215
pub(crate) fn LLVMIsAArgument(Val: &Value) -> Option<&Value>;

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "llvm/ADT/StringRef.h"
1010
#include "llvm/BinaryFormat/Magic.h"
1111
#include "llvm/Bitcode/BitcodeWriter.h"
12+
#include "llvm/IR/AutoUpgrade.h"
1213
#include "llvm/IR/DIBuilder.h"
1314
#include "llvm/IR/DebugInfoMetadata.h"
1415
#include "llvm/IR/DiagnosticHandler.h"
@@ -1901,6 +1902,17 @@ extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
19011902
Mangler().getNameWithPrefix(OS, GV, true);
19021903
}
19031904

1905+
extern "C" bool
1906+
LLVMRustUpgradeIntrinsicFunction(LLVMValueRef Fn, LLVMValueRef *NewFn,
1907+
bool canUpgradeDebugIntrinsicsToRecords) {
1908+
Function *F = unwrap<Function>(Fn);
1909+
Function *NewF = nullptr;
1910+
bool CanUpgrade =
1911+
UpgradeIntrinsicFunction(F, NewF, canUpgradeDebugIntrinsicsToRecords);
1912+
*NewFn = wrap(NewF);
1913+
return CanUpgrade;
1914+
}
1915+
19041916
extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) {
19051917
auto *CB = unwrap<CallBase>(CallSite);
19061918
switch (CB->getIntrinsicID()) {

0 commit comments

Comments
 (0)