[llvm] c70f6e1 - [Metadata] Introduce MD_pcsections
Marco Elver via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 6 06:53:24 PDT 2022
Author: Marco Elver
Date: 2022-09-06T15:52:44+02:00
New Revision: c70f6e1362e38f36dceca0342490d659aa45a1a5
URL: https://github.com/llvm/llvm-project/commit/c70f6e1362e38f36dceca0342490d659aa45a1a5
DIFF: https://github.com/llvm/llvm-project/commit/c70f6e1362e38f36dceca0342490d659aa45a1a5.diff
LOG: [Metadata] Introduce MD_pcsections
Introduces MD_pcsections metadata kind. See added documentation for
more details.
Subsequent patches enable propagating PC sections metadata through code
generation to the AsmPrinter.
RFC: https://discourse.llvm.org/t/rfc-pc-keyed-metadata-at-runtime/64191
Reviewed By: dvyukov, vitalybuka
Differential Revision: https://reviews.llvm.org/D130875
Added:
llvm/docs/PCSectionsMetadata.rst
Modified:
llvm/docs/Reference.rst
llvm/include/llvm/IR/FixedMetadataKinds.def
llvm/include/llvm/IR/MDBuilder.h
llvm/lib/IR/MDBuilder.cpp
llvm/unittests/IR/MDBuilderTest.cpp
Removed:
################################################################################
diff --git a/llvm/docs/PCSectionsMetadata.rst b/llvm/docs/PCSectionsMetadata.rst
new file mode 100644
index 0000000000000..3be8af7b45764
--- /dev/null
+++ b/llvm/docs/PCSectionsMetadata.rst
@@ -0,0 +1,116 @@
+=========================
+LLVM PC Sections Metadata
+=========================
+
+.. contents::
+ :local:
+
+Introduction
+============
+
+PC Sections Metadata can be attached to instructions and functions, for which
+addresses, viz. program counters (PCs), are to be emitted in specially encoded
+binary sections. Metadata is assigned as an ``MDNode`` of the ``MD_pcsections``
+(``!pcsections``) kind; the following section describes the metadata format.
+
+Metadata Format
+===============
+
+An arbitrary number of interleaved ``MDString`` and constant operators can be
+added, where a new ``MDString`` always denotes a section name, followed by an
+arbitrary number of auxiliary constant data encoded along the PC of the
+instruction or function. The first operator must be a ``MDString`` denoting the
+first section.
+
+.. code-block:: none
+
+ !0 = !{
+ !"<section#1>"
+ [ , !1 ... ]
+ [ !"<section#2">
+ [ , !2 ... ]
+ ... ]
+ }
+ !1 = !{ iXX <aux-consts#1>, ... }
+ !2 = !{ iXX <aux-consts#2>, ... }
+ ...
+
+The occurrence of ``section#1``, ``section#2``, ..., ``section#N`` in the
+metadata causes the backend to emit the PC for the associated instruction or
+function to all named sections. For each emitted PC in a section #N, the
+constants ``aux-consts#N`` in the tuple ``!N`` will be emitted after the PC.
+Multiple tuples with constant data may be provided after a section name string
+(e.g. ``!0 = !{"s1", !1, !2}``), and a single constant tuple may be reused for
+
diff erent sections (e.g. ``!0 = !{"s1", !1, "s2", !1}``).
+
+Binary Encoding
+===============
+
+*Instructions* result in emitting a single PC, and *functions* result in
+emission of the start of the function and a 32-bit size. This is followed by
+the auxiliary constants that followed the respective section name in the
+``MD_pcsections`` metadata.
+
+To avoid relocations in the final binary, each PC address stored at ``entry``
+is a relative relocation, computed as ``pc - entry``. To decode, a user has to
+compute ``entry + *entry``.
+
+The size of each entry depends on the code model. With large and medium sized
+code models, the entry size matches pointer size. For any smaller code model
+the entry size is just 32 bits.
+
+Guarantees on Code Generation
+=============================
+
+Attaching ``!pcsections`` metadata to LLVM IR instructions *shall not* affect
+optimizations or code generation outside the requested PC sections.
+
+While relying on LLVM IR metadata to request PC sections makes the above
+guarantee relatively trivial, propagation of metadata through the optimization
+and code generation pipeline has the following guarantees.
+
+Metadata Propagation
+--------------------
+
+In general, LLVM *does not make any guarantees* about preserving IR metadata
+(attached to an ``Instruction``) through IR transformations. When using PC
+sections metadata, this guarantee is unchanged, and ``!pcsections`` metadata is
+remains *optional* until lowering to machine IR (MIR).
+
+Note for Code Generation
+------------------------
+
+As with other LLVM IR metadata, there are no requirements for LLVM IR
+transformation passes to preserve ``!pcsections`` metadata, with the following
+exceptions:
+
+ * The ``AtomicExpandPass`` shall preserve ``!pcsections`` metadata
+ according to the below rules 1-4.
+
+When translating LLVM IR to MIR, the ``!pcsections`` metadata shall be copied
+from the source ``Instruction`` to the target ``MachineInstr`` (set with
+``MachineInstr::setPCSections()``). The instruction selectors and MIR
+optimization passes shall preserve PC sections metadata as follows:
+
+ 1. Replacements will preserve PC sections metadata of the replaced
+ instruction.
+
+ 2. Duplications will preserve PC sections metadata of the copied
+ instruction.
+
+ 3. Merging will preserve PC sections metadata of one of the two
+ instructions (no guarantee on which instruction's metadata is used).
+
+ 4. Deletions will loose PC sections metadata.
+
+This is similar to debug info, and the ``BuildMI()`` helper provides a
+convenient way to propagate debug info and ``!pcsections`` metadata in the
+``MIMetadata`` bundle.
+
+Note for Metadata Users
+-----------------------
+
+Use cases for ``!pcsections`` metadata should either be fully tolerant to
+missing metadata, or the passes inserting ``!pcsections`` metadata should run
+*after* all LLVM IR optimization passes to preserve the metadata until being
+translated to MIR.
diff --git a/llvm/docs/Reference.rst b/llvm/docs/Reference.rst
index f6b80eb96caf4..9353eb757fdbc 100644
--- a/llvm/docs/Reference.rst
+++ b/llvm/docs/Reference.rst
@@ -33,6 +33,7 @@ LLVM and API reference documentation.
MarkedUpDisassembly
MIRLangRef
OptBisect
+ PCSectionsMetadata
PDB/index
PointerAuth
ScudoHardenedAllocator
diff --git a/llvm/include/llvm/IR/FixedMetadataKinds.def b/llvm/include/llvm/IR/FixedMetadataKinds.def
index 09810662cfea4..3d986325c5d33 100644
--- a/llvm/include/llvm/IR/FixedMetadataKinds.def
+++ b/llvm/include/llvm/IR/FixedMetadataKinds.def
@@ -48,3 +48,4 @@ LLVM_FIXED_MD_KIND(MD_exclude, "exclude", 33)
LLVM_FIXED_MD_KIND(MD_memprof, "memprof", 34)
LLVM_FIXED_MD_KIND(MD_callsite, "callsite", 35)
LLVM_FIXED_MD_KIND(MD_kcfi_type, "kcfi_type", 36)
+LLVM_FIXED_MD_KIND(MD_pcsections, "pcsections", 37)
diff --git a/llvm/include/llvm/IR/MDBuilder.h b/llvm/include/llvm/IR/MDBuilder.h
index 21d7b8b6da715..f31a769b6b442 100644
--- a/llvm/include/llvm/IR/MDBuilder.h
+++ b/llvm/include/llvm/IR/MDBuilder.h
@@ -15,6 +15,7 @@
#define LLVM_IR_MDBUILDER_H
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/Support/DataTypes.h"
@@ -112,6 +113,16 @@ class MDBuilder {
/// prologue for the "function" santizier.
MDNode *createRTTIPointerPrologue(Constant *PrologueSig, Constant *RTTI);
+ //===------------------------------------------------------------------===//
+ // PC sections metadata.
+ //===------------------------------------------------------------------===//
+
+ /// A pair of PC section name with auxilliary constant data.
+ using PCSection = std::pair<StringRef, SmallVector<Constant *>>;
+
+ /// Return metadata for PC sections.
+ MDNode *createPCSections(ArrayRef<PCSection> Sections);
+
//===------------------------------------------------------------------===//
// AA metadata.
//===------------------------------------------------------------------===//
diff --git a/llvm/lib/IR/MDBuilder.cpp b/llvm/lib/IR/MDBuilder.cpp
index fc59fda9fe221..d028eb4a21dd9 100644
--- a/llvm/lib/IR/MDBuilder.cpp
+++ b/llvm/lib/IR/MDBuilder.cpp
@@ -158,6 +158,27 @@ MDNode *MDBuilder::createRTTIPointerPrologue(Constant *PrologueSig,
return MDNode::get(Context, Ops);
}
+MDNode *MDBuilder::createPCSections(ArrayRef<PCSection> Sections) {
+ SmallVector<Metadata *, 2> Ops;
+
+ for (const auto &Entry : Sections) {
+ const StringRef &Sec = Entry.first;
+ Ops.push_back(createString(Sec));
+
+ // If auxiliary data for this section exists, append it.
+ const SmallVector<Constant *> &AuxConsts = Entry.second;
+ if (!AuxConsts.empty()) {
+ SmallVector<Metadata *, 1> AuxMDs;
+ AuxMDs.reserve(AuxConsts.size());
+ for (Constant *C : AuxConsts)
+ AuxMDs.push_back(createConstant(C));
+ Ops.push_back(MDNode::get(Context, AuxMDs));
+ }
+ }
+
+ return MDNode::get(Context, Ops);
+}
+
MDNode *MDBuilder::createAnonymousAARoot(StringRef Name, MDNode *Extra) {
SmallVector<Metadata *, 3> Args(1, nullptr);
if (Extra)
diff --git a/llvm/unittests/IR/MDBuilderTest.cpp b/llvm/unittests/IR/MDBuilderTest.cpp
index f8d08b5f3eae6..2b5ab81b60663 100644
--- a/llvm/unittests/IR/MDBuilderTest.cpp
+++ b/llvm/unittests/IR/MDBuilderTest.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Operator.h"
@@ -104,4 +105,26 @@ TEST_F(MDBuilderTest, createTBAANode) {
EXPECT_EQ(mdconst::extract<ConstantInt>(N2->getOperand(2))->getZExtValue(),
1U);
}
+TEST_F(MDBuilderTest, createPCSections) {
+ MDBuilder MDHelper(Context);
+ ConstantInt *C1 = ConstantInt::get(Context, APInt(8, 1));
+ ConstantInt *C2 = ConstantInt::get(Context, APInt(8, 2));
+ MDNode *PCS = MDHelper.createPCSections({{"s1", {C1, C2}}, {"s2", {}}});
+ ASSERT_EQ(PCS->getNumOperands(), 3U);
+ const auto *S1 = dyn_cast<MDString>(PCS->getOperand(0));
+ const auto *Aux = dyn_cast<MDNode>(PCS->getOperand(1));
+ const auto *S2 = dyn_cast<MDString>(PCS->getOperand(2));
+ ASSERT_NE(S1, nullptr);
+ ASSERT_NE(Aux, nullptr);
+ ASSERT_NE(S2, nullptr);
+ EXPECT_EQ(S1->getString(), "s1");
+ EXPECT_EQ(S2->getString(), "s2");
+ ASSERT_EQ(Aux->getNumOperands(), 2U);
+ ASSERT_TRUE(isa<ConstantAsMetadata>(Aux->getOperand(0)));
+ ASSERT_TRUE(isa<ConstantAsMetadata>(Aux->getOperand(1)));
+ EXPECT_EQ(mdconst::extract<ConstantInt>(Aux->getOperand(0))->getValue(),
+ C1->getValue());
+ EXPECT_EQ(mdconst::extract<ConstantInt>(Aux->getOperand(1))->getValue(),
+ C2->getValue());
}
+} // namespace
More information about the llvm-commits
mailing list