Skip to content

Commit 5094f4c

Browse files
committed
[llvm-lib] Add support for -defArm64Native argument.
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 3a080a0 commit 5094f4c

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)