diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -1523,8 +1523,23 @@ //===----------------------------------------------------------------------===// LogicalResult ResumeOp::verify() { - if (!getValue().getDefiningOp()) - return emitOpError("expects landingpad value as operand"); + auto parentFunc = getOperation()->getParentOfType(); + if (!parentFunc) { + return emitOpError( + "expects parent operation implementing FunctionOpInterface"); + } + // All landingpad ops should have the same type, so we can simply use the + // first one. + Type landingpadTy; + parentFunc.walk([&landingpadTy](LandingpadOp landingpadOp) { + landingpadTy = landingpadOp.getType(); + return WalkResult::interrupt(); + }); + if (!landingpadTy || landingpadTy != getOperand().getType()) { + return emitOpError("expects landingpad operation in the same function and " + "with the same type as this operation's operand"); + } + // No check for personality of function - landingpad op verifies it. return success(); } diff --git a/mlir/test/Dialect/LLVMIR/invalid-typed-pointers.mlir b/mlir/test/Dialect/LLVMIR/invalid-typed-pointers.mlir --- a/mlir/test/Dialect/LLVMIR/invalid-typed-pointers.mlir +++ b/mlir/test/Dialect/LLVMIR/invalid-typed-pointers.mlir @@ -145,7 +145,7 @@ llvm.return %0 : i32 ^bb2: // pred: ^bb0 %2 = llvm.landingpad cleanup : !llvm.struct<(ptr, i32)> - // expected-error@+1 {{'llvm.resume' op expects landingpad value as operand}} + // expected-error@+1 {{'llvm.resume' op expects landingpad operation in the same function and with the same type as this operation's operand}} llvm.resume %0 : i32 } diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir --- a/mlir/test/Dialect/LLVMIR/invalid.mlir +++ b/mlir/test/Dialect/LLVMIR/invalid.mlir @@ -798,7 +798,18 @@ llvm.return %0 : i32 ^bb2: // pred: ^bb0 %2 = llvm.landingpad cleanup : !llvm.struct<(ptr, i32)> - // expected-error@+1 {{'llvm.resume' op expects landingpad value as operand}} + // expected-error@+1 {{'llvm.resume' op expects landingpad operation in the same function and with the same type as this operation's operand}} + llvm.resume %0 : i32 +} + +// ----- + +llvm.func @foo(i32) -> i32 +llvm.func @__gxx_personality_v0(...) -> i32 + +llvm.func @caller(%arg0: i32) -> i32 attributes { personality = @__gxx_personality_v0 } { + %0 = llvm.mlir.constant(1 : i32) : i32 + // expected-error@+1 {{'llvm.resume' op expects landingpad operation in the same function and with the same type as this operation's operand}} llvm.resume %0 : i32 } diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir --- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir +++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir @@ -427,6 +427,27 @@ llvm.return %0 : i32 } +llvm.func @foo2() -> !llvm.struct<(ptr, i32)> + +// CHECK-LABEL: llvm.func @resumeNoLandingpadValue( +// CHECK-SAME: %[[ARG:.*]]: i32) +llvm.func @resumeNoLandingpadValue(%arg0: i32) -> i32 attributes { personality = @__gxx_personality_v0 } { +// CHECK: %[[VAL_0:.*]] = llvm.call @foo2() : () -> !llvm.struct<(ptr, i32)> +// CHECK: %[[VAL_1:.*]] = llvm.invoke @foo(%[[ARG]]) to ^[[BB1:.*]] unwind ^[[BB2:.*]] : (i32) -> i32 + %0 = llvm.call @foo2() : () -> !llvm.struct<(ptr, i32)> + %1 = llvm.invoke @foo(%arg0) to ^bb1 unwind ^bb2 : (i32) -> i32 +// CHECK: ^[[BB1]]: +// CHECK: llvm.return %[[VAL_1]] : i32 +^bb1: // pred: ^bb0 + llvm.return %1 : i32 +// CHECK: ^[[BB2]]: +// CHECK: %[[VAL_2:.*]] = llvm.landingpad cleanup : !llvm.struct<(ptr, i32)> +// CHECK: llvm.resume %[[VAL_0]] : !llvm.struct<(ptr, i32)> +^bb2: // pred: ^bb0 + %2 = llvm.landingpad cleanup : !llvm.struct<(ptr, i32)> + llvm.resume %0 : !llvm.struct<(ptr, i32)> +} + // CHECK-LABEL: @useFreezeOp func.func @useFreezeOp(%arg0: i32) { // CHECK: = llvm.freeze %[[ARG0:.*]] : i32