#include "llvm-c/lto.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/Object/IRObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include <string>
#include <vector>
const GlobalValue *symbol;
};
- std::unique_ptr<Module> _module;
+ std::unique_ptr<object::IRObjectFile> IRFile;
std::unique_ptr<TargetMachine> _target;
- MCObjectFileInfo ObjFileInfo;
StringSet _linkeropt_strings;
std::vector<const char *> _deplibs;
std::vector<const char *> _linkeropts;
StringSet _defines;
StringMap<NameAndAttributes> _undefines;
std::vector<const char*> _asm_undefines;
- MCContext _context;
- // Use mangler to add GlobalPrefix to names to match linker names.
- Mangler _mangler;
-
- LTOModule(std::unique_ptr<Module> M, TargetMachine *TM);
+ LTOModule(std::unique_ptr<object::IRObjectFile> Obj, TargetMachine *TM);
public:
/// Returns 'true' if the file or memory contents is LLVM bitcode.
TargetOptions options, std::string &errMsg,
StringRef path = "");
+ const Module &getModule() const {
+ return const_cast<LTOModule*>(this)->getModule();
+ }
+ Module &getModule() {
+ return IRFile->getModule();
+ }
+
/// Return the Module's target triple.
const std::string &getTargetTriple() {
- return _module->getTargetTriple();
+ return getModule().getTargetTriple();
}
/// Set the Module's target triple.
void setTargetTriple(StringRef Triple) {
- _module->setTargetTriple(Triple);
+ getModule().setTargetTriple(Triple);
}
/// Get the number of symbols
return nullptr;
}
- /// Return the Module.
- Module *getLLVVMModule() { return _module.get(); }
-
const std::vector<const char*> &getAsmUndefinedRefs() {
return _asm_undefines;
}
bool parseSymbols(std::string &errMsg);
/// Add a symbol which isn't defined just yet to a list to be resolved later.
- void addPotentialUndefinedSymbol(const GlobalValue *dcl, bool isFunc);
+ void addPotentialUndefinedSymbol(const object::BasicSymbolRef &Sym,
+ bool isFunc);
/// Add a defined symbol to the list.
- void addDefinedSymbol(const char *Name, const GlobalValue *Def,
- bool IsFunction);
-
- /// Add a function symbol as defined to the list.
- void addDefinedFunctionSymbol(const Function *f);
- void addDefinedFunctionSymbol(const char *Name, const Function *F);
+ void addDefinedSymbol(const char *Name, const GlobalValue *def,
+ bool isFunction);
/// Add a data symbol as defined to the list.
- void addDefinedDataSymbol(const GlobalValue *v);
- void addDefinedDataSymbol(const char *Name, const GlobalValue *V);
+ void addDefinedDataSymbol(const object::BasicSymbolRef &Sym);
+ void addDefinedDataSymbol(const char*Name, const GlobalValue *v);
- /// Add global symbols from module-level ASM to the defined or undefined
- /// lists.
- bool addAsmGlobalSymbols(std::string &errMsg);
+ /// Add a function symbol as defined to the list.
+ void addDefinedFunctionSymbol(const object::BasicSymbolRef &Sym);
+ void addDefinedFunctionSymbol(const char *Name, const Function *F);
/// Add a global symbol from module-level ASM to the defined list.
void addAsmGlobalSymbol(const char *, lto_symbol_attributes scope);
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/MC/SubtargetFeature.h"
-#include "llvm/Object/RecordStreamer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include <system_error>
using namespace llvm;
-LTOModule::LTOModule(std::unique_ptr<Module> M, TargetMachine *TM)
- : _module(std::move(M)), _target(TM),
- _context(_target->getMCAsmInfo(), _target->getRegisterInfo(),
- &ObjFileInfo),
- _mangler(TM->getDataLayout()) {
- ObjFileInfo.InitMCObjectFileInfo(TM->getTargetTriple(),
- TM->getRelocationModel(), TM->getCodeModel(),
- _context);
-}
+LTOModule::LTOModule(std::unique_ptr<object::IRObjectFile> Obj,
+ llvm::TargetMachine *TM)
+ : IRFile(std::move(Obj)), _target(TM) {}
/// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM
/// bitcode.
LTOModule *LTOModule::makeLTOModule(std::unique_ptr<MemoryBuffer> Buffer,
TargetOptions options,
std::string &errMsg) {
- // parse bitcode buffer
- ErrorOr<Module *> ModuleOrErr =
+ ErrorOr<Module *> MOrErr =
getLazyBitcodeModule(Buffer.get(), getGlobalContext());
- if (std::error_code EC = ModuleOrErr.getError()) {
+ if (std::error_code EC = MOrErr.getError()) {
errMsg = EC.message();
return nullptr;
}
- Buffer.release();
- std::unique_ptr<Module> m(ModuleOrErr.get());
+ std::unique_ptr<Module> M(MOrErr.get());
- std::string TripleStr = m->getTargetTriple();
+ std::string TripleStr = M->getTargetTriple();
if (TripleStr.empty())
TripleStr = sys::getDefaultTargetTriple();
llvm::Triple Triple(TripleStr);
TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr,
options);
- m->materializeAllPermanently();
+ M->materializeAllPermanently(true);
+ M->setDataLayout(target->getDataLayout());
- LTOModule *Ret = new LTOModule(std::move(m), target);
+ std::unique_ptr<object::IRObjectFile> IRObj(
+ new object::IRObjectFile(std::move(Buffer), std::move(M)));
- // We need a MCContext set up in order to get mangled names of private
- // symbols. It is a bit odd that we need to report uses and definitions
- // of private symbols, but it does look like ld64 expects to be informed
- // of at least the ones with an 'l' prefix.
- MCContext &Context = Ret->_context;
- const TargetLoweringObjectFile &TLOF =
- target->getTargetLowering()->getObjFileLowering();
- const_cast<TargetLoweringObjectFile &>(TLOF).Initialize(Context, *target);
+ LTOModule *Ret = new LTOModule(std::move(IRObj), target);
if (Ret->parseSymbols(errMsg)) {
delete Ret;
entry.setValue(info);
}
-void LTOModule::addDefinedDataSymbol(const GlobalValue *V) {
+void LTOModule::addDefinedDataSymbol(const object::BasicSymbolRef &Sym) {
SmallString<64> Buffer;
- _target->getNameWithPrefix(Buffer, V, _mangler);
+ {
+ raw_svector_ostream OS(Buffer);
+ Sym.printName(OS);
+ }
+
+ const GlobalValue *V = IRFile->getSymbolGV(Sym.getRawDataRefImpl());
addDefinedDataSymbol(Buffer.c_str(), V);
}
}
}
-void LTOModule::addDefinedFunctionSymbol(const Function *F) {
+void LTOModule::addDefinedFunctionSymbol(const object::BasicSymbolRef &Sym) {
SmallString<64> Buffer;
- _target->getNameWithPrefix(Buffer, F, _mangler);
+ {
+ raw_svector_ostream OS(Buffer);
+ Sym.printName(OS);
+ }
+
+ const Function *F =
+ cast<Function>(IRFile->getSymbolGV(Sym.getRawDataRefImpl()));
addDefinedFunctionSymbol(Buffer.c_str(), F);
}
void LTOModule::addDefinedSymbol(const char *Name, const GlobalValue *def,
bool isFunction) {
- // ignore all llvm.* symbols
- if (def->getName().startswith("llvm."))
- return;
-
// set alignment part log2() can have rounding errors
uint32_t align = def->getAlignment();
uint32_t attr = align ? countTrailingZeros(align) : 0;
entry.setValue(info);
}
-/// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet to a
-/// list to be resolved later.
-void
-LTOModule::addPotentialUndefinedSymbol(const GlobalValue *decl, bool isFunc) {
- // ignore all llvm.* symbols
- if (decl->getName().startswith("llvm."))
- return;
-
- // ignore all aliases
- if (isa<GlobalAlias>(decl))
- return;
-
+/// Add a symbol which isn't defined just yet to a list to be resolved later.
+void LTOModule::addPotentialUndefinedSymbol(const object::BasicSymbolRef &Sym,
+ bool isFunc) {
SmallString<64> name;
- _target->getNameWithPrefix(name, decl, _mangler);
+ {
+ raw_svector_ostream OS(name);
+ Sym.printName(OS);
+ }
StringMap<NameAndAttributes>::value_type &entry =
_undefines.GetOrCreateValue(name);
info.name = entry.getKey().data();
+ const GlobalValue *decl = IRFile->getSymbolGV(Sym.getRawDataRefImpl());
+
if (decl->hasExternalWeakLinkage())
info.attributes = LTO_SYMBOL_DEFINITION_WEAKUNDEF;
else
entry.setValue(info);
}
-/// addAsmGlobalSymbols - Add global symbols from module-level ASM to the
-/// defined or undefined lists.
-bool LTOModule::addAsmGlobalSymbols(std::string &errMsg) {
- const std::string &inlineAsm = _module->getModuleInlineAsm();
- if (inlineAsm.empty())
- return false;
-
- std::unique_ptr<RecordStreamer> Streamer(new RecordStreamer(_context));
- MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(inlineAsm);
- SourceMgr SrcMgr;
- SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
- std::unique_ptr<MCAsmParser> Parser(
- createMCAsmParser(SrcMgr, _context, *Streamer, *_target->getMCAsmInfo()));
- const Target &T = _target->getTarget();
- std::unique_ptr<MCInstrInfo> MCII(T.createMCInstrInfo());
- std::unique_ptr<MCSubtargetInfo> STI(T.createMCSubtargetInfo(
- _target->getTargetTriple(), _target->getTargetCPU(),
- _target->getTargetFeatureString()));
- std::unique_ptr<MCTargetAsmParser> TAP(
- T.createMCAsmParser(*STI, *Parser.get(), *MCII,
- _target->Options.MCOptions));
- if (!TAP) {
- errMsg = "target " + std::string(T.getName()) +
- " does not define AsmParser.";
- return true;
- }
-
- Parser->setTargetParser(*TAP);
- if (Parser->Run(false))
- return true;
-
- for (auto &KV : *Streamer) {
- StringRef Key = KV.first();
- RecordStreamer::State Value = KV.second;
- if (Value == RecordStreamer::DefinedGlobal)
- addAsmGlobalSymbol(Key.data(), LTO_SYMBOL_SCOPE_DEFAULT);
- else if (Value == RecordStreamer::Defined)
- addAsmGlobalSymbol(Key.data(), LTO_SYMBOL_SCOPE_INTERNAL);
- else if (Value == RecordStreamer::Global ||
- Value == RecordStreamer::Used)
- addAsmGlobalSymbolUndef(Key.data());
- }
-
- return false;
-}
-
-/// isDeclaration - Return 'true' if the global value is a declaration.
-static bool isDeclaration(const GlobalValue &V) {
- if (V.hasAvailableExternallyLinkage())
- return true;
-
- if (V.isMaterializable())
- return false;
-
- return V.isDeclaration();
-}
-
/// 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) {
- // add functions
- for (Module::iterator f = _module->begin(), e = _module->end(); f != e; ++f) {
- if (isDeclaration(*f))
- addPotentialUndefinedSymbol(f, true);
- else
- addDefinedFunctionSymbol(f);
- }
+ for (auto &Sym : IRFile->symbols()) {
+ const GlobalValue *GV = IRFile->getSymbolGV(Sym.getRawDataRefImpl());
+ uint32_t Flags = Sym.getFlags();
+ bool IsUndefined = Flags & object::BasicSymbolRef::SF_Undefined;
+
+ if (!GV) {
+ SmallString<64> Buffer;
+ {
+ raw_svector_ostream OS(Buffer);
+ Sym.printName(OS);
+ }
+ const char *Name = Buffer.c_str();
+
+ if (IsUndefined)
+ addAsmGlobalSymbolUndef(Name);
+ else if (Flags & object::BasicSymbolRef::SF_Global)
+ addAsmGlobalSymbol(Name, LTO_SYMBOL_SCOPE_DEFAULT);
+ else
+ addAsmGlobalSymbol(Name, LTO_SYMBOL_SCOPE_INTERNAL);
+ continue;
+ }
- // add data
- for (Module::global_iterator v = _module->global_begin(),
- e = _module->global_end(); v != e; ++v) {
- if (isDeclaration(*v))
- addPotentialUndefinedSymbol(v, false);
- else
- addDefinedDataSymbol(v);
- }
+ auto *F = dyn_cast<Function>(GV);
+ if (IsUndefined) {
+ addPotentialUndefinedSymbol(Sym, F != nullptr);
+ continue;
+ }
- // add asm globals
- if (addAsmGlobalSymbols(errMsg))
- return true;
+ if (F) {
+ addDefinedFunctionSymbol(Sym);
+ continue;
+ }
- // add aliases
- for (const auto &Alias : _module->aliases())
- addDefinedDataSymbol(&Alias);
+ if (isa<GlobalVariable>(GV)) {
+ addDefinedDataSymbol(Sym);
+ continue;
+ }
+
+ assert(isa<GlobalAlias>(GV));
+ addDefinedDataSymbol(Sym);
+ }
// make symbols for all undefines
for (StringMap<NameAndAttributes>::iterator u =_undefines.begin(),
/// parseMetadata - Parse metadata from the module
void LTOModule::parseMetadata() {
// Linker Options
- if (Value *Val = _module->getModuleFlag("Linker Options")) {
+ if (Value *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));