diff --git a/mlir/lib/Support/ToolUtilities.cpp b/mlir/lib/Support/ToolUtilities.cpp --- a/mlir/lib/Support/ToolUtilities.cpp +++ b/mlir/lib/Support/ToolUtilities.cpp @@ -14,6 +14,7 @@ #include "mlir/Support/LLVM.h" #include "mlir/Support/LogicalResult.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" using namespace mlir; @@ -21,16 +22,55 @@ mlir::splitAndProcessBuffer(std::unique_ptr originalBuffer, ChunkBufferHandler processChunkBuffer, raw_ostream &os) { - const char splitMarker[] = "// -----"; + const char splitMarkerConst[] = "// -----"; + StringRef splitMarker(splitMarkerConst); + const int splitMarkerLen = splitMarker.size(); auto *origMemBuffer = originalBuffer.get(); - SmallVector sourceBuffers; - origMemBuffer->getBuffer().split(sourceBuffers, splitMarker); + SmallVector rawSourceBuffers; + const int checkLen = 2; + // Split dropping the last checkLen chars to enable flagging near misses. + origMemBuffer->getBuffer().split(rawSourceBuffers, + splitMarker.drop_back(checkLen)); + if (rawSourceBuffers.empty()) + return success(); // Add the original buffer to the source manager. llvm::SourceMgr fileSourceMgr; fileSourceMgr.AddNewSourceBuffer(std::move(originalBuffer), llvm::SMLoc()); + // Flag near misses by iterating over all the sub-buffers found when splitting + // with the prefix of the splitMarker. Use a sliding window where we only + // add a buffer as a sourceBuffer if terminated by a full match of the + // splitMarker (followed by newline), else flag a warning and extend the + // size of the buffer under consideration assuming there is no near miss. + SmallVector sourceBuffers; + StringRef prev; + for (auto buffer : rawSourceBuffers) { + if (prev.empty()) { + prev = buffer; + continue; + } + + // Check that suffix is as expected and doesn't have any dash post. + bool expectedSuffix = buffer.startswith(splitMarker.take_back(checkLen)) && + buffer.size() > checkLen && buffer[checkLen] != '0'; + if (expectedSuffix) { + sourceBuffers.push_back(prev); + prev = buffer.drop_front(checkLen); + } else { + // TODO: Consider making this a failure. + auto splitLoc = llvm::SMLoc::getFromPointer(buffer.data()); + fileSourceMgr.PrintMessage(llvm::errs(), splitLoc, + llvm::SourceMgr::DK_Warning, + "near miss with file split marker"); + prev = StringRef(prev.data(), + prev.size() + splitMarkerLen - checkLen + buffer.size()); + } + } + if (!prev.empty()) + sourceBuffers.push_back(prev); + // Process each chunk in turn. bool hadFailure = false; for (auto &subBuffer : sourceBuffers) { diff --git a/mlir/test/Conversion/ShapeToStandard/shape-to-standard.mlir b/mlir/test/Conversion/ShapeToStandard/shape-to-standard.mlir --- a/mlir/test/Conversion/ShapeToStandard/shape-to-standard.mlir +++ b/mlir/test/Conversion/ShapeToStandard/shape-to-standard.mlir @@ -593,7 +593,7 @@ return } -// ---- +// ----- // CHECK-LABEL: @broadcast_to_known_rank func @broadcast_to_known_rank(%a : tensor<1xindex>, %b : tensor<3xindex>) diff --git a/mlir/test/Conversion/TosaToSCF/tosa-to-scf.mlir b/mlir/test/Conversion/TosaToSCF/tosa-to-scf.mlir --- a/mlir/test/Conversion/TosaToSCF/tosa-to-scf.mlir +++ b/mlir/test/Conversion/TosaToSCF/tosa-to-scf.mlir @@ -30,7 +30,7 @@ return %1 : tensor } -// ---- +// ----- // CHECK-LABEL: func @if_test // CHECK-SAME: ([[ARG0:%.+]]: tensor, [[ARG1:%.+]]: tensor, [[ARG2:%.+]]: tensor) diff --git a/mlir/test/Dialect/OpenACC/canonicalize.mlir b/mlir/test/Dialect/OpenACC/canonicalize.mlir --- a/mlir/test/Dialect/OpenACC/canonicalize.mlir +++ b/mlir/test/Dialect/OpenACC/canonicalize.mlir @@ -61,7 +61,7 @@ // CHECK: func @testupdateop // CHECK-NOT: acc.update -// ---- +// ----- func @testenterdataop(%a: memref<10xf32>, %ifCond: i1) -> () { acc.enter_data if(%ifCond) create(%a: memref<10xf32>) diff --git a/mlir/test/Dialect/SCF/canonicalize.mlir b/mlir/test/Dialect/SCF/canonicalize.mlir --- a/mlir/test/Dialect/SCF/canonicalize.mlir +++ b/mlir/test/Dialect/SCF/canonicalize.mlir @@ -250,7 +250,7 @@ // CHECK-NOT: scf.if // CHECK: return -// ---- +// ----- func @empty_else(%cond: i1, %v : memref) { scf.if %cond { diff --git a/mlir/test/Dialect/Shape/canonicalize.mlir b/mlir/test/Dialect/Shape/canonicalize.mlir --- a/mlir/test/Dialect/Shape/canonicalize.mlir +++ b/mlir/test/Dialect/Shape/canonicalize.mlir @@ -1319,7 +1319,7 @@ return %1 : tensor<3xindex> } -// ---- +// ----- // CHECK-LABEL: max_same_arg // CHECK-SAME: (%[[SHAPE:.*]]: !shape.shape) @@ -1329,7 +1329,7 @@ return %1 : !shape.shape } -// ---- +// ----- // CHECK-LABEL: min_same_arg // CHECK-SAME: (%[[SHAPE:.*]]: !shape.shape) @@ -1338,7 +1338,7 @@ // CHECK: return %[[SHAPE]] return %1 : !shape.shape } -// ---- +// ----- // CHECK-LABEL: @cstr_broadcastable_folding func @cstr_broadcastable_folding(%arg : tensor) { diff --git a/mlir/test/mlir-opt/nearmiss.mlir b/mlir/test/mlir-opt/nearmiss.mlir new file mode 100644 --- /dev/null +++ b/mlir/test/mlir-opt/nearmiss.mlir @@ -0,0 +1,21 @@ +// RUN: mlir-opt --split-input-file --verify-diagnostics %s 2> %t && FileCheck --input-file %t %s +// RUN: cat %t + +func @main() {return} + +// ----- + +// expected-note @+1 {{see existing symbol definition here}} +func @foo() { return } +// CHECK: warning: near miss with file split marker +// CHECK: ---- +// ---- + +// expected-error @+1 {{redefinition of symbol named 'foo'}} +func @foo() { return } +// CHECK: warning: near miss with file split marker +// CHECK: ---- +// ---- +func @bar2() {return } + +// ----