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:
Rafael Espindola
2011-03-02 04:14:42 +00:00
parent f7af396c95
commit 38c4e53549
7 changed files with 336 additions and 82 deletions

View File

@@ -75,7 +75,6 @@ LTOCodeGenerator::LTOCodeGenerator()
{
InitializeAllTargets();
InitializeAllAsmPrinters();
InitializeAllAsmParsers();
}
LTOCodeGenerator::~LTOCodeGenerator()
@@ -88,7 +87,13 @@ LTOCodeGenerator::~LTOCodeGenerator()
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;
}
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() {
if (_scopeRestrictionsDone) return;
Module *mergedModule = _linker.getModule();
@@ -258,38 +291,47 @@ void LTOCodeGenerator::applyScopeRestrictions() {
passes.add(createVerifierPass());
// mark which symbols can not be internalized
if (!_mustPreserveSymbols.empty()) {
MCContext Context(*_target->getMCAsmInfo(), NULL);
Mangler mangler(Context, *_target->getTargetData());
std::vector<const char*> mustPreserveList;
SmallString<64> Buffer;
for (Module::iterator f = mergedModule->begin(),
e = mergedModule->end(); f != e; ++f) {
Buffer.clear();
mangler.getNameWithPrefix(Buffer, f, false);
if (!f->isDeclaration() &&
_mustPreserveSymbols.count(Buffer))
mustPreserveList.push_back(f->getName().data());
}
for (Module::global_iterator v = mergedModule->global_begin(),
e = mergedModule->global_end(); v != e; ++v) {
Buffer.clear();
mangler.getNameWithPrefix(Buffer, v, false);
if (!v->isDeclaration() &&
_mustPreserveSymbols.count(Buffer))
mustPreserveList.push_back(v->getName().data());
}
for (Module::alias_iterator a = mergedModule->alias_begin(),
e = mergedModule->alias_end(); a != e; ++a) {
Buffer.clear();
mangler.getNameWithPrefix(Buffer, a, false);
if (!a->isDeclaration() &&
_mustPreserveSymbols.count(Buffer))
mustPreserveList.push_back(a->getName().data());
}
passes.add(createInternalizePass(mustPreserveList));
MCContext Context(*_target->getMCAsmInfo(), NULL);
Mangler mangler(Context, *_target->getTargetData());
std::vector<const char*> mustPreserveList;
SmallPtrSet<GlobalValue*, 8> asmUsed;
for (Module::iterator f = mergedModule->begin(),
e = mergedModule->end(); f != e; ++f)
applyRestriction(*f, mustPreserveList, asmUsed, mangler);
for (Module::global_iterator v = mergedModule->global_begin(),
e = mergedModule->global_end(); v != e; ++v)
applyRestriction(*v, mustPreserveList, asmUsed, mangler);
for (Module::alias_iterator a = mergedModule->alias_begin(),
e = mergedModule->alias_end(); a != e; ++a)
applyRestriction(*a, mustPreserveList, asmUsed, mangler);
GlobalVariable *LLVMCompilerUsed =
mergedModule->getGlobalVariable("llvm.compiler.used");
findUsedValues(LLVMCompilerUsed, asmUsed);
if (LLVMCompilerUsed)
LLVMCompilerUsed->eraseFromParent();
const llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context);
std::vector<Constant*> asmUsed2;
for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = asmUsed.begin(),
e = asmUsed.end(); i !=e; ++i) {
GlobalValue *GV = *i;
Constant *c = ConstantExpr::getBitCast(GV, i8PTy);
asmUsed2.push_back(c);
}
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
passes.run(*mergedModule);