1
Fork 0

Move rustllvm into rustc_llvm

This commit is contained in:
Vadim Petrochenkov 2020-07-26 20:11:30 +03:00
parent d92155bf6a
commit 10d3f8a484
17 changed files with 23 additions and 27 deletions

View file

@ -0,0 +1,6 @@
[*.{h,cpp}]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 2

View file

@ -0,0 +1,226 @@
#include "LLVMWrapper.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Support/Path.h"
using namespace llvm;
using namespace llvm::object;
struct RustArchiveMember {
const char *Filename;
const char *Name;
Archive::Child Child;
RustArchiveMember()
: Filename(nullptr), Name(nullptr),
Child(nullptr, nullptr, nullptr)
{
}
~RustArchiveMember() {}
};
struct RustArchiveIterator {
bool First;
Archive::child_iterator Cur;
Archive::child_iterator End;
std::unique_ptr<Error> Err;
RustArchiveIterator(Archive::child_iterator Cur, Archive::child_iterator End,
std::unique_ptr<Error> Err)
: First(true),
Cur(Cur),
End(End),
Err(std::move(Err)) {}
};
enum class LLVMRustArchiveKind {
GNU,
BSD,
DARWIN,
COFF,
};
static Archive::Kind fromRust(LLVMRustArchiveKind Kind) {
switch (Kind) {
case LLVMRustArchiveKind::GNU:
return Archive::K_GNU;
case LLVMRustArchiveKind::BSD:
return Archive::K_BSD;
case LLVMRustArchiveKind::DARWIN:
return Archive::K_DARWIN;
case LLVMRustArchiveKind::COFF:
return Archive::K_COFF;
default:
report_fatal_error("Bad ArchiveKind.");
}
}
typedef OwningBinary<Archive> *LLVMRustArchiveRef;
typedef RustArchiveMember *LLVMRustArchiveMemberRef;
typedef Archive::Child *LLVMRustArchiveChildRef;
typedef Archive::Child const *LLVMRustArchiveChildConstRef;
typedef RustArchiveIterator *LLVMRustArchiveIteratorRef;
extern "C" LLVMRustArchiveRef LLVMRustOpenArchive(char *Path) {
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOr =
MemoryBuffer::getFile(Path, -1, false);
if (!BufOr) {
LLVMRustSetLastError(BufOr.getError().message().c_str());
return nullptr;
}
Expected<std::unique_ptr<Archive>> ArchiveOr =
Archive::create(BufOr.get()->getMemBufferRef());
if (!ArchiveOr) {
LLVMRustSetLastError(toString(ArchiveOr.takeError()).c_str());
return nullptr;
}
OwningBinary<Archive> *Ret = new OwningBinary<Archive>(
std::move(ArchiveOr.get()), std::move(BufOr.get()));
return Ret;
}
extern "C" void LLVMRustDestroyArchive(LLVMRustArchiveRef RustArchive) {
delete RustArchive;
}
extern "C" LLVMRustArchiveIteratorRef
LLVMRustArchiveIteratorNew(LLVMRustArchiveRef RustArchive) {
Archive *Archive = RustArchive->getBinary();
#if LLVM_VERSION_GE(10, 0)
std::unique_ptr<Error> Err = std::make_unique<Error>(Error::success());
#else
std::unique_ptr<Error> Err = llvm::make_unique<Error>(Error::success());
#endif
auto Cur = Archive->child_begin(*Err);
if (*Err) {
LLVMRustSetLastError(toString(std::move(*Err)).c_str());
return nullptr;
}
auto End = Archive->child_end();
return new RustArchiveIterator(Cur, End, std::move(Err));
}
extern "C" LLVMRustArchiveChildConstRef
LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef RAI) {
if (RAI->Cur == RAI->End)
return nullptr;
// Advancing the iterator validates the next child, and this can
// uncover an error. LLVM requires that we check all Errors,
// so we only advance the iterator if we actually need to fetch
// the next child.
// This means we must not advance the iterator in the *first* call,
// but instead advance it *before* fetching the child in all later calls.
if (!RAI->First) {
++RAI->Cur;
if (*RAI->Err) {
LLVMRustSetLastError(toString(std::move(*RAI->Err)).c_str());
return nullptr;
}
} else {
RAI->First = false;
}
if (RAI->Cur == RAI->End)
return nullptr;
const Archive::Child &Child = *RAI->Cur.operator->();
Archive::Child *Ret = new Archive::Child(Child);
return Ret;
}
extern "C" void LLVMRustArchiveChildFree(LLVMRustArchiveChildRef Child) {
delete Child;
}
extern "C" void LLVMRustArchiveIteratorFree(LLVMRustArchiveIteratorRef RAI) {
delete RAI;
}
extern "C" const char *
LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef Child, size_t *Size) {
Expected<StringRef> NameOrErr = Child->getName();
if (!NameOrErr) {
// rustc_codegen_llvm currently doesn't use this error string, but it might be
// useful in the future, and in the mean time this tells LLVM that the
// error was not ignored and that it shouldn't abort the process.
LLVMRustSetLastError(toString(NameOrErr.takeError()).c_str());
return nullptr;
}
StringRef Name = NameOrErr.get();
*Size = Name.size();
return Name.data();
}
extern "C" const char *LLVMRustArchiveChildData(LLVMRustArchiveChildRef Child,
size_t *Size) {
StringRef Buf;
Expected<StringRef> BufOrErr = Child->getBuffer();
if (!BufOrErr) {
LLVMRustSetLastError(toString(BufOrErr.takeError()).c_str());
return nullptr;
}
Buf = BufOrErr.get();
*Size = Buf.size();
return Buf.data();
}
extern "C" LLVMRustArchiveMemberRef
LLVMRustArchiveMemberNew(char *Filename, char *Name,
LLVMRustArchiveChildRef Child) {
RustArchiveMember *Member = new RustArchiveMember;
Member->Filename = Filename;
Member->Name = Name;
if (Child)
Member->Child = *Child;
return Member;
}
extern "C" void LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) {
delete Member;
}
extern "C" LLVMRustResult
LLVMRustWriteArchive(char *Dst, size_t NumMembers,
const LLVMRustArchiveMemberRef *NewMembers,
bool WriteSymbtab, LLVMRustArchiveKind RustKind) {
std::vector<NewArchiveMember> Members;
auto Kind = fromRust(RustKind);
for (size_t I = 0; I < NumMembers; I++) {
auto Member = NewMembers[I];
assert(Member->Name);
if (Member->Filename) {
Expected<NewArchiveMember> MOrErr =
NewArchiveMember::getFile(Member->Filename, true);
if (!MOrErr) {
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
return LLVMRustResult::Failure;
}
MOrErr->MemberName = sys::path::filename(MOrErr->MemberName);
Members.push_back(std::move(*MOrErr));
} else {
Expected<NewArchiveMember> MOrErr =
NewArchiveMember::getOldMember(Member->Child, true);
if (!MOrErr) {
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
return LLVMRustResult::Failure;
}
Members.push_back(std::move(*MOrErr));
}
}
auto Result = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false);
if (!Result)
return LLVMRustResult::Success;
LLVMRustSetLastError(toString(std::move(Result)).c_str());
return LLVMRustResult::Failure;
}

