Skip to content

Commit cf7a27a

Browse files
committed
Add IR and codegen support for deactivation symbols.
Deactivation symbols are a mechanism for allowing object files to disable specific instructions in other object files at link time. The initial use case is for pointer field protection. For more information, see the RFC: https://discourse.llvm.org/t/rfc-deactivation-symbols/85556 Pull Request: llvm#133536
1 parent 4bf047a commit cf7a27a

37 files changed

+400
-65
lines changed

llvm/docs/LangRef.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3090,6 +3090,21 @@ A "convergencectrl" operand bundle is only valid on a ``convergent`` operation.
30903090
When present, the operand bundle must contain exactly one value of token type.
30913091
See the :doc:`ConvergentOperations` document for details.
30923092

3093+
Deactivation Symbol Operand Bundles
3094+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3095+
3096+
A ``"deactivation-symbol"`` operand bundle is valid on the following
3097+
instructions (AArch64 only):
3098+
3099+
- Call to a normal function with ``notail`` attribute.
3100+
- Call to ``llvm.ptrauth.sign`` or ``llvm.ptrauth.auth`` intrinsics.
3101+
3102+
This operand bundle specifies that if the deactivation symbol is defined
3103+
to a valid value for the target, the marked instruction will return the
3104+
value of its first argument instead of calling the specified function
3105+
or intrinsic. This is achieved with ``PATCHINST`` relocations on the
3106+
target instructions (see the AArch64 psABI for details).
3107+
30933108
.. _moduleasm:
30943109

30953110
Module-Level Inline Assembly

llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ class LLVM_ABI CallLowering {
162162

163163
/// True if this call results in convergent operations.
164164
bool IsConvergent = true;
165+
166+
GlobalValue *DeactivationSymbol = nullptr;
165167
};
166168

167169
/// Argument handling is mostly uniform between the four places that

llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct MachineIRBuilderState {
5656
MDNode *PCSections = nullptr;
5757
/// MMRA Metadata to be set on any instruction we create.
5858
MDNode *MMRA = nullptr;
59+
Value *DS = nullptr;
5960

6061
/// \name Fields describing the insertion point.
6162
/// @{
@@ -369,6 +370,7 @@ class LLVM_ABI MachineIRBuilder {
369370
State.II = MI.getIterator();
370371
setPCSections(MI.getPCSections());
371372
setMMRAMetadata(MI.getMMRAMetadata());
373+
setDeactivationSymbol(MI.getDeactivationSymbol());
372374
}
373375
/// @}
374376

@@ -405,6 +407,9 @@ class LLVM_ABI MachineIRBuilder {
405407
/// Set the PC sections metadata to \p MD for all the next build instructions.
406408
void setMMRAMetadata(MDNode *MMRA) { State.MMRA = MMRA; }
407409

410+
Value *getDeactivationSymbol() { return State.DS; }
411+
void setDeactivationSymbol(Value *DS) { State.DS = DS; }
412+
408413
/// Get the current instruction's MMRA metadata.
409414
MDNode *getMMRAMetadata() { return State.MMRA; }
410415

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,6 +1563,10 @@ enum NodeType {
15631563
// Outputs: Output Chain
15641564
CLEAR_CACHE,
15651565

1566+
// Untyped node storing deactivation symbol reference
1567+
// (DeactivationSymbolSDNode).
1568+
DEACTIVATION_SYMBOL,
1569+
15661570
/// BUILTIN_OP_END - This must be the last enum value in this list.
15671571
/// The target-specific pre-isel opcode values start here.
15681572
BUILTIN_OP_END

llvm/include/llvm/CodeGen/MachineFunction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1207,7 +1207,7 @@ class LLVM_ABI MachineFunction {
12071207
ArrayRef<MachineMemOperand *> MMOs, MCSymbol *PreInstrSymbol = nullptr,
12081208
MCSymbol *PostInstrSymbol = nullptr, MDNode *HeapAllocMarker = nullptr,
12091209
MDNode *PCSections = nullptr, uint32_t CFIType = 0,
1210-
MDNode *MMRAs = nullptr);
1210+
MDNode *MMRAs = nullptr, Value *DS = nullptr);
12111211

12121212
/// Allocate a string and populate it with the given external symbol name.
12131213
const char *createExternalSymbolName(StringRef Name);

llvm/include/llvm/CodeGen/MachineInstr.h

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -160,29 +160,33 @@ class MachineInstr
160160
///
161161
/// This has to be defined eagerly due to the implementation constraints of
162162
/// `PointerSumType` where it is used.
163-
class ExtraInfo final : TrailingObjects<ExtraInfo, MachineMemOperand *,
164-
MCSymbol *, MDNode *, uint32_t> {
163+
class ExtraInfo final
164+
: TrailingObjects<ExtraInfo, MachineMemOperand *, MCSymbol *, MDNode *,
165+
uint32_t, Value *> {
165166
public:
166167
static ExtraInfo *create(BumpPtrAllocator &Allocator,
167168
ArrayRef<MachineMemOperand *> MMOs,
168169
MCSymbol *PreInstrSymbol = nullptr,
169170
MCSymbol *PostInstrSymbol = nullptr,
170171
MDNode *HeapAllocMarker = nullptr,
171172
MDNode *PCSections = nullptr, uint32_t CFIType = 0,
172-
MDNode *MMRAs = nullptr) {
173+
MDNode *MMRAs = nullptr, Value *DS = nullptr) {
173174
bool HasPreInstrSymbol = PreInstrSymbol != nullptr;
174175
bool HasPostInstrSymbol = PostInstrSymbol != nullptr;
175176
bool HasHeapAllocMarker = HeapAllocMarker != nullptr;
176177
bool HasMMRAs = MMRAs != nullptr;
177178
bool HasCFIType = CFIType != 0;
178179
bool HasPCSections = PCSections != nullptr;
180+
bool HasDS = DS != nullptr;
179181
auto *Result = new (Allocator.Allocate(
180-
totalSizeToAlloc<MachineMemOperand *, MCSymbol *, MDNode *, uint32_t>(
182+
totalSizeToAlloc<MachineMemOperand *, MCSymbol *, MDNode *, uint32_t,
183+
Value *>(
181184
MMOs.size(), HasPreInstrSymbol + HasPostInstrSymbol,
182-
HasHeapAllocMarker + HasPCSections + HasMMRAs, HasCFIType),
185+
HasHeapAllocMarker + HasPCSections + HasMMRAs, HasCFIType, HasDS),
183186
alignof(ExtraInfo)))
184187
ExtraInfo(MMOs.size(), HasPreInstrSymbol, HasPostInstrSymbol,
185-
HasHeapAllocMarker, HasPCSections, HasCFIType, HasMMRAs);
188+
HasHeapAllocMarker, HasPCSections, HasCFIType, HasMMRAs,
189+
HasDS);
186190

187191
// Copy the actual data into the trailing objects.
188192
std::copy(MMOs.begin(), MMOs.end(),
@@ -203,6 +207,8 @@ class MachineInstr
203207
Result->getTrailingObjects<uint32_t>()[0] = CFIType;
204208
if (HasMMRAs)
205209
Result->getTrailingObjects<MDNode *>()[MDNodeIdx++] = MMRAs;
210+
if (HasDS)
211+
Result->getTrailingObjects<Value *>()[0] = DS;
206212

207213
return Result;
208214
}
@@ -241,6 +247,10 @@ class MachineInstr
241247
: nullptr;
242248
}
243249

250+
Value *getDeactivationSymbol() const {
251+
return HasDS ? getTrailingObjects<Value *>()[0] : 0;
252+
}
253+
244254
private:
245255
friend TrailingObjects;
246256

@@ -256,6 +266,7 @@ class MachineInstr
256266
const bool HasPCSections;
257267
const bool HasCFIType;
258268
const bool HasMMRAs;
269+
const bool HasDS;
259270

260271
// Implement the `TrailingObjects` internal API.
261272
size_t numTrailingObjects(OverloadToken<MachineMemOperand *>) const {
@@ -270,16 +281,19 @@ class MachineInstr
270281
size_t numTrailingObjects(OverloadToken<uint32_t>) const {
271282
return HasCFIType;
272283
}
284+
size_t numTrailingObjects(OverloadToken<Value *>) const {
285+
return HasDS;
286+
}
273287

274288
// Just a boring constructor to allow us to initialize the sizes. Always use
275289
// the `create` routine above.
276290
ExtraInfo(int NumMMOs, bool HasPreInstrSymbol, bool HasPostInstrSymbol,
277291
bool HasHeapAllocMarker, bool HasPCSections, bool HasCFIType,
278-
bool HasMMRAs)
292+
bool HasMMRAs, bool HasDS)
279293
: NumMMOs(NumMMOs), HasPreInstrSymbol(HasPreInstrSymbol),
280294
HasPostInstrSymbol(HasPostInstrSymbol),
281295
HasHeapAllocMarker(HasHeapAllocMarker), HasPCSections(HasPCSections),
282-
HasCFIType(HasCFIType), HasMMRAs(HasMMRAs) {}
296+
HasCFIType(HasCFIType), HasMMRAs(HasMMRAs), HasDS(HasDS) {}
283297
};
284298

285299
/// Enumeration of the kinds of inline extra info available. It is important
@@ -868,6 +882,14 @@ class MachineInstr
868882
return nullptr;
869883
}
870884

885+
Value *getDeactivationSymbol() const {
886+
if (!Info)
887+
return nullptr;
888+
if (ExtraInfo *EI = Info.get<EIIK_OutOfLine>())
889+
return EI->getDeactivationSymbol();
890+
return nullptr;
891+
}
892+
871893
/// Helper to extract a CFI type hash if one has been added.
872894
uint32_t getCFIType() const {
873895
if (!Info)
@@ -1970,6 +1992,8 @@ class MachineInstr
19701992
/// Set the CFI type for the instruction.
19711993
LLVM_ABI void setCFIType(MachineFunction &MF, uint32_t Type);
19721994

1995+
LLVM_ABI void setDeactivationSymbol(MachineFunction &MF, Value *DS);
1996+
19731997
/// Return the MIFlags which represent both MachineInstrs. This
19741998
/// should be used when merging two MachineInstrs into one. This routine does
19751999
/// not modify the MIFlags of this MachineInstr.
@@ -2080,7 +2104,7 @@ class MachineInstr
20802104
void setExtraInfo(MachineFunction &MF, ArrayRef<MachineMemOperand *> MMOs,
20812105
MCSymbol *PreInstrSymbol, MCSymbol *PostInstrSymbol,
20822106
MDNode *HeapAllocMarker, MDNode *PCSections,
2083-
uint32_t CFIType, MDNode *MMRAs);
2107+
uint32_t CFIType, MDNode *MMRAs, Value *DS);
20842108
};
20852109

