1
Fork 0

Auto merge of #84171 - ricobbe:raw-dylib-via-llvm, r=petrochenkov

Partial support for raw-dylib linkage

First cut of functionality for issue #58713: add support for `#[link(kind = "raw-dylib")]` on `extern` blocks in lib crates compiled to .rlib files.  Does not yet support `#[link_name]` attributes on functions, or the `#[link_ordinal]` attribute, or `#[link(kind = "raw-dylib")]` on `extern` blocks in bin crates; I intend to publish subsequent PRs to fill those gaps.  It's also not yet clear whether this works for functions in `extern "stdcall"` blocks; I also intend to investigate that shortly and make any necessary changes as a follow-on PR.

This implementation calls out to an LLVM function to construct the actual `.idata` sections as temporary `.lib` files on disk and then links those into the generated .rlib.
This commit is contained in:
bors 2021-06-06 03:59:17 +00:00
commit 9a576175cc
27 changed files with 481 additions and 20 deletions

View file

@ -6,6 +6,7 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFFImportFile.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/Support/Signals.h"
@ -1722,3 +1723,54 @@ extern "C" LLVMValueRef
LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
}
// This struct contains all necessary info about a symbol exported from a DLL.
// At the moment, it's just the symbol's name, but we use a separate struct to
// make it easier to add other information like ordinal later.
struct LLVMRustCOFFShortExport {
const char* name;
};
// Machine must be a COFF machine type, as defined in PE specs.
extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
const char* ImportName,
const char* Path,
const LLVMRustCOFFShortExport* Exports,
size_t NumExports,
uint16_t Machine,
bool MinGW)
{
std::vector<llvm::object::COFFShortExport> ConvertedExports;
ConvertedExports.reserve(NumExports);
for (size_t i = 0; i < NumExports; ++i) {
ConvertedExports.push_back(llvm::object::COFFShortExport{
Exports[i].name, // Name
std::string{}, // ExtName
std::string{}, // SymbolName
std::string{}, // AliasTarget
0, // Ordinal
false, // Noname
false, // Data
false, // Private
false // Constant
});
}
auto Error = llvm::object::writeImportLibrary(
ImportName,
Path,
ConvertedExports,
static_cast<llvm::COFF::MachineTypes>(Machine),
MinGW);
if (Error) {
std::string errorString;
llvm::raw_string_ostream stream(errorString);
stream << Error;
stream.flush();
LLVMRustSetLastError(errorString.c_str());
return LLVMRustResult::Failure;
} else {
return LLVMRustResult::Success;
}
}