Skip to content

[llvm-lib] Add support for -defArm64Native argument. #81426

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions lld/COFF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,7 @@ std::string LinkerDriver::getImportName(bool asLib) {

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

if (!ctx.config.incremental) {
checkError(writeImportLibrary(libName, path, exports, ctx.config.machine,
ctx.config.mingw));
checkError(writeImportLibrary(libName, path, exports, nativeExports,
ctx.config.machine, ctx.config.mingw));
return;
}

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

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

if (Error e = writeImportLibrary(libName, tmpName, exports,
if (Error e = writeImportLibrary(libName, tmpName, exports, nativeExports,
ctx.config.machine, ctx.config.mingw)) {
checkError(std::move(e));
return;
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Object/COFFImportFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ struct COFFShortExport {

Error writeImportLibrary(StringRef ImportName, StringRef Path,
ArrayRef<COFFShortExport> Exports,
ArrayRef<COFFShortExport> NativeExports,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For users of this API, could you add a comment about the difference between Exports and NativeExports?

(Rust is pondering what to do here: rust-lang/rust#120996)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I created #81600 with a clarification.

COFF::MachineTypes Machine, bool MinGW);

} // namespace object
Expand Down
112 changes: 60 additions & 52 deletions llvm/lib/Object/COFFImportFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,

Error writeImportLibrary(StringRef ImportName, StringRef Path,
ArrayRef<COFFShortExport> Exports,
ArrayRef<COFFShortExport> NativeExports,
MachineTypes Machine, bool MinGW) {

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

for (const COFFShortExport &E : Exports) {
if (E.Private)
continue;

ImportType ImportType = IMPORT_CODE;
if (E.Data)
ImportType = IMPORT_DATA;
if (E.Constant)
ImportType = IMPORT_CONST;

StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName;
std::string Name;

if (E.ExtName.empty()) {
Name = std::string(SymbolName);
} else {
Expected<std::string> ReplacedName =
replace(SymbolName, E.Name, E.ExtName);
if (!ReplacedName)
return ReplacedName.takeError();
Name.swap(*ReplacedName);
}
auto addExports = [&](ArrayRef<COFFShortExport> Exp,
MachineTypes M) -> Error {
for (const COFFShortExport &E : Exp) {
if (E.Private)
continue;

ImportType ImportType = IMPORT_CODE;
if (E.Data)
ImportType = IMPORT_DATA;
if (E.Constant)
ImportType = IMPORT_CONST;

StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName;
std::string Name;

if (E.ExtName.empty()) {
Name = std::string(SymbolName);
} else {
Expected<std::string> ReplacedName =
replace(SymbolName, E.Name, E.ExtName);
if (!ReplacedName)
return ReplacedName.takeError();
Name.swap(*ReplacedName);
}

if (!E.AliasTarget.empty() && Name != E.AliasTarget) {
Members.push_back(
OF.createWeakExternal(E.AliasTarget, Name, false, Machine));
Members.push_back(
OF.createWeakExternal(E.AliasTarget, Name, true, Machine));
continue;
}
if (!E.AliasTarget.empty() && Name != E.AliasTarget) {
Members.push_back(OF.createWeakExternal(E.AliasTarget, Name, false, M));
Members.push_back(OF.createWeakExternal(E.AliasTarget, Name, true, M));
continue;
}

ImportNameType NameType;
std::string ExportName;
if (E.Noname) {
NameType = IMPORT_ORDINAL;
} else if (!E.ExportAs.empty()) {
NameType = IMPORT_NAME_EXPORTAS;
ExportName = E.ExportAs;
} else {
NameType = getNameType(SymbolName, E.Name, Machine, MinGW);
}
ImportNameType NameType;
std::string ExportName;
if (E.Noname) {
NameType = IMPORT_ORDINAL;
} else if (!E.ExportAs.empty()) {
NameType = IMPORT_NAME_EXPORTAS;
ExportName = E.ExportAs;
} else {
NameType = getNameType(SymbolName, E.Name, M, MinGW);
}

// On ARM64EC, use EXPORTAS to import demangled name for mangled symbols.
if (ImportType == IMPORT_CODE && isArm64EC(Machine)) {
if (std::optional<std::string> MangledName =
getArm64ECMangledFunctionName(Name)) {
if (ExportName.empty()) {
// On ARM64EC, use EXPORTAS to import demangled name for mangled symbols.
if (ImportType == IMPORT_CODE && isArm64EC(M)) {
if (std::optional<std::string> MangledName =
getArm64ECMangledFunctionName(Name)) {
if (ExportName.empty()) {
NameType = IMPORT_NAME_EXPORTAS;
ExportName.swap(Name);
}
Name = std::move(*MangledName);
} else if (ExportName.empty()) {
NameType = IMPORT_NAME_EXPORTAS;
ExportName.swap(Name);
ExportName = std::move(*getArm64ECDemangledFunctionName(Name));
}
Name = std::move(*MangledName);
} else if (ExportName.empty()) {
NameType = IMPORT_NAME_EXPORTAS;
ExportName = std::move(*getArm64ECDemangledFunctionName(Name));
}

Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType,
NameType, ExportName, M));
}
return Error::success();
};

Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType,
NameType, ExportName, Machine));
}
if (Error e = addExports(Exports, Machine))
return e;
if (Error e = addExports(NativeExports, NativeMachine))
return e;

return writeArchive(Path, Members, SymtabWritingMode::NormalSymtab,
MinGW ? object::Archive::K_GNU : object::Archive::K_COFF,
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,9 @@ int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> ArgsArr) {
}
}

if (!Path.empty() && writeImportLibrary(Def->OutputFile, Path, Def->Exports,
Machine, /*MinGW=*/true))
if (!Path.empty() &&
writeImportLibrary(Def->OutputFile, Path, Def->Exports, std::nullopt,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that you're passing std::nullopt here, while in lld/COFF, you pass a real initialized array (which isn't ever used other than passing into this function). Is this because you're planning on using the array in lld?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I plan on using it in both llvm-dlltool and lld. I plan to submit llvm-dlltool as soon as this PR settles, lld part will need general ARM64X support in lld, to it will take more time. There was no strong reason to differentiate them in this PR, I guess it was easy to extract the declaration in lld from my WIP tree, while llvm-dlltool will need a small bit of refactoring.

Machine, /*MinGW=*/true))
return 1;
return 0;
}
30 changes: 28 additions & 2 deletions llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,34 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
return 1;
}

return writeImportLibrary(Def->OutputFile, OutputPath, Def->Exports,
LibMachine,
std::vector<COFFShortExport> NativeExports;
std::string OutputFile = Def->OutputFile;

if (isArm64EC(LibMachine) && Args.hasArg(OPT_nativedeffile)) {
std::unique_ptr<MemoryBuffer> NativeMB =
openFile(Args.getLastArg(OPT_nativedeffile)->getValue());
if (!NativeMB)
return 1;

if (!NativeMB->getBufferSize()) {
llvm::errs() << "native definition file empty\n";
return 1;
}

Expected<COFFModuleDefinition> NativeDef =
parseCOFFModuleDefinition(*NativeMB, COFF::IMAGE_FILE_MACHINE_ARM64);

if (!NativeDef) {
llvm::errs() << "error parsing native definition\n"
<< errorToErrorCode(NativeDef.takeError()).message();
return 1;
}
NativeExports = std::move(NativeDef->Exports);
OutputFile = std::move(NativeDef->OutputFile);
}

return writeImportLibrary(OutputFile, OutputPath, Def->Exports,
NativeExports, LibMachine,
/*MinGW=*/false)
? 1
: 0;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/ToolDrivers/llvm-lib/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def libpath: P<"libpath", "Object file search path">;
def lst : F<"list">, HelpText<"List contents of .lib file on stdout">;
def out : P<"out", "Path to file to write output">;
def deffile : P<"def", "def file to use to generate import library">;
def nativedeffile : P<"defArm64Native", "def file to use to generate native ARM64 symbols in ARM64EC import library">;

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