Rewrite LLVM's archive writer in Rust
This allows it to be used by other codegen backends
This commit is contained in:
parent
c3a1c023c0
commit
be6708428f
24 changed files with 445 additions and 527 deletions
82
compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
Normal file
82
compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
// Derived from code in LLVM, which is:
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Derived from:
|
||||
// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/include/llvm/Object/ArchiveWriter.h
|
||||
// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/lib/Object/ArchiveWriter.cpp
|
||||
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::sys;
|
||||
using namespace llvm::object;
|
||||
|
||||
static bool isArchiveSymbol(const object::BasicSymbolRef &S) {
|
||||
Expected<uint32_t> SymFlagsOrErr = S.getFlags();
|
||||
if (!SymFlagsOrErr)
|
||||
// FIXME: Actually report errors helpfully.
|
||||
report_fatal_error(SymFlagsOrErr.takeError());
|
||||
if (*SymFlagsOrErr & object::SymbolRef::SF_FormatSpecific)
|
||||
return false;
|
||||
if (!(*SymFlagsOrErr & object::SymbolRef::SF_Global))
|
||||
return false;
|
||||
if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef void *(*LLVMRustGetSymbolsCallback)(void *, const char *);
|
||||
typedef void *(*LLVMRustGetSymbolsErrorCallback)(const char *);
|
||||
|
||||
// Note: This is implemented in C++ instead of using the C api from Rust as IRObjectFile doesn't
|
||||
// implement getSymbolName, only printSymbolName, which is inaccessible from the C api.
|
||||
extern "C" void *LLVMRustGetSymbols(
|
||||
char *BufPtr, size_t BufLen, void *State, LLVMRustGetSymbolsCallback Callback,
|
||||
LLVMRustGetSymbolsErrorCallback ErrorCallback) {
|
||||
std::unique_ptr<MemoryBuffer> Buf =
|
||||
MemoryBuffer::getMemBuffer(StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"),
|
||||
false);
|
||||
SmallString<0> SymNameBuf;
|
||||
raw_svector_ostream SymName(SymNameBuf);
|
||||
|
||||
// In the scenario when LLVMContext is populated SymbolicFile will contain a
|
||||
// reference to it, thus SymbolicFile should be destroyed first.
|
||||
LLVMContext Context;
|
||||
std::unique_ptr<object::SymbolicFile> Obj;
|
||||
|
||||
const file_magic Type = identify_magic(Buf->getBuffer());
|
||||
if (Type != file_magic::bitcode) {
|
||||
return ErrorCallback("not bitcode");
|
||||
}
|
||||
auto ObjOrErr = object::SymbolicFile::createSymbolicFile(
|
||||
Buf->getMemBufferRef(), file_magic::bitcode, &Context);
|
||||
if (!ObjOrErr) {
|
||||
Error E = ObjOrErr.takeError();
|
||||
SmallString<0> ErrorBuf;
|
||||
raw_svector_ostream Error(ErrorBuf);
|
||||
Error << E << '\0';
|
||||
return ErrorCallback(Error.str().data());
|
||||
}
|
||||
Obj = std::move(*ObjOrErr);
|
||||
|
||||
for (const object::BasicSymbolRef &S : Obj->symbols()) {
|
||||
if (!isArchiveSymbol(S))
|
||||
continue;
|
||||
if (Error E = S.printName(SymName)) {
|
||||
SmallString<0> ErrorBuf;
|
||||
raw_svector_ostream Error(ErrorBuf);
|
||||
Error << E << '\0';
|
||||
return ErrorCallback(Error.str().data());
|
||||
}
|
||||
SymName << '\0';
|
||||
if (void *E = Callback(State, SymNameBuf.str().data())) {
|
||||
return E;
|
||||
}
|
||||
SymNameBuf.clear();
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue