mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-12 03:32:10 +00:00
Add a special streamer to libLTO that just records symbols definitions and
uses. The result produced by the streamer is used to give the linker more accurate information and to add to llvm.compiler.used. The second improvement removes the need for the user to add __attribute__((used)) to functions only used in inline asm. The first one lets us build firefox with LTO on Darwin :-) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@126830 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f7af396c95
commit
38c4e53549
@ -211,15 +211,20 @@ public:
|
|||||||
void setTargetTriple(StringRef T) { TargetTriple = T; }
|
void setTargetTriple(StringRef T) { TargetTriple = T; }
|
||||||
|
|
||||||
/// Set the module-scope inline assembly blocks.
|
/// Set the module-scope inline assembly blocks.
|
||||||
void setModuleInlineAsm(StringRef Asm) { GlobalScopeAsm = Asm; }
|
void setModuleInlineAsm(StringRef Asm) {
|
||||||
|
GlobalScopeAsm = Asm;
|
||||||
|
if (!GlobalScopeAsm.empty() &&
|
||||||
|
GlobalScopeAsm[GlobalScopeAsm.size()-1] != '\n')
|
||||||
|
GlobalScopeAsm += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
/// Append to the module-scope inline assembly blocks, automatically inserting
|
/// Append to the module-scope inline assembly blocks, automatically inserting
|
||||||
/// a separating newline if necessary.
|
/// a separating newline if necessary.
|
||||||
void appendModuleInlineAsm(StringRef Asm) {
|
void appendModuleInlineAsm(StringRef Asm) {
|
||||||
|
GlobalScopeAsm += Asm;
|
||||||
if (!GlobalScopeAsm.empty() &&
|
if (!GlobalScopeAsm.empty() &&
|
||||||
GlobalScopeAsm[GlobalScopeAsm.size()-1] != '\n')
|
GlobalScopeAsm[GlobalScopeAsm.size()-1] != '\n')
|
||||||
GlobalScopeAsm += '\n';
|
GlobalScopeAsm += '\n';
|
||||||
GlobalScopeAsm += Asm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
@ -249,11 +249,7 @@ bool LLParser::ParseModuleAsm() {
|
|||||||
if (ParseToken(lltok::kw_asm, "expected 'module asm'") ||
|
if (ParseToken(lltok::kw_asm, "expected 'module asm'") ||
|
||||||
ParseStringConstant(AsmStr)) return true;
|
ParseStringConstant(AsmStr)) return true;
|
||||||
|
|
||||||
const std::string &AsmSoFar = M->getModuleInlineAsm();
|
M->appendModuleInlineAsm(AsmStr);
|
||||||
if (AsmSoFar.empty())
|
|
||||||
M->setModuleInlineAsm(AsmStr);
|
|
||||||
else
|
|
||||||
M->setModuleInlineAsm(AsmSoFar+"\n"+AsmStr);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1338,9 +1338,12 @@ void AssemblyWriter::printModule(const Module *M) {
|
|||||||
CurPos = NewLine+1;
|
CurPos = NewLine+1;
|
||||||
NewLine = Asm.find_first_of('\n', CurPos);
|
NewLine = Asm.find_first_of('\n', CurPos);
|
||||||
}
|
}
|
||||||
Out << "module asm \"";
|
std::string rest(Asm.begin()+CurPos, Asm.end());
|
||||||
PrintEscapedString(std::string(Asm.begin()+CurPos, Asm.end()), Out);
|
if (!rest.empty()) {
|
||||||
Out << "\"\n";
|
Out << "module asm \"";
|
||||||
|
PrintEscapedString(rest, Out);
|
||||||
|
Out << "\"\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop over the dependent libraries and emit them.
|
// Loop over the dependent libraries and emit them.
|
||||||
|
@ -75,7 +75,6 @@ LTOCodeGenerator::LTOCodeGenerator()
|
|||||||
{
|
{
|
||||||
InitializeAllTargets();
|
InitializeAllTargets();
|
||||||
InitializeAllAsmPrinters();
|
InitializeAllAsmPrinters();
|
||||||
InitializeAllAsmParsers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LTOCodeGenerator::~LTOCodeGenerator()
|
LTOCodeGenerator::~LTOCodeGenerator()
|
||||||
@ -88,7 +87,13 @@ LTOCodeGenerator::~LTOCodeGenerator()
|
|||||||
|
|
||||||
bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg)
|
bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg)
|
||||||
{
|
{
|
||||||
return _linker.LinkInModule(mod->getLLVVMModule(), &errMsg);
|
bool ret = _linker.LinkInModule(mod->getLLVVMModule(), &errMsg);
|
||||||
|
|
||||||
|
const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs();
|
||||||
|
for (int i = 0, e = undefs.size(); i != e; ++i)
|
||||||
|
_asmUndefinedRefs[undefs[i]] = 1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -249,6 +254,34 @@ bool LTOCodeGenerator::determineTarget(std::string& errMsg)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LTOCodeGenerator::applyRestriction(GlobalValue &GV,
|
||||||
|
std::vector<const char*> &mustPreserveList,
|
||||||
|
SmallPtrSet<GlobalValue*, 8> &asmUsed,
|
||||||
|
Mangler &mangler) {
|
||||||
|
SmallString<64> Buffer;
|
||||||
|
mangler.getNameWithPrefix(Buffer, &GV, false);
|
||||||
|
|
||||||
|
if (GV.isDeclaration())
|
||||||
|
return;
|
||||||
|
if (_mustPreserveSymbols.count(Buffer))
|
||||||
|
mustPreserveList.push_back(GV.getName().data());
|
||||||
|
if (_asmUndefinedRefs.count(Buffer))
|
||||||
|
asmUsed.insert(&GV);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void findUsedValues(GlobalVariable *LLVMUsed,
|
||||||
|
SmallPtrSet<GlobalValue*, 8> &UsedValues) {
|
||||||
|
if (LLVMUsed == 0) return;
|
||||||
|
|
||||||
|
ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer());
|
||||||
|
if (Inits == 0) return;
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
|
||||||
|
if (GlobalValue *GV =
|
||||||
|
dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
|
||||||
|
UsedValues.insert(GV);
|
||||||
|
}
|
||||||
|
|
||||||
void LTOCodeGenerator::applyScopeRestrictions() {
|
void LTOCodeGenerator::applyScopeRestrictions() {
|
||||||
if (_scopeRestrictionsDone) return;
|
if (_scopeRestrictionsDone) return;
|
||||||
Module *mergedModule = _linker.getModule();
|
Module *mergedModule = _linker.getModule();
|
||||||
@ -258,38 +291,47 @@ void LTOCodeGenerator::applyScopeRestrictions() {
|
|||||||
passes.add(createVerifierPass());
|
passes.add(createVerifierPass());
|
||||||
|
|
||||||
// mark which symbols can not be internalized
|
// mark which symbols can not be internalized
|
||||||
if (!_mustPreserveSymbols.empty()) {
|
MCContext Context(*_target->getMCAsmInfo(), NULL);
|
||||||
MCContext Context(*_target->getMCAsmInfo(), NULL);
|
Mangler mangler(Context, *_target->getTargetData());
|
||||||
Mangler mangler(Context, *_target->getTargetData());
|
std::vector<const char*> mustPreserveList;
|
||||||
std::vector<const char*> mustPreserveList;
|
SmallPtrSet<GlobalValue*, 8> asmUsed;
|
||||||
SmallString<64> Buffer;
|
|
||||||
for (Module::iterator f = mergedModule->begin(),
|
for (Module::iterator f = mergedModule->begin(),
|
||||||
e = mergedModule->end(); f != e; ++f) {
|
e = mergedModule->end(); f != e; ++f)
|
||||||
Buffer.clear();
|
applyRestriction(*f, mustPreserveList, asmUsed, mangler);
|
||||||
mangler.getNameWithPrefix(Buffer, f, false);
|
for (Module::global_iterator v = mergedModule->global_begin(),
|
||||||
if (!f->isDeclaration() &&
|
e = mergedModule->global_end(); v != e; ++v)
|
||||||
_mustPreserveSymbols.count(Buffer))
|
applyRestriction(*v, mustPreserveList, asmUsed, mangler);
|
||||||
mustPreserveList.push_back(f->getName().data());
|
for (Module::alias_iterator a = mergedModule->alias_begin(),
|
||||||
}
|
e = mergedModule->alias_end(); a != e; ++a)
|
||||||
for (Module::global_iterator v = mergedModule->global_begin(),
|
applyRestriction(*a, mustPreserveList, asmUsed, mangler);
|
||||||
e = mergedModule->global_end(); v != e; ++v) {
|
|
||||||
Buffer.clear();
|
GlobalVariable *LLVMCompilerUsed =
|
||||||
mangler.getNameWithPrefix(Buffer, v, false);
|
mergedModule->getGlobalVariable("llvm.compiler.used");
|
||||||
if (!v->isDeclaration() &&
|
findUsedValues(LLVMCompilerUsed, asmUsed);
|
||||||
_mustPreserveSymbols.count(Buffer))
|
if (LLVMCompilerUsed)
|
||||||
mustPreserveList.push_back(v->getName().data());
|
LLVMCompilerUsed->eraseFromParent();
|
||||||
}
|
|
||||||
for (Module::alias_iterator a = mergedModule->alias_begin(),
|
const llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context);
|
||||||
e = mergedModule->alias_end(); a != e; ++a) {
|
std::vector<Constant*> asmUsed2;
|
||||||
Buffer.clear();
|
for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = asmUsed.begin(),
|
||||||
mangler.getNameWithPrefix(Buffer, a, false);
|
e = asmUsed.end(); i !=e; ++i) {
|
||||||
if (!a->isDeclaration() &&
|
GlobalValue *GV = *i;
|
||||||
_mustPreserveSymbols.count(Buffer))
|
Constant *c = ConstantExpr::getBitCast(GV, i8PTy);
|
||||||
mustPreserveList.push_back(a->getName().data());
|
asmUsed2.push_back(c);
|
||||||
}
|
|
||||||
passes.add(createInternalizePass(mustPreserveList));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size());
|
||||||
|
LLVMCompilerUsed =
|
||||||
|
new llvm::GlobalVariable(*mergedModule, ATy, false,
|
||||||
|
llvm::GlobalValue::AppendingLinkage,
|
||||||
|
llvm::ConstantArray::get(ATy, asmUsed2),
|
||||||
|
"llvm.compiler.used");
|
||||||
|
|
||||||
|
LLVMCompilerUsed->setSection("llvm.metadata");
|
||||||
|
|
||||||
|
passes.add(createInternalizePass(mustPreserveList));
|
||||||
|
|
||||||
// apply scope restrictions
|
// apply scope restrictions
|
||||||
passes.run(*mergedModule);
|
passes.run(*mergedModule);
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "llvm/LLVMContext.h"
|
#include "llvm/LLVMContext.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -46,6 +47,10 @@ private:
|
|||||||
bool generateObjectFile(llvm::raw_ostream& out,
|
bool generateObjectFile(llvm::raw_ostream& out,
|
||||||
std::string& errMsg);
|
std::string& errMsg);
|
||||||
void applyScopeRestrictions();
|
void applyScopeRestrictions();
|
||||||
|
void applyRestriction(llvm::GlobalValue &GV,
|
||||||
|
std::vector<const char*> &mustPreserveList,
|
||||||
|
llvm::SmallPtrSet<llvm::GlobalValue*, 8> &asmUsed,
|
||||||
|
llvm::Mangler &mangler);
|
||||||
bool determineTarget(std::string& errMsg);
|
bool determineTarget(std::string& errMsg);
|
||||||
|
|
||||||
typedef llvm::StringMap<uint8_t> StringSet;
|
typedef llvm::StringMap<uint8_t> StringSet;
|
||||||
@ -57,6 +62,7 @@ private:
|
|||||||
bool _scopeRestrictionsDone;
|
bool _scopeRestrictionsDone;
|
||||||
lto_codegen_model _codeModel;
|
lto_codegen_model _codeModel;
|
||||||
StringSet _mustPreserveSymbols;
|
StringSet _mustPreserveSymbols;
|
||||||
|
StringSet _asmUndefinedRefs;
|
||||||
llvm::MemoryBuffer* _nativeObjectFile;
|
llvm::MemoryBuffer* _nativeObjectFile;
|
||||||
std::vector<const char*> _codegenOptions;
|
std::vector<const char*> _codegenOptions;
|
||||||
std::string _mCpu;
|
std::string _mCpu;
|
||||||
|
@ -26,11 +26,18 @@
|
|||||||
#include "llvm/Support/Host.h"
|
#include "llvm/Support/Host.h"
|
||||||
#include "llvm/Support/Path.h"
|
#include "llvm/Support/Path.h"
|
||||||
#include "llvm/Support/Process.h"
|
#include "llvm/Support/Process.h"
|
||||||
|
#include "llvm/Support/SourceMgr.h"
|
||||||
#include "llvm/Support/system_error.h"
|
#include "llvm/Support/system_error.h"
|
||||||
#include "llvm/Target/Mangler.h"
|
#include "llvm/Target/Mangler.h"
|
||||||
#include "llvm/Target/SubtargetFeature.h"
|
#include "llvm/Target/SubtargetFeature.h"
|
||||||
#include "llvm/MC/MCAsmInfo.h"
|
#include "llvm/MC/MCAsmInfo.h"
|
||||||
#include "llvm/MC/MCContext.h"
|
#include "llvm/MC/MCContext.h"
|
||||||
|
#include "llvm/MC/MCExpr.h"
|
||||||
|
#include "llvm/MC/MCInst.h"
|
||||||
|
#include "llvm/MC/MCParser/MCAsmParser.h"
|
||||||
|
#include "llvm/MC/MCStreamer.h"
|
||||||
|
#include "llvm/MC/MCSymbol.h"
|
||||||
|
#include "llvm/Target/TargetAsmParser.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Target/TargetRegistry.h"
|
#include "llvm/Target/TargetRegistry.h"
|
||||||
#include "llvm/Target/TargetSelect.h"
|
#include "llvm/Target/TargetSelect.h"
|
||||||
@ -73,7 +80,7 @@ bool LTOModule::isTargetMatch(MemoryBuffer *buffer, const char *triplePrefix) {
|
|||||||
|
|
||||||
|
|
||||||
LTOModule::LTOModule(Module *m, TargetMachine *t)
|
LTOModule::LTOModule(Module *m, TargetMachine *t)
|
||||||
: _module(m), _target(t), _symbolsParsed(false)
|
: _module(m), _target(t)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +130,12 @@ LTOModule *LTOModule::makeLTOModule(const void *mem, size_t length,
|
|||||||
|
|
||||||
LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer,
|
LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer,
|
||||||
std::string &errMsg) {
|
std::string &errMsg) {
|
||||||
InitializeAllTargets();
|
static bool Initialized = false;
|
||||||
|
if (!Initialized) {
|
||||||
|
InitializeAllTargets();
|
||||||
|
InitializeAllAsmParsers();
|
||||||
|
Initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
// parse bitcode buffer
|
// parse bitcode buffer
|
||||||
OwningPtr<Module> m(ParseBitcodeFile(buffer, getGlobalContext(), &errMsg));
|
OwningPtr<Module> m(ParseBitcodeFile(buffer, getGlobalContext(), &errMsg));
|
||||||
@ -144,7 +156,13 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer,
|
|||||||
Features.getDefaultSubtargetFeatures("" /* cpu */, llvm::Triple(Triple));
|
Features.getDefaultSubtargetFeatures("" /* cpu */, llvm::Triple(Triple));
|
||||||
std::string FeatureStr = Features.getString();
|
std::string FeatureStr = Features.getString();
|
||||||
TargetMachine *target = march->createTargetMachine(Triple, FeatureStr);
|
TargetMachine *target = march->createTargetMachine(Triple, FeatureStr);
|
||||||
return new LTOModule(m.take(), target);
|
LTOModule *Ret = new LTOModule(m.take(), target);
|
||||||
|
bool Err = Ret->ParseSymbols();
|
||||||
|
if (Err) {
|
||||||
|
delete Ret;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -383,7 +401,8 @@ void LTOModule::addDefinedSymbol(GlobalValue *def, Mangler &mangler,
|
|||||||
_symbols.push_back(info);
|
_symbols.push_back(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LTOModule::addAsmGlobalSymbol(const char *name) {
|
void LTOModule::addAsmGlobalSymbol(const char *name,
|
||||||
|
lto_symbol_attributes scope) {
|
||||||
StringSet::value_type &entry = _defines.GetOrCreateValue(name);
|
StringSet::value_type &entry = _defines.GetOrCreateValue(name);
|
||||||
|
|
||||||
// only add new define if not already defined
|
// only add new define if not already defined
|
||||||
@ -393,13 +412,32 @@ void LTOModule::addAsmGlobalSymbol(const char *name) {
|
|||||||
entry.setValue(1);
|
entry.setValue(1);
|
||||||
const char *symbolName = entry.getKey().data();
|
const char *symbolName = entry.getKey().data();
|
||||||
uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR;
|
uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR;
|
||||||
attr |= LTO_SYMBOL_SCOPE_DEFAULT;
|
attr |= scope;
|
||||||
NameAndAttributes info;
|
NameAndAttributes info;
|
||||||
info.name = symbolName;
|
info.name = symbolName;
|
||||||
info.attributes = (lto_symbol_attributes)attr;
|
info.attributes = (lto_symbol_attributes)attr;
|
||||||
_symbols.push_back(info);
|
_symbols.push_back(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LTOModule::addAsmGlobalSymbolUndef(const char *name) {
|
||||||
|
StringMap<NameAndAttributes>::value_type &entry =
|
||||||
|
_undefines.GetOrCreateValue(name);
|
||||||
|
|
||||||
|
_asm_undefines.push_back(entry.getKey().data());
|
||||||
|
|
||||||
|
// we already have the symbol
|
||||||
|
if (entry.getValue().name)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t attr = LTO_SYMBOL_DEFINITION_UNDEFINED;;
|
||||||
|
attr |= LTO_SYMBOL_SCOPE_DEFAULT;
|
||||||
|
NameAndAttributes info;
|
||||||
|
info.name = entry.getKey().data();
|
||||||
|
info.attributes = (lto_symbol_attributes)attr;
|
||||||
|
|
||||||
|
entry.setValue(info);
|
||||||
|
}
|
||||||
|
|
||||||
void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl,
|
void LTOModule::addPotentialUndefinedSymbol(GlobalValue *decl,
|
||||||
Mangler &mangler) {
|
Mangler &mangler) {
|
||||||
// ignore all llvm.* symbols
|
// ignore all llvm.* symbols
|
||||||
@ -454,12 +492,194 @@ void LTOModule::findExternalRefs(Value *value, Mangler &mangler) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LTOModule::lazyParseSymbols() {
|
namespace {
|
||||||
if (_symbolsParsed)
|
class RecordStreamer : public MCStreamer {
|
||||||
return;
|
public:
|
||||||
|
enum State { NeverSeen, Global, Defined, DefinedGlobal, Used};
|
||||||
|
|
||||||
_symbolsParsed = true;
|
private:
|
||||||
|
StringMap<State> Symbols;
|
||||||
|
|
||||||
|
void markDefined(const MCSymbol &Symbol) {
|
||||||
|
State &S = Symbols[Symbol.getName()];
|
||||||
|
switch (S) {
|
||||||
|
case DefinedGlobal:
|
||||||
|
case Global:
|
||||||
|
S = DefinedGlobal;
|
||||||
|
break;
|
||||||
|
case NeverSeen:
|
||||||
|
case Defined:
|
||||||
|
case Used:
|
||||||
|
S = Defined;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void markGlobal(const MCSymbol &Symbol) {
|
||||||
|
State &S = Symbols[Symbol.getName()];
|
||||||
|
switch (S) {
|
||||||
|
case DefinedGlobal:
|
||||||
|
case Defined:
|
||||||
|
S = DefinedGlobal;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NeverSeen:
|
||||||
|
case Global:
|
||||||
|
case Used:
|
||||||
|
S = Global;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void markUsed(const MCSymbol &Symbol) {
|
||||||
|
State &S = Symbols[Symbol.getName()];
|
||||||
|
switch (S) {
|
||||||
|
case DefinedGlobal:
|
||||||
|
case Defined:
|
||||||
|
case Global:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NeverSeen:
|
||||||
|
case Used:
|
||||||
|
S = Used;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: mostly copied for the obj streamer.
|
||||||
|
void AddValueSymbols(const MCExpr *Value) {
|
||||||
|
switch (Value->getKind()) {
|
||||||
|
case MCExpr::Target:
|
||||||
|
// FIXME: What should we do in here?
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MCExpr::Constant:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MCExpr::Binary: {
|
||||||
|
const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
|
||||||
|
AddValueSymbols(BE->getLHS());
|
||||||
|
AddValueSymbols(BE->getRHS());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MCExpr::SymbolRef:
|
||||||
|
markUsed(cast<MCSymbolRefExpr>(Value)->getSymbol());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MCExpr::Unary:
|
||||||
|
AddValueSymbols(cast<MCUnaryExpr>(Value)->getSubExpr());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef StringMap<State>::const_iterator const_iterator;
|
||||||
|
|
||||||
|
const_iterator begin() {
|
||||||
|
return Symbols.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() {
|
||||||
|
return Symbols.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordStreamer(MCContext &Context) : MCStreamer(Context) {}
|
||||||
|
|
||||||
|
virtual void ChangeSection(const MCSection *Section) {}
|
||||||
|
virtual void InitSections() {}
|
||||||
|
virtual void EmitLabel(MCSymbol *Symbol) {
|
||||||
|
Symbol->setSection(*getCurrentSection());
|
||||||
|
markDefined(*Symbol);
|
||||||
|
}
|
||||||
|
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {}
|
||||||
|
virtual void EmitThumbFunc(MCSymbol *Func) {}
|
||||||
|
virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
|
||||||
|
// FIXME: should we handle aliases?
|
||||||
|
markDefined(*Symbol);
|
||||||
|
}
|
||||||
|
virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) {
|
||||||
|
if (Attribute == MCSA_Global)
|
||||||
|
markGlobal(*Symbol);
|
||||||
|
}
|
||||||
|
virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
|
||||||
|
virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {}
|
||||||
|
virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) {}
|
||||||
|
virtual void EmitCOFFSymbolStorageClass(int StorageClass) {}
|
||||||
|
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
|
||||||
|
unsigned Size , unsigned ByteAlignment) {
|
||||||
|
markDefined(*Symbol);
|
||||||
|
}
|
||||||
|
virtual void EmitCOFFSymbolType(int Type) {}
|
||||||
|
virtual void EndCOFFSymbolDef() {}
|
||||||
|
virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||||
|
unsigned ByteAlignment) {
|
||||||
|
markDefined(*Symbol);
|
||||||
|
}
|
||||||
|
virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
|
||||||
|
virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {}
|
||||||
|
virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
|
||||||
|
uint64_t Size, unsigned ByteAlignment) {}
|
||||||
|
virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {}
|
||||||
|
virtual void EmitValueImpl(const MCExpr *Value, unsigned Size,
|
||||||
|
bool isPCRel, unsigned AddrSpace) {}
|
||||||
|
virtual void EmitULEB128Value(const MCExpr *Value,
|
||||||
|
unsigned AddrSpace = 0) {}
|
||||||
|
virtual void EmitSLEB128Value(const MCExpr *Value,
|
||||||
|
unsigned AddrSpace = 0) {}
|
||||||
|
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
|
||||||
|
unsigned ValueSize,
|
||||||
|
unsigned MaxBytesToEmit) {}
|
||||||
|
virtual void EmitCodeAlignment(unsigned ByteAlignment,
|
||||||
|
unsigned MaxBytesToEmit) {}
|
||||||
|
virtual void EmitValueToOffset(const MCExpr *Offset,
|
||||||
|
unsigned char Value ) {}
|
||||||
|
virtual void EmitFileDirective(StringRef Filename) {}
|
||||||
|
virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta,
|
||||||
|
const MCSymbol *LastLabel,
|
||||||
|
const MCSymbol *Label) {}
|
||||||
|
|
||||||
|
virtual void EmitInstruction(const MCInst &Inst) {
|
||||||
|
// Scan for values.
|
||||||
|
for (unsigned i = Inst.getNumOperands(); i--; )
|
||||||
|
if (Inst.getOperand(i).isExpr())
|
||||||
|
AddValueSymbols(Inst.getOperand(i).getExpr());
|
||||||
|
}
|
||||||
|
virtual void Finish() {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LTOModule::addAsmGlobalSymbols(MCContext &Context) {
|
||||||
|
const std::string &inlineAsm = _module->getModuleInlineAsm();
|
||||||
|
|
||||||
|
OwningPtr<RecordStreamer> Streamer(new RecordStreamer(Context));
|
||||||
|
MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(inlineAsm);
|
||||||
|
SourceMgr SrcMgr;
|
||||||
|
SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
|
||||||
|
OwningPtr<MCAsmParser> Parser(createMCAsmParser(_target->getTarget(), SrcMgr,
|
||||||
|
Context, *Streamer,
|
||||||
|
*_target->getMCAsmInfo()));
|
||||||
|
OwningPtr<TargetAsmParser>
|
||||||
|
TAP(_target->getTarget().createAsmParser(*Parser.get(), *_target.get()));
|
||||||
|
Parser->setTargetParser(*TAP);
|
||||||
|
int Res = Parser->Run(false);
|
||||||
|
if (Res)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (RecordStreamer::const_iterator i = Streamer->begin(),
|
||||||
|
e = Streamer->end(); i != e; ++i) {
|
||||||
|
StringRef Key = i->first();
|
||||||
|
RecordStreamer::State Value = i->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LTOModule::ParseSymbols() {
|
||||||
// Use mangler to add GlobalPrefix to names to match linker names.
|
// Use mangler to add GlobalPrefix to names to match linker names.
|
||||||
MCContext Context(*_target->getMCAsmInfo(), NULL);
|
MCContext Context(*_target->getMCAsmInfo(), NULL);
|
||||||
Mangler mangler(Context, *_target->getTargetData());
|
Mangler mangler(Context, *_target->getTargetData());
|
||||||
@ -482,30 +702,8 @@ void LTOModule::lazyParseSymbols() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add asm globals
|
// add asm globals
|
||||||
const std::string &inlineAsm = _module->getModuleInlineAsm();
|
if (addAsmGlobalSymbols(Context))
|
||||||
const std::string glbl = ".globl";
|
return true;
|
||||||
std::string asmSymbolName;
|
|
||||||
std::string::size_type pos = inlineAsm.find(glbl, 0);
|
|
||||||
while (pos != std::string::npos) {
|
|
||||||
// eat .globl
|
|
||||||
pos = pos + 6;
|
|
||||||
|
|
||||||
// skip white space between .globl and symbol name
|
|
||||||
std::string::size_type pbegin = inlineAsm.find_first_not_of(' ', pos);
|
|
||||||
if (pbegin == std::string::npos)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// find end-of-line
|
|
||||||
std::string::size_type pend = inlineAsm.find_first_of('\n', pbegin);
|
|
||||||
if (pend == std::string::npos)
|
|
||||||
break;
|
|
||||||
|
|
||||||
asmSymbolName.assign(inlineAsm, pbegin, pend - pbegin);
|
|
||||||
addAsmGlobalSymbol(asmSymbolName.c_str());
|
|
||||||
|
|
||||||
// search next .globl
|
|
||||||
pos = inlineAsm.find(glbl, pend);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add aliases
|
// add aliases
|
||||||
for (Module::alias_iterator i = _module->alias_begin(),
|
for (Module::alias_iterator i = _module->alias_begin(),
|
||||||
@ -526,17 +724,16 @@ void LTOModule::lazyParseSymbols() {
|
|||||||
_symbols.push_back(info);
|
_symbols.push_back(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t LTOModule::getSymbolCount() {
|
uint32_t LTOModule::getSymbolCount() {
|
||||||
lazyParseSymbols();
|
|
||||||
return _symbols.size();
|
return _symbols.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lto_symbol_attributes LTOModule::getSymbolAttributes(uint32_t index) {
|
lto_symbol_attributes LTOModule::getSymbolAttributes(uint32_t index) {
|
||||||
lazyParseSymbols();
|
|
||||||
if (index < _symbols.size())
|
if (index < _symbols.size())
|
||||||
return _symbols[index].attributes;
|
return _symbols[index].attributes;
|
||||||
else
|
else
|
||||||
@ -544,7 +741,6 @@ lto_symbol_attributes LTOModule::getSymbolAttributes(uint32_t index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *LTOModule::getSymbolName(uint32_t index) {
|
const char *LTOModule::getSymbolName(uint32_t index) {
|
||||||
lazyParseSymbols();
|
|
||||||
if (index < _symbols.size())
|
if (index < _symbols.size())
|
||||||
return _symbols[index].name;
|
return _symbols[index].name;
|
||||||
else
|
else
|
||||||
|
@ -64,11 +64,14 @@ struct LTOModule {
|
|||||||
const char* getSymbolName(uint32_t index);
|
const char* getSymbolName(uint32_t index);
|
||||||
|
|
||||||
llvm::Module * getLLVVMModule() { return _module.get(); }
|
llvm::Module * getLLVVMModule() { return _module.get(); }
|
||||||
|
const std::vector<const char*> &getAsmUndefinedRefs() {
|
||||||
|
return _asm_undefines;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LTOModule(llvm::Module* m, llvm::TargetMachine* t);
|
LTOModule(llvm::Module* m, llvm::TargetMachine* t);
|
||||||
|
|
||||||
void lazyParseSymbols();
|
bool ParseSymbols();
|
||||||
void addDefinedSymbol(llvm::GlobalValue* def,
|
void addDefinedSymbol(llvm::GlobalValue* def,
|
||||||
llvm::Mangler& mangler,
|
llvm::Mangler& mangler,
|
||||||
bool isFunction);
|
bool isFunction);
|
||||||
@ -80,7 +83,10 @@ private:
|
|||||||
llvm::Mangler &mangler);
|
llvm::Mangler &mangler);
|
||||||
void addDefinedDataSymbol(llvm::GlobalValue* v,
|
void addDefinedDataSymbol(llvm::GlobalValue* v,
|
||||||
llvm::Mangler &mangler);
|
llvm::Mangler &mangler);
|
||||||
void addAsmGlobalSymbol(const char *);
|
bool addAsmGlobalSymbols(llvm::MCContext &Context);
|
||||||
|
void addAsmGlobalSymbol(const char *,
|
||||||
|
lto_symbol_attributes scope);
|
||||||
|
void addAsmGlobalSymbolUndef(const char *);
|
||||||
void addObjCClass(llvm::GlobalVariable* clgv);
|
void addObjCClass(llvm::GlobalVariable* clgv);
|
||||||
void addObjCCategory(llvm::GlobalVariable* clgv);
|
void addObjCCategory(llvm::GlobalVariable* clgv);
|
||||||
void addObjCClassRef(llvm::GlobalVariable* clgv);
|
void addObjCClassRef(llvm::GlobalVariable* clgv);
|
||||||
@ -103,11 +109,11 @@ private:
|
|||||||
|
|
||||||
llvm::OwningPtr<llvm::Module> _module;
|
llvm::OwningPtr<llvm::Module> _module;
|
||||||
llvm::OwningPtr<llvm::TargetMachine> _target;
|
llvm::OwningPtr<llvm::TargetMachine> _target;
|
||||||
bool _symbolsParsed;
|
|
||||||
std::vector<NameAndAttributes> _symbols;
|
std::vector<NameAndAttributes> _symbols;
|
||||||
// _defines and _undefines only needed to disambiguate tentative definitions
|
// _defines and _undefines only needed to disambiguate tentative definitions
|
||||||
StringSet _defines;
|
StringSet _defines;
|
||||||
llvm::StringMap<NameAndAttributes> _undefines;
|
llvm::StringMap<NameAndAttributes> _undefines;
|
||||||
|
std::vector<const char*> _asm_undefines;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LTO_MODULE_H
|
#endif // LTO_MODULE_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user