Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions llvm/include/llvm/LTO/LTO.h
Original file line number Diff line number Diff line change
Expand Up @@ -541,20 +541,21 @@ class LTO {
void addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
ArrayRef<SymbolResolution> Res, unsigned Partition,
bool InSummary);

// These functions take a range of symbol resolutions [ResI, ResE) and consume
// the resolutions used by a single input module by incrementing ResI. After
// these functions return, [ResI, ResE) will refer to the resolution range for
// the remaining modules in the InputFile.
Error addModule(InputFile &Input, unsigned ModI,
const SymbolResolution *&ResI, const SymbolResolution *ResE);
const SymbolResolution *&ResI,
ArrayRef<SymbolResolution> Res);

Expected<RegularLTOState::AddedModule>
addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
const SymbolResolution *&ResI, const SymbolResolution *ResE);
addRegularLTO(InputFile &Input, BitcodeModule BM,
ArrayRef<InputFile::Symbol> Syms, const SymbolResolution *&ResI,
ArrayRef<SymbolResolution> Res);
Error linkRegularLTO(RegularLTOState::AddedModule Mod,
bool LivenessFromIndex);

// This function takes a range of symbol resolutions [ResI, ResE) and consume
// the resolutions used by a single input module by incrementing ResI. After
// these functions return, [ResI, ResE) will refer to the resolution range for
// the remaining modules in the InputFile.
Error addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
const SymbolResolution *&ResI, const SymbolResolution *ResE);

Expand Down
50 changes: 35 additions & 15 deletions llvm/lib/LTO/LTO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ Error LTO::add(std::unique_ptr<InputFile> Input,

const SymbolResolution *ResI = Res.begin();
for (unsigned I = 0; I != Input->Mods.size(); ++I)
if (Error Err = addModule(*Input, I, ResI, Res.end()))
if (Error Err = addModule(*Input, I, ResI, Res))
return Err;

assert(ResI == Res.end());
Expand All @@ -753,7 +753,7 @@ Error LTO::add(std::unique_ptr<InputFile> Input,

Error LTO::addModule(InputFile &Input, unsigned ModI,
const SymbolResolution *&ResI,
const SymbolResolution *ResE) {
ArrayRef<SymbolResolution> Res) {
Expected<BitcodeLTOInfo> LTOInfo = Input.Mods[ModI].getLTOInfo();
if (!LTOInfo)
return LTOInfo.takeError();
Expand Down Expand Up @@ -782,16 +782,16 @@ Error LTO::addModule(InputFile &Input, unsigned ModI,
bool IsThinLTO = LTOInfo->IsThinLTO && (LTOMode != LTOK_UnifiedRegular);

auto ModSyms = Input.module_symbols(ModI);
addModuleToGlobalRes(ModSyms, {ResI, ResE},
addModuleToGlobalRes(ModSyms, {ResI, Res.end()},
IsThinLTO ? ThinLTO.ModuleMap.size() + 1 : 0,
LTOInfo->HasSummary);

if (IsThinLTO)
return addThinLTO(BM, ModSyms, ResI, ResE);
return addThinLTO(BM, ModSyms, ResI, Res.end());

RegularLTO.EmptyCombinedModule = false;
Expected<RegularLTOState::AddedModule> ModOrErr =
addRegularLTO(BM, ModSyms, ResI, ResE);
addRegularLTO(Input, BM, ModSyms, ResI, Res);
if (!ModOrErr)
return ModOrErr.takeError();

Expand Down Expand Up @@ -839,10 +839,9 @@ handleNonPrevailingComdat(GlobalValue &GV,
// Add a regular LTO object to the link.
// The resulting module needs to be linked into the combined LTO module with
// linkRegularLTO.
Expected<LTO::RegularLTOState::AddedModule>
LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
const SymbolResolution *&ResI,
const SymbolResolution *ResE) {
Expected<LTO::RegularLTOState::AddedModule> LTO::addRegularLTO(
InputFile &Input, BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
const SymbolResolution *&ResI, ArrayRef<SymbolResolution> Res) {
RegularLTOState::AddedModule Mod;
Expected<std::unique_ptr<Module>> MOrErr =
BM.getLazyModule(RegularLTO.Ctx, /*ShouldLazyLoadMetadata*/ true,
Expand All @@ -855,13 +854,34 @@ LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
if (Error Err = M.materializeMetadata())
return std::move(Err);

// If cfi.functions is present and we are in regular LTO mode, LowerTypeTests
// will rename local functions in the merged module as "<function name>.1".
// This causes linking errors, since other parts of the module expect the
// original function name.
if (LTOMode == LTOK_UnifiedRegular)
if (LTOMode == LTOK_UnifiedRegular) {
// cfi.functions metadata is intended to be used with ThinLTO and may
// trigger invalid IR transformations if they are present when doing regular
// LTO, so delete it.
if (NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions"))
M.eraseNamedMetadata(CfiFunctionsMD);
} else if (NamedMDNode *AliasesMD = M.getNamedMetadata("aliases")) {
// Delete aliases entries for non-prevailing symbols on the ThinLTO side of
// this input file.
std::set<StringRef> Prevailing;
for (auto P : zip(Input.symbols(), Res))
if (std::get<1>(P).Prevailing && !std::get<0>(P).getIRName().empty())
Prevailing.insert(std::get<0>(P).getIRName());
std::vector<MDNode *> AliasGroups;
for (MDNode *AliasGroup : AliasesMD->operands()) {
std::vector<Metadata *> Aliases;
for (Metadata *Alias : AliasGroup->operands()) {
if (isa<MDString>(Alias) &&
Prevailing.count(cast<MDString>(Alias)->getString()))
Aliases.push_back(Alias);
}
if (Aliases.size() > 1)
AliasGroups.push_back(MDTuple::get(RegularLTO.Ctx, Aliases));
}
AliasesMD->clearOperands();
for (MDNode *G : AliasGroups)
AliasesMD->addOperand(G);
}

UpgradeDebugInfo(M);

Expand Down Expand Up @@ -899,7 +919,7 @@ LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
std::set<const Comdat *> NonPrevailingComdats;
SmallSet<StringRef, 2> NonPrevailingAsmSymbols;
for (const InputFile::Symbol &Sym : Syms) {
assert(ResI != ResE);
assert(ResI != Res.end());
SymbolResolution Res = *ResI++;

assert(MsymI != MsymE);
Expand Down
127 changes: 70 additions & 57 deletions llvm/lib/Transforms/IPO/LowerTypeTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,8 +502,7 @@ class LowerTypeTestsModule {
uint8_t *exportTypeId(StringRef TypeId, const TypeIdLowering &TIL);
TypeIdLowering importTypeId(StringRef TypeId);
void importTypeTest(CallInst *CI);
void importFunction(Function *F, bool isJumpTableCanonical,
std::vector<GlobalAlias *> &AliasesToErase);
void importFunction(Function *F, bool isJumpTableCanonical);

BitSetInfo
buildBitSet(Metadata *TypeId,
Expand Down Expand Up @@ -1103,9 +1102,8 @@ void LowerTypeTestsModule::maybeReplaceComdat(Function *F,

// ThinLTO backend: the function F has a jump table entry; update this module
// accordingly. isJumpTableCanonical describes the type of the jump table entry.
void LowerTypeTestsModule::importFunction(
Function *F, bool isJumpTableCanonical,
std::vector<GlobalAlias *> &AliasesToErase) {
void LowerTypeTestsModule::importFunction(Function *F,
bool isJumpTableCanonical) {
assert(F->getType()->getAddressSpace() == 0);

GlobalValue::VisibilityTypes Visibility = F->getVisibility();
Expand Down Expand Up @@ -1135,23 +1133,23 @@ void LowerTypeTestsModule::importFunction(
} else {
F->setName(Name + ".cfi");
maybeReplaceComdat(F, Name);
F->setLinkage(GlobalValue::ExternalLinkage);
FDecl = Function::Create(F->getFunctionType(), GlobalValue::ExternalLinkage,
F->getAddressSpace(), Name, &M);
FDecl->setVisibility(Visibility);
Visibility = GlobalValue::HiddenVisibility;

// Delete aliases pointing to this function, they'll be re-created in the
// merged output. Don't do it yet though because ScopedSaveAliaseesAndUsed
// will want to reset the aliasees first.
// Update aliases pointing to this function to also include the ".cfi" suffix,
// We expect the jump table entry to either point to the real function or an
// alias. Redirect all other users to the jump table entry.
for (auto &U : F->uses()) {
if (auto *A = dyn_cast<GlobalAlias>(U.getUser())) {
std::string AliasName = A->getName().str() + ".cfi";
Function *AliasDecl = Function::Create(
F->getFunctionType(), GlobalValue::ExternalLinkage,
F->getAddressSpace(), "", &M);
AliasDecl->takeName(A);
A->replaceAllUsesWith(AliasDecl);
AliasesToErase.push_back(A);
A->setName(AliasName);
}
}
}
Expand Down Expand Up @@ -2077,16 +2075,13 @@ bool LowerTypeTestsModule::lower() {
Decls.push_back(&F);
}

std::vector<GlobalAlias *> AliasesToErase;
{
ScopedSaveAliaseesAndUsed S(M);
for (auto *F : Defs)
importFunction(F, /*isJumpTableCanonical*/ true, AliasesToErase);
importFunction(F, /*isJumpTableCanonical*/ true);
for (auto *F : Decls)
importFunction(F, /*isJumpTableCanonical*/ false, AliasesToErase);
importFunction(F, /*isJumpTableCanonical*/ false);
}
for (GlobalAlias *GA : AliasesToErase)
GA->eraseFromParent();

return true;
}
Expand Down Expand Up @@ -2137,6 +2132,18 @@ bool LowerTypeTestsModule::lower() {
if (auto Alias = dyn_cast<AliasSummary>(RefGVS.get()))
AddressTaken.insert(Alias->getAliaseeGUID());
}
auto IsAddressTaken = [&](GlobalValue::GUID GUID) {
if (AddressTaken.count(GUID))
return true;
auto VI = ExportSummary->getValueInfo(GUID);
if (!VI)
return false;
for (auto &I : VI.getSummaryList())
if (auto Alias = dyn_cast<AliasSummary>(I.get()))
if (AddressTaken.count(Alias->getAliaseeGUID()))
return true;
return false;
};
for (auto *FuncMD : CfiFunctionsMD->operands()) {
assert(FuncMD->getNumOperands() >= 2);
StringRef FunctionName =
Expand All @@ -2153,7 +2160,7 @@ bool LowerTypeTestsModule::lower() {
// have no live references (and are not exported with cross-DSO CFI.)
if (!ExportSummary->isGUIDLive(GUID))
continue;
if (!AddressTaken.count(GUID)) {
if (!IsAddressTaken(GUID)) {
if (!CrossDsoCfi || Linkage != CFL_Definition)
continue;

Expand Down Expand Up @@ -2227,6 +2234,43 @@ bool LowerTypeTestsModule::lower() {
}
}

struct AliasToCreate {
Function *Alias;
std::string TargetName;
};
std::vector<AliasToCreate> AliasesToCreate;

// Parse alias data to replace stand-in function declarations for aliases
// with an alias to the intended target.
if (ExportSummary) {
if (NamedMDNode *AliasesMD = M.getNamedMetadata("aliases")) {
for (auto *AliasMD : AliasesMD->operands()) {
std::vector<Function *> Aliases;
for (Metadata *MD : AliasMD->operands()) {
auto *MDS = dyn_cast<MDString>(MD);
if (!MDS)
continue;
StringRef AliasName = MDS->getString();
if (!ExportedFunctions.count(AliasName))
continue;
auto *AliasF = M.getFunction(AliasName);
if (AliasF)
Aliases.push_back(AliasF);
}

if (Aliases.empty())
continue;

for (unsigned I = 1; I != Aliases.size(); ++I) {
auto *AliasF = Aliases[I];
ExportedFunctions.erase(AliasF->getName());
AliasesToCreate.push_back(
{AliasF, std::string(Aliases[0]->getName())});
}
}
}
}

DenseMap<GlobalObject *, GlobalTypeMember *> GlobalTypeMembers;
for (GlobalObject &GO : M.global_objects()) {
if (isa<GlobalVariable>(GO) && GO.isDeclarationForLinker())
Expand Down Expand Up @@ -2414,47 +2458,16 @@ bool LowerTypeTestsModule::lower() {

allocateByteArrays();

// Parse alias data to replace stand-in function declarations for aliases
// with an alias to the intended target.
if (ExportSummary) {
if (NamedMDNode *AliasesMD = M.getNamedMetadata("aliases")) {
for (auto *AliasMD : AliasesMD->operands()) {
assert(AliasMD->getNumOperands() >= 4);
StringRef AliasName =
cast<MDString>(AliasMD->getOperand(0))->getString();
StringRef Aliasee = cast<MDString>(AliasMD->getOperand(1))->getString();

if (auto It = ExportedFunctions.find(Aliasee);
It == ExportedFunctions.end() ||
It->second.Linkage != CFL_Definition || !M.getNamedAlias(Aliasee))
continue;

GlobalValue::VisibilityTypes Visibility =
static_cast<GlobalValue::VisibilityTypes>(
cast<ConstantAsMetadata>(AliasMD->getOperand(2))
->getValue()
->getUniqueInteger()
.getZExtValue());
bool Weak =
static_cast<bool>(cast<ConstantAsMetadata>(AliasMD->getOperand(3))
->getValue()
->getUniqueInteger()
.getZExtValue());

auto *Alias = GlobalAlias::create("", M.getNamedAlias(Aliasee));
Alias->setVisibility(Visibility);
if (Weak)
Alias->setLinkage(GlobalValue::WeakAnyLinkage);

if (auto *F = M.getFunction(AliasName)) {
Alias->takeName(F);
F->replaceAllUsesWith(Alias);
F->eraseFromParent();
} else {
Alias->setName(AliasName);
}
}
}
for (auto A : AliasesToCreate) {
auto *Target = M.getNamedValue(A.TargetName);
if (!isa<GlobalAlias>(Target))
continue;
auto *AliasGA = GlobalAlias::create("", Target);
AliasGA->setVisibility(A.Alias->getVisibility());
AliasGA->setLinkage(A.Alias->getLinkage());
AliasGA->takeName(A.Alias);
A.Alias->replaceAllUsesWith(AliasGA);
A.Alias->eraseFromParent();
}

// Emit .symver directives for exported functions, if they exist.
Expand Down
31 changes: 15 additions & 16 deletions llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,10 @@ void splitAndWriteThinLTOBitcode(
for (auto &F : M)
if ((!F.hasLocalLinkage() || F.hasAddressTaken()) && HasTypeMetadata(&F))
CfiFunctions.insert(&F);
for (auto &A : M.aliases())
if (auto *F = dyn_cast<Function>(A.getAliasee()))
if (HasTypeMetadata(F))
CfiFunctions.insert(&A);

// Remove all globals with type metadata, globals with comdats that live in
// MergedM, and aliases pointing to such globals from the thin LTO module.
Expand All @@ -403,12 +407,12 @@ void splitAndWriteThinLTOBitcode(
auto &Ctx = MergedM->getContext();
SmallVector<MDNode *, 8> CfiFunctionMDs;
for (auto *V : CfiFunctions) {
Function &F = *cast<Function>(V);
Function &F = *cast<Function>(V->getAliaseeObject());
SmallVector<MDNode *, 2> Types;
F.getMetadata(LLVMContext::MD_type, Types);

SmallVector<Metadata *, 4> Elts;
Elts.push_back(MDString::get(Ctx, F.getName()));
Elts.push_back(MDString::get(Ctx, V->getName()));
CfiFunctionLinkage Linkage;
if (lowertypetests::isJumpTableCanonical(&F))
Linkage = CFL_Definition;
Expand All @@ -428,29 +432,24 @@ void splitAndWriteThinLTOBitcode(
NMD->addOperand(MD);
}

SmallVector<MDNode *, 8> FunctionAliases;
MapVector<Function *, std::vector<GlobalAlias *>> FunctionAliases;
for (auto &A : M.aliases()) {
if (!isa<Function>(A.getAliasee()))
continue;

auto *F = cast<Function>(A.getAliasee());

Metadata *Elts[] = {
MDString::get(Ctx, A.getName()),
MDString::get(Ctx, F->getName()),
ConstantAsMetadata::get(
ConstantInt::get(Type::getInt8Ty(Ctx), A.getVisibility())),
ConstantAsMetadata::get(
ConstantInt::get(Type::getInt8Ty(Ctx), A.isWeakForLinker())),
};

FunctionAliases.push_back(MDTuple::get(Ctx, Elts));
FunctionAliases[F].push_back(&A);
}

if (!FunctionAliases.empty()) {
NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("aliases");
for (auto *MD : FunctionAliases)
NMD->addOperand(MD);
for (auto &Alias : FunctionAliases) {
std::vector<Metadata *> Elts;
Elts.push_back(MDString::get(Ctx, Alias.first->getName()));
for (auto *A : Alias.second)
Elts.push_back(MDString::get(Ctx, A->getName()));
NMD->addOperand(MDTuple::get(Ctx, Elts));
}
}

SmallVector<MDNode *, 8> Symvers;
Expand Down
Loading
Loading