20862110
/// Special DenseMapInfo traits to compare MachineInstr* by *value* of the

llvm/include/llvm/CodeGen/MachineInstrBuilder.h

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,29 +70,44 @@ enum {
7070
} // end namespace RegState
7171

7272
/// Set of metadata that should be preserved when using BuildMI(). This provides
73-
/// a more convenient way of preserving DebugLoc, PCSections and MMRA.
73+
/// a more convenient way of preserving certain data from the original
74+
/// instruction.
7475
class MIMetadata {
7576
public:
7677
MIMetadata() = default;
77-
MIMetadata(DebugLoc DL, MDNode *PCSections = nullptr, MDNode *MMRA = nullptr)
78-
: DL(std::move(DL)), PCSections(PCSections), MMRA(MMRA) {}
78+
MIMetadata(DebugLoc DL, MDNode *PCSections = nullptr, MDNode *MMRA = nullptr,
79+
Value *DeactivationSymbol = nullptr)
80+
: DL(std::move(DL)), PCSections(PCSections), MMRA(MMRA),
81+
DeactivationSymbol(DeactivationSymbol) {}
7982
MIMetadata(const DILocation *DI, MDNode *PCSections = nullptr,
8083
MDNode *MMRA = nullptr)
8184
: DL(DI), PCSections(PCSections), MMRA(MMRA) {}
8285
explicit MIMetadata(const Instruction &From)
8386
: DL(From.getDebugLoc()),
84-
PCSections(From.getMetadata(LLVMContext::MD_pcsections)) {}
87+
PCSections(From.getMetadata(LLVMContext::MD_pcsections)),
88+
DeactivationSymbol(getDeactivationSymbol(&From)) {}
8589
explicit MIMetadata(const MachineInstr &From)
86-
: DL(From.getDebugLoc()), PCSections(From.getPCSections()) {}
90+
: DL(From.getDebugLoc()), PCSections(From.getPCSections()),
91+
DeactivationSymbol(From.getDeactivationSymbol()) {}
8792

8893
const DebugLoc &getDL() const { return DL; }
8994
MDNode *getPCSections() const { return PCSections; }
9095
MDNode *getMMRAMetadata() const { return MMRA; }
96+
Value *getDeactivationSymbol() const { return DeactivationSymbol; }
9197

9298
private:
9399
DebugLoc DL;
94100
MDNode *PCSections = nullptr;
95101
MDNode *MMRA = nullptr;
102+
Value *DeactivationSymbol = nullptr;
103+
104+
static inline Value *getDeactivationSymbol(const Instruction *I) {
105+
if (auto *CB = dyn_cast<CallBase>(I))
106+
if (auto Bundle =
107+
CB->getOperandBundle(llvm::LLVMContext::OB_deactivation_symbol))
108+
return Bundle->Inputs[0].get();
109+
return nullptr;
110+
}
96111
};
97112

98113
class MachineInstrBuilder {
@@ -348,6 +363,8 @@ class MachineInstrBuilder {
348363
MI->setPCSections(*MF, MIMD.getPCSections());
349364
if (MIMD.getMMRAMetadata())
350365
MI->setMMRAMetadata(*MF, MIMD.getMMRAMetadata());
366+
if (MIMD.getDeactivationSymbol())
367+
MI->setDeactivationSymbol(*MF, MIMD.getDeactivationSymbol());
351368
return *this;
352369
}
353370

llvm/include/llvm/CodeGen/SelectionDAG.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,7 @@ class SelectionDAG {
763763
int64_t offset = 0, unsigned TargetFlags = 0) {
764764
return getGlobalAddress(GV, DL, VT, offset, true, TargetFlags);
765765
}
766+
LLVM_ABI SDValue getDeactivationSymbol(const GlobalValue *GV);
766767
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget = false);
767768
SDValue getTargetFrameIndex(int FI, EVT VT) {
768769
return getFrameIndex(FI, VT, true);

llvm/include/llvm/CodeGen/SelectionDAGISel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class SelectionDAGISel {
150150
OPC_RecordChild7,
151151
OPC_RecordMemRef,
152152
OPC_CaptureGlueInput,
153+
OPC_CaptureDeactivationSymbol,
153154
OPC_MoveChild,
154155
OPC_MoveChild0,
155156
OPC_MoveChild1,

llvm/include/llvm/CodeGen/SelectionDAGNodes.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,6 +1980,23 @@ class GlobalAddressSDNode : public SDNode {
19801980
}
19811981
};
19821982

1983+
class DeactivationSymbolSDNode : public SDNode {
1984+
friend class SelectionDAG;
1985+
1986+
const GlobalValue *TheGlobal;
1987+
1988+
DeactivationSymbolSDNode(const GlobalValue *GV, SDVTList VTs)
1989+
: SDNode(ISD::DEACTIVATION_SYMBOL, 0, DebugLoc(), VTs),
1990+
TheGlobal(GV) {}
1991+
1992+
public:
1993+
const GlobalValue *getGlobal() const { return TheGlobal; }
1994+
1995+
static bool classof(const SDNode *N) {
1996+
return N->getOpcode() == ISD::DEACTIVATION_SYMBOL;
1997+
}
1998+
};
1999+
19832000
class FrameIndexSDNode : public SDNode {
19842001
friend class SelectionDAG;
19852002

0 commit comments

Comments
 (0)