diff --git a/src/support/file.cpp b/src/support/file.cpp index cfd656391be..d8663146fdf 100644 --- a/src/support/file.cpp +++ b/src/support/file.cpp @@ -47,7 +47,8 @@ template<> std::string do_read_stdin::operator()() { } template -T wasm::read_file(const std::string& filename, Flags::BinaryOption binary) { +T wasm::read_file(const fs::path& filename, + Flags::BinaryOption binary) { if (filename == "-") { return do_read_stdin{}(); } @@ -95,11 +96,13 @@ std::string wasm::read_possible_response_file(const std::string& input) { } // Explicit instantiations for the explicit specializations. -template std::string wasm::read_file<>(const std::string&, Flags::BinaryOption); -template std::vector wasm::read_file<>(const std::string&, +template std::string wasm::read_file<>(const fs::path&, + Flags::BinaryOption); +template std::vector wasm::read_file<>(const fs::path&, Flags::BinaryOption); -wasm::Output::Output(const std::string& filename, Flags::BinaryOption binary) +wasm::Output::Output(const fs::path& filename, + Flags::BinaryOption binary) : outfile(), out([this, filename, binary]() { // Ensure a single return at the very end, to avoid clang-tidy warnings // about the types of different returns here. @@ -121,13 +124,8 @@ wasm::Output::Output(const std::string& filename, Flags::BinaryOption binary) return buffer; }()) {} -void wasm::copy_file(std::string input, std::string output) { - std::ifstream src(input, std::ios::binary); - std::ofstream dst(output, std::ios::binary); - dst << src.rdbuf(); -} - -size_t wasm::file_size(std::string filename) { - std::ifstream infile(filename, std::ifstream::ate | std::ifstream::binary); - return infile.tellg(); +void wasm::copy_file(fs::path input, + fs::path output) { + fs::copy_file( + input, output, fs::copy_options::overwrite_existing); } diff --git a/src/support/file.h b/src/support/file.h index ae91831c98f..254da502156 100644 --- a/src/support/file.h +++ b/src/support/file.h @@ -21,11 +21,14 @@ #ifndef wasm_support_file_h #define wasm_support_file_h +#include #include #include #include #include +namespace fs = std::experimental::filesystem; + namespace wasm { namespace Flags { @@ -35,12 +38,12 @@ enum BinaryOption { Binary, Text }; std::vector read_stdin(); template -T read_file(const std::string& filename, Flags::BinaryOption binary); +T read_file(const fs::path& filename, Flags::BinaryOption binary); // Declare the valid explicit specializations. -extern template std::string read_file<>(const std::string&, +extern template std::string read_file<>(const fs::path&, Flags::BinaryOption); -extern template std::vector read_file<>(const std::string&, +extern template std::vector read_file<>(const fs::path&, Flags::BinaryOption); // Given a string which may be a response file (i.e., a filename starting @@ -51,7 +54,7 @@ std::string read_possible_response_file(const std::string&); class Output { public: // An empty filename or "-" will open stdout instead. - Output(const std::string& filename, Flags::BinaryOption binary); + Output(const fs::path& filename, Flags::BinaryOption binary); ~Output() = default; template std::ostream& operator<<(const T& v) { return out << v; } @@ -69,11 +72,8 @@ class Output { std::ostream out; }; -// Copies a file to another file -void copy_file(std::string input, std::string output); - -// Retusn the size of a file -size_t file_size(std::string filename); +// Copies a file to another file, overwriting if the file exists +void copy_file(fs::path input, fs::path output); } // namespace wasm diff --git a/src/support/path.cpp b/src/support/path.cpp index 1858fe1e931..4ddd186016f 100644 --- a/src/support/path.cpp +++ b/src/support/path.cpp @@ -61,7 +61,7 @@ std::string getBaseName(const std::string& path) { return path; } -std::string getBinaryenRoot() { +fs::path getBinaryenRoot() { auto* envVar = getenv("BINARYEN_ROOT"); if (envVar) { return envVar; @@ -69,26 +69,26 @@ std::string getBinaryenRoot() { return "."; } -static std::string binDir; +static fs::path binDir; -std::string getBinaryenBinDir() { +fs::path getBinaryenBinDir() { if (binDir.empty()) { - return getBinaryenRoot() + getPathSeparator() + "bin" + getPathSeparator(); + return getBinaryenRoot() / "bin" / ""; } else { return binDir; } } -void setBinaryenBinDir(const std::string& dir) { +void setBinaryenBinDir(const fs::path& dir) { binDir = dir; - if (binDir.empty() || binDir.back() != getPathSeparator()) { + if (binDir.empty() || binDir.string().back() != getPathSeparator()) { binDir += getPathSeparator(); } } // Gets the path to a binaryen binary tool, like wasm-opt -std::string getBinaryenBinaryTool(const std::string& name) { - return getBinaryenBinDir() + name; +fs::path getBinaryenBinaryTool(const std::string& name) { + return getBinaryenBinDir().append(name); } } // namespace wasm::Path diff --git a/src/support/path.h b/src/support/path.h index 78e85ca5cad..3bfcf6aac3f 100644 --- a/src/support/path.h +++ b/src/support/path.h @@ -22,8 +22,11 @@ #define wasm_support_path_h #include +#include #include +namespace fs = std::experimental::filesystem; + namespace wasm::Path { char getPathSeparator(); @@ -31,16 +34,16 @@ std::string getDirName(const std::string& path); std::string getBaseName(const std::string& path); // Get the binaryen root dor. -std::string getBinaryenRoot(); +fs::path getBinaryenRoot(); // Get the binaryen bin dir. -std::string getBinaryenBinDir(); +fs::path getBinaryenBinDir(); // Set the binaryen bin dir (allows tools to change it based on user input). -void setBinaryenBinDir(const std::string& dir); +void setBinaryenBinDir(const fs::path& dir); // Gets the path to a binaryen binary tool, like wasm-opt. -std::string getBinaryenBinaryTool(const std::string& name); +fs::path getBinaryenBinaryTool(const std::string& name); } // namespace wasm::Path diff --git a/src/tools/wasm-as.cpp b/src/tools/wasm-as.cpp index cc4f6fda2f9..427c88feab6 100644 --- a/src/tools/wasm-as.cpp +++ b/src/tools/wasm-as.cpp @@ -31,8 +31,8 @@ using namespace wasm; int main(int argc, const char* argv[]) { bool debugInfo = false; - std::string symbolMap; - std::string sourceMapFilename; + fs::path symbolMap; + fs::path sourceMapFilename; std::string sourceMapUrl; const std::string WasmAsOption = "wasm-as options"; @@ -142,11 +142,11 @@ int main(int argc, const char* argv[]) { ModuleWriter writer; writer.setBinary(true); writer.setDebugInfo(debugInfo); - if (sourceMapFilename.size()) { + if (!sourceMapFilename.empty()) { writer.setSourceMapFilename(sourceMapFilename); writer.setSourceMapUrl(sourceMapUrl); } - if (symbolMap.size() > 0) { + if (!symbolMap.empty() > 0) { writer.setSymbolMap(symbolMap); } writer.write(wasm, options.extra["output"]); diff --git a/src/tools/wasm-dis.cpp b/src/tools/wasm-dis.cpp index f9f30335963..e4b7e4e149c 100644 --- a/src/tools/wasm-dis.cpp +++ b/src/tools/wasm-dis.cpp @@ -27,7 +27,7 @@ using namespace wasm; int main(int argc, const char* argv[]) { - std::string sourceMapFilename; + fs::path sourceMapFilename; const std::string WasmDisOption = "wasm-dis options"; diff --git a/src/tools/wasm-emscripten-finalize.cpp b/src/tools/wasm-emscripten-finalize.cpp index 0f63e8112d1..a535ac3bc88 100644 --- a/src/tools/wasm-emscripten-finalize.cpp +++ b/src/tools/wasm-emscripten-finalize.cpp @@ -39,12 +39,12 @@ using namespace wasm; int main(int argc, const char* argv[]) { const uint64_t INVALID_BASE = -1; - std::string infile; - std::string outfile; - std::string inputSourceMapFilename; - std::string outputSourceMapFilename; + fs::path infile; + fs::path outfile; + fs::path inputSourceMapFilename; + fs::path outputSourceMapFilename; std::string outputSourceMapUrl; - std::string dataSegmentFile; + fs::path dataSegmentFile; bool emitBinary = true; bool debugInfo = false; bool DWARF = false; @@ -213,7 +213,7 @@ int main(int argc, const char* argv[]) { // We will write the modified wasm if the user asked us to, either by // specifying an output file or requesting text output (which goes to stdout // by default). - auto writeOutput = outfile.size() > 0 || !emitBinary; + auto writeOutput = !outfile.empty() || !emitBinary; Module wasm; options.applyFeatures(wasm); @@ -314,7 +314,7 @@ int main(int argc, const char* argv[]) { writer.setDebugInfo(debugInfo); // writer.setSymbolMap(symbolMap); writer.setBinary(emitBinary); - if (outputSourceMapFilename.size()) { + if (!outputSourceMapFilename.empty()) { writer.setSourceMapFilename(outputSourceMapFilename); writer.setSourceMapUrl(outputSourceMapUrl); } diff --git a/src/tools/wasm-metadce.cpp b/src/tools/wasm-metadce.cpp index 029d4aae8ba..7ac82f709f8 100644 --- a/src/tools/wasm-metadce.cpp +++ b/src/tools/wasm-metadce.cpp @@ -421,7 +421,7 @@ int main(int argc, const char* argv[]) { std::vector passes; bool emitBinary = true; bool debugInfo = false; - std::string graphFile; + fs::path graphFile; bool dump = false; const std::string WasmMetaDCEOption = "wasm-opt options"; @@ -512,7 +512,7 @@ int main(int argc, const char* argv[]) { }); options.parse(argc, argv); - if (graphFile.size() == 0) { + if (graphFile.empty()) { Fatal() << "no graph file provided."; } diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index 0d279dc0864..2af2c0af309 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -88,8 +88,8 @@ int main(int argc, const char* argv[]) { std::string emitJSWrapper; std::string emitSpecWrapper; std::string emitWasm2CWrapper; - std::string inputSourceMapFilename; - std::string outputSourceMapFilename; + fs::path inputSourceMapFilename; + fs::path outputSourceMapFilename; std::string outputSourceMapUrl; const std::string WasmOptOption = "wasm-opt options"; @@ -266,7 +266,7 @@ int main(int argc, const char* argv[]) { // down in TranslateToFuzzReader, but there is also an optional initial fuzz // file that if it exists we read it, then add more fuzz on top. if (!translateToFuzz || initialFuzz.size()) { - std::string inputFile = + fs::path inputFile = translateToFuzz ? initialFuzz : options.extra["infile"]; ModuleReader reader; // Enable DWARF parsing if we were asked for debug info, and were not @@ -412,7 +412,7 @@ int main(int argc, const char* argv[]) { ModuleWriter writer; writer.setBinary(emitBinary); writer.setDebugInfo(options.passOptions.debugInfo); - if (outputSourceMapFilename.size()) { + if (!outputSourceMapFilename.empty()) { writer.setSourceMapFilename(outputSourceMapFilename); writer.setSourceMapUrl(outputSourceMapUrl); } diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index f3f252477bd..f5a6a773b69 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -71,6 +71,8 @@ std::string GetLastErrorStdStr() { return std::string(); } #endif + +using fs::file_size; using namespace wasm; // A timeout on every execution of the command. @@ -230,15 +232,16 @@ static std::unordered_set functionsWeTriedToRemove; struct Reducer : public WalkerPass>> { - std::string command, test, working; + std::string command; + fs::path test, working; bool binary, deNan, verbose, debugInfo; ToolOptions& toolOptions; // test is the file we write to that the command will operate on // working is the current temporary state, the reduction so far Reducer(std::string command, - std::string test, - std::string working, + fs::path test, + fs::path working, bool binary, bool deNan, bool verbose, @@ -296,8 +299,10 @@ struct Reducer // try both combining with a generic shrink (so minor pass overhead is // compensated for), and without for (auto pass : passes) { - std::string currCommand = Path::getBinaryenBinaryTool("wasm-opt") + " "; - currCommand += working + " -o " + test + " " + pass + " " + extraFlags; + std::string currCommand = + Path::getBinaryenBinaryTool("wasm-opt").string(); + currCommand += " " + working.string() + " -o " + test.string() + " " + + pass + " " + extraFlags; if (!binary) { currCommand += " -S "; } @@ -312,7 +317,7 @@ struct Reducer if (ProgramResult(command) == expected) { std::cerr << "| command \"" << currCommand << "\" succeeded, reduced size to " << newSize << '\n'; - copy_file(test, working); + wasm::copy_file(test, working); more = true; oldSize = newSize; } @@ -459,7 +464,7 @@ struct Reducer void noteReduction(size_t amount = 1) { reduced += amount; - copy_file(test, working); + wasm::copy_file(test, working); } // tests a reduction on an arbitrary child @@ -1184,9 +1189,10 @@ struct Reducer // int main(int argc, const char* argv[]) { - std::string input, test, working, command; + fs::path input, test, working; + std::string command; // By default, look for binaries alongside our own binary. - std::string binDir = Path::getDirName(argv[0]); + fs::path binDir = Path::getDirName(argv[0]); bool binary = true, deNan = false, verbose = false, debugInfo = false, force = false; @@ -1298,10 +1304,10 @@ int main(int argc, const char* argv[]) { WASM_UNREACHABLE("unexpected type system"); } - if (test.size() == 0) { + if (test.empty()) { Fatal() << "test file not provided\n"; } - if (working.size() == 0) { + if (working.empty()) { Fatal() << "working file not provided\n"; } @@ -1319,7 +1325,7 @@ int main(int argc, const char* argv[]) { std::cerr << "|extra flags: " << extraFlags << '\n'; // get the expected output - copy_file(input, test); + wasm::copy_file(input, test); expected.getFromExecution(command); std::cerr << "|expected result:\n" << expected << '\n'; @@ -1361,7 +1367,7 @@ int main(int argc, const char* argv[]) { << "running the command on the given input gives the same result as " "when running it on either a trivial valid wasm or a file with " "nonsense in it. does the script not look at the test file (" + - test + ")? (use -f to ignore this check)"; + test.string() + ")? (use -f to ignore this check)"; } } } @@ -1370,8 +1376,8 @@ int main(int argc, const char* argv[]) { "(read-written) binary\n"; { // read and write it - auto cmd = Path::getBinaryenBinaryTool("wasm-opt") + " " + input + " -o " + - test + " " + extraFlags; + auto cmd = Path::getBinaryenBinaryTool("wasm-opt").string() + " " + + input.string() + " -o " + test.string() + " " + extraFlags; if (!binary) { cmd += " -S "; } @@ -1388,7 +1394,7 @@ int main(int argc, const char* argv[]) { } } - copy_file(input, working); + wasm::copy_file(input, working); auto workingSize = file_size(working); std::cerr << "|input size: " << workingSize << "\n"; @@ -1482,5 +1488,5 @@ int main(int argc, const char* argv[]) { << '\n'; } std::cerr << "|finished, final size: " << file_size(working) << "\n"; - copy_file(working, test); // just to avoid confusion + wasm::copy_file(working, test); // just to avoid confusion } diff --git a/src/wasm-io.h b/src/wasm-io.h index ae66c39320d..88169514d0c 100644 --- a/src/wasm-io.h +++ b/src/wasm-io.h @@ -58,17 +58,18 @@ class ModuleReader : public ModuleIOBase { } // read text - void readText(std::string filename, Module& wasm); + void readText(fs::path filename, Module& wasm); // read binary - void readBinary(std::string filename, + void readBinary(fs::path filename, Module& wasm, - std::string sourceMapFilename = ""); + fs::path sourceMapFilename = ""); // read text or binary, checking the contents for what it is. If `filename` is // empty, read from stdin. - void - read(std::string filename, Module& wasm, std::string sourceMapFilename = ""); + void read(fs::path filename, + Module& wasm, + fs::path sourceMapFilename = ""); // check whether a file is a wasm binary - bool isBinaryFile(std::string filename); + bool isBinaryFile(fs::path filename); private: bool DWARF = false; @@ -77,11 +78,11 @@ class ModuleReader : public ModuleIOBase { bool skipFunctionBodies = false; - void readStdin(Module& wasm, std::string sourceMapFilename); + void readStdin(Module& wasm, fs::path sourceMapFilename); void readBinaryData(std::vector& input, Module& wasm, - std::string sourceMapFilename); + fs::path sourceMapFilename); }; class ModuleWriter : public ModuleIOBase { @@ -90,8 +91,8 @@ class ModuleWriter : public ModuleIOBase { // TODO: Remove `emitModuleName`. See the comment in wasm-binary.h bool emitModuleName = false; - std::string symbolMap; - std::string sourceMapFilename; + fs::path symbolMap; + fs::path sourceMapFilename; std::string sourceMapUrl; public: @@ -100,8 +101,10 @@ class ModuleWriter : public ModuleIOBase { ModuleWriter() { setDebugInfo(false); } void setBinary(bool binary_) { binary = binary_; } - void setSymbolMap(std::string symbolMap_) { symbolMap = symbolMap_; } - void setSourceMapFilename(std::string sourceMapFilename_) { + void setSymbolMap(fs::path symbolMap_) { + symbolMap = symbolMap_; + } + void setSourceMapFilename(fs::path sourceMapFilename_) { sourceMapFilename = sourceMapFilename_; } void setSourceMapUrl(std::string sourceMapUrl_) { @@ -111,15 +114,15 @@ class ModuleWriter : public ModuleIOBase { // write text void writeText(Module& wasm, Output& output); - void writeText(Module& wasm, std::string filename); + void writeText(Module& wasm, fs::path filename); // write binary void writeBinary(Module& wasm, Output& output); - void writeBinary(Module& wasm, std::string filename); + void writeBinary(Module& wasm, fs::path filename); // write text or binary, defaulting to binary unless setBinary(false), // and unless there is no output file (in which case we write text // to stdout). void write(Module& wasm, Output& output); - void write(Module& wasm, std::string filename); + void write(Module& wasm, fs::path filename); }; } // namespace wasm diff --git a/src/wasm/wasm-io.cpp b/src/wasm/wasm-io.cpp index b544046f6ce..a380dabe58e 100644 --- a/src/wasm/wasm-io.cpp +++ b/src/wasm/wasm-io.cpp @@ -51,7 +51,7 @@ static void readTextData(std::string& input, Module& wasm, IRProfile profile) { } } -void ModuleReader::readText(std::string filename, Module& wasm) { +void ModuleReader::readText(fs::path filename, Module& wasm) { BYN_TRACE("reading text from " << filename << "\n"); auto input(read_file(filename, Flags::Text)); readTextData(input, wasm, profile); @@ -59,7 +59,7 @@ void ModuleReader::readText(std::string filename, Module& wasm) { void ModuleReader::readBinaryData(std::vector& input, Module& wasm, - std::string sourceMapFilename) { + fs::path sourceMapFilename) { std::unique_ptr sourceMapStream; // Assume that the wasm has had its initial features applied, and use those // while parsing. @@ -67,7 +67,7 @@ void ModuleReader::readBinaryData(std::vector& input, parser.setDebugInfo(debugInfo); parser.setDWARF(DWARF); parser.setSkipFunctionBodies(skipFunctionBodies); - if (sourceMapFilename.size()) { + if (!sourceMapFilename.empty()) { sourceMapStream = std::make_unique(); sourceMapStream->open(sourceMapFilename); parser.setDebugLocations(sourceMapStream.get()); @@ -78,15 +78,15 @@ void ModuleReader::readBinaryData(std::vector& input, } } -void ModuleReader::readBinary(std::string filename, +void ModuleReader::readBinary(fs::path filename, Module& wasm, - std::string sourceMapFilename) { + fs::path sourceMapFilename) { BYN_TRACE("reading binary from " << filename << "\n"); auto input(read_file>(filename, Flags::Binary)); readBinaryData(input, wasm, sourceMapFilename); } -bool ModuleReader::isBinaryFile(std::string filename) { +bool ModuleReader::isBinaryFile(fs::path filename) { std::ifstream infile; std::ios_base::openmode flags = std::ifstream::in | std::ifstream::binary; infile.open(filename, flags); @@ -97,11 +97,11 @@ bool ModuleReader::isBinaryFile(std::string filename) { buffer[3] == 'm'; } -void ModuleReader::read(std::string filename, +void ModuleReader::read(fs::path filename, Module& wasm, - std::string sourceMapFilename) { + fs::path sourceMapFilename) { // empty filename or "-" means read from stdin - if (!filename.size() || filename == "-") { + if (filename.empty() || filename == "-") { readStdin(wasm, sourceMapFilename); return; } @@ -109,7 +109,7 @@ void ModuleReader::read(std::string filename, readBinary(filename, wasm, sourceMapFilename); } else { // default to text - if (sourceMapFilename.size()) { + if (!sourceMapFilename.empty()) { std::cerr << "Binaryen ModuleReader::read() - source map filename " "provided, but file appears to not be binary\n"; } @@ -119,7 +119,8 @@ void ModuleReader::read(std::string filename, // TODO: reading into a vector then copying into a string is unnecessarily // inefficient. It would be better to read just once into a stringstream. -void ModuleReader::readStdin(Module& wasm, std::string sourceMapFilename) { +void ModuleReader::readStdin(Module& wasm, + fs::path sourceMapFilename) { std::vector input = read_stdin(); if (input.size() >= 4 && input[0] == '\0' && input[1] == 'a' && input[2] == 's' && input[3] == 'm') { @@ -140,7 +141,7 @@ void ModuleWriter::writeText(Module& wasm, Output& output) { output.getStream() << wasm; } -void ModuleWriter::writeText(Module& wasm, std::string filename) { +void ModuleWriter::writeText(Module& wasm, fs::path filename) { BYN_TRACE("writing text to " << filename << "\n"); Output output(filename, Flags::Text); writeText(wasm, output); @@ -155,13 +156,13 @@ void ModuleWriter::writeBinary(Module& wasm, Output& output) { writer.setEmitModuleName(true); } std::unique_ptr sourceMapStream; - if (sourceMapFilename.size()) { + if (!sourceMapFilename.empty()) { sourceMapStream = std::make_unique(); sourceMapStream->open(sourceMapFilename); writer.setSourceMap(sourceMapStream.get(), sourceMapUrl); } - if (symbolMap.size() > 0) { - writer.setSymbolMap(symbolMap); + if (!symbolMap.empty()) { + writer.setSymbolMap(symbolMap.string()); } writer.write(); buffer.writeTo(output); @@ -170,7 +171,7 @@ void ModuleWriter::writeBinary(Module& wasm, Output& output) { } } -void ModuleWriter::writeBinary(Module& wasm, std::string filename) { +void ModuleWriter::writeBinary(Module& wasm, fs::path filename) { BYN_TRACE("writing binary to " << filename << "\n"); Output output(filename, Flags::Binary); writeBinary(wasm, output); @@ -184,8 +185,8 @@ void ModuleWriter::write(Module& wasm, Output& output) { } } -void ModuleWriter::write(Module& wasm, std::string filename) { - if (binary && filename.size() > 0) { +void ModuleWriter::write(Module& wasm, fs::path filename) { + if (binary && !filename.empty()) { writeBinary(wasm, filename); } else { writeText(wasm, filename); diff --git a/third_party/llvm-project/include/llvm/Support/FileSystem.h b/third_party/llvm-project/include/llvm/Support/FileSystem.h index a29a9d78794..3fd7f1dc107 100644 --- a/third_party/llvm-project/include/llvm/Support/FileSystem.h +++ b/third_party/llvm-project/include/llvm/Support/FileSystem.h @@ -1213,7 +1213,7 @@ class directory_entry { // when traversing a directory. The design of this class wraps most of the // information in basic_file_status, so on platforms where we can't populate // that whole structure, callers end up paying for a stat(). - // std::filesystem::directory_entry may be a better model. + // fs::directory_entry may be a better model. std::string Path; file_type Type = file_type::type_unknown; // Most platforms can provide this. bool FollowSymlinks = true; // Affects the behavior of status().