[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