From 2b624fea84abdd963ea06aca648b4da1477ec65f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 12 Oct 2019 10:56:16 +0200 Subject: [PATCH 1/2] Add dlltool functionality Don't need no patched lld --kill-at behaviour now. --- src/link.cpp | 27 ++++------------ src/zig_llvm.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ src/zig_llvm.h | 3 ++ 3 files changed, 91 insertions(+), 21 deletions(-) diff --git a/src/link.cpp b/src/link.cpp index de35a18f33..61192724f2 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -2054,27 +2054,12 @@ static const char *get_def_lib(CodeGen *parent, const char *name, Buf *def_in_fi lib_final_path = buf_alloc(); os_path_join(artifact_dir, final_lib_basename, lib_final_path); - args.resize(0); - args.append("link"); - coff_append_machine_arg(parent, &args); - args.append("-lldmingw"); - args.append("-kill-at"); - - args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_final_path)))); - args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(lib_final_path)))); - - if (parent->verbose_link) { - for (size_t i = 0; i < args.length; i += 1) { - fprintf(stderr, "%s ", args.at(i)); - } - fprintf(stderr, "\n"); - } - - Buf diag = BUF_INIT; - ZigLLVM_ObjectFormatType target_ofmt = target_object_format(parent->zig_target); - if (!zig_lld_link(target_ofmt, args.items, args.length, &diag)) { - fprintf(stderr, "%s\n", buf_ptr(&diag)); - exit(1); + if (ZigLLVMWriteImportLibrary(buf_ptr(def_final_path), + parent->zig_target->arch, + buf_ptr(lib_final_path), + /* kill_at */ true)) + { + zig_panic("link: could not emit %s", buf_ptr(lib_final_path)); } } else { // cache hit diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 8166173051..ac17e6edfe 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -34,6 +34,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -938,6 +941,85 @@ class MyOStream: public raw_ostream { size_t pos; }; +bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch, + const char *output_lib_path, const bool kill_at) +{ + COFF::MachineTypes machine = COFF::IMAGE_FILE_MACHINE_UNKNOWN; + + switch (arch) { + case ZigLLVM_x86: + machine = COFF::IMAGE_FILE_MACHINE_I386; + break; + case ZigLLVM_x86_64: + machine = COFF::IMAGE_FILE_MACHINE_AMD64; + break; + case ZigLLVM_arm: + case ZigLLVM_armeb: + case ZigLLVM_thumb: + case ZigLLVM_thumbeb: + machine = COFF::IMAGE_FILE_MACHINE_ARMNT; + break; + case ZigLLVM_aarch64: + case ZigLLVM_aarch64_be: + machine = COFF::IMAGE_FILE_MACHINE_ARM64; + break; + default: + break; + } + + if (machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) { + return true; + } + + auto bufOrErr = MemoryBuffer::getFile(def_path); + if (!bufOrErr) { + return false; + } + + MemoryBuffer& buf = *bufOrErr.get(); + Expected def = + object::parseCOFFModuleDefinition(buf, machine, /* MingwDef */ true); + + if (!def) { + return true; + } + + // The exports-juggling code below is ripped from LLVM's DllToolDriver.cpp + + // If ExtName is set (if the "ExtName = Name" syntax was used), overwrite + // Name with ExtName and clear ExtName. When only creating an import + // library and not linking, the internal name is irrelevant. This avoids + // cases where writeImportLibrary tries to transplant decoration from + // symbol decoration onto ExtName. + for (object::COFFShortExport& E : def->Exports) { + if (!E.ExtName.empty()) { + E.Name = E.ExtName; + E.ExtName.clear(); + } + } + + if (machine == COFF::IMAGE_FILE_MACHINE_I386 && kill_at) { + for (object::COFFShortExport& E : def->Exports) { + if (!E.AliasTarget.empty() || (!E.Name.empty() && E.Name[0] == '?')) + continue; + E.SymbolName = E.Name; + // Trim off the trailing decoration. Symbols will always have a + // starting prefix here (either _ for cdecl/stdcall, @ for fastcall + // or ? for C++ functions). Vectorcall functions won't have any + // fixed prefix, but the function base name will still be at least + // one char. + E.Name = E.Name.substr(0, E.Name.find('@', 1)); + // By making sure E.SymbolName != E.Name for decorated symbols, + // writeImportLibrary writes these symbols with the type + // IMPORT_NAME_UNDECORATE. + } + } + + return static_cast( + object::writeImportLibrary(def->OutputFile, output_lib_path, + def->Exports, machine, /* MinGW */ true)); +} + bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count, ZigLLVM_OSType os_type) { diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 8522a03c40..a3043b7e25 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -465,6 +465,9 @@ ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char * ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count, enum ZigLLVM_OSType os_type); +bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch, + const char *output_lib_path, const bool kill_at); + ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum ZigLLVM_SubArchType *sub_arch_type, enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type, enum ZigLLVM_ObjectFormatType *oformat); From 60cf3f8a8c26ad4131c5842238cefe6b45a67d9f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 12 Oct 2019 10:57:11 +0200 Subject: [PATCH 2/2] Revert LLD patch The source is now squeaky-clean again. --- deps/lld/COFF/DriverUtils.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/deps/lld/COFF/DriverUtils.cpp b/deps/lld/COFF/DriverUtils.cpp index 5003a99da4..4360ac23b2 100644 --- a/deps/lld/COFF/DriverUtils.cpp +++ b/deps/lld/COFF/DriverUtils.cpp @@ -638,18 +638,10 @@ void fixupExports() { if (config->killAt && config->machine == I386) { for (Export &e : config->exports) { - if (!e.name.empty() && e.name[0] == '?') - continue; - e.symbolName = e.name; - // Trim off the trailing decoration. Symbols will always have a - // starting prefix here (either _ for cdecl/stdcall, @ for fastcall - // or ? for C++ functions). Vectorcall functions won't have any - // fixed prefix, but the function base name will still be at least - // one char. - e.name = e.name.substr(0, e.name.find('@', 1)); - // By making sure E.SymbolName != E.Name for decorated symbols, - // writeImportLibrary writes these symbols with the type - // IMPORT_NAME_UNDECORATE. + e.name = killAt(e.name, true); + e.exportName = killAt(e.exportName, false); + e.extName = killAt(e.extName, true); + e.symbolName = killAt(e.symbolName, true); } }