|
17 | 17 | #include "clang/CIR/Dialect/IR/CIRTypes.h"
|
18 | 18 | #include "clang/CIR/Interfaces/CIRLoopOpInterface.h"
|
19 | 19 | #include "clang/CIR/MissingFeatures.h"
|
| 20 | +#include "llvm/ADT/SetOperations.h" |
| 21 | +#include "llvm/ADT/SmallSet.h" |
20 | 22 | #include "llvm/ADT/StringExtras.h"
|
21 | 23 | #include "llvm/ADT/TypeSwitch.h"
|
22 | 24 | #include "llvm/Support/ErrorHandling.h"
|
23 | 25 | #include "llvm/Support/LogicalResult.h"
|
24 | 26 | #include <numeric>
|
25 | 27 | #include <optional>
|
26 |
| -#include <set> |
27 | 28 |
|
28 | 29 | #include "mlir/Dialect/Func/IR/FuncOps.h"
|
29 | 30 | #include "mlir/Dialect/LLVMIR/LLVMTypes.h"
|
@@ -2928,23 +2929,46 @@ LogicalResult cir::FuncOp::verify() {
|
2928 | 2929 | << "' must have empty body";
|
2929 | 2930 | }
|
2930 | 2931 |
|
2931 |
| - std::set<llvm::StringRef> labels; |
2932 |
| - std::set<llvm::StringRef> gotos; |
2933 |
| - |
| 2932 | + llvm::SmallSet<llvm::StringRef, 16> labels; |
| 2933 | + llvm::SmallSet<llvm::StringRef, 16> gotos; |
| 2934 | + llvm::SmallSet<llvm::StringRef, 16> blockAddresses; |
| 2935 | + bool invalidBlockAddress = false; |
2934 | 2936 | getOperation()->walk([&](mlir::Operation *op) {
|
2935 | 2937 | if (auto lab = dyn_cast<cir::LabelOp>(op)) {
|
2936 |
| - labels.emplace(lab.getLabel()); |
| 2938 | + labels.insert(lab.getLabel()); |
2937 | 2939 | } else if (auto goTo = dyn_cast<cir::GotoOp>(op)) {
|
2938 |
| - gotos.emplace(goTo.getLabel()); |
| 2940 | + gotos.insert(goTo.getLabel()); |
| 2941 | + } else if (auto blkAdd = dyn_cast<cir::BlockAddressOp>(op)) { |
| 2942 | + if (blkAdd.getFunc() != getSymName()) { |
| 2943 | + // Stop the walk early, no need to continue |
| 2944 | + invalidBlockAddress = true; |
| 2945 | + return mlir::WalkResult::interrupt(); |
| 2946 | + } |
| 2947 | + blockAddresses.insert(blkAdd.getLabel()); |
2939 | 2948 | }
|
| 2949 | + return mlir::WalkResult::advance(); |
2940 | 2950 | });
|
2941 | 2951 |
|
2942 |
| - std::vector<llvm::StringRef> mismatched; |
2943 |
| - std::set_difference(gotos.begin(), gotos.end(), labels.begin(), labels.end(), |
2944 |
| - std::back_inserter(mismatched)); |
| 2952 | + if (invalidBlockAddress) |
| 2953 | + return emitOpError() << "blockaddress references a different function"; |
| 2954 | + |
| 2955 | + llvm::SmallSet<llvm::StringRef, 16> mismatched; |
| 2956 | + if (!labels.empty() || !gotos.empty()) { |
| 2957 | + mismatched = llvm::set_difference(gotos, labels); |
| 2958 | + |
| 2959 | + if (!mismatched.empty()) |
| 2960 | + return emitOpError() << "goto/label mismatch"; |
| 2961 | + } |
2945 | 2962 |
|
2946 |
| - if (!mismatched.empty()) |
2947 |
| - return emitOpError() << "goto/label mismatch"; |
| 2963 | + mismatched.clear(); |
| 2964 | + |
| 2965 | + if (!labels.empty() || !blockAddresses.empty()) { |
| 2966 | + mismatched = llvm::set_difference(blockAddresses, labels); |
| 2967 | + |
| 2968 | + if (!mismatched.empty()) |
| 2969 | + return emitOpError() |
| 2970 | + << "expects an existing label target in the referenced function"; |
| 2971 | + } |
2948 | 2972 |
|
2949 | 2973 | return success();
|
2950 | 2974 | }
|
|
0 commit comments