View file

@ -0,0 +1,70 @@
#include "LLVMWrapper.h"
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/LEB128.h"
#include <iostream>
using namespace llvm;
extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
const char* const Filenames[],
size_t FilenamesLen,
RustStringRef BufferOut) {
// LLVM 11's CoverageFilenamesSectionWriter uses its new `Version4` format,
// so we're manually writing the `Version3` format ourselves.
RawRustStringOstream OS(BufferOut);
encodeULEB128(FilenamesLen, OS);
for (size_t i = 0; i < FilenamesLen; i++) {
StringRef Filename(Filenames[i]);
encodeULEB128(Filename.size(), OS);
OS << Filename;
}
}
extern "C" void LLVMRustCoverageWriteMappingToBuffer(
const unsigned *VirtualFileMappingIDs,
unsigned NumVirtualFileMappingIDs,
const coverage::CounterExpression *Expressions,
unsigned NumExpressions,
coverage::CounterMappingRegion *MappingRegions,
unsigned NumMappingRegions,
RustStringRef BufferOut) {
auto CoverageMappingWriter = coverage::CoverageMappingWriter(
makeArrayRef(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
makeArrayRef(Expressions, NumExpressions),
makeMutableArrayRef(MappingRegions, NumMappingRegions));
RawRustStringOstream OS(BufferOut);
CoverageMappingWriter.write(OS);
}
extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F, const char *FuncName) {
StringRef FuncNameRef(FuncName);
return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef));
}
extern "C" uint64_t LLVMRustCoverageComputeHash(const char *Name) {
StringRef NameRef(Name);
return IndexedInstrProf::ComputeHash(NameRef);
}
extern "C" void LLVMRustCoverageWriteSectionNameToString(LLVMModuleRef M,
RustStringRef Str) {
Triple TargetTriple(unwrap(M)->getTargetTriple());
auto name = getInstrProfSectionName(IPSK_covmap,
TargetTriple.getObjectFormat());
RawRustStringOstream OS(Str);
OS << name;
}
extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) {
auto name = getCoverageMappingVarName();
RawRustStringOstream OS(Str);
OS << name;
}
extern "C" uint32_t LLVMRustCoverageMappingVersion() {
return coverage::CovMapVersion::Version3;
}

