diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -7423,10 +7423,10 @@ '``annotation``' Metadata ^^^^^^^^^^^^^^^^^^^^^^^^^ -The ``annotation`` metadata can be used to attach a tuple of annotation strings -to any instruction. This metadata does not impact the semantics of the program -and may only be used to provide additional insight about the program and -transformations to users. +The ``annotation`` metadata can be used to attach a tuple of annotation strings +or a tuple of a tuple of annotation strings to any instruction. This metadata does +not impact the semantics of the program and may only be used to provide additional +insight about the program and transformations to users. Example: @@ -7435,6 +7435,13 @@ %a.addr = alloca ptr, align 8, !annotation !0 !0 = !{!"auto-init"} +Embedding tuple of strings example: + +.. code-block:: test + %a.ptr = getelementptr ptr, ptr %base, i64 0. !annotation !0 + !0 = !{!1} + !1 = !{!"gep offset", !"0"} + '``func_sanitize``' Metadata ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -339,7 +339,11 @@ /// If this instruction already has !annotation metadata, append \p Annotation /// to the existing node. void addAnnotationMetadata(StringRef Annotation); - + /// Adds an !annotation metadata node with an array of \p Annotations + /// as a tuple to this instruction. If this instruction already has + /// !annotation metadata, append the tuple to + /// the existing node. + void addAnnotationMetadata(SmallVector Annotations); /// Returns the AA metadata for this instruction. AAMDNodes getAAMetadata() const; diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h --- a/llvm/include/llvm/IR/Metadata.h +++ b/llvm/include/llvm/IR/Metadata.h @@ -789,6 +789,13 @@ Op.MD = nullptr; return *this; } + + // Check if MDOperand is of type MDString and equals `Str`. + bool equalsStr(StringRef Str) const { + return isa(this->get()) && + cast(this->get())->getString() == Str; + } + ~MDOperand() { untrack(); } Metadata *get() const { return MD; } diff --git a/llvm/lib/CodeGen/BasicBlockSections.cpp b/llvm/lib/CodeGen/BasicBlockSections.cpp --- a/llvm/lib/CodeGen/BasicBlockSections.cpp +++ b/llvm/lib/CodeGen/BasicBlockSections.cpp @@ -300,7 +300,7 @@ if (Existing) { MDTuple *Tuple = cast(Existing); for (const auto &N : Tuple->operands()) - if (cast(N.get())->getString() == MetadataName) + if (N.equalsStr(MetadataName)) return true; } diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -119,7 +119,7 @@ auto *MetadataName = "unsafe-stack-size"; if (auto &N = Existing->getOperand(0)) { - if (cast(N.get())->getString() == MetadataName) { + if (N.equalsStr(MetadataName)) { if (auto &Op = Existing->getOperand(1)) { auto Val = mdconst::extract(Op)->getZExtValue(); FrameInfo.setUnsafeStackSize(Val); diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -1539,23 +1539,52 @@ Value::setMetadata(KindID, Node); } +void Instruction::addAnnotationMetadata(SmallVector Annotations) { + SmallSetVector AnnotationsSet(Annotations.begin(), + Annotations.end()); + MDBuilder MDB(getContext()); + + auto *Existing = getMetadata(LLVMContext::MD_annotation); + SmallVector Names; + if (Existing) { + auto *Tuple = cast(Existing); + for (auto &N : Tuple->operands()) { + if (isa(N.get())) + continue; + auto *MDAnnotationTuple = cast(N); + if (any_of(MDAnnotationTuple->operands(), [&AnnotationsSet](auto &Op) { + return AnnotationsSet.contains(cast(Op)->getString()); + })) + return; + Names.push_back(N); + } + } + + SmallVector MDAnnotationStrings; + for (StringRef Annotation : Annotations) + MDAnnotationStrings.push_back(MDB.createString(Annotation)); + MDNode *InfoTuple = MDTuple::get(getContext(), MDAnnotationStrings); + Names.push_back(InfoTuple); + MDNode *MD = MDTuple::get(getContext(), Names); + setMetadata(LLVMContext::MD_annotation, MD); +} + void Instruction::addAnnotationMetadata(StringRef Name) { MDBuilder MDB(getContext()); auto *Existing = getMetadata(LLVMContext::MD_annotation); SmallVector Names; - bool AppendName = true; if (Existing) { auto *Tuple = cast(Existing); for (auto &N : Tuple->operands()) { - if (cast(N.get())->getString() == Name) - AppendName = false; + if (isa(N.get()) && + cast(N.get())->getString() == Name) + return; Names.push_back(N.get()); } } - if (AppendName) - Names.push_back(MDB.createString(Name)); + Names.push_back(MDB.createString(Name)); MDNode *MD = MDTuple::get(getContext(), Names); setMetadata(LLVMContext::MD_annotation, MD); } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -4678,8 +4678,15 @@ Check(isa(Annotation), "annotation must be a tuple"); Check(Annotation->getNumOperands() >= 1, "annotation must have at least one operand"); - for (const MDOperand &Op : Annotation->operands()) - Check(isa(Op.get()), "operands must be strings"); + for (const MDOperand &Op : Annotation->operands()) { + bool TupleOfStrings = + isa(Op.get()) && + all_of(cast(Op)->operands(), [](auto &Annotation) { + return isa(Annotation.get()); + }); + Check(isa(Op.get()) || TupleOfStrings, + "operands must be a string or a tuple of strings"); + } } void Verifier::visitAliasScopeMetadata(const MDNode *MD) { diff --git a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp --- a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -1291,7 +1291,7 @@ if (Existing) { MDTuple *Tuple = cast(Existing); for (const auto &N : Tuple->operands()) { - if (cast(N.get())->getString() == MetadataName) + if (N.equalsStr(MetadataName)) return; Names.push_back(N.get()); } diff --git a/llvm/lib/Transforms/Scalar/AnnotationRemarks.cpp b/llvm/lib/Transforms/Scalar/AnnotationRemarks.cpp --- a/llvm/lib/Transforms/Scalar/AnnotationRemarks.cpp +++ b/llvm/lib/Transforms/Scalar/AnnotationRemarks.cpp @@ -57,7 +57,12 @@ for (const MDOperand &Op : I.getMetadata(LLVMContext::MD_annotation)->operands()) { - auto Iter = Mapping.insert({cast(Op.get())->getString(), 0}); + StringRef AnnotationStr = + isa(Op.get()) + ? cast(Op.get())->getString() + : cast(cast(Op.get())->getOperand(0).get()) + ->getString(); + auto Iter = Mapping.insert({AnnotationStr, 0}); Iter.first->second++; } } diff --git a/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp b/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp --- a/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp +++ b/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp @@ -387,7 +387,8 @@ return false; return any_of(I->getMetadata(LLVMContext::MD_annotation)->operands(), [](const MDOperand &Op) { - return cast(Op.get())->getString() == "auto-init"; + return isa(Op.get()) && + cast(Op.get())->getString() == "auto-init"; }); } diff --git a/llvm/test/Verifier/annotation-metadata.ll b/llvm/test/Verifier/annotation-metadata.ll --- a/llvm/test/Verifier/annotation-metadata.ll +++ b/llvm/test/Verifier/annotation-metadata.ll @@ -5,7 +5,7 @@ ; CHECK: annotation must have at least one operand %a.addr = alloca ptr, align 8, !annotation !0 -; CHECK-NEXT: operands must be strings +; CHECK-NEXT: operands must be a string or a tuple of strings ret void, !annotation !1 }