Skip to content

Commit a38152e

Browse files
authored
[llvm-lib] Add support for -defArm64Native argument. (#81426)
This can be used to create import libraries that contain both ARM64EC and native exports. The implementation follows observed MSVC lib.exe behaviour. It's ignored on targets other than ARM64EC.
1 parent ecd63af commit a38152e

File tree

7 files changed

+306
-62
lines changed

7 files changed

+306
-62
lines changed

lld/COFF/Driver.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,7 @@ std::string LinkerDriver::getImportName(bool asLib) {
939939

940940
void LinkerDriver::createImportLibrary(bool asLib) {
941941
llvm::TimeTraceScope timeScope("Create import library");
942-
std::vector<COFFShortExport> exports;
942+
std::vector<COFFShortExport> exports, nativeExports;
943943
for (Export &e1 : ctx.config.exports) {
944944
COFFShortExport e2;
945945
e2.Name = std::string(e1.name);
@@ -958,8 +958,8 @@ void LinkerDriver::createImportLibrary(bool asLib) {
958958
std::string path = getImplibPath();
959959

960960
if (!ctx.config.incremental) {
961-
checkError(writeImportLibrary(libName, path, exports, ctx.config.machine,
962-
ctx.config.mingw));
961+
checkError(writeImportLibrary(libName, path, exports, nativeExports,
962+
ctx.config.machine, ctx.config.mingw));
963963
return;
964964
}
965965

@@ -968,8 +968,8 @@ void LinkerDriver::createImportLibrary(bool asLib) {
968968
ErrorOr<std::unique_ptr<MemoryBuffer>> oldBuf = MemoryBuffer::getFile(
969969
path, /*IsText=*/false, /*RequiresNullTerminator=*/false);
970970
if (!oldBuf) {
971-
checkError(writeImportLibrary(libName, path, exports, ctx.config.machine,
972-
ctx.config.mingw));
971+
checkError(writeImportLibrary(libName, path, exports, nativeExports,
972+
ctx.config.machine, ctx.config.mingw));
973973
return;
974974
}
975975

@@ -979,7 +979,7 @@ void LinkerDriver::createImportLibrary(bool asLib) {
979979
fatal("cannot create temporary file for import library " + path + ": " +
980980
ec.message());
981981

982-
if (Error e = writeImportLibrary(libName, tmpName, exports,
982+
if (Error e = writeImportLibrary(libName, tmpName, exports, nativeExports,
983983
ctx.config.machine, ctx.config.mingw)) {
984984
checkError(std::move(e));
985985
return;

llvm/include/llvm/Object/COFFImportFile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ struct COFFShortExport {
137137

138138
Error writeImportLibrary(StringRef ImportName, StringRef Path,
139139
ArrayRef<COFFShortExport> Exports,
140+
ArrayRef<COFFShortExport> NativeExports,
140141
COFF::MachineTypes Machine, bool MinGW);
141142

142143
} // namespace object

llvm/lib/Object/COFFImportFile.cpp

Lines changed: 60 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,7 @@ NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,
625625

626626
Error writeImportLibrary(StringRef ImportName, StringRef Path,
627627
ArrayRef<COFFShortExport> Exports,
628+
ArrayRef<COFFShortExport> NativeExports,
628629
MachineTypes Machine, bool MinGW) {
629630

630631
MachineTypes NativeMachine =
@@ -642,66 +643,73 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path,
642643
std::vector<uint8_t> NullThunk;
643644
Members.push_back(OF.createNullThunk(NullThunk));
644645

645-
for (const COFFShortExport &E : Exports) {
646-
if (E.Private)
647-
continue;
648-
649-
ImportType ImportType = IMPORT_CODE;
650-
if (E.Data)
651-
ImportType = IMPORT_DATA;
652-
if (E.Constant)
653-
ImportType = IMPORT_CONST;
654-
655-
StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName;
656-
std::string Name;
657-
658-
if (E.ExtName.empty()) {
659-
Name = std::string(SymbolName);
660-
} else {
661-
Expected<std::string> ReplacedName =
662-
replace(SymbolName, E.Name, E.ExtName);
663-
if (!ReplacedName)
664-
return ReplacedName.takeError();
665-
Name.swap(*ReplacedName);
666-
}
646+
auto addExports = [&](ArrayRef<COFFShortExport> Exp,
647+
MachineTypes M) -> Error {
648+
for (const COFFShortExport &E : Exp) {
649+
if (E.Private)
650+
continue;
651+
652+
ImportType ImportType = IMPORT_CODE;
653+
if (E.Data)
654+
ImportType = IMPORT_DATA;
655+
if (E.Constant)
656+
ImportType = IMPORT_CONST;
657+
658+
StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName;
659+
std::string Name;
660+
661+
if (E.ExtName.empty()) {
662+
Name = std::string(SymbolName);
663+
} else {
664+
Expected<std::string> ReplacedName =
665+
replace(SymbolName, E.Name, E.ExtName);
666+
if (!ReplacedName)
667+
return ReplacedName.takeError();
668+
Name.swap(*ReplacedName);
669+
}
667670

668-
if (!E.AliasTarget.empty() && Name != E.AliasTarget) {
669-
Members.push_back(
670-
OF.createWeakExternal(E.AliasTarget, Name, false, Machine));
671-
Members.push_back(
672-
OF.createWeakExternal(E.AliasTarget, Name, true, Machine));
673-
continue;
674-
}
671+
if (!E.AliasTarget.empty() && Name != E.AliasTarget) {
672+
Members.push_back(OF.createWeakExternal(E.AliasTarget, Name, false, M));
673+
Members.push_back(OF.createWeakExternal(E.AliasTarget, Name, true, M));
674+
continue;
675+
}
675676

676-
ImportNameType NameType;
677-
std::string ExportName;
678-
if (E.Noname) {
679-
NameType = IMPORT_ORDINAL;
680-
} else if (!E.ExportAs.empty()) {
681-
NameType = IMPORT_NAME_EXPORTAS;
682-
ExportName = E.ExportAs;
683-
} else {
684-
NameType = getNameType(SymbolName, E.Name, Machine, MinGW);
685-
}
677+
ImportNameType NameType;
678+
std::string ExportName;
679+
if (E.Noname) {
680+
NameType = IMPORT_ORDINAL;
681+
} else if (!E.ExportAs.empty()) {
682+
NameType = IMPORT_NAME_EXPORTAS;
683+
ExportName = E.ExportAs;
684+
} else {
685+
NameType = getNameType(SymbolName, E.Name, M, MinGW);
686+
}
686687

687-
// On ARM64EC, use EXPORTAS to import demangled name for mangled symbols.
688-
if (ImportType == IMPORT_CODE && isArm64EC(Machine)) {
689-
if (std::optional<std::string> MangledName =
690-
getArm64ECMangledFunctionName(Name)) {
691-
if (ExportName.empty()) {
688+
// On ARM64EC, use EXPORTAS to import demangled name for mangled symbols.
689+
if (ImportType == IMPORT_CODE && isArm64EC(M)) {
690+
if (std::optional<std::string> MangledName =
691+
getArm64ECMangledFunctionName(Name)) {
692+
if (ExportName.empty()) {
693+
NameType = IMPORT_NAME_EXPORTAS;
694+
ExportName.swap(Name);
695+
}
696+
Name = std::move(*MangledName);
697+
} else if (ExportName.empty()) {
692698
NameType = IMPORT_NAME_EXPORTAS;
693-
ExportName.swap(Name);
699+
ExportName = std::move(*getArm64ECDemangledFunctionName(Name));
694700
}
695-
Name = std::move(*MangledName);
696-
} else if (ExportName.empty()) {
697-
NameType = IMPORT_NAME_EXPORTAS;
698-
ExportName = std::move(*getArm64ECDemangledFunctionName(Name));
699701
}
702+
703+
Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType,
704+
NameType, ExportName, M));
700705
}
706+
return Error::success();
707+
};
701708

702-
Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType,
703-
NameType, ExportName, Machine));
704-
}
709+
if (Error e = addExports(Exports, Machine))
710+
return e;
711+
if (Error e = addExports(NativeExports, NativeMachine))
712+
return e;
705713

706714
return writeArchive(Path, Members, SymtabWritingMode::NormalSymtab,
707715
MinGW ? object::Archive::K_GNU : object::Archive::K_COFF,

llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,9 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> ArgsArr) {
215215
}
216216
}
217217

218-
if (!Path.empty() && writeImportLibrary(Def->OutputFile, Path, Def->Exports,
219-
Machine, /*MinGW=*/true))
218+
if (!Path.empty() &&
219+
writeImportLibrary(Def->OutputFile, Path, Def->Exports, std::nullopt,
220+
Machine, /*MinGW=*/true))
220221
return 1;
221222
return 0;
222223
}

llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,34 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
392392
return 1;
393393
}
394394

395-
return writeImportLibrary(Def->OutputFile, OutputPath, Def->Exports,
396-
LibMachine,
395+
std::vector<COFFShortExport> NativeExports;
396+
std::string OutputFile = Def->OutputFile;
397+
398+
if (isArm64EC(LibMachine) && Args.hasArg(OPT_nativedeffile)) {
399+
std::unique_ptr<MemoryBuffer> NativeMB =
400+
openFile(Args.getLastArg(OPT_nativedeffile)->getValue());
401+
if (!NativeMB)
402+
return 1;
403+
404+
if (!NativeMB->getBufferSize()) {
405+
llvm::errs() << "native definition file empty\n";
406+
return 1;
407+
}
408+
409+
Expected<COFFModuleDefinition> NativeDef =
410+
parseCOFFModuleDefinition(*NativeMB, COFF::IMAGE_FILE_MACHINE_ARM64);
411+
412+
if (!NativeDef) {
413+
llvm::errs() << "error parsing native definition\n"
414+
<< errorToErrorCode(NativeDef.takeError()).message();
415+
return 1;
416+
}
417+
NativeExports = std::move(NativeDef->Exports);
418+
OutputFile = std::move(NativeDef->OutputFile);
419+
}
420+
421+
return writeImportLibrary(OutputFile, OutputPath, Def->Exports,
422+
NativeExports, LibMachine,
397423
/*MinGW=*/false)
398424
? 1
399425
: 0;

llvm/lib/ToolDrivers/llvm-lib/Options.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def libpath: P<"libpath", "Object file search path">;
2323
def lst : F<"list">, HelpText<"List contents of .lib file on stdout">;
2424
def out : P<"out", "Path to file to write output">;
2525
def deffile : P<"def", "def file to use to generate import library">;
26+
def nativedeffile : P<"defArm64Native", "def file to use to generate native ARM64 symbols in ARM64EC import library">;
2627

2728
def llvmlibthin : F<"llvmlibthin">,
2829
HelpText<"Make .lib point to .obj files instead of copying their contents">;

0 commit comments

Comments
 (0)