#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/Analysis.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Mangler.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCExpr.h"
llvm::TargetMachine *TM)
: IRFile(std::move(Obj)), _target(TM) {}
+LTOModule::LTOModule(std::unique_ptr<object::IRObjectFile> Obj,
+ llvm::TargetMachine *TM,
+ std::unique_ptr<LLVMContext> Context)
+ : OwnedContext(std::move(Context)), IRFile(std::move(Obj)), _target(TM) {}
+
+LTOModule::~LTOModule() {}
+
/// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM
/// bitcode.
bool LTOModule::isBitcodeFile(const void *Mem, size_t Length) {
IRObjectFile::findBitcodeInMemBuffer(Buffer->getMemBufferRef());
if (!BCOrErr)
return false;
- std::string Triple = getBitcodeTargetTriple(*BCOrErr, getGlobalContext());
+ LLVMContext Context;
+ std::string Triple = getBitcodeTargetTriple(*BCOrErr, Context);
return StringRef(Triple).startswith(TriplePrefix);
}
-LTOModule *LTOModule::createFromFile(const char *path, TargetOptions options,
- std::string &errMsg) {
+std::string LTOModule::getProducerString(MemoryBuffer *Buffer) {
+ ErrorOr<MemoryBufferRef> BCOrErr =
+ IRObjectFile::findBitcodeInMemBuffer(Buffer->getMemBufferRef());
+ if (!BCOrErr)
+ return "";
+ LLVMContext Context;
+ return getBitcodeProducerString(*BCOrErr, Context);
+}
+
+ErrorOr<std::unique_ptr<LTOModule>>
+LTOModule::createFromFile(LLVMContext &Context, const char *path,
+ TargetOptions options) {
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
MemoryBuffer::getFile(path);
- if (std::error_code EC = BufferOrErr.getError()) {
- errMsg = EC.message();
- return nullptr;
- }
+ if (std::error_code EC = BufferOrErr.getError())
+ return EC;
std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrErr.get());
- return makeLTOModule(Buffer->getMemBufferRef(), options, errMsg);
+ return makeLTOModule(Buffer->getMemBufferRef(), options, &Context);
}
-LTOModule *LTOModule::createFromOpenFile(int fd, const char *path, size_t size,
- TargetOptions options,
- std::string &errMsg) {
- return createFromOpenFileSlice(fd, path, size, 0, options, errMsg);
+ErrorOr<std::unique_ptr<LTOModule>>
+LTOModule::createFromOpenFile(LLVMContext &Context, int fd, const char *path,
+ size_t size, TargetOptions options) {
+ return createFromOpenFileSlice(Context, fd, path, size, 0, options);
}
-LTOModule *LTOModule::createFromOpenFileSlice(int fd, const char *path,
- size_t map_size, off_t offset,
- TargetOptions options,
- std::string &errMsg) {
+ErrorOr<std::unique_ptr<LTOModule>>
+LTOModule::createFromOpenFileSlice(LLVMContext &Context, int fd,
+ const char *path, size_t map_size,
+ off_t offset, TargetOptions options) {
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
MemoryBuffer::getOpenFileSlice(fd, path, map_size, offset);
- if (std::error_code EC = BufferOrErr.getError()) {
- errMsg = EC.message();
- return nullptr;
- }
+ if (std::error_code EC = BufferOrErr.getError())
+ return EC;
std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrErr.get());
- return makeLTOModule(Buffer->getMemBufferRef(), options, errMsg);
+ return makeLTOModule(Buffer->getMemBufferRef(), options, &Context);
}
-LTOModule *LTOModule::createFromBuffer(const void *mem, size_t length,
- TargetOptions options,
- std::string &errMsg, StringRef path) {
+ErrorOr<std::unique_ptr<LTOModule>>
+LTOModule::createFromBuffer(LLVMContext &Context, const void *mem,
+ size_t length, TargetOptions options,
+ StringRef path) {
+ return createInContext(mem, length, options, path, &Context);
+}
+
+ErrorOr<std::unique_ptr<LTOModule>>
+LTOModule::createInLocalContext(const void *mem, size_t length,
+ TargetOptions options, StringRef path) {
+ return createInContext(mem, length, options, path, nullptr);
+}
+
+ErrorOr<std::unique_ptr<LTOModule>>
+LTOModule::createInContext(const void *mem, size_t length,
+ TargetOptions options, StringRef path,
+ LLVMContext *Context) {
StringRef Data((const char *)mem, length);
MemoryBufferRef Buffer(Data, path);
- return makeLTOModule(Buffer, options, errMsg);
+ return makeLTOModule(Buffer, options, Context);
}
-LTOModule *LTOModule::makeLTOModule(MemoryBufferRef Buffer,
- TargetOptions options,
- std::string &errMsg) {
+static ErrorOr<std::unique_ptr<Module>>
+parseBitcodeFileImpl(MemoryBufferRef Buffer, LLVMContext &Context,
+ bool ShouldBeLazy) {
+
+ // Find the buffer.
ErrorOr<MemoryBufferRef> MBOrErr =
IRObjectFile::findBitcodeInMemBuffer(Buffer);
- if (std::error_code EC = MBOrErr.getError()) {
- errMsg = EC.message();
- return nullptr;
+ if (std::error_code EC = MBOrErr.getError())
+ return EC;
+
+ if (!ShouldBeLazy) {
+ // Parse the full file.
+ ErrorOr<std::unique_ptr<Module>> M = parseBitcodeFile(*MBOrErr, Context);
+ if (std::error_code EC = M.getError())
+ return EC;
+ return std::move(*M);
}
- ErrorOr<Module *> MOrErr = parseBitcodeFile(*MBOrErr, getGlobalContext());
- if (std::error_code EC = MOrErr.getError()) {
- errMsg = EC.message();
- return nullptr;
+
+ // Parse lazily.
+ std::unique_ptr<MemoryBuffer> LightweightBuf =
+ MemoryBuffer::getMemBuffer(*MBOrErr, false);
+ ErrorOr<std::unique_ptr<Module>> M = getLazyBitcodeModule(
+ std::move(LightweightBuf), Context, true /*ShouldLazyLoadMetadata*/);
+ if (std::error_code EC = M.getError())
+ return EC;
+ return std::move(*M);
+}
+
+ErrorOr<std::unique_ptr<LTOModule>>
+LTOModule::makeLTOModule(MemoryBufferRef Buffer, TargetOptions options,
+ LLVMContext *Context) {
+ std::unique_ptr<LLVMContext> OwnedContext;
+ if (!Context) {
+ OwnedContext = llvm::make_unique<LLVMContext>();
+ Context = OwnedContext.get();
}
- std::unique_ptr<Module> M(MOrErr.get());
+
+ // If we own a context, we know this is being used only for symbol
+ // extraction, not linking. Be lazy in that case.
+ ErrorOr<std::unique_ptr<Module>> MOrErr =
+ parseBitcodeFileImpl(Buffer, *Context,
+ /* ShouldBeLazy */ static_cast<bool>(OwnedContext));
+ if (std::error_code EC = MOrErr.getError())
+ return EC;
+ std::unique_ptr<Module> &M = *MOrErr;
std::string TripleStr = M->getTargetTriple();
if (TripleStr.empty())
llvm::Triple Triple(TripleStr);
// find machine architecture for this module
+ std::string errMsg;
const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg);
if (!march)
- return nullptr;
+ return std::unique_ptr<LTOModule>(nullptr);
// construct LTOModule, hand over ownership of module and target
SubtargetFeatures Features;
TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr,
options);
- M->setDataLayout(target->getSubtargetImpl()->getDataLayout());
+ M->setDataLayout(target->createDataLayout());
std::unique_ptr<object::IRObjectFile> IRObj(
new object::IRObjectFile(Buffer, std::move(M)));
- LTOModule *Ret = new LTOModule(std::move(IRObj), target);
-
- if (Ret->parseSymbols(errMsg)) {
- delete Ret;
- return nullptr;
- }
+ std::unique_ptr<LTOModule> Ret;
+ if (OwnedContext)
+ Ret.reset(new LTOModule(std::move(IRObj), target, std::move(OwnedContext)));
+ else
+ Ret.reset(new LTOModule(std::move(IRObj), target));
+ Ret->parseSymbols();
Ret->parseMetadata();
- return Ret;
+ return std::move(Ret);
}
/// Create a MemoryBuffer from a memory range with an optional name.
Constant *cn = gvn->getInitializer();
if (ConstantDataArray *ca = dyn_cast<ConstantDataArray>(cn)) {
if (ca->isCString()) {
- name = ".objc_class_name_" + ca->getAsCString().str();
+ name = (".objc_class_name_" + ca->getAsCString()).str();
return true;
}
}
// second slot in __OBJC,__class is pointer to superclass name
std::string superclassName;
if (objcClassNameFromExpression(c->getOperand(1), superclassName)) {
- NameAndAttributes info;
- StringMap<NameAndAttributes>::value_type &entry =
- _undefines.GetOrCreateValue(superclassName);
- if (!entry.getValue().name) {
- const char *symbolName = entry.getKey().data();
- info.name = symbolName;
+ auto IterBool =
+ _undefines.insert(std::make_pair(superclassName, NameAndAttributes()));
+ if (IterBool.second) {
+ NameAndAttributes &info = IterBool.first->second;
+ info.name = IterBool.first->first().data();
info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
info.isFunction = false;
info.symbol = clgv;
- entry.setValue(info);
}
}
// third slot in __OBJC,__class is pointer to class name
std::string className;
if (objcClassNameFromExpression(c->getOperand(2), className)) {
- StringSet::value_type &entry = _defines.GetOrCreateValue(className);
- entry.setValue(1);
+ auto Iter = _defines.insert(className).first;
NameAndAttributes info;
- info.name = entry.getKey().data();
+ info.name = Iter->first().data();
info.attributes = LTO_SYMBOL_PERMISSIONS_DATA |
LTO_SYMBOL_DEFINITION_REGULAR | LTO_SYMBOL_SCOPE_DEFAULT;
info.isFunction = false;
if (!objcClassNameFromExpression(c->getOperand(1), targetclassName))
return;
- NameAndAttributes info;
- StringMap<NameAndAttributes>::value_type &entry =
- _undefines.GetOrCreateValue(targetclassName);
+ auto IterBool =
+ _undefines.insert(std::make_pair(targetclassName, NameAndAttributes()));
- if (entry.getValue().name)
+ if (!IterBool.second)
return;
- const char *symbolName = entry.getKey().data();
- info.name = symbolName;
+ NameAndAttributes &info = IterBool.first->second;
+ info.name = IterBool.first->first().data();
info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
info.isFunction = false;
info.symbol = clgv;
- entry.setValue(info);
}
/// addObjCClassRef - Parse i386/ppc ObjC class list data structure.
if (!objcClassNameFromExpression(clgv->getInitializer(), targetclassName))
return;
- NameAndAttributes info;
- StringMap<NameAndAttributes>::value_type &entry =
- _undefines.GetOrCreateValue(targetclassName);
- if (entry.getValue().name)
+ auto IterBool =
+ _undefines.insert(std::make_pair(targetclassName, NameAndAttributes()));
+
+ if (!IterBool.second)
return;
- const char *symbolName = entry.getKey().data();
- info.name = symbolName;
+ NameAndAttributes &info = IterBool.first->second;
+ info.name = IterBool.first->first().data();
info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
info.isFunction = false;
info.symbol = clgv;
- entry.setValue(info);
}
void LTOModule::addDefinedDataSymbol(const object::BasicSymbolRef &Sym) {
else
attr |= LTO_SYMBOL_SCOPE_DEFAULT;
- StringSet::value_type &entry = _defines.GetOrCreateValue(Name);
- entry.setValue(1);
+ if (def->hasComdat())
+ attr |= LTO_SYMBOL_COMDAT;
+
+ if (isa<GlobalAlias>(def))
+ attr |= LTO_SYMBOL_ALIAS;
+
+ auto Iter = _defines.insert(Name).first;
// fill information structure
NameAndAttributes info;
- StringRef NameRef = entry.getKey();
+ StringRef NameRef = Iter->first();
info.name = NameRef.data();
assert(info.name[NameRef.size()] == '\0');
info.attributes = attr;
/// defined list.
void LTOModule::addAsmGlobalSymbol(const char *name,
lto_symbol_attributes scope) {
- StringSet::value_type &entry = _defines.GetOrCreateValue(name);
+ auto IterBool = _defines.insert(name);
// only add new define if not already defined
- if (entry.getValue())
+ if (!IterBool.second)
return;
- entry.setValue(1);
-
- NameAndAttributes &info = _undefines[entry.getKey().data()];
+ NameAndAttributes &info = _undefines[IterBool.first->first().data()];
if (info.symbol == nullptr) {
// FIXME: This is trying to take care of module ASM like this:
// much.
// fill information structure
- info.name = entry.getKey().data();
+ info.name = IterBool.first->first().data();
info.attributes =
LTO_SYMBOL_PERMISSIONS_DATA | LTO_SYMBOL_DEFINITION_REGULAR | scope;
info.isFunction = false;
/// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to the
/// undefined list.
void LTOModule::addAsmGlobalSymbolUndef(const char *name) {
- StringMap<NameAndAttributes>::value_type &entry =
- _undefines.GetOrCreateValue(name);
+ auto IterBool = _undefines.insert(std::make_pair(name, NameAndAttributes()));
- _asm_undefines.push_back(entry.getKey().data());
+ _asm_undefines.push_back(IterBool.first->first().data());
// we already have the symbol
- if (entry.getValue().name)
+ if (!IterBool.second)
return;
uint32_t attr = LTO_SYMBOL_DEFINITION_UNDEFINED;
attr |= LTO_SYMBOL_SCOPE_DEFAULT;
- NameAndAttributes info;
- info.name = entry.getKey().data();
+ NameAndAttributes &info = IterBool.first->second;
+ info.name = IterBool.first->first().data();
info.attributes = attr;
info.isFunction = false;
info.symbol = nullptr;
-
- entry.setValue(info);
}
/// Add a symbol which isn't defined just yet to a list to be resolved later.
Sym.printName(OS);
}
- StringMap<NameAndAttributes>::value_type &entry =
- _undefines.GetOrCreateValue(name);
+ auto IterBool = _undefines.insert(std::make_pair(name, NameAndAttributes()));
// we already have the symbol
- if (entry.getValue().name)
+ if (!IterBool.second)
return;
- NameAndAttributes info;
+ NameAndAttributes &info = IterBool.first->second;
- info.name = entry.getKey().data();
+ info.name = IterBool.first->first().data();
const GlobalValue *decl = IRFile->getSymbolGV(Sym.getRawDataRefImpl());
info.isFunction = isFunc;
info.symbol = decl;
-
- entry.setValue(info);
}
-/// parseSymbols - Parse the symbols from the module and model-level ASM and add
-/// them to either the defined or undefined lists.
-bool LTOModule::parseSymbols(std::string &errMsg) {
+void LTOModule::parseSymbols() {
for (auto &Sym : IRFile->symbols()) {
const GlobalValue *GV = IRFile->getSymbolGV(Sym.getRawDataRefImpl());
uint32_t Flags = Sym.getFlags();
NameAndAttributes info = u->getValue();
_symbols.push_back(info);
}
-
- return false;
}
/// parseMetadata - Parse metadata from the module
void LTOModule::parseMetadata() {
+ raw_string_ostream OS(LinkerOpts);
+
// Linker Options
- if (Value *Val = getModule().getModuleFlag("Linker Options")) {
+ if (Metadata *Val = getModule().getModuleFlag("Linker Options")) {
MDNode *LinkerOptions = cast<MDNode>(Val);
for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) {
MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i));
for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) {
MDString *MDOption = cast<MDString>(MDOptions->getOperand(ii));
- StringRef Op = _linkeropt_strings.
- GetOrCreateValue(MDOption->getString()).getKey();
- StringRef DepLibName = _target->getSubtargetImpl()
- ->getTargetLowering()
- ->getObjFileLowering()
- .getDepLibFromLinkerOpt(Op);
- if (!DepLibName.empty())
- _deplibs.push_back(DepLibName.data());
- else if (!Op.empty())
- _linkeropts.push_back(Op.data());
+ OS << " " << MDOption->getString();
}
}
}
+ // Globals
+ Mangler Mang;
+ for (const NameAndAttributes &Sym : _symbols) {
+ if (!Sym.symbol)
+ continue;
+ _target->getObjFileLowering()->emitLinkerFlagsForGlobal(OS, Sym.symbol,
+ Mang);
+ }
+
// Add other interesting metadata here.
}