Skip to content

Commit 478bd07

Browse files
committed
[mlir][llvm] Verify consistency of llvm.resume and llvm.landingpad types
Following the steps of the LLVM verifier (https://github.com/llvm/llvm-project/blob/b2c48559c882fd558f91e471c4d23ea7b0c6e718/llvm/lib/IR/Verifier.cpp#L4195), checks in llvm.func verifier are added to ensure consistency of llvm.landingpad operations' result types and llvm.resume operations' input types. As in LLVM, we will allow llvm.resume operations with input values defined by operations other than llvm.landingpad. Signed-off-by: Victor Perez <[email protected]> Reviewed By: gysit, Dinistro Differential Revision: https://reviews.llvm.org/D146968
1 parent 09c6c7b commit 478bd07

File tree

3 files changed

+102
-15
lines changed

3 files changed

+102
-15
lines changed

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,9 @@ LogicalResult LandingpadOp::verify() {
12631263
"llvm.landingpad needs to be in a function with a personality");
12641264
}
12651265

1266+
// Consistency of llvm.landingpad result types is checked in
1267+
// LLVMFuncOp::verify().
1268+
12661269
if (!getCleanup() && getOperands().empty())
12671270
return emitError("landingpad instruction expects at least one clause or "
12681271
"cleanup attribute");
@@ -1523,8 +1526,8 @@ LogicalResult ReturnOp::verify() {
15231526
//===----------------------------------------------------------------------===//
15241527

15251528
LogicalResult ResumeOp::verify() {
1526-
if (!getValue().getDefiningOp<LandingpadOp>())
1527-
return emitOpError("expects landingpad value as operand");
1529+
// Consistency of llvm.resume value types is checked in LLVMFuncOp::verify().
1530+
15281531
// No check for personality of function - landingpad op verifies it.
15291532
return success();
15301533
}
@@ -2171,6 +2174,42 @@ LogicalResult LLVMFuncOp::verify() {
21712174
return success();
21722175
}
21732176

2177+
Type landingpadResultTy;
2178+
StringRef diagnosticMessage;
2179+
bool isLandingpadTypeConsistent =
2180+
!walk([&](Operation *op) {
2181+
const auto checkType = [&](Type type, StringRef errorMessage) {
2182+
if (!landingpadResultTy) {
2183+
landingpadResultTy = type;
2184+
return WalkResult::advance();
2185+
}
2186+
if (landingpadResultTy != type) {
2187+
diagnosticMessage = errorMessage;
2188+
return WalkResult::interrupt();
2189+
}
2190+
return WalkResult::advance();
2191+
};
2192+
return TypeSwitch<Operation *, WalkResult>(op)
2193+
.Case<LandingpadOp>([&](auto landingpad) {
2194+
constexpr StringLiteral errorMessage =
2195+
"'llvm.landingpad' should have a consistent result type "
2196+
"inside a function";
2197+
return checkType(landingpad.getType(), errorMessage);
2198+
})
2199+
.Case<ResumeOp>([&](auto resume) {
2200+
constexpr StringLiteral errorMessage =
2201+
"'llvm.resume' should have a consistent input type inside a "
2202+
"function";
2203+
return checkType(resume.getValue().getType(), errorMessage);
2204+
})
2205+
.Default([](auto) { return WalkResult::skip(); });
2206+
}).wasInterrupted();
2207+
if (!isLandingpadTypeConsistent) {
2208+
assert(!diagnosticMessage.empty() &&
2209+
"Expecting a non-empty diagnostic message");
2210+
return emitError(diagnosticMessage);
2211+
}
2212+
21742213
return success();
21752214
}
21762215

