github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/third_party/mlir/lib/Support/MlirOptMain.cpp (about) 1 //===- MlirOptMain.cpp - MLIR Optimizer Driver ----------------------------===// 2 // 3 // Copyright 2019 The MLIR Authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // ============================================================================= 17 // 18 // This is a utility that runs an optimization pass and prints the result back 19 // out. It is designed to support unit testing. 20 // 21 //===----------------------------------------------------------------------===// 22 23 #include "mlir/Support/MlirOptMain.h" 24 #include "mlir/Analysis/Passes.h" 25 #include "mlir/IR/Attributes.h" 26 #include "mlir/IR/Diagnostics.h" 27 #include "mlir/IR/Location.h" 28 #include "mlir/IR/MLIRContext.h" 29 #include "mlir/IR/Module.h" 30 #include "mlir/Parser.h" 31 #include "mlir/Pass/Pass.h" 32 #include "mlir/Pass/PassManager.h" 33 #include "mlir/Transforms/Passes.h" 34 #include "llvm/Support/FileUtilities.h" 35 #include "llvm/Support/Regex.h" 36 #include "llvm/Support/SourceMgr.h" 37 38 using namespace mlir; 39 using namespace llvm; 40 using llvm::SMLoc; 41 42 /// Perform the actions on the input file indicated by the command line flags 43 /// within the specified context. 44 /// 45 /// This typically parses the main source file, runs zero or more optimization 46 /// passes, then prints the output. 47 /// 48 static LogicalResult 49 performActions(raw_ostream &os, bool verifyDiagnostics, bool verifyPasses, 50 SourceMgr &sourceMgr, MLIRContext *context, 51 const std::vector<const mlir::PassRegistryEntry *> &passList) { 52 OwningModuleRef module(parseSourceFile(sourceMgr, context)); 53 if (!module) 54 return failure(); 55 56 // Apply any pass manager command line options. 57 PassManager pm(verifyPasses); 58 applyPassManagerCLOptions(pm); 59 60 // Run each of the passes that were selected. 61 for (const auto *passEntry : passList) 62 passEntry->addToPipeline(pm); 63 64 // Run the pipeline. 65 if (failed(pm.run(*module))) 66 return failure(); 67 68 // Print the output. 69 module->print(os); 70 return success(); 71 } 72 73 /// Parses the memory buffer. If successfully, run a series of passes against 74 /// it and print the result. 75 static LogicalResult 76 processBuffer(raw_ostream &os, std::unique_ptr<MemoryBuffer> ownedBuffer, 77 bool verifyDiagnostics, bool verifyPasses, 78 const std::vector<const mlir::PassRegistryEntry *> &passList) { 79 // Tell sourceMgr about this buffer, which is what the parser will pick up. 80 SourceMgr sourceMgr; 81 sourceMgr.AddNewSourceBuffer(std::move(ownedBuffer), SMLoc()); 82 83 // Parse the input file. 84 MLIRContext context; 85 86 // If we are in verify diagnostics mode then we have a lot of work to do, 87 // otherwise just perform the actions without worrying about it. 88 if (!verifyDiagnostics) { 89 SourceMgrDiagnosticHandler sourceMgrHandler(sourceMgr, &context); 90 return performActions(os, verifyDiagnostics, verifyPasses, sourceMgr, 91 &context, passList); 92 } 93 94 SourceMgrDiagnosticVerifierHandler sourceMgrHandler(sourceMgr, &context); 95 96 // Do any processing requested by command line flags. We don't care whether 97 // these actions succeed or fail, we only care what diagnostics they produce 98 // and whether they match our expectations. 99 performActions(os, verifyDiagnostics, verifyPasses, sourceMgr, &context, 100 passList); 101 102 // Verify the diagnostic handler to make sure that each of the diagnostics 103 // matched. 104 return sourceMgrHandler.verify(); 105 } 106 107 /// Split the specified file on a marker and process each chunk independently 108 /// according to the normal processBuffer logic. This is primarily used to 109 /// allow a large number of small independent parser tests to be put into a 110 /// single test, but could be used for other purposes as well. 111 static LogicalResult splitAndProcessFile( 112 raw_ostream &os, std::unique_ptr<MemoryBuffer> originalBuffer, 113 bool verifyDiagnostics, bool verifyPasses, 114 const std::vector<const mlir::PassRegistryEntry *> &passList) { 115 const char marker[] = "// -----"; 116 auto *origMemBuffer = originalBuffer.get(); 117 SmallVector<StringRef, 8> sourceBuffers; 118 origMemBuffer->getBuffer().split(sourceBuffers, marker); 119 120 // Add the original buffer to the source manager. 121 SourceMgr fileSourceMgr; 122 fileSourceMgr.AddNewSourceBuffer(std::move(originalBuffer), SMLoc()); 123 124 bool hadUnexpectedResult = false; 125 126 // Process each chunk in turn. If any fails, then return a failure of the 127 // tool. 128 for (auto &subBuffer : sourceBuffers) { 129 auto splitLoc = SMLoc::getFromPointer(subBuffer.data()); 130 unsigned splitLine = fileSourceMgr.getLineAndColumn(splitLoc).first; 131 auto subMemBuffer = MemoryBuffer::getMemBufferCopy( 132 subBuffer, origMemBuffer->getBufferIdentifier() + 133 Twine(" split at line #") + Twine(splitLine)); 134 if (failed(processBuffer(os, std::move(subMemBuffer), verifyDiagnostics, 135 verifyPasses, passList))) 136 hadUnexpectedResult = true; 137 } 138 139 return failure(hadUnexpectedResult); 140 } 141 142 LogicalResult 143 mlir::MlirOptMain(raw_ostream &os, std::unique_ptr<MemoryBuffer> buffer, 144 const std::vector<const mlir::PassRegistryEntry *> &passList, 145 bool splitInputFile, bool verifyDiagnostics, 146 bool verifyPasses) { 147 // The split-input-file mode is a very specific mode that slices the file 148 // up into small pieces and checks each independently. 149 if (splitInputFile) 150 return splitAndProcessFile(os, std::move(buffer), verifyDiagnostics, 151 verifyPasses, passList); 152 153 return processBuffer(os, std::move(buffer), verifyDiagnostics, verifyPasses, 154 passList); 155 }