Skip to content

Commit 87a4215

Browse files
authored
[Clang] Always verify LLVM IR inputs (llvm#134396)
We get a lot of issues that basically boil down to "I passed malformed LLVM IR to clang and it crashed". Clang does not perform IR verification by default in (non-assertion-enabled) release builds, and that's sensible for IR that Clang itself produces, which is expected to always be valid. However, if people pass in their own handwritten IR, we should report if it is malformed, instead of crashing. We should also report it in a way that does not produce a crash trace and ask for a bug report, as currently happens in assertions-enabled builds. This aligns the behavior with how opt/llc work.
1 parent f280d60 commit 87a4215

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

clang/include/clang/Basic/DiagnosticFrontendKinds.td

+2
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,8 @@ def err_ast_action_on_llvm_ir : Error<
379379
"cannot apply AST actions to LLVM IR file '%0'">,
380380
DefaultFatal;
381381

382+
def err_invalid_llvm_ir : Error<"invalid LLVM IR input: %0">;
383+
382384
def err_os_unsupport_riscv_fmv : Error<
383385
"function multiversioning is currently only supported on Linux">;
384386

clang/lib/CodeGen/CodeGenAction.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "llvm/IR/LLVMContext.h"
4040
#include "llvm/IR/LLVMRemarkStreamer.h"
4141
#include "llvm/IR/Module.h"
42+
#include "llvm/IR/Verifier.h"
4243
#include "llvm/IRReader/IRReader.h"
4344
#include "llvm/LTO/LTOBackend.h"
4445
#include "llvm/Linker/Linker.h"
@@ -1048,8 +1049,17 @@ CodeGenAction::loadModule(MemoryBufferRef MBRef) {
10481049

10491050
// Handle textual IR and bitcode file with one single module.
10501051
llvm::SMDiagnostic Err;
1051-
if (std::unique_ptr<llvm::Module> M = parseIR(MBRef, Err, *VMContext))
1052+
if (std::unique_ptr<llvm::Module> M = parseIR(MBRef, Err, *VMContext)) {
1053+
// For LLVM IR files, always verify the input and report the error in a way
1054+
// that does not ask people to report an issue for it.
1055+
std::string VerifierErr;
1056+
raw_string_ostream VerifierErrStream(VerifierErr);
1057+
if (llvm::verifyModule(*M, &VerifierErrStream)) {
1058+
CI.getDiagnostics().Report(diag::err_invalid_llvm_ir) << VerifierErr;
1059+
return {};
1060+
}
10521061
return M;
1062+
}
10531063

10541064
// If MBRef is a bitcode with multiple modules (e.g., -fsplit-lto-unit
10551065
// output), place the extra modules (actually only one, a regular LTO module)

clang/test/CodeGen/invalid_llvm_ir.ll

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
; RUN: not %clang %s 2>&1 | FileCheck %s
2+
; RUN: llvm-as -disable-verify < %s > %t.bc
3+
; RUN: not %clang %t.bc 2>&1 | FileCheck %s
4+
5+
; CHECK: error: invalid LLVM IR input: PHINode should have one entry for each predecessor of its parent basic block!
6+
; CHECK-NEXT: %phi = phi i32 [ 0, %entry ]
7+
8+
define void @test() {
9+
entry:
10+
%phi = phi i32 [ 0, %entry ]
11+
ret void
12+
}

0 commit comments

Comments
 (0)