Skip to content

Commit f6a261a

Browse files
committed
[MLIR][LLVM] Avoid importing broken calls and invokes
This commit adds a check to catch calls/invokes that do not satisfy the return type of their callee. This is not verified in LLVM IR but is considered UB. Importing this into MLIR will lead to verification errors, thus we should avoid this early on.
1 parent 928cad4 commit f6a261a

File tree

2 files changed

+58
-16
lines changed

2 files changed

+58
-16
lines changed

mlir/lib/Target/LLVMIR/ModuleImport.cpp

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,7 +1620,7 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
16201620
return success();
16211621
}
16221622
if (inst->getOpcode() == llvm::Instruction::Call) {
1623-
auto callInst = cast<llvm::CallInst>(inst);
1623+
auto *callInst = cast<llvm::CallInst>(inst);
16241624
llvm::Value *calledOperand = callInst->getCalledOperand();
16251625

16261626
FailureOr<SmallVector<Value>> operands =
@@ -1629,10 +1629,10 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
16291629
return failure();
16301630

16311631
auto callOp = [&]() -> FailureOr<Operation *> {
1632-
if (auto asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
1633-
Type resultTy = convertType(callInst->getType());
1634-
if (!resultTy)
1635-
return failure();
1632+
Type resultTy = convertType(callInst->getType());
1633+
if (!resultTy)
1634+
return failure();
1635+
if (auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
16361636
return builder
16371637
.create<InlineAsmOp>(
16381638
loc, resultTy, *operands,
@@ -1642,17 +1642,21 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
16421642
/*is_align_stack=*/false, /*asm_dialect=*/nullptr,
16431643
/*operand_attrs=*/nullptr)
16441644
.getOperation();
1645-
} else {
1646-
LLVMFunctionType funcTy = convertFunctionType(callInst);
1647-
if (!funcTy)
1648-
return failure();
1649-
1650-
FlatSymbolRefAttr callee = convertCalleeName(callInst);
1651-
auto callOp = builder.create<CallOp>(loc, funcTy, callee, *operands);
1652-
if (failed(convertCallAttributes(callInst, callOp)))
1653-
return failure();
1654-
return callOp.getOperation();
16551645
}
1646+
LLVMFunctionType funcTy = convertFunctionType(callInst);
1647+
if (!funcTy)
1648+
return failure();
1649+
1650+
if (funcTy.getReturnType() != resultTy)
1651+
return emitError(loc)
1652+
<< "incompatible call and function return types: " << resultTy
1653+
<< " vs. " << funcTy.getReturnType();
1654+
1655+
FlatSymbolRefAttr callee = convertCalleeName(callInst);
1656+
auto callOp = builder.create<CallOp>(loc, funcTy, callee, *operands);
1657+
if (failed(convertCallAttributes(callInst, callOp)))
1658+
return failure();
1659+
return callOp.getOperation();
16561660
}();
16571661

16581662
if (failed(callOp))
@@ -1720,6 +1724,14 @@ LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
17201724
if (!funcTy)
17211725
return failure();
17221726

1727+
Type resultTy = convertType(invokeInst->getType());
1728+
if (!resultTy)
1729+
return failure();
1730+
if (funcTy.getReturnType() != resultTy)
1731+
return emitError(loc)
1732+
<< "incompatible invoke and function return types: " << resultTy
1733+
<< " vs. " << funcTy.getReturnType();
1734+
17231735
FlatSymbolRefAttr calleeName = convertCalleeName(invokeInst);
17241736

17251737
// Create the invoke operation. Normal destination block arguments will be

mlir/test/Target/LLVMIR/Import/import-failure.ll

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: not mlir-translate -import-llvm -emit-expensive-warnings -split-input-file %s 2>&1 | FileCheck %s
1+
; RUN: not mlir-translate -import-llvm -emit-expensive-warnings -split-input-file %s 2>&1 -o /dev/null | FileCheck %s
22

33
; CHECK: <unknown>
44
; CHECK-SAME: error: unhandled instruction: indirectbr ptr %dst, [label %bb1, label %bb2]
@@ -353,3 +353,33 @@ declare void @llvm.experimental.noalias.scope.decl(metadata)
353353
; CHECK: import-failure.ll
354354
; CHECK-SAME: warning: unhandled data layout token: ni:42
355355
target datalayout = "e-ni:42-i64:64"
356+
357+
; // -----
358+
359+
; CHECK: <unknown>
360+
; CHECK-SAME: incompatible call and function return types: 'i64' vs. '!llvm.ptr'
361+
define i64 @incompatible_call_and_callee_types() {
362+
L.entry:
363+
%0 = call i64 @callee()
364+
ret i64 %0
365+
}
366+
367+
declare ptr @callee()
368+
369+
; // -----
370+
371+
; CHECK: <unknown>
372+
; CHECK-SAME: incompatible invoke and function return types: '!llvm.void' vs. 'i32'
373+
define void @f() personality ptr @__gxx_personality_v0 {
374+
entry:
375+
invoke void @g() to label %bb1 unwind label %bb2
376+
bb1:
377+
ret void
378+
bb2:
379+
%0 = landingpad i32 cleanup
380+
unreachable
381+
}
382+
383+
declare i32 @g()
384+
385+
declare i32 @__gxx_personality_v0(...)

0 commit comments

Comments
 (0)