Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
7 changes: 4 additions & 3 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1020,13 +1020,14 @@ On ELF platforms, IFuncs are resolved by the dynamic linker at load time. On
Mach-O platforms, they are lowered in terms of ``.symbol_resolver`` functions,
which lazily resolve the callee the first time they are called.

IFunc may have an optional :ref:`linkage type <linkage>` and an optional
:ref:`visibility style <visibility>`.
IFunc may have an optional :ref:`linkage type <linkage>`, an optional
:ref:`visibility style <visibility>`, an option partition, and an optional
list of attached :ref:`metadata <metadata>`.

Syntax::

@<Name> = [Linkage] [PreemptionSpecifier] [Visibility] ifunc <IFuncTy>, <ResolverTy>* @<Resolver>
[, partition "name"]
[, partition "name"] (, !name !N)*


.. _langref_comdats:
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1258,6 +1258,9 @@ bool LLParser::parseAliasOrIFunc(const std::string &Name, unsigned NameID,
GV->setPartition(Lex.getStrVal());
if (parseToken(lltok::StringConstant, "expected partition string"))
return true;
} else if (!IsAlias && Lex.getKind() == lltok::MetadataVar) {
if (parseGlobalObjectMetadataAttachment(*GI.get()))
return true;
} else {
return tokError("unknown alias or ifunc property!");
}
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2630,6 +2630,9 @@ void ModuleBitcodeWriter::writeModuleMetadata() {
for (const Function &F : M)
if (F.isDeclaration() && F.hasMetadata())
AddDeclAttachedMetadata(F);
for (const GlobalIFunc &GI : M.ifuncs())
if (GI.hasMetadata())
AddDeclAttachedMetadata(GI);
// FIXME: Only store metadata for declarations here, and move data for global
// variable definitions to a separate block (PR28134).
for (const GlobalVariable &GV : M.globals())
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,12 @@ ValueEnumerator::ValueEnumerator(const Module &M,
EnumerateMetadata(&F, Op);
}
}
for (const GlobalIFunc &GIF : M.ifuncs()) {
MDs.clear();
GIF.getAllMetadata(MDs);
for (const auto &I : MDs)
EnumerateMetadata(nullptr, I.second);
}

// Optimize constant ordering.
OptimizeConstants(FirstConstant, Values.size());
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/IR/AsmWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,7 @@ void SlotTracker::processModule() {
for (const GlobalIFunc &I : TheModule->ifuncs()) {
if (!I.hasName())
CreateModuleSlot(&I);
processGlobalObjectMetadata(I);
}

// Add metadata used by named metadata.
Expand Down Expand Up @@ -4077,6 +4078,11 @@ void AssemblyWriter::printIFunc(const GlobalIFunc *GI) {
printEscapedString(GI->getPartition(), Out);
Out << '"';
}
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
GI->getAllMetadata(MDs);
if (!MDs.empty()) {
printMetadataAttachments(MDs, ", ");
}

printInfoComment(*GI);
Out << '\n';
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,18 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) {
}

void Verifier::visitGlobalIFunc(const GlobalIFunc &GI) {
visitGlobalValue(GI);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect we need to do a bit more in the verifier. Particularly for !dbg. And maybe !associated. (Also probably should check that there's no section or comdat, but I guess that's an existing issue.)

I don't see any BitcodeReader changes; does that just work without any changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any BitcodeReader changes; does that just work without any changes?

Yes, the BitcodeWriter saves the metadata on function declarations, global variables, and ifuncs (added in this PR) in a bitc::METADATA_GLOBAL_DECL_ATTACHMENT record, which IIUC creates an association between the metadata and the GlobalObject they belong to.
Function MetadataLoader::MetadataLoaderImpl::parseGlobalObjectAttachment in the BitcodeReader consumes the record and adds the metadata to the associated llvm::GlobalObject (which is a base class of Function, GlobalVariable, and GlobalIFunc).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And maybe !associated

What special property of an !associated on an ifunc should we check?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking a bit more, I guess there isn't anything specific to ifuncs for !associated.

SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
GI.getAllMetadata(MDs);
for (const auto &I : MDs) {
CheckDI(I.first != LLVMContext::MD_dbg,
"an ifunc may not have a !dbg attachment", &GI);
Check(I.first != LLVMContext::MD_prof,
"an ifunc may not have a !prof attachment", &GI);
visitMDNode(*I.second, AreDebugLocsAllowed::No);
}

Check(GlobalIFunc::isValidLinkage(GI.getLinkage()),
"IFunc should have private, internal, linkonce, weak, linkonce_odr, "
"weak_odr, or external linkage!",
Expand Down
8 changes: 8 additions & 0 deletions llvm/test/Assembler/metadata.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
; CHECK-UNMAT: @global = global i32 0, !foo [[M2:![0-9]+]], !foo [[M3:![0-9]+]], !baz [[M3]]
@global = global i32 0, !foo !2, !foo !3, !baz !3

; CHECK-UNMAT: @ifunc_func = ifunc void (...), ptr @resolver, !foo [[M2]]
@ifunc_func = ifunc void (...), ptr @resolver, !foo !2

define internal ptr @resolver() {
entry:
ret ptr @test
}

; CHECK-LABEL: @test
; CHECK: ret void, !foo [[M0:![0-9]+]], !bar [[M1:![0-9]+]]
define void @test() !dbg !1 {
Expand Down