diff -ruN zig-0.15.1.orig/src/zig_llvm.cpp zig-0.15.1/src/zig_llvm.cpp --- zig-0.15.1.orig/src/zig_llvm.cpp 2025-08-27 22:13:38.418809910 +0800 +++ zig-0.15.1/src/zig_llvm.cpp 2025-08-27 22:53:09.408882779 +0800 @@ -62,7 +62,6 @@ #include #include -#include #if __GNUC__ >= 9 #pragma GCC diagnostic pop @@ -71,6 +70,10 @@ #include #include +#include +#include +#include +#include using namespace llvm; @@ -80,6 +83,85 @@ static const bool assertions_on = false; #endif +namespace { + class Pipe { + public: + Pipe(llvm::raw_ostream *output) : output(output) {} + ~Pipe() { + if (fd[0] != -1) close(fd[0]); + if (fd[1] != -1) close(fd[1]); + } + bool open() { return pipe(fd) == 0; } + int getRead() const { return fd[0]; } + int getWrite() const { return fd[1]; } + void closeWrite() { close(fd[1]); fd[1] = -1; } + void flush() const { + constexpr size_t size = 1024; + char buf[size]; + ssize_t ret; + do { + ret = read(getRead(), buf, size); + if (ret > 0 && output) + output->write(buf, ret); + } while (ret == size || (ret == -1 && errno == EINTR)); + } + private: + int fd[2] = {-1, -1}; + llvm::raw_ostream *output; + }; +} + +static bool InvokeLld(const char *variant, llvm::ArrayRef args, + llvm::raw_ostream &stdoutOS, + llvm::raw_ostream &stderrOS, bool disableOutput) +{ + Pipe outPipe(disableOutput ? nullptr : &stdoutOS), + errPipe(disableOutput ? nullptr : &stderrOS); + if (!outPipe.open()) + return false; + if (!errPipe.open()) + return false; + + posix_spawn_file_actions_t actions; + posix_spawn_file_actions_init(&actions); + posix_spawn_file_actions_adddup2(&actions, outPipe.getWrite(), STDOUT_FILENO); + posix_spawn_file_actions_adddup2(&actions, errPipe.getWrite(), STDERR_FILENO); + + // We need the command as argument, and end with nullptr. + SmallVector arguments{const_cast(variant)}; + for (size_t arg = 1; arg != args.size(); ++arg) + arguments.push_back(const_cast(args[arg])); + arguments.push_back(nullptr); + + pid_t pid; + if (posix_spawnp(&pid, variant, &actions, nullptr, arguments.data(), environ) != 0) + return false; + posix_spawn_file_actions_destroy(&actions); + outPipe.closeWrite(); + errPipe.closeWrite(); + + // Wait for child to finish and flush pipes. + sigset_t signals, old; + sigemptyset(&signals); + sigaddset(&signals, SIGCHLD); + pthread_sigmask(SIG_BLOCK, &signals, &old); + pollfd pollfds[2] = {{outPipe.getRead(), POLLIN}, {errPipe.getRead(), POLLIN}}; + int wstatus; + do { + poll(pollfds, 2, -1); + if (pollfds[0].revents & POLLIN) + outPipe.flush(); + if (pollfds[1].revents & POLLIN) + errPipe.flush(); + } while (waitpid(pid, &wstatus, WNOHANG) == 0); + pthread_sigmask(SIG_SETMASK, &old, nullptr); + + outPipe.flush(); + errPipe.flush(); + + return WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0; +} + LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple, const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, LLVMCodeModel CodeModel, bool function_sections, bool data_sections, ZigLLVMFloatABI float_abi, @@ -560,17 +642,17 @@ bool ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_early, bool disable_output) { std::vector args(argv, argv + argc); - return lld::coff::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output); + return InvokeLld("lld-link-20", llvm::ArrayRef(argv, argc), llvm::outs(), llvm::errs(), disable_output); } bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output) { std::vector args(argv, argv + argc); - return lld::elf::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output); + return InvokeLld("ld.lld-20", llvm::ArrayRef(argv, argc), llvm::outs(), llvm::errs(), disable_output); } bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disable_output) { std::vector args(argv, argv + argc); - return lld::wasm::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output); + return InvokeLld("wasm-ld-20", llvm::ArrayRef(argv, argc), llvm::outs(), llvm::errs(), disable_output); } static_assert((FloatABI::ABIType)ZigLLVMFloatABI_Default == FloatABI::ABIType::Default, "");