| ... | ... | @@ -34,6 +34,9 @@ |
| 34 | 34 | #include <llvm/MC/SubtargetFeature.h> |
| 35 | 35 | #include <llvm/Object/Archive.h> |
| 36 | 36 | #include <llvm/Object/ArchiveWriter.h> |
| 37 | #include <llvm/Object/COFF.h> |
| 38 | #include <llvm/Object/COFFImportFile.h> |
| 39 | #include <llvm/Object/COFFModuleDefinition.h> |
| 37 | 40 | #include <llvm/PassRegistry.h> |
| 38 | 41 | #include <llvm/Support/FileSystem.h> |
| 39 | 42 | #include <llvm/Support/TargetParser.h> |
| ... | ... | @@ -938,6 +941,85 @@ class MyOStream: public raw_ostream { |
| 938 | 941 | size_t pos; |
| 939 | 942 | }; |
| 940 | 943 | |
| 944 | bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch, |
| 945 | const char *output_lib_path, const bool kill_at) |
| 946 | { |
| 947 | COFF::MachineTypes machine = COFF::IMAGE_FILE_MACHINE_UNKNOWN; |
| 948 | |
| 949 | switch (arch) { |
| 950 | case ZigLLVM_x86: |
| 951 | machine = COFF::IMAGE_FILE_MACHINE_I386; |
| 952 | break; |
| 953 | case ZigLLVM_x86_64: |
| 954 | machine = COFF::IMAGE_FILE_MACHINE_AMD64; |
| 955 | break; |
| 956 | case ZigLLVM_arm: |
| 957 | case ZigLLVM_armeb: |
| 958 | case ZigLLVM_thumb: |
| 959 | case ZigLLVM_thumbeb: |
| 960 | machine = COFF::IMAGE_FILE_MACHINE_ARMNT; |
| 961 | break; |
| 962 | case ZigLLVM_aarch64: |
| 963 | case ZigLLVM_aarch64_be: |
| 964 | machine = COFF::IMAGE_FILE_MACHINE_ARM64; |
| 965 | break; |
| 966 | default: |
| 967 | break; |
| 968 | } |
| 969 | |
| 970 | if (machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) { |
| 971 | return true; |
| 972 | } |
| 973 | |
| 974 | auto bufOrErr = MemoryBuffer::getFile(def_path); |
| 975 | if (!bufOrErr) { |
| 976 | return false; |
| 977 | } |
| 978 | |
| 979 | MemoryBuffer& buf = *bufOrErr.get(); |
| 980 | Expected<object::COFFModuleDefinition> def = |
| 981 | object::parseCOFFModuleDefinition(buf, machine, /* MingwDef */ true); |
| 982 | |
| 983 | if (!def) { |
| 984 | return true; |
| 985 | } |
| 986 | |
| 987 | // The exports-juggling code below is ripped from LLVM's DllToolDriver.cpp |
| 988 | |
| 989 | // If ExtName is set (if the "ExtName = Name" syntax was used), overwrite |
| 990 | // Name with ExtName and clear ExtName. When only creating an import |
| 991 | // library and not linking, the internal name is irrelevant. This avoids |
| 992 | // cases where writeImportLibrary tries to transplant decoration from |
| 993 | // symbol decoration onto ExtName. |
| 994 | for (object::COFFShortExport& E : def->Exports) { |
| 995 | if (!E.ExtName.empty()) { |
| 996 | E.Name = E.ExtName; |
| 997 | E.ExtName.clear(); |
| 998 | } |
| 999 | } |
| 1000 | |
| 1001 | if (machine == COFF::IMAGE_FILE_MACHINE_I386 && kill_at) { |
| 1002 | for (object::COFFShortExport& E : def->Exports) { |
| 1003 | if (!E.AliasTarget.empty() || (!E.Name.empty() && E.Name[0] == '?')) |
| 1004 | continue; |
| 1005 | E.SymbolName = E.Name; |
| 1006 | // Trim off the trailing decoration. Symbols will always have a |
| 1007 | // starting prefix here (either _ for cdecl/stdcall, @ for fastcall |
| 1008 | // or ? for C++ functions). Vectorcall functions won't have any |
| 1009 | // fixed prefix, but the function base name will still be at least |
| 1010 | // one char. |
| 1011 | E.Name = E.Name.substr(0, E.Name.find('@', 1)); |
| 1012 | // By making sure E.SymbolName != E.Name for decorated symbols, |
| 1013 | // writeImportLibrary writes these symbols with the type |
| 1014 | // IMPORT_NAME_UNDECORATE. |
| 1015 | } |
| 1016 | } |
| 1017 | |
| 1018 | return static_cast<bool>( |
| 1019 | object::writeImportLibrary(def->OutputFile, output_lib_path, |
| 1020 | def->Exports, machine, /* MinGW */ true)); |
| 1021 | } |
| 1022 | |
| 941 | 1023 | bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count, |
| 942 | 1024 | ZigLLVM_OSType os_type) |
| 943 | 1025 | { |