mlir/test/Dialect/LLVMIR/invalid-typed-pointers.mlir

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,39 @@ llvm.func @caller(%arg0: i32) -> i32 attributes { personality = @__gxx_personali
138138
llvm.func @foo(i32) -> i32
139139
llvm.func @__gxx_personality_v0(...) -> i32
140140

141+
// expected-error@below {{'llvm.resume' should have a consistent input type inside a function}}
142+
llvm.func @caller(%arg0: i32, %arg1: !llvm.struct<(ptr<i32>, i32)>) -> i32 attributes { personality = @__gxx_personality_v0 } {
143+
%0 = llvm.invoke @foo(%arg0) to ^bb1 unwind ^bb2 : (i32) -> i32
144+
^bb1:
145+
%1 = llvm.invoke @foo(%0) to ^bb3 unwind ^bb4 : (i32) -> i32
146+
^bb2:
147+
%2 = llvm.landingpad cleanup : !llvm.struct<(ptr<i8>, i32)>
148+
llvm.resume %arg1 : !llvm.struct<(ptr<i32>, i32)>
149+
^bb3:
150+
llvm.return %1 : i32
151+
^bb4:
152+
%3 = llvm.landingpad cleanup : !llvm.struct<(ptr<i8>, i32)>
153+
llvm.resume %3 : !llvm.struct<(ptr<i8>, i32)>
154+
}
155+
156+
// -----
157+
158+
llvm.func @foo(i32) -> i32
159+
llvm.func @__gxx_personality_v0(...) -> i32
160+
161+
// expected-error@below {{'llvm.landingpad' should have a consistent result type inside a function}}
141162
llvm.func @caller(%arg0: i32) -> i32 attributes { personality = @__gxx_personality_v0 } {
142-
%0 = llvm.mlir.constant(1 : i32) : i32
143-
%1 = llvm.invoke @foo(%0) to ^bb1 unwind ^bb2 : (i32) -> i32
144-
^bb1: // pred: ^bb0
145-
llvm.return %0 : i32
146-
^bb2: // pred: ^bb0
163+
%0 = llvm.invoke @foo(%arg0) to ^bb1 unwind ^bb2 : (i32) -> i32
164+
^bb1:
165+
%1 = llvm.invoke @foo(%0) to ^bb3 unwind ^bb4 : (i32) -> i32
166+
^bb2:
147167
%2 = llvm.landingpad cleanup : !llvm.struct<(ptr<i8>, i32)>
148-
// expected-error@+1 {{'llvm.resume' op expects landingpad value as operand}}
149-
llvm.resume %0 : i32
168+
llvm.resume %2 : !llvm.struct<(ptr<i8>, i32)>
169+
^bb3:
170+
llvm.return %1 : i32
171+
^bb4:
172+
%3 = llvm.landingpad cleanup : !llvm.struct<(ptr<i32>, i32)>
173+
llvm.resume %3 : !llvm.struct<(ptr<i32>, i32)>
150174
}
151175

152176
// -----

mlir/test/Dialect/LLVMIR/invalid.mlir

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -791,15 +791,39 @@ llvm.func @caller(%arg0: i32) -> i32 attributes { personality = @__gxx_personali
791791
llvm.func @foo(i32) -> i32
792792
llvm.func @__gxx_personality_v0(...) -> i32
793793

794+
// expected-error@below {{'llvm.resume' should have a consistent input type inside a function}}
794795
llvm.func @caller(%arg0: i32) -> i32 attributes { personality = @__gxx_personality_v0 } {
795-
%0 = llvm.mlir.constant(1 : i32) : i32
796-
%1 = llvm.invoke @foo(%0) to ^bb1 unwind ^bb2 : (i32) -> i32
797-
^bb1: // pred: ^bb0
798-
llvm.return %0 : i32
799-
^bb2: // pred: ^bb0
796+
%0 = llvm.invoke @foo(%arg0) to ^bb1 unwind ^bb2 : (i32) -> i32
797+
^bb1:
798+
%1 = llvm.invoke @foo(%0) to ^bb3 unwind ^bb4 : (i32) -> i32
799+
^bb2:
800800
%2 = llvm.landingpad cleanup : !llvm.struct<(ptr, i32)>
801-
// expected-error@+1 {{'llvm.resume' op expects landingpad value as operand}}
802801
llvm.resume %0 : i32
802+
^bb3:
803+
llvm.return %1 : i32
804+
^bb4:
805+
%3 = llvm.landingpad cleanup : !llvm.struct<(ptr, i32)>
806+
llvm.resume %3 : !llvm.struct<(ptr, i32)>
807+
}
808+
809+
// -----
810+
811+
llvm.func @foo(i32) -> i32
812+
llvm.func @__gxx_personality_v0(...) -> i32
813+
814+
// expected-error@below {{'llvm.landingpad' should have a consistent result type inside a function}}
815+
llvm.func @caller(%arg0: i32) -> i32 attributes { personality = @__gxx_personality_v0 } {
816+
%0 = llvm.invoke @foo(%arg0) to ^bb1 unwind ^bb2 : (i32) -> i32
817+
^bb1:
818+
%1 = llvm.invoke @foo(%0) to ^bb3 unwind ^bb4 : (i32) -> i32
819+
^bb2:
820+
%2 = llvm.landingpad cleanup : !llvm.struct<(ptr, i32)>
821+
llvm.resume %2 : !llvm.struct<(ptr, i32)>
822+
^bb3:
823+
llvm.return %1 : i32
824+
^bb4:
825+
%3 = llvm.landingpad cleanup : i32
826+
llvm.resume %3 : i32
803827
}
804828

805829
// -----

0 commit comments

Comments
 (0)