View file

@ -0,0 +1,115 @@
#include "llvm-c/BitReader.h"
#include "llvm-c/Core.h"
#include "llvm-c/Object.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/Lint.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Vectorize.h"
#define LLVM_VERSION_GE(major, minor) \
(LLVM_VERSION_MAJOR > (major) || \
LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR >= (minor))
#define LLVM_VERSION_EQ(major, minor) \
(LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR == (minor))
#define LLVM_VERSION_LE(major, minor) \
(LLVM_VERSION_MAJOR < (major) || \
LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR <= (minor))
#define LLVM_VERSION_LT(major, minor) (!LLVM_VERSION_GE((major), (minor)))
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/Linker/Linker.h"
extern "C" void LLVMRustSetLastError(const char *);
enum class LLVMRustResult { Success, Failure };
enum LLVMRustAttribute {
AlwaysInline = 0,
ByVal = 1,
Cold = 2,
InlineHint = 3,
MinSize = 4,
Naked = 5,
NoAlias = 6,
NoCapture = 7,
NoInline = 8,
NonNull = 9,
NoRedZone = 10,
NoReturn = 11,
NoUnwind = 12,
OptimizeForSize = 13,
ReadOnly = 14,
SExt = 15,
StructRet = 16,
UWTable = 17,
ZExt = 18,
InReg = 19,
SanitizeThread = 20,
SanitizeAddress = 21,
SanitizeMemory = 22,
NonLazyBind = 23,
OptimizeNone = 24,
ReturnsTwice = 25,
ReadNone = 26,
InaccessibleMemOnly = 27,
};
typedef struct OpaqueRustString *RustStringRef;
typedef struct LLVMOpaqueTwine *LLVMTwineRef;
typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef;
extern "C" void LLVMRustStringWriteImpl(RustStringRef Str, const char *Ptr,
size_t Size);
class RawRustStringOstream : public llvm::raw_ostream {
RustStringRef Str;
uint64_t Pos;
void write_impl(const char *Ptr, size_t Size) override {
LLVMRustStringWriteImpl(Str, Ptr, Size);
Pos += Size;
}
uint64_t current_pos() const override { return Pos; }
public:
explicit RawRustStringOstream(RustStringRef Str) : Str(Str), Pos(0) {}
~RawRustStringOstream() {
// LLVM requires this.
flush();
}
};

View file

@ -0,0 +1,48 @@
#include "llvm/Linker/Linker.h"
#include "LLVMWrapper.h"
using namespace llvm;
struct RustLinker {
Linker L;
LLVMContext &Ctx;
RustLinker(Module &M) :
L(M),
Ctx(M.getContext())
{}
};
extern "C" RustLinker*
LLVMRustLinkerNew(LLVMModuleRef DstRef) {
Module *Dst = unwrap(DstRef);
return new RustLinker(*Dst);
}
extern "C" void
LLVMRustLinkerFree(RustLinker *L) {
delete L;
}
extern "C" bool
LLVMRustLinkerAdd(RustLinker *L, char *BC, size_t Len) {
std::unique_ptr<MemoryBuffer> Buf =
MemoryBuffer::getMemBufferCopy(StringRef(BC, Len));
Expected<std::unique_ptr<Module>> SrcOrError =
llvm::getLazyBitcodeModule(Buf->getMemBufferRef(), L->Ctx);
if (!SrcOrError) {
LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
return false;
}
auto Src = std::move(*SrcOrError);
if (L->L.linkInModule(std::move(Src))) {
LLVMRustSetLastError("");
return false;
}
return true;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,16 @@
This directory currently contains some LLVM support code. This will generally
be sent upstream to LLVM in time; for now it lives here.
NOTE: the LLVM C++ ABI is subject to between-version breakage and must *never*
be exposed to Rust. To allow for easy auditing of that, all Rust-exposed types
must be typedef-ed as "LLVMXyz", or "LLVMRustXyz" if they were defined here.
Functions that return a failure status and leave the error in
the LLVM last error should return an LLVMRustResult rather than an
int or anything to avoid confusion.
When translating enums, add a single `Other` variant as the first
one to allow for new variants to be added. It should abort when used
as an input.
All other types must not be typedef-ed as such.

File diff suppressed because it is too large Load diff