Skip to content

Commit 156479c

Browse files
Set up the shadow stack in LSSA
This paves the way for introducing some RPI/PI optimizations and also moves us a bit closer to the model where all that's possible to do in IR is done in IR. Setting up the shadow stack in IR is a tricky problem since we don't want to spill it to an alloca even in debug code. We therefore modify how we refer to the shadow stack: 1) For the main function, we use an untracked SSA local. Note how we are introducing a new concept here - usually all SSA locals are tracked. 2) For funclets, we repurpose the pre-existing PHYSREG node to allow us to refer to the LLVM argument directly. However, the IR representation is just one part of the problem. Another is the fact codegen needs to refer to the shadow stack directly, for debug info and helper call generation purposes. Since some of this needs to happen "in the prolog", before any IR is generated, we also introduce a concept of "late" and "early" prologs. They are sequenced as follows: - "Early" prolog - codegen (LLVM IR) - "Middle" prolog - LSSA (IR) - "Late" prolog - codegen (LLVM IR) This is almost a zero-diff change; the few diffs are due to the different ordering of native stack init and shadow stack init for RPI methods.
1 parent a9f328d commit 156479c

File tree

7 files changed

+279
-222
lines changed

7 files changed

+279
-222
lines changed

src/coreclr/jit/gentree.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8178,7 +8178,7 @@ GenTree* Compiler::gtNewPhysRegNode(regNumber reg, var_types type)
81788178
{
81798179
#ifdef TARGET_ARM64
81808180
assert(genIsValidIntReg(reg) || (reg == REG_SPBASE) || (reg == REG_FFR));
8181-
#else
8181+
#elif !defined(TARGET_WASM)
81828182
assert(genIsValidIntReg(reg) || (reg == REG_SPBASE));
81838183
#endif
81848184
GenTree* result = new (this, GT_PHYSREG) GenTreePhysReg(reg, type);

src/coreclr/jit/llvm.h

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ class Llvm
285285
{
286286
private:
287287
static const unsigned SHADOW_STACK_ARG_INDEX = 0;
288-
static const unsigned DEFAULT_SHADOW_STACK_ALIGNMENT = TARGET_POINTER_SIZE;
288+
static const unsigned ORIGINAL_SHADOW_STACK_ARG_INDEX = 1;
289289
static const unsigned MIN_HEAP_OBJ_SIZE = TARGET_POINTER_SIZE * 2;
290290

291291
void* const m_pEECorInfo; // TODO-LLVM: workaround for not changing the JIT/EE interface.
@@ -301,7 +301,6 @@ class Llvm
301301
// Lowering members.
302302
LIR::Range* m_currentRange = nullptr;
303303
SideEffectSet m_scratchSideEffects; // Used for IsInvariantInRange.
304-
bool m_anyFilterFunclets = false;
305304

306305
// Optimization facts provided by lowering.
307306
BooleanFact m_anyVirtuallyUnwindableCalleesViaLowering = BooleanFact::Unknown;
@@ -316,6 +315,7 @@ class Llvm
316315

317316
// Shared between LSSA and codegen.
318317
bool m_anyAddressExposedOrPinnedShadowLocals = false;
318+
GenTree* m_prologEnd = nullptr; // First 'user' node after the prolog.
319319

320320
// Codegen members.
321321
llvm::IRBuilder<> _builder;
@@ -329,8 +329,6 @@ class Llvm
329329
EHRegionInfo* m_EHRegionsInfo;
330330
Value* m_exceptionThrownAddressValue = nullptr;
331331

332-
Value* m_rootFunctionShadowStackValue = nullptr;
333-
334332
// Codegen emit context.
335333
unsigned m_currentLlvmFunctionIndex = ROOT_FUNC_IDX;
336334
unsigned m_currentProtectedRegionIndex = EHblkDsc::NO_ENCLOSING_INDEX;
@@ -344,10 +342,9 @@ class Llvm
344342
unsigned m_lineNumberCount;
345343
CORINFO_LLVM_LINE_NUMBER_DEBUG_INFO* m_lineNumbers;
346344

347-
unsigned m_shadowFrameAlignment = DEFAULT_SHADOW_STACK_ALIGNMENT;
348345
unsigned _shadowStackLocalsSize = 0;
349-
unsigned _originalShadowStackLclNum = BAD_VAR_NUM;
350-
unsigned _shadowStackLclNum = BAD_VAR_NUM;
346+
unsigned m_shadowStackSsaNum = SsaConfig::RESERVED_SSA_NUM;
347+
unsigned m_shadowStackLclNum = BAD_VAR_NUM;
351348
unsigned m_sparseVirtualUnwindFrameLclNum = BAD_VAR_NUM;
352349
unsigned m_preciseVirtualUnwindFrameLclNum = BAD_VAR_NUM;
353350
unsigned _llvmArgCount = 0;
@@ -473,7 +470,6 @@ class Llvm
473470
void lowerVirtualStubCall(GenTreeCall* callNode);
474471
void insertNullCheckForCall(GenTreeCall* callNode);
475472
void lowerDelegateInvoke(GenTreeCall* callNode);
476-
void lowerReversePInvokeExit(GenTreeCall* callNode);
477473
void lowerUnmanagedCall(GenTreeCall* callNode);
478474
void lowerCallToShadowStack(GenTreeCall* callNode);
479475
void lowerCallReturn(GenTreeCall* callNode);
@@ -485,7 +481,6 @@ class Llvm
485481
GenTree* normalizeStructUse(LIR::Use& use, ClassLayout* layout);
486482

487483
unsigned representAsLclVar(LIR::Use& use);
488-
GenTree* insertShadowStackAddr(GenTree* insertBefore, unsigned offset, unsigned shadowStackLclNum);
489484
GenTreeAddrMode* createAddrModeNode(GenTree* base, unsigned offset);
490485

491486
void lowerCollectOptimizationFacts(GenTree* node);
@@ -496,7 +491,7 @@ class Llvm
496491
void dissolvePromotedLocal(unsigned lclNum);
497492

498493
bool isFirstBlockCanonical();
499-
GenTree* lowerAndInsertIntoFirstBlock(LIR::Range& range, GenTree* insertAfter = nullptr);
494+
GenTree* lowerAndInsertIntoFirstBlock(LIR::Range&& range, GenTree* insertAfter = nullptr);
500495

501496
public:
502497
PhaseStatus AddVirtualUnwindFrame();
@@ -546,8 +541,6 @@ class Llvm
546541
bool callIsInTry, bool callIsInFilter DEBUGARG(const char** pReasonWhyNot = nullptr)) const;
547542
bool isPotentialGcSafePoint(GenTree* node) const;
548543
bool isShadowFrameLocal(LclVarDsc* varDsc) const;
549-
bool isShadowStackLocal(unsigned lclNum) const;
550-
bool isFuncletParameter(unsigned lclNum) const;
551544

552545
// ================================================================================================================
553546
// | Codegen |
@@ -561,14 +554,14 @@ class Llvm
561554

562555
void initializeFunctions();
563556
void annotateFunctions();
564-
void generateProlog();
565-
void initializeShadowStack();
557+
void generateEarlyProlog();
566558
void initializeLocals();
567559
void initializeBlocks();
560+
void generateLateProlog();
568561
void generateUnwindBlocks();
569562
void generateBlocks();
570563
void generateBlock(BasicBlock* block);
571-
void fillPhis();
564+
void generatePhis();
572565
void generateAuxiliaryArtifacts();
573566
void verifyGeneratedCode();
574567
void displayGeneratedCode();
@@ -595,6 +588,7 @@ class Llvm
595588
void buildCmp(GenTreeOp* node);
596589
void buildCnsDouble(GenTreeDblCon* node);
597590
void buildIntegralConst(GenTreeIntConCommon* node);
591+
void buildPhysReg(GenTreePhysReg* physReg);
598592
void buildCall(GenTreeCall* node);
599593
void buildInd(GenTreeIndir* indNode);
600594
void buildBlk(GenTreeBlk* blkNode);
@@ -669,7 +663,6 @@ class Llvm
669663
llvm::Constant* getIntPtrConst(target_size_t value, Type* llvmType = nullptr);
670664
Value* getShadowStack();
671665
Value* getShadowStackForCallee(bool isTailCall = false);
672-
Value* getOriginalShadowStack();
673666

674667
void setCurrentEmitContextForBlock(BasicBlock* block);
675668
void setCurrentEmitContextBlocks(LlvmBlockRange* llvmBlocks);
@@ -693,7 +686,7 @@ class Llvm
693686
LlvmBlockRange* getLlvmBlocksForBlock(BasicBlock* block);
694687
llvm::BasicBlock* getFirstLlvmBlockForBlock(BasicBlock* block);
695688
llvm::BasicBlock* getLastLlvmBlockForBlock(BasicBlock* block);
696-
llvm::BasicBlock* getOrCreatePrologLlvmBlockForFunction(unsigned funcIdx);
689+
llvm::IRBuilderBase::InsertPoint getOrCreateEarlyPrologForFunction(unsigned funcIdx);
697690

698691
bool isReachable(BasicBlock* block) const;
699692
BasicBlock* getFirstBlockForFunction(unsigned funcIdx) const;

0 commit comments

Comments
 (0)