From b5767010a8ea2f5e2148da5f3e37041185211370 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 27 Mar 2020 17:03:32 -0700 Subject: [PATCH] [lld][WebAssembly] Early error if output file cannot be created. This matches the behaviour of the ELF driver. Also move the `createFiles` to be `checkConfig` and report `no input files` there. Again this is mostly to match the structure of the ELF linker better. Differential Revision: https://reviews.llvm.org/D76960 --- lld/test/wasm/early-exit-for-bad-paths.s | 22 ++++++++++++++++++++++ lld/test/wasm/lto/opt-level.ll | 2 +- lld/test/wasm/responsefile.test | 4 ++-- lld/wasm/Driver.cpp | 24 +++++++++++++++++------- 4 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 lld/test/wasm/early-exit-for-bad-paths.s diff --git a/lld/test/wasm/early-exit-for-bad-paths.s b/lld/test/wasm/early-exit-for-bad-paths.s new file mode 100644 index 0000000..2866bfa --- /dev/null +++ b/lld/test/wasm/early-exit-for-bad-paths.s @@ -0,0 +1,22 @@ +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o + +# RUN: not wasm-ld %t.o -o does_not_exist/output 2>&1 | \ +# RUN: FileCheck %s -check-prefixes=NO-DIR-OUTPUT,CHECK +# RUN: not wasm-ld %t.o -o %s/dir_is_a_file 2>&1 | \ +# RUN: FileCheck %s -check-prefixes=DIR-IS-OUTPUT,CHECK +# TODO(sbc): check similar check for -Map file once we add that option + +# NO-DIR-OUTPUT: error: cannot open output file does_not_exist/output: +# DIR-IS-OUTPUT: error: cannot open output file {{.*}}/dir_is_a_file: + +# We should exit before doing the actual link. If an undefined symbol error is +# discovered we haven't bailed out early as expected. +# CHECK-NOT: undefined_symbol + +# RUN: not wasm-ld %t.o -o / 2>&1 | FileCheck %s -check-prefixes=ROOT,CHECK +# ROOT: error: cannot open output file / + +_start: + .functype _start () -> () + call undefined_symbol + end_function diff --git a/lld/test/wasm/lto/opt-level.ll b/lld/test/wasm/lto/opt-level.ll index f6156e7..d2d5527 100644 --- a/lld/test/wasm/lto/opt-level.ll +++ b/lld/test/wasm/lto/opt-level.ll @@ -11,7 +11,7 @@ ; RUN: FileCheck --check-prefix=INVALID %s ; INVALID: invalid optimization level for LTO: 6 -; RUN: not wasm-ld -o %t3 -m elf_x86_64 -e main --lto-O-1 %t.o 2>&1 | \ +; RUN: not wasm-ld -o %t3 -e main --lto-O-1 %t.o 2>&1 | \ ; RUN: FileCheck --check-prefix=INVALIDNEGATIVE %s ; INVALIDNEGATIVE: invalid optimization level for LTO: 4294967295 diff --git a/lld/test/wasm/responsefile.test b/lld/test/wasm/responsefile.test index ba2afd0..85ac41f 100644 --- a/lld/test/wasm/responsefile.test +++ b/lld/test/wasm/responsefile.test @@ -10,11 +10,11 @@ RUN: FileCheck --check-prefix=INVRSP %s INVRSP: invalid response file quoting: foobar RUN: echo "blah\foo" > %t.rsp -RUN: not wasm-ld --rsp-quoting=windows @%t.rsp 2>&1 | \ +RUN: not wasm-ld -o a.out --rsp-quoting=windows @%t.rsp 2>&1 | \ RUN: FileCheck --check-prefix=WINRSP %s WINRSP: error: cannot open blah\foo: RUN: echo "blah\foo" > %t.rsp -RUN: not wasm-ld --rsp-quoting=posix @%t.rsp 2>&1 | \ +RUN: not wasm-ld -o a.out --rsp-quoting=posix @%t.rsp 2>&1 | \ RUN: FileCheck --check-prefix=POSRSP %s POSRSP: error: cannot open blahfoo: diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index d0b01d5..aaf5808 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -15,6 +15,7 @@ #include "Writer.h" #include "lld/Common/Args.h" #include "lld/Common/ErrorHandler.h" +#include "lld/Common/Filesystem.h" #include "lld/Common/Memory.h" #include "lld/Common/Reproduce.h" #include "lld/Common/Strings.h" @@ -304,6 +305,8 @@ void LinkerDriver::createFiles(opt::InputArgList &args) { break; } } + if (files.empty() && errorCount() == 0) + error("no input files"); } static StringRef getEntry(opt::InputArgList &args) { @@ -728,16 +731,27 @@ void LinkerDriver::link(ArrayRef argsArr) { errorHandler().errorLimit = args::getInteger(args, OPT_error_limit, 20); readConfigs(args); + + createFiles(args); + if (errorCount()) + return; + setConfigs(); checkOptions(args); + if (errorCount()) + return; if (auto *arg = args.getLastArg(OPT_allow_undefined_file)) readImportFile(arg->getValue()); - if (!args.hasArg(OPT_INPUT)) { - error("no input files"); + // Fail early if the output file or map file is not writable. If a user has a + // long link, e.g. due to a large LTO link, they do not wish to run it and + // find that it failed because there was a mistake in their command-line. + if (auto e = tryCreateFile(config->outputFile)) + error("cannot open output file " + config->outputFile + ": " + e.message()); + // TODO(sbc): add check for map file too once we add support for that. + if (errorCount()) return; - } // Handle --trace-symbol. for (auto *arg : args.filtered(OPT_trace_symbol)) @@ -748,10 +762,6 @@ void LinkerDriver::link(ArrayRef argsArr) { createSyntheticSymbols(); - createFiles(args); - if (errorCount()) - return; - // Add all files to the symbol table. This will add almost all // symbols that we need to the symbol table. for (InputFile *f : files) -- 2.7.4