[llvm] [llvm-dlltool] Add ARM64EC target support. (PR #81624)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 13 08:33:34 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-binary-utilities
Author: Jacek Caban (cjacek)
<details>
<summary>Changes</summary>
Depends on #<!-- -->81620.
Add new target and a new -n option allowing to specify native module definition file, similar to how -defArm64Native works in llvm-lib. This also changes archive format to use K_COFF like non-mingw targets. It's required on ARM64EC, but it should be fine for other targets too.
CC @<!-- -->bylaws
---
Full diff: https://github.com/llvm/llvm-project/pull/81624.diff
4 Files Affected:
- (modified) llvm/lib/Object/COFFImportFile.cpp (+1-1)
- (modified) llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp (+67-39)
- (modified) llvm/lib/ToolDrivers/llvm-dlltool/Options.td (+3)
- (added) llvm/test/tools/llvm-dlltool/arm64ec.test (+46)
``````````diff
diff --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp
index f6f6cf2a1602cf..376dd126baf61a 100644
--- a/llvm/lib/Object/COFFImportFile.cpp
+++ b/llvm/lib/Object/COFFImportFile.cpp
@@ -712,7 +712,7 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path,
return e;
return writeArchive(Path, Members, SymtabWritingMode::NormalSymtab,
- MinGW ? object::Archive::K_GNU : object::Archive::K_COFF,
+ object::Archive::K_COFF,
/*Deterministic*/ true, /*Thin*/ false,
/*OldArchiveBuf*/ nullptr, isArm64EC(Machine));
}
diff --git a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
index 834903857a88eb..fa716a281a69fc 100644
--- a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
+++ b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
@@ -75,6 +75,7 @@ MachineTypes getEmulation(StringRef S) {
.Case("i386:x86-64", IMAGE_FILE_MACHINE_AMD64)
.Case("arm", IMAGE_FILE_MACHINE_ARMNT)
.Case("arm64", IMAGE_FILE_MACHINE_ARM64)
+ .Case("arm64ec", IMAGE_FILE_MACHINE_ARM64EC)
.Default(IMAGE_FILE_MACHINE_UNKNOWN);
}
@@ -87,7 +88,8 @@ MachineTypes getMachine(Triple T) {
case Triple::arm:
return COFF::IMAGE_FILE_MACHINE_ARMNT;
case Triple::aarch64:
- return COFF::IMAGE_FILE_MACHINE_ARM64;
+ return T.isWindowsArm64EC() ? COFF::IMAGE_FILE_MACHINE_ARM64EC
+ : COFF::IMAGE_FILE_MACHINE_ARM64;
default:
return COFF::IMAGE_FILE_MACHINE_UNKNOWN;
}
@@ -110,6 +112,46 @@ std::optional<std::string> getPrefix(StringRef Argv0) {
return ProgName.str();
}
+bool parseModuleDefinition(StringRef DefFileName, MachineTypes Machine,
+ bool AddUnderscores,
+ std::vector<COFFShortExport> &Exports,
+ std::string &OutputFile) {
+ std::unique_ptr<MemoryBuffer> MB = openFile(DefFileName);
+ if (!MB)
+ return false;
+
+ if (!MB->getBufferSize()) {
+ llvm::errs() << "definition file empty\n";
+ return false;
+ }
+
+ Expected<COFFModuleDefinition> Def = parseCOFFModuleDefinition(
+ *MB, Machine, /*MingwDef=*/true, AddUnderscores);
+ if (!Def) {
+ llvm::errs() << "error parsing definition\n"
+ << errorToErrorCode(Def.takeError()).message() << "\n";
+ return false;
+ }
+
+ if (OutputFile.empty())
+ OutputFile = std::move(Def->OutputFile);
+
+ // 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 (COFFShortExport &E : Def->Exports) {
+ if (!E.ExtName.empty()) {
+ E.Name = E.ExtName;
+ E.ExtName.clear();
+ }
+ }
+
+ Exports = std::move(Def->Exports);
+ return true;
+}
+
} // namespace
int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> ArgsArr) {
@@ -128,7 +170,7 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> ArgsArr) {
(!Args.hasArgNoClaim(OPT_d) && !Args.hasArgNoClaim(OPT_l))) {
Table.printHelp(outs(), "llvm-dlltool [options] file...", "llvm-dlltool",
false);
- llvm::outs() << "\nTARGETS: i386, i386:x86-64, arm, arm64\n";
+ llvm::outs() << "\nTARGETS: i386, i386:x86-64, arm, arm64, arm64ec\n";
return 1;
}
@@ -141,16 +183,6 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> ArgsArr) {
return 1;
}
- std::unique_ptr<MemoryBuffer> MB =
- openFile(Args.getLastArg(OPT_d)->getValue());
- if (!MB)
- return 1;
-
- if (!MB->getBufferSize()) {
- llvm::errs() << "definition file empty\n";
- return 1;
- }
-
COFF::MachineTypes Machine = getDefaultMachine();
if (std::optional<std::string> Prefix = getPrefix(ArgsArr[0])) {
Triple T(*Prefix);
@@ -166,40 +198,35 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> ArgsArr) {
}
bool AddUnderscores = !Args.hasArg(OPT_no_leading_underscore);
- Expected<COFFModuleDefinition> Def = parseCOFFModuleDefinition(
- *MB, Machine, /*MingwDef=*/true, AddUnderscores);
- if (!Def) {
- llvm::errs() << "error parsing definition\n"
- << errorToErrorCode(Def.takeError()).message() << "\n";
- return 1;
- }
-
- // Do this after the parser because parseCOFFModuleDefinition sets OutputFile.
+ std::string OutputFile;
if (auto *Arg = Args.getLastArg(OPT_D))
- Def->OutputFile = Arg->getValue();
+ OutputFile = Arg->getValue();
- if (Def->OutputFile.empty()) {
- llvm::errs() << "no DLL name specified\n";
- return 1;
+ std::vector<COFFShortExport> Exports, NativeExports;
+
+ if (Args.hasArg(OPT_n)) {
+ if (!isArm64EC(Machine)) {
+ llvm::errs() << "native .def file is supported only on arm64ec target\n";
+ return 1;
+ }
+ if (!parseModuleDefinition(Args.getLastArg(OPT_n)->getValue(),
+ IMAGE_FILE_MACHINE_ARM64, AddUnderscores,
+ NativeExports, OutputFile))
+ return 1;
}
- std::string Path = std::string(Args.getLastArgValue(OPT_l));
+ if (!parseModuleDefinition(Args.getLastArg(OPT_d)->getValue(), Machine,
+ AddUnderscores, Exports, OutputFile))
+ return 1;
- // 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 (COFFShortExport& E : Def->Exports) {
- if (!E.ExtName.empty()) {
- E.Name = E.ExtName;
- E.ExtName.clear();
- }
+ if (OutputFile.empty()) {
+ llvm::errs() << "no DLL name specified\n";
+ return 1;
}
if (Machine == IMAGE_FILE_MACHINE_I386 && Args.hasArg(OPT_k)) {
- for (COFFShortExport& E : Def->Exports) {
+ for (COFFShortExport &E : Exports) {
if (!E.AliasTarget.empty() || (!E.Name.empty() && E.Name[0] == '?'))
continue;
E.SymbolName = E.Name;
@@ -215,8 +242,9 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> ArgsArr) {
}
}
- if (!Path.empty() && writeImportLibrary(Def->OutputFile, Path, Def->Exports,
- Machine, /*MinGW=*/true))
+ std::string Path = std::string(Args.getLastArgValue(OPT_l));
+ if (!Path.empty() && writeImportLibrary(OutputFile, Path, Exports, Machine,
+ /*MinGW=*/true, NativeExports))
return 1;
return 0;
}
diff --git a/llvm/lib/ToolDrivers/llvm-dlltool/Options.td b/llvm/lib/ToolDrivers/llvm-dlltool/Options.td
index fee408fd0e9a80..ba94aed067e6ad 100644
--- a/llvm/lib/ToolDrivers/llvm-dlltool/Options.td
+++ b/llvm/lib/ToolDrivers/llvm-dlltool/Options.td
@@ -12,6 +12,9 @@ def D_long : JoinedOrSeparate<["--"], "dllname">, Alias<D>;
def d: JoinedOrSeparate<["-"], "d">, HelpText<"Input .def File">;
def d_long : JoinedOrSeparate<["--"], "input-def">, Alias<d>;
+def n: JoinedOrSeparate<["-"], "n">, HelpText<"Input native .def File on ARM64EC">;
+def n_long : JoinedOrSeparate<["--"], "input-native-def">, Alias<d>;
+
def k: Flag<["-"], "k">, HelpText<"Kill @n Symbol from export">;
def k_alias: Flag<["--"], "kill-at">, Alias<k>;
diff --git a/llvm/test/tools/llvm-dlltool/arm64ec.test b/llvm/test/tools/llvm-dlltool/arm64ec.test
new file mode 100644
index 00000000000000..77cef16a5fb193
--- /dev/null
+++ b/llvm/test/tools/llvm-dlltool/arm64ec.test
@@ -0,0 +1,46 @@
+Test creating ARM64EC importlib.
+
+RUN: split-file %s %t.dir && cd %t.dir
+
+RUN: llvm-dlltool -m arm64ec -d test.def -l test.lib
+RUN: llvm-nm --print-armap test.lib | FileCheck --check-prefix=ARMAP %s
+
+ARMAP: Archive map
+ARMAP-NEXT: __IMPORT_DESCRIPTOR_test in test.dll
+ARMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll
+ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll
+ARMAP-EMPTY:
+ARMAP-NEXT: Archive EC map
+ARMAP-NEXT: #func in test.dll
+ARMAP-NEXT: __imp_aux_func in test.dll
+ARMAP-NEXT: __imp_func in test.dll
+ARMAP-NEXT: func in test.dll
+
+RUN: llvm-dlltool -m arm64ec -d test.def -n test2.def -l test2.lib
+RUN: llvm-nm --print-armap test2.lib | FileCheck --check-prefix=ARMAP2 %s
+
+ARMAP2: Archive map
+ARMAP2-NEXT: __IMPORT_DESCRIPTOR_test in test.dll
+ARMAP2-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll
+ARMAP2-NEXT: __imp_otherfunc in test.dll
+ARMAP2-NEXT: otherfunc in test.dll
+ARMAP2-NEXT: test_NULL_THUNK_DATA in test.dll
+ARMAP2-EMPTY:
+ARMAP2-NEXT: Archive EC map
+ARMAP2-NEXT: #func in test.dll
+ARMAP2-NEXT: __imp_aux_func in test.dll
+ARMAP2-NEXT: __imp_func in test.dll
+ARMAP2-NEXT: func in test.dll
+
+RUN: not llvm-dlltool -m arm64 -d test.def -n test2.def -l test2.lib 2>&1 | FileCheck --check-prefix=ERR %s
+ERR: native .def file is supported only on arm64ec target
+
+#--- test.def
+LIBRARY test.dll
+EXPORTS
+ func
+
+#--- test2.def
+LIBRARY test.dll
+EXPORTS
+ otherfunc
``````````
</details>
https://github.com/llvm/llvm-project/pull/81624
More information about the llvm-commits
mailing list