Skip to content

Commit 1c43e64

Browse files
authored
[CodeGen] Port ShadowStackGCLowering to new pass manager (#75324)
IIUC the new pass system was designed with parallelism. This pass needs to add some global variables into the current module, this is not allowed by [WritingAnLLVMPass](https://llvm.org/docs/WritingAnLLVMPass.html#the-functionpass-class), so convert it to module pass, see FIXME in `GetFrameMap`. Therefore, this will trigger assertion in `CodeGenPassBuilder`: https://github.com/llvm/llvm-project/blob/effd47ed45e3badd756103346a7c3b9e1e939e5e/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h#L200-L207 Will fix it in future.
1 parent 40c07b5 commit 1c43e64

File tree

6 files changed

+97
-32
lines changed

6 files changed

+97
-32
lines changed

llvm/include/llvm/CodeGen/CodeGenPassBuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "llvm/CodeGen/ReplaceWithVeclib.h"
3939
#include "llvm/CodeGen/SafeStack.h"
4040
#include "llvm/CodeGen/SelectOptimize.h"
41+
#include "llvm/CodeGen/ShadowStackGCLowering.h"
4142
#include "llvm/CodeGen/SjLjEHPrepare.h"
4243
#include "llvm/CodeGen/UnreachableBlockElim.h"
4344
#include "llvm/CodeGen/WasmEHPrepare.h"
@@ -642,6 +643,9 @@ void CodeGenPassBuilder<Derived>::addIRPasses(AddIRPass &addPass) const {
642643
// Run GC lowering passes for builtin collectors
643644
// TODO: add a pass insertion point here
644645
addPass(GCLoweringPass());
646+
// FIXME: `ShadowStackGCLoweringPass` now is a
647+
// module pass, so it will trigger assertion.
648+
// See comment of `AddingFunctionPasses`
645649
addPass(ShadowStackGCLoweringPass());
646650
addPass(LowerConstantIntrinsicsPass());
647651

llvm/include/llvm/CodeGen/MachinePassRegistry.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ MODULE_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis, (PIC))
2626
MODULE_PASS("pre-isel-intrinsic-lowering", PreISelIntrinsicLoweringPass, ())
2727
MODULE_PASS("jmc-instrumenter", JMCInstrumenterPass, ())
2828
MODULE_PASS("lower-emutls", LowerEmuTLSPass, ())
29+
MODULE_PASS("shadow-stack-gc-lowering", ShadowStackGCLoweringPass, ())
2930
#undef MODULE_PASS
3031

3132
#ifndef FUNCTION_ANALYSIS
@@ -133,7 +134,6 @@ MACHINE_FUNCTION_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis,
133134
DUMMY_FUNCTION_PASS("atomic-expand", AtomicExpandPass, ())
134135
DUMMY_FUNCTION_PASS("codegenprepare", CodeGenPreparePass, ())
135136
DUMMY_FUNCTION_PASS("gc-lowering", GCLoweringPass, ())
136-
DUMMY_FUNCTION_PASS("shadow-stack-gc-lowering", ShadowStackGCLoweringPass, ())
137137
DUMMY_FUNCTION_PASS("stack-protector", StackProtectorPass, ())
138138
#undef DUMMY_FUNCTION_PASS
139139

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//===- llvm/CodeGen/ShadowStackGCLowering.h ---------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CODEGEN_SHADOWSTACKGCLOWERING_H
10+
#define LLVM_CODEGEN_SHADOWSTACKGCLOWERING_H
11+
12+
#include "llvm/IR/PassManager.h"
13+
14+
namespace llvm {
15+
16+
class ShadowStackGCLoweringPass
17+
: public PassInfoMixin<ShadowStackGCLoweringPass> {
18+
public:
19+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
20+
};
21+
22+
} // namespace llvm
23+
24+
#endif // LLVM_CODEGEN_SHADOWSTACKGCLOWERING_H

llvm/lib/CodeGen/ShadowStackGCLowering.cpp

Lines changed: 66 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
//
1616
//===----------------------------------------------------------------------===//
1717

18+
#include "llvm/CodeGen/ShadowStackGCLowering.h"
1819
#include "llvm/ADT/SmallVector.h"
1920
#include "llvm/ADT/StringExtras.h"
2021
#include "llvm/Analysis/DomTreeUpdater.h"
22+
#include "llvm/CodeGen/GCMetadata.h"
2123
#include "llvm/CodeGen/Passes.h"
2224
#include "llvm/IR/BasicBlock.h"
2325
#include "llvm/IR/Constant.h"
@@ -50,7 +52,7 @@ using namespace llvm;
5052

5153
namespace {
5254

53-
class ShadowStackGCLowering : public FunctionPass {
55+
class ShadowStackGCLoweringImpl {
5456
/// RootChain - This is the global linked-list that contains the chain of GC
5557
/// roots.
5658
GlobalVariable *Head = nullptr;
@@ -64,13 +66,10 @@ class ShadowStackGCLowering : public FunctionPass {
6466
std::vector<std::pair<CallInst *, AllocaInst *>> Roots;
6567

6668
public:
67-
static char ID;
68-
69-
ShadowStackGCLowering();
69+
ShadowStackGCLoweringImpl() = default;
7070

71-
bool doInitialization(Module &M) override;
72-
void getAnalysisUsage(AnalysisUsage &AU) const override;
73-
bool runOnFunction(Function &F) override;
71+
bool doInitialization(Module &M);
72+
bool runOnFunction(Function &F, DomTreeUpdater *DTU);
7473

7574
private:
7675
bool IsNullValue(Value *V);
@@ -86,8 +85,51 @@ class ShadowStackGCLowering : public FunctionPass {
8685
const char *Name);
8786
};
8887

88+
class ShadowStackGCLowering : public FunctionPass {
89+
ShadowStackGCLoweringImpl Impl;
90+
91+
public:
92+
static char ID;
93+
94+
ShadowStackGCLowering();
95+
96+
bool doInitialization(Module &M) override { return Impl.doInitialization(M); }
97+
void getAnalysisUsage(AnalysisUsage &AU) const override {
98+
AU.addPreserved<DominatorTreeWrapperPass>();
99+
}
100+
bool runOnFunction(Function &F) override {
101+
std::optional<DomTreeUpdater> DTU;
102+
if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
103+
DTU.emplace(DTWP->getDomTree(), DomTreeUpdater::UpdateStrategy::Lazy);
104+
return Impl.runOnFunction(F, DTU ? &*DTU : nullptr);
105+
}
106+
};
107+
89108
} // end anonymous namespace
90109

110+
PreservedAnalyses ShadowStackGCLoweringPass::run(Module &M,
111+
ModuleAnalysisManager &MAM) {
112+
auto &Map = MAM.getResult<CollectorMetadataAnalysis>(M);
113+
if (Map.StrategyMap.contains("shadow-stack"))
114+
return PreservedAnalyses::all();
115+
116+
ShadowStackGCLoweringImpl Impl;
117+
bool Changed = Impl.doInitialization(M);
118+
for (auto &F : M) {
119+
auto &FAM =
120+
MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
121+
auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(F);
122+
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
123+
Changed |= Impl.runOnFunction(F, DT ? &DTU : nullptr);
124+
}
125+
126+
if (!Changed)
127+
return PreservedAnalyses::all();
128+
PreservedAnalyses PA;
129+
PA.preserve<DominatorTreeAnalysis>();
130+
return PA;
131+
}
132+
91133
char ShadowStackGCLowering::ID = 0;
92134
char &llvm::ShadowStackGCLoweringID = ShadowStackGCLowering::ID;
93135

@@ -104,7 +146,7 @@ ShadowStackGCLowering::ShadowStackGCLowering() : FunctionPass(ID) {
104146
initializeShadowStackGCLoweringPass(*PassRegistry::getPassRegistry());
105147
}
106148

107-
Constant *ShadowStackGCLowering::GetFrameMap(Function &F) {
149+
Constant *ShadowStackGCLoweringImpl::GetFrameMap(Function &F) {
108150
// doInitialization creates the abstract type of this value.
109151
Type *VoidPtr = PointerType::getUnqual(F.getContext());
110152

@@ -158,7 +200,7 @@ Constant *ShadowStackGCLowering::GetFrameMap(Function &F) {
158200
return ConstantExpr::getGetElementPtr(FrameMap->getType(), GV, GEPIndices);
159201
}
160202

161-
Type *ShadowStackGCLowering::GetConcreteStackEntryType(Function &F) {
203+
Type *ShadowStackGCLoweringImpl::GetConcreteStackEntryType(Function &F) {
162204
// doInitialization creates the generic version of this type.
163205
std::vector<Type *> EltTys;
164206
EltTys.push_back(StackEntryTy);
@@ -170,7 +212,7 @@ Type *ShadowStackGCLowering::GetConcreteStackEntryType(Function &F) {
170212

171213
/// doInitialization - If this module uses the GC intrinsics, find them now. If
172214
/// not, exit fast.
173-
bool ShadowStackGCLowering::doInitialization(Module &M) {
215+
bool ShadowStackGCLoweringImpl::doInitialization(Module &M) {
174216
bool Active = false;
175217
for (Function &F : M) {
176218
if (F.hasGC() && F.getGC() == "shadow-stack") {
@@ -224,13 +266,13 @@ bool ShadowStackGCLowering::doInitialization(Module &M) {
224266
return true;
225267
}
226268

227-
bool ShadowStackGCLowering::IsNullValue(Value *V) {
269+
bool ShadowStackGCLoweringImpl::IsNullValue(Value *V) {
228270
if (Constant *C = dyn_cast<Constant>(V))
229271
return C->isNullValue();
230272
return false;
231273
}
232274

233-
void ShadowStackGCLowering::CollectRoots(Function &F) {
275+
void ShadowStackGCLoweringImpl::CollectRoots(Function &F) {
234276
// FIXME: Account for original alignment. Could fragment the root array.
235277
// Approach 1: Null initialize empty slots at runtime. Yuck.
236278
// Approach 2: Emit a map of the array instead of just a count.
@@ -258,11 +300,10 @@ void ShadowStackGCLowering::CollectRoots(Function &F) {
258300
Roots.insert(Roots.begin(), MetaRoots.begin(), MetaRoots.end());
259301
}
260302

261-
GetElementPtrInst *ShadowStackGCLowering::CreateGEP(LLVMContext &Context,
262-
IRBuilder<> &B, Type *Ty,
263-
Value *BasePtr, int Idx,
264-
int Idx2,
265-
const char *Name) {
303+
GetElementPtrInst *
304+
ShadowStackGCLoweringImpl::CreateGEP(LLVMContext &Context, IRBuilder<> &B,
305+
Type *Ty, Value *BasePtr, int Idx,
306+
int Idx2, const char *Name) {
266307
Value *Indices[] = {ConstantInt::get(Type::getInt32Ty(Context), 0),
267308
ConstantInt::get(Type::getInt32Ty(Context), Idx),
268309
ConstantInt::get(Type::getInt32Ty(Context), Idx2)};
@@ -273,9 +314,11 @@ GetElementPtrInst *ShadowStackGCLowering::CreateGEP(LLVMContext &Context,
273314
return dyn_cast<GetElementPtrInst>(Val);
274315
}
275316

276-
GetElementPtrInst *ShadowStackGCLowering::CreateGEP(LLVMContext &Context,
277-
IRBuilder<> &B, Type *Ty, Value *BasePtr,
278-
int Idx, const char *Name) {
317+
GetElementPtrInst *ShadowStackGCLoweringImpl::CreateGEP(LLVMContext &Context,
318+
IRBuilder<> &B,
319+
Type *Ty,
320+
Value *BasePtr, int Idx,
321+
const char *Name) {
279322
Value *Indices[] = {ConstantInt::get(Type::getInt32Ty(Context), 0),
280323
ConstantInt::get(Type::getInt32Ty(Context), Idx)};
281324
Value *Val = B.CreateGEP(Ty, BasePtr, Indices, Name);
@@ -285,12 +328,9 @@ GetElementPtrInst *ShadowStackGCLowering::CreateGEP(LLVMContext &Context,
285328
return dyn_cast<GetElementPtrInst>(Val);
286329
}
287330

288-
void ShadowStackGCLowering::getAnalysisUsage(AnalysisUsage &AU) const {
289-
AU.addPreserved<DominatorTreeWrapperPass>();
290-
}
291-
292331
/// runOnFunction - Insert code to maintain the shadow stack.
293-
bool ShadowStackGCLowering::runOnFunction(Function &F) {
332+
bool ShadowStackGCLoweringImpl::runOnFunction(Function &F,
333+
DomTreeUpdater *DTU) {
294334
// Quick exit for functions that do not use the shadow stack GC.
295335
if (!F.hasGC() || F.getGC() != "shadow-stack")
296336
return false;
@@ -305,10 +345,6 @@ bool ShadowStackGCLowering::runOnFunction(Function &F) {
305345
if (Roots.empty())
306346
return false;
307347

308-
std::optional<DomTreeUpdater> DTU;
309-
if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
310-
DTU.emplace(DTWP->getDomTree(), DomTreeUpdater::UpdateStrategy::Lazy);
311-
312348
// Build the constant map and figure the type of the shadow stack entry.
313349
Value *FrameMap = GetFrameMap(F);
314350
Type *ConcreteStackEntryTy = GetConcreteStackEntryType(F);
@@ -359,8 +395,7 @@ bool ShadowStackGCLowering::runOnFunction(Function &F) {
359395
AtEntry.CreateStore(NewHeadVal, Head);
360396

361397
// For each instruction that escapes...
362-
EscapeEnumerator EE(F, "gc_cleanup", /*HandleExceptions=*/true,
363-
DTU ? &*DTU : nullptr);
398+
EscapeEnumerator EE(F, "gc_cleanup", /*HandleExceptions=*/true, DTU);
364399
while (IRBuilder<> *AtExit = EE.Next()) {
365400
// Pop the entry from the shadow stack. Don't reuse CurrentHead from
366401
// AtEntry, since that would make the value live for the entire function.

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
#include "llvm/CodeGen/LowerEmuTLS.h"
8787
#include "llvm/CodeGen/SafeStack.h"
8888
#include "llvm/CodeGen/SelectOptimize.h"
89+
#include "llvm/CodeGen/ShadowStackGCLowering.h"
8990
#include "llvm/CodeGen/SjLjEHPrepare.h"
9091
#include "llvm/CodeGen/TypePromotion.h"
9192
#include "llvm/CodeGen/WasmEHPrepare.h"

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ MODULE_PASS("sanmd-module", SanitizerBinaryMetadataPass())
128128
MODULE_PASS("scc-oz-module-inliner",
129129
buildInlinerPipeline(OptimizationLevel::Oz,
130130
ThinOrFullLTOPhase::None))
131+
MODULE_PASS("shadow-stack-gc-lowering", ShadowStackGCLoweringPass())
131132
MODULE_PASS("strip", StripSymbolsPass())
132133
MODULE_PASS("strip-dead-debug-info", StripDeadDebugInfoPass())
133134
MODULE_PASS("strip-dead-prototypes", StripDeadPrototypesPass())

0 commit comments

Comments
 (0)