* Don't call raw_string_ostream::flush(), which is essentially a no-op * Strip unneeded calls to raw_string_ostream::str(), to avoid excess indirection.
125 lines
4.5 KiB
C++
125 lines
4.5 KiB
C++
//===- mlir-src-sharder.cpp - A tool for sharder generated source files ---===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "mlir/Support/FileUtilities.h"
|
|
#include "mlir/Support/LLVM.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/InitLLVM.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include "llvm/Support/ToolOutputFile.h"
|
|
|
|
using namespace mlir;
|
|
|
|
/// Create a dependency file for `-d` option.
|
|
///
|
|
/// This functionality is generally only for the benefit of the build system,
|
|
/// and is modeled after the same option in TableGen.
|
|
static LogicalResult createDependencyFile(StringRef outputFilename,
|
|
StringRef dependencyFile) {
|
|
if (outputFilename == "-") {
|
|
llvm::errs() << "error: the option -d must be used together with -o\n";
|
|
return failure();
|
|
}
|
|
|
|
std::string errorMessage;
|
|
std::unique_ptr<llvm::ToolOutputFile> outputFile =
|
|
openOutputFile(dependencyFile, &errorMessage);
|
|
if (!outputFile) {
|
|
llvm::errs() << errorMessage << "\n";
|
|
return failure();
|
|
}
|
|
|
|
outputFile->os() << outputFilename << ":\n";
|
|
outputFile->keep();
|
|
return success();
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
// FIXME: This is necessary because we link in TableGen, which defines its
|
|
// options as static variables.. some of which overlap with our options.
|
|
llvm::cl::ResetCommandLineParser();
|
|
|
|
llvm::cl::opt<unsigned> opShardIndex(
|
|
"op-shard-index", llvm::cl::desc("The current shard index"));
|
|
llvm::cl::opt<std::string> inputFilename(llvm::cl::Positional,
|
|
llvm::cl::desc("<input file>"),
|
|
llvm::cl::init("-"));
|
|
llvm::cl::opt<std::string> outputFilename(
|
|
"o", llvm::cl::desc("Output filename"), llvm::cl::value_desc("filename"),
|
|
llvm::cl::init("-"));
|
|
llvm::cl::list<std::string> includeDirs(
|
|
"I", llvm::cl::desc("Directory of include files"),
|
|
llvm::cl::value_desc("directory"), llvm::cl::Prefix);
|
|
llvm::cl::opt<std::string> dependencyFilename(
|
|
"d", llvm::cl::desc("Dependency filename"),
|
|
llvm::cl::value_desc("filename"), llvm::cl::init(""));
|
|
llvm::cl::opt<bool> writeIfChanged(
|
|
"write-if-changed",
|
|
llvm::cl::desc("Only write to the output file if it changed"));
|
|
|
|
// `ResetCommandLineParser` at the above unregistered the "D" option
|
|
// of `llvm-tblgen`, which caused `TestOps.cpp` to fail due to
|
|
// "Unknnown command line argument '-D...`" when a macros name is
|
|
// present. The following is a workaround to re-register it again.
|
|
llvm::cl::list<std::string> macroNames(
|
|
"D",
|
|
llvm::cl::desc(
|
|
"Name of the macro to be defined -- ignored by mlir-src-sharder"),
|
|
llvm::cl::value_desc("macro name"), llvm::cl::Prefix);
|
|
|
|
llvm::InitLLVM y(argc, argv);
|
|
llvm::cl::ParseCommandLineOptions(argc, argv);
|
|
|
|
// Open the input file.
|
|
std::string errorMessage;
|
|
std::unique_ptr<llvm::MemoryBuffer> inputFile =
|
|
openInputFile(inputFilename, &errorMessage);
|
|
if (!inputFile) {
|
|
llvm::errs() << errorMessage << "\n";
|
|
return 1;
|
|
}
|
|
|
|
// Write the output to a buffer.
|
|
std::string outputStr;
|
|
llvm::raw_string_ostream os(outputStr);
|
|
os << "#define GET_OP_DEFS_" << opShardIndex << "\n"
|
|
<< inputFile->getBuffer();
|
|
|
|
// Determine whether we need to write the output file.
|
|
bool shouldWriteOutput = true;
|
|
if (writeIfChanged) {
|
|
// Only update the real output file if there are any differences. This
|
|
// prevents recompilation of all the files depending on it if there aren't
|
|
// any.
|
|
if (auto existingOrErr =
|
|
llvm::MemoryBuffer::getFile(outputFilename, /*IsText=*/true))
|
|
if (std::move(existingOrErr.get())->getBuffer() == outputStr)
|
|
shouldWriteOutput = false;
|
|
}
|
|
|
|
// Populate the output file if necessary.
|
|
if (shouldWriteOutput) {
|
|
std::unique_ptr<llvm::ToolOutputFile> outputFile =
|
|
openOutputFile(outputFilename, &errorMessage);
|
|
if (!outputFile) {
|
|
llvm::errs() << errorMessage << "\n";
|
|
return 1;
|
|
}
|
|
outputFile->os() << os.str();
|
|
outputFile->keep();
|
|
}
|
|
|
|
// Always write the depfile, even if the main output hasn't changed. If it's
|
|
// missing, Ninja considers the output dirty.
|
|
if (!dependencyFilename.empty())
|
|
if (failed(createDependencyFile(outputFilename, dependencyFilename)))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|