LLVM  15.0.0git
AArch64StackTagging.cpp
Go to the documentation of this file.
1 //===- AArch64StackTagging.cpp - Stack tagging in IR --===//
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 
10 #include "AArch64.h"
11 #include "AArch64InstrInfo.h"
12 #include "AArch64Subtarget.h"
13 #include "AArch64TargetMachine.h"
14 #include "llvm/ADT/DenseMap.h"
16 #include "llvm/ADT/MapVector.h"
17 #include "llvm/ADT/None.h"
18 #include "llvm/ADT/Optional.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/Statistic.h"
22 #include "llvm/Analysis/CFG.h"
23 #include "llvm/Analysis/LoopInfo.h"
40 #include "llvm/IR/DebugLoc.h"
41 #include "llvm/IR/Dominators.h"
42 #include "llvm/IR/Function.h"
44 #include "llvm/IR/IRBuilder.h"
45 #include "llvm/IR/InstIterator.h"
46 #include "llvm/IR/Instruction.h"
47 #include "llvm/IR/Instructions.h"
48 #include "llvm/IR/IntrinsicInst.h"
49 #include "llvm/IR/IntrinsicsAArch64.h"
50 #include "llvm/IR/Metadata.h"
51 #include "llvm/IR/ValueHandle.h"
52 #include "llvm/InitializePasses.h"
53 #include "llvm/Pass.h"
54 #include "llvm/Support/Casting.h"
55 #include "llvm/Support/Debug.h"
59 #include <cassert>
60 #include <iterator>
61 #include <utility>
62 
63 using namespace llvm;
64 
65 #define DEBUG_TYPE "aarch64-stack-tagging"
66 
68  "stack-tagging-merge-init", cl::Hidden, cl::init(true), cl::ZeroOrMore,
69  cl::desc("merge stack variable initializers with tagging when possible"));
70 
71 static cl::opt<bool>
72  ClUseStackSafety("stack-tagging-use-stack-safety", cl::Hidden,
73  cl::init(true), cl::ZeroOrMore,
74  cl::desc("Use Stack Safety analysis results"));
75 
76 static cl::opt<unsigned> ClScanLimit("stack-tagging-merge-init-scan-limit",
77  cl::init(40), cl::Hidden);
78 
79 static cl::opt<unsigned>
80  ClMergeInitSizeLimit("stack-tagging-merge-init-size-limit", cl::init(272),
81  cl::Hidden);
82 
84  "stack-tagging-max-lifetimes-for-alloca", cl::Hidden, cl::init(3),
86  cl::desc("How many lifetime ends to handle for a single alloca."),
87  cl::Optional);
88 
89 static const Align kTagGranuleSize = Align(16);
90 
91 namespace {
92 
93 class InitializerBuilder {
94  uint64_t Size;
95  const DataLayout *DL;
96  Value *BasePtr;
97  Function *SetTagFn;
98  Function *SetTagZeroFn;
99  Function *StgpFn;
100 
101  // List of initializers sorted by start offset.
102  struct Range {
103  uint64_t Start, End;
104  Instruction *Inst;
105  };
106  SmallVector<Range, 4> Ranges;
107  // 8-aligned offset => 8-byte initializer
108  // Missing keys are zero initialized.
109  std::map<uint64_t, Value *> Out;
110 
111 public:
112  InitializerBuilder(uint64_t Size, const DataLayout *DL, Value *BasePtr,
113  Function *SetTagFn, Function *SetTagZeroFn,
114  Function *StgpFn)
115  : Size(Size), DL(DL), BasePtr(BasePtr), SetTagFn(SetTagFn),
116  SetTagZeroFn(SetTagZeroFn), StgpFn(StgpFn) {}
117 
118  bool addRange(uint64_t Start, uint64_t End, Instruction *Inst) {
119  auto I =
120  llvm::lower_bound(Ranges, Start, [](const Range &LHS, uint64_t RHS) {
121  return LHS.End <= RHS;
122  });
123  if (I != Ranges.end() && End > I->Start) {
124  // Overlap - bail.
125  return false;
126  }
127  Ranges.insert(I, {Start, End, Inst});
128  return true;
129  }
130 
131  bool addStore(uint64_t Offset, StoreInst *SI, const DataLayout *DL) {
132  int64_t StoreSize = DL->getTypeStoreSize(SI->getOperand(0)->getType());
133  if (!addRange(Offset, Offset + StoreSize, SI))
134  return false;
135  IRBuilder<> IRB(SI);
136  applyStore(IRB, Offset, Offset + StoreSize, SI->getOperand(0));
137  return true;
138  }
139 
140  bool addMemSet(uint64_t Offset, MemSetInst *MSI) {
141  uint64_t StoreSize = cast<ConstantInt>(MSI->getLength())->getZExtValue();
142  if (!addRange(Offset, Offset + StoreSize, MSI))
143  return false;
144  IRBuilder<> IRB(MSI);
145  applyMemSet(IRB, Offset, Offset + StoreSize,
146  cast<ConstantInt>(MSI->getValue()));
147  return true;
148  }
149 
150  void applyMemSet(IRBuilder<> &IRB, int64_t Start, int64_t End,
151  ConstantInt *V) {
152  // Out[] does not distinguish between zero and undef, and we already know
153  // that this memset does not overlap with any other initializer. Nothing to
154  // do for memset(0).
155  if (V->isZero())
156  return;
157  for (int64_t Offset = Start - Start % 8; Offset < End; Offset += 8) {
158  uint64_t Cst = 0x0101010101010101UL;
159  int LowBits = Offset < Start ? (Start - Offset) * 8 : 0;
160  if (LowBits)
161  Cst = (Cst >> LowBits) << LowBits;
162  int HighBits = End - Offset < 8 ? (8 - (End - Offset)) * 8 : 0;
163  if (HighBits)
164  Cst = (Cst << HighBits) >> HighBits;
165  ConstantInt *C =
166  ConstantInt::get(IRB.getInt64Ty(), Cst * V->getZExtValue());
167 
168  Value *&CurrentV = Out[Offset];
169  if (!CurrentV) {
170  CurrentV = C;
171  } else {
172  CurrentV = IRB.CreateOr(CurrentV, C);
173  }
174  }
175  }
176 
177  // Take a 64-bit slice of the value starting at the given offset (in bytes).
178  // Offset can be negative. Pad with zeroes on both sides when necessary.
179  Value *sliceValue(IRBuilder<> &IRB, Value *V, int64_t Offset) {
180  if (Offset > 0) {
181  V = IRB.CreateLShr(V, Offset * 8);
182  V = IRB.CreateZExtOrTrunc(V, IRB.getInt64Ty());
183  } else if (Offset < 0) {
184  V = IRB.CreateZExtOrTrunc(V, IRB.getInt64Ty());
185  V = IRB.CreateShl(V, -Offset * 8);
186  } else {
187  V = IRB.CreateZExtOrTrunc(V, IRB.getInt64Ty());
188  }
189  return V;
190  }
191 
192  void applyStore(IRBuilder<> &IRB, int64_t Start, int64_t End,
193  Value *StoredValue) {
194  StoredValue = flatten(IRB, StoredValue);
195  for (int64_t Offset = Start - Start % 8; Offset < End; Offset += 8) {
196  Value *V = sliceValue(IRB, StoredValue, Offset - Start);
197  Value *&CurrentV = Out[Offset];
198  if (!CurrentV) {
199  CurrentV = V;
200  } else {
201  CurrentV = IRB.CreateOr(CurrentV, V);
202  }
203  }
204  }
205 
206  void generate(IRBuilder<> &IRB) {
207  LLVM_DEBUG(dbgs() << "Combined initializer\n");
208  // No initializers => the entire allocation is undef.
209  if (Ranges.empty()) {
210  emitUndef(IRB, 0, Size);
211  return;
212  }
213 
214  // Look through 8-byte initializer list 16 bytes at a time;
215  // If one of the two 8-byte halfs is non-zero non-undef, emit STGP.
216  // Otherwise, emit zeroes up to next available item.
217  uint64_t LastOffset = 0;
218  for (uint64_t Offset = 0; Offset < Size; Offset += 16) {
219  auto I1 = Out.find(Offset);
220  auto I2 = Out.find(Offset + 8);
221  if (I1 == Out.end() && I2 == Out.end())
222  continue;
223 
224  if (Offset > LastOffset)
225  emitZeroes(IRB, LastOffset, Offset - LastOffset);
226 
227  Value *Store1 = I1 == Out.end() ? Constant::getNullValue(IRB.getInt64Ty())
228  : I1->second;
229  Value *Store2 = I2 == Out.end() ? Constant::getNullValue(IRB.getInt64Ty())
230  : I2->second;
231  emitPair(IRB, Offset, Store1, Store2);
232  LastOffset = Offset + 16;
233  }
234 
235  // memset(0) does not update Out[], therefore the tail can be either undef
236  // or zero.
237  if (LastOffset < Size)
238  emitZeroes(IRB, LastOffset, Size - LastOffset);
239 
240  for (const auto &R : Ranges) {
241  R.Inst->eraseFromParent();
242  }
243  }
244 
245  void emitZeroes(IRBuilder<> &IRB, uint64_t Offset, uint64_t Size) {
246  LLVM_DEBUG(dbgs() << " [" << Offset << ", " << Offset + Size
247  << ") zero\n");
248  Value *Ptr = BasePtr;
249  if (Offset)
250  Ptr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), Ptr, Offset);
251  IRB.CreateCall(SetTagZeroFn,
252  {Ptr, ConstantInt::get(IRB.getInt64Ty(), Size)});
253  }
254 
255  void emitUndef(IRBuilder<> &IRB, uint64_t Offset, uint64_t Size) {
256  LLVM_DEBUG(dbgs() << " [" << Offset << ", " << Offset + Size
257  << ") undef\n");
258  Value *Ptr = BasePtr;
259  if (Offset)
260  Ptr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), Ptr, Offset);
261  IRB.CreateCall(SetTagFn, {Ptr, ConstantInt::get(IRB.getInt64Ty(), Size)});
262  }
263 
264  void emitPair(IRBuilder<> &IRB, uint64_t Offset, Value *A, Value *B) {
265  LLVM_DEBUG(dbgs() << " [" << Offset << ", " << Offset + 16 << "):\n");
266  LLVM_DEBUG(dbgs() << " " << *A << "\n " << *B << "\n");
267  Value *Ptr = BasePtr;
268  if (Offset)
269  Ptr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), Ptr, Offset);
270  IRB.CreateCall(StgpFn, {Ptr, A, B});
271  }
272 
273  Value *flatten(IRBuilder<> &IRB, Value *V) {
274  if (V->getType()->isIntegerTy())
275  return V;
276  // vector of pointers -> vector of ints
277  if (VectorType *VecTy = dyn_cast<VectorType>(V->getType())) {
278  LLVMContext &Ctx = IRB.getContext();
279  Type *EltTy = VecTy->getElementType();
280  if (EltTy->isPointerTy()) {
281  uint32_t EltSize = DL->getTypeSizeInBits(EltTy);
282  auto *NewTy = FixedVectorType::get(
283  IntegerType::get(Ctx, EltSize),
284  cast<FixedVectorType>(VecTy)->getNumElements());
285  V = IRB.CreatePointerCast(V, NewTy);
286  }
287  }
288  return IRB.CreateBitOrPointerCast(
289  V, IRB.getIntNTy(DL->getTypeStoreSize(V->getType()) * 8));
290  }
291 };
292 
293 class AArch64StackTagging : public FunctionPass {
294  const bool MergeInit;
295  const bool UseStackSafety;
296 
297 public:
298  static char ID; // Pass ID, replacement for typeid
299 
300  AArch64StackTagging(bool IsOptNone = false)
301  : FunctionPass(ID),
302  MergeInit(ClMergeInit.getNumOccurrences() ? ClMergeInit : !IsOptNone),
303  UseStackSafety(ClUseStackSafety.getNumOccurrences() ? ClUseStackSafety
304  : !IsOptNone) {
306  }
307 
308  bool isInterestingAlloca(const AllocaInst &AI);
309 
310  void tagAlloca(AllocaInst *AI, Instruction *InsertBefore, Value *Ptr,
311  uint64_t Size);
312  void untagAlloca(AllocaInst *AI, Instruction *InsertBefore, uint64_t Size);
313 
314  Instruction *collectInitializers(Instruction *StartInst, Value *StartPtr,
315  uint64_t Size, InitializerBuilder &IB);
316 
317  Instruction *insertBaseTaggedPointer(
319  const DominatorTree *DT);
320  bool runOnFunction(Function &F) override;
321 
322  StringRef getPassName() const override { return "AArch64 Stack Tagging"; }
323 
324 private:
325  Function *F = nullptr;
326  Function *SetTagFunc = nullptr;
327  const DataLayout *DL = nullptr;
328  AAResults *AA = nullptr;
329  const StackSafetyGlobalInfo *SSI = nullptr;
330 
331  void getAnalysisUsage(AnalysisUsage &AU) const override {
332  AU.setPreservesCFG();
333  if (UseStackSafety)
335  if (MergeInit)
337  }
338 };
339 
340 } // end anonymous namespace
341 
342 char AArch64StackTagging::ID = 0;
343 
344 INITIALIZE_PASS_BEGIN(AArch64StackTagging, DEBUG_TYPE, "AArch64 Stack Tagging",
345  false, false)
348 INITIALIZE_PASS_END(AArch64StackTagging, DEBUG_TYPE, "AArch64 Stack Tagging",
350 
352  return new AArch64StackTagging(IsOptNone);
353 }
354 
355 Instruction *AArch64StackTagging::collectInitializers(Instruction *StartInst,
356  Value *StartPtr,
357  uint64_t Size,
358  InitializerBuilder &IB) {
359  MemoryLocation AllocaLoc{StartPtr, Size};
360  Instruction *LastInst = StartInst;
361  BasicBlock::iterator BI(StartInst);
362 
363  unsigned Count = 0;
364  for (; Count < ClScanLimit && !BI->isTerminator(); ++BI) {
365  if (!isa<DbgInfoIntrinsic>(*BI))
366  ++Count;
367 
368  if (isNoModRef(AA->getModRefInfo(&*BI, AllocaLoc)))
369  continue;
370 
371  if (!isa<StoreInst>(BI) && !isa<MemSetInst>(BI)) {
372  // If the instruction is readnone, ignore it, otherwise bail out. We
373  // don't even allow readonly here because we don't want something like:
374  // A[1] = 2; strlen(A); A[2] = 2; -> memcpy(A, ...); strlen(A).
375  if (BI->mayWriteToMemory() || BI->mayReadFromMemory())
376  break;
377  continue;
378  }
379 
380  if (StoreInst *NextStore = dyn_cast<StoreInst>(BI)) {
381  if (!NextStore->isSimple())
382  break;
383 
384  // Check to see if this store is to a constant offset from the start ptr.
386  isPointerOffset(StartPtr, NextStore->getPointerOperand(), *DL);
387  if (!Offset)
388  break;
389 
390  if (!IB.addStore(*Offset, NextStore, DL))
391  break;
392  LastInst = NextStore;
393  } else {
394  MemSetInst *MSI = cast<MemSetInst>(BI);
395 
396  if (MSI->isVolatile() || !isa<ConstantInt>(MSI->getLength()))
397  break;
398 
399  if (!isa<ConstantInt>(MSI->getValue()))
400  break;
401 
402  // Check to see if this store is to a constant offset from the start ptr.
403  Optional<int64_t> Offset = isPointerOffset(StartPtr, MSI->getDest(), *DL);
404  if (!Offset)
405  break;
406 
407  if (!IB.addMemSet(*Offset, MSI))
408  break;
409  LastInst = MSI;
410  }
411  }
412  return LastInst;
413 }
414 
415 bool AArch64StackTagging::isInterestingAlloca(const AllocaInst &AI) {
416  // FIXME: support dynamic allocas
417  bool IsInteresting =
418  AI.getAllocatedType()->isSized() && AI.isStaticAlloca() &&
419  // alloca() may be called with 0 size, ignore it.
420  AI.getAllocationSizeInBits(*DL).getValue() > 0 &&
421  // inalloca allocas are not treated as static, and we don't want
422  // dynamic alloca instrumentation for them as well.
423  !AI.isUsedWithInAlloca() &&
424  // swifterror allocas are register promoted by ISel
425  !AI.isSwiftError() &&
426  // safe allocas are not interesting
427  !(SSI && SSI->isSafe(AI));
428  return IsInteresting;
429 }
430 
431 void AArch64StackTagging::tagAlloca(AllocaInst *AI, Instruction *InsertBefore,
432  Value *Ptr, uint64_t Size) {
433  auto SetTagZeroFunc =
434  Intrinsic::getDeclaration(F->getParent(), Intrinsic::aarch64_settag_zero);
435  auto StgpFunc =
436  Intrinsic::getDeclaration(F->getParent(), Intrinsic::aarch64_stgp);
437 
438  InitializerBuilder IB(Size, DL, Ptr, SetTagFunc, SetTagZeroFunc, StgpFunc);
439  bool LittleEndian =
441  // Current implementation of initializer merging assumes little endianness.
442  if (MergeInit && !F->hasOptNone() && LittleEndian &&
443  Size < ClMergeInitSizeLimit) {
444  LLVM_DEBUG(dbgs() << "collecting initializers for " << *AI
445  << ", size = " << Size << "\n");
446  InsertBefore = collectInitializers(InsertBefore, Ptr, Size, IB);
447  }
448 
449  IRBuilder<> IRB(InsertBefore);
450  IB.generate(IRB);
451 }
452 
453 void AArch64StackTagging::untagAlloca(AllocaInst *AI, Instruction *InsertBefore,
454  uint64_t Size) {
455  IRBuilder<> IRB(InsertBefore);
456  IRB.CreateCall(SetTagFunc, {IRB.CreatePointerCast(AI, IRB.getInt8PtrTy()),
457  ConstantInt::get(IRB.getInt64Ty(), Size)});
458 }
459 
460 Instruction *AArch64StackTagging::insertBaseTaggedPointer(
461  const MapVector<AllocaInst *, memtag::AllocaInfo> &AllocasToInstrument,
462  const DominatorTree *DT) {
463  BasicBlock *PrologueBB = nullptr;
464  // Try sinking IRG as deep as possible to avoid hurting shrink wrap.
465  for (auto &I : AllocasToInstrument) {
466  const memtag::AllocaInfo &Info = I.second;
467  AllocaInst *AI = Info.AI;
468  if (!PrologueBB) {
469  PrologueBB = AI->getParent();
470  continue;
471  }
472  PrologueBB = DT->findNearestCommonDominator(PrologueBB, AI->getParent());
473  }
474  assert(PrologueBB);
475 
476  IRBuilder<> IRB(&PrologueBB->front());
477  Function *IRG_SP =
478  Intrinsic::getDeclaration(F->getParent(), Intrinsic::aarch64_irg_sp);
479  Instruction *Base =
480  IRB.CreateCall(IRG_SP, {Constant::getNullValue(IRB.getInt64Ty())});
481  Base->setName("basetag");
482  return Base;
483 }
484 
485 // FIXME: check for MTE extension
487  if (!Fn.hasFnAttribute(Attribute::SanitizeMemTag))
488  return false;
489 
490  if (UseStackSafety)
491  SSI = &getAnalysis<StackSafetyGlobalInfoWrapperPass>().getResult();
492  F = &Fn;
493  DL = &Fn.getParent()->getDataLayout();
494  if (MergeInit)
495  AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
496 
498  [this](const AllocaInst &AI) { return isInterestingAlloca(AI); });
499  for (Instruction &I : instructions(F))
500  SIB.visit(I);
501  memtag::StackInfo &SInfo = SIB.get();
502 
503  if (SInfo.AllocasToInstrument.empty())
504  return false;
505 
506  std::unique_ptr<DominatorTree> DeleteDT;
507  DominatorTree *DT = nullptr;
508  if (auto *P = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
509  DT = &P->getDomTree();
510 
511  if (DT == nullptr) {
512  DeleteDT = std::make_unique<DominatorTree>(*F);
513  DT = DeleteDT.get();
514  }
515 
516  std::unique_ptr<PostDominatorTree> DeletePDT;
517  PostDominatorTree *PDT = nullptr;
518  if (auto *P = getAnalysisIfAvailable<PostDominatorTreeWrapperPass>())
519  PDT = &P->getPostDomTree();
520 
521  if (PDT == nullptr) {
522  DeletePDT = std::make_unique<PostDominatorTree>(*F);
523  PDT = DeletePDT.get();
524  }
525 
526  SetTagFunc =
527  Intrinsic::getDeclaration(F->getParent(), Intrinsic::aarch64_settag);
528 
529  Instruction *Base = insertBaseTaggedPointer(SInfo.AllocasToInstrument, DT);
530 
531  int NextTag = 0;
532  for (auto &I : SInfo.AllocasToInstrument) {
533  memtag::AllocaInfo &Info = I.second;
534  assert(Info.AI && isInterestingAlloca(*Info.AI));
535  TrackingVH<Instruction> OldAI = Info.AI;
537  AllocaInst *AI = Info.AI;
538  int Tag = NextTag;
539  NextTag = (NextTag + 1) % 16;
540  // Replace alloca with tagp(alloca).
541  IRBuilder<> IRB(Info.AI->getNextNode());
543  F->getParent(), Intrinsic::aarch64_tagp, {Info.AI->getType()});
544  Instruction *TagPCall =
545  IRB.CreateCall(TagP, {Constant::getNullValue(Info.AI->getType()), Base,
546  ConstantInt::get(IRB.getInt64Ty(), Tag)});
547  if (Info.AI->hasName())
548  TagPCall->setName(Info.AI->getName() + ".tag");
549  Info.AI->replaceAllUsesWith(TagPCall);
550  TagPCall->setOperand(0, Info.AI);
551 
552  // Calls to functions that may return twice (e.g. setjmp) confuse the
553  // postdominator analysis, and will leave us to keep memory tagged after
554  // function return. Work around this by always untagging at every return
555  // statement if return_twice functions are called.
556  bool StandardLifetime =
557  SInfo.UnrecognizedLifetimes.empty() &&
558  memtag::isStandardLifetime(Info.LifetimeStart, Info.LifetimeEnd, DT,
559  ClMaxLifetimes) &&
560  !SInfo.CallsReturnTwice;
561  if (StandardLifetime) {
562  IntrinsicInst *Start = Info.LifetimeStart[0];
563  uint64_t Size =
564  cast<ConstantInt>(Start->getArgOperand(0))->getZExtValue();
565  Size = alignTo(Size, kTagGranuleSize);
566  tagAlloca(AI, Start->getNextNode(), Start->getArgOperand(1), Size);
567 
568  auto TagEnd = [&](Instruction *Node) { untagAlloca(AI, Node, Size); };
569  if (!DT || !PDT ||
570  !memtag::forAllReachableExits(*DT, *PDT, Start, Info.LifetimeEnd,
571  SInfo.RetVec, TagEnd)) {
572  for (auto *End : Info.LifetimeEnd)
573  End->eraseFromParent();
574  }
575  } else {
576  uint64_t Size = Info.AI->getAllocationSizeInBits(*DL).getValue() / 8;
577  Value *Ptr = IRB.CreatePointerCast(TagPCall, IRB.getInt8PtrTy());
578  tagAlloca(AI, &*IRB.GetInsertPoint(), Ptr, Size);
579  for (auto &RI : SInfo.RetVec) {
580  untagAlloca(AI, RI, Size);
581  }
582  // We may have inserted tag/untag outside of any lifetime interval.
583  // Remove all lifetime intrinsics for this alloca.
584  for (auto &II : Info.LifetimeStart)
585  II->eraseFromParent();
586  for (auto &II : Info.LifetimeEnd)
587  II->eraseFromParent();
588  }
589 
590  // Fixup debug intrinsics to point to the new alloca.
591  for (auto DVI : Info.DbgVariableIntrinsics)
592  DVI->replaceVariableLocationOp(OldAI, Info.AI);
593  }
594 
595  // If we have instrumented at least one alloca, all unrecognized lifetime
596  // intrinsics have to go.
597  for (auto &I : SInfo.UnrecognizedLifetimes)
598  I->eraseFromParent();
599 
600  return true;
601 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:76
llvm::alignTo
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:148
StackSafetyAnalysis.h
llvm::Type::isSized
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
Definition: Type.h:264
MachineInstr.h
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::DominatorTreeBase::findNearestCommonDominator
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
Find nearest common dominator basic block for basic block A and B.
Definition: GenericDomTree.h:468
llvm::initializeAArch64StackTaggingPass
void initializeAArch64StackTaggingPass(PassRegistry &)
ClUseStackSafety
static cl::opt< bool > ClUseStackSafety("stack-tagging-use-stack-safety", cl::Hidden, cl::init(true), cl::ZeroOrMore, cl::desc("Use Stack Safety analysis results"))
llvm::Instruction::getModule
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
Definition: Instruction.cpp:65
AArch64.h
llvm::IRBuilderBase::getInt64Ty
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Definition: IRBuilder.h:506
Optional.h
llvm::memtag::StackInfo
Definition: MemoryTaggingSupport.h:54
llvm::StackSafetyGlobalInfo::isSafe
bool isSafe(const AllocaInst &AI) const
Definition: StackSafetyAnalysis.cpp:966
llvm::DataLayout
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:113
llvm::Intrinsic::getDeclaration
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
Definition: Function.cpp:1410
Metadata.h
llvm::BasicBlock::iterator
InstListType::iterator iterator
Instruction iterators...
Definition: BasicBlock.h:87
IntrinsicInst.h
llvm::Type::isPointerTy
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:218
InstIterator.h
DEBUG_TYPE
#define DEBUG_TYPE
Definition: AArch64StackTagging.cpp:65
flatten
loop flatten
Definition: LoopFlatten.cpp:966
llvm::Function
Definition: Function.h:60
llvm::lower_bound
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1724
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
Pass.h
GetElementPtrTypeIterator.h
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1185
Statistic.h
llvm::memtag::StackInfo::CallsReturnTwice
bool CallsReturnTwice
Definition: MemoryTaggingSupport.h:58
llvm::IRBuilder<>
MapVector.h
ValueTracking.h
Local.h
llvm::IRBuilderBase::CreateOr
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1372
llvm::DominatorTree
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:166
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
MachineBasicBlock.h
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:139
ScalarEvolution.h
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
DenseMap.h
llvm::Optional< int64_t >
llvm::MapVector
This class implements a map that also provides access to all stored values in a deterministic order.
Definition: MapVector.h:37
ClScanLimit
static cl::opt< unsigned > ClScanLimit("stack-tagging-merge-init-scan-limit", cl::init(40), cl::Hidden)
RHS
Value * RHS
Definition: X86PartialReduction.cpp:76
llvm::dwarf::Tag
Tag
Definition: Dwarf.h:105
llvm::cl::ReallyHidden
@ ReallyHidden
Definition: CommandLine.h:140
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
DepthFirstIterator.h
I1
@ I1
Definition: DXILOpLowering.cpp:37
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:240
llvm::MemSetBase::getValue
Value * getValue() const
Definition: IntrinsicInst.h:854
MachineRegisterInfo.h
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:55
AliasAnalysis.h
llvm::memtag::StackInfo::RetVec
SmallVector< Instruction *, 8 > RetVec
Definition: MemoryTaggingSupport.h:57
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::isPointerOffset
Optional< int64_t > isPointerOffset(const Value *Ptr1, const Value *Ptr2, const DataLayout &DL)
If Ptr1 is provably equal to Ptr2 plus a constant offset, return that offset.
Definition: ValueTracking.cpp:7177
Instruction.h
llvm::Triple::isLittleEndian
bool isLittleEndian() const
Tests whether the target triple is little endian.
Definition: Triple.cpp:1701
LHS
Value * LHS
Definition: X86PartialReduction.cpp:75
llvm::ConstantInt
This is the shared class of boolean and integer constants.
Definition: Constants.h:79
llvm::AllocaInst::isStaticAlloca
bool isStaticAlloca() const
Return true if this alloca is in the entry block of the function and is a constant size.
Definition: Instructions.cpp:1419
ClMaxLifetimes
static cl::opt< size_t > ClMaxLifetimes("stack-tagging-max-lifetimes-for-alloca", cl::Hidden, cl::init(3), cl::ReallyHidden, cl::desc("How many lifetime ends to handle for a single alloca."), cl::Optional)
MachineLoopInfo.h
AArch64TargetMachine.h
AArch64InstrInfo.h
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:31
llvm::AAResults
Definition: AliasAnalysis.h:511
PostDominators.h
llvm::AllocaInst::getAllocatedType
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
Definition: Instructions.h:114
llvm::memtag::StackInfoBuilder
Definition: MemoryTaggingSupport.h:61
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::ARM_PROC::A
@ A
Definition: ARMBaseInfo.h:34
llvm::IRBuilderBase::getIntNTy
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
Definition: IRBuilder.h:514
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
llvm::memtag::forAllReachableExits
bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const Instruction *Start, const SmallVectorImpl< IntrinsicInst * > &Ends, const SmallVectorImpl< Instruction * > &RetVec, llvm::function_ref< void(Instruction *)> Callback)
Definition: MemoryTaggingSupport.cpp:40
false
Definition: StackSlotColoring.cpp:141
MemoryTaggingSupport.h
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
kTagGranuleSize
static const Align kTagGranuleSize
Definition: AArch64StackTagging.cpp:89
llvm::Instruction
Definition: Instruction.h:42
llvm::IRBuilderBase::getInt8Ty
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
Definition: IRBuilder.h:491
llvm::IRBuilderBase::getContext
LLVMContext & getContext() const
Definition: IRBuilder.h:175
llvm::Value::setName
void setName(const Twine &Name)
Change the name of the value.
Definition: Value.cpp:372
llvm::codeview::EncodedFramePtrReg::BasePtr
@ BasePtr
llvm::ConstantInt::get
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:919
DebugLoc.h
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
Align
uint64_t Align
Definition: ELFObjHandler.cpp:81
llvm::FixedVectorType::get
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition: Type.cpp:684
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
llvm::AllocaInst::getAllocationSizeInBits
Optional< TypeSize > getAllocationSizeInBits(const DataLayout &DL) const
Get allocation size in bits.
Definition: Instructions.cpp:57
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
llvm::MemSetInst
This class wraps the llvm.memset intrinsic.
Definition: IntrinsicInst.h:993
llvm::IRBuilderBase::CreatePointerCast
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:1998
INITIALIZE_PASS_BEGIN
INITIALIZE_PASS_BEGIN(AArch64StackTagging, DEBUG_TYPE, "AArch64 Stack Tagging", false, false) INITIALIZE_PASS_END(AArch64StackTagging
INITIALIZE_PASS_END
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:58
LoopInfo.h
llvm::AllocaInst::isSwiftError
bool isSwiftError() const
Return true if this alloca is used as a swifterror argument to a call.
Definition: Instructions.h:149
llvm::cl::ZeroOrMore
@ ZeroOrMore
Definition: CommandLine.h:116
llvm::Type::isIntegerTy
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:191
llvm::VectorType
Base class of all SIMD vector types.
Definition: DerivedTypes.h:389
llvm::Function::hasFnAttribute
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.cpp:625
llvm::cl::opt< bool >
ClMergeInitSizeLimit
static cl::opt< unsigned > ClMergeInitSizeLimit("stack-tagging-merge-init-size-limit", cl::init(272), cl::Hidden)
llvm::instructions
inst_range instructions(Function *F)
Definition: InstIterator.h:133
llvm::StoreInst
An instruction for storing to memory.
Definition: Instructions.h:305
llvm::isNoModRef
LLVM_NODISCARD bool isNoModRef(const ModRefInfo MRI)
Definition: AliasAnalysis.h:185
llvm::IRBuilderBase::GetInsertPoint
BasicBlock::iterator GetInsertPoint() const
Definition: IRBuilder.h:174
llvm::AMDGPU::Hwreg::Offset
Offset
Definition: SIDefines.h:405
uint64_t
llvm::GlobalValue::getParent
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:577
llvm::memtag::StackInfo::UnrecognizedLifetimes
SmallVector< Instruction *, 4 > UnrecognizedLifetimes
Definition: MemoryTaggingSupport.h:56
INITIALIZE_PASS_DEPENDENCY
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::IRBuilderBase::getInt8PtrTy
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
Definition: IRBuilder.h:549
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:432
TargetPassConfig.h
MachineFunctionPass.h
llvm::TrackingVH
Value handle that tracks a Value across RAUW.
Definition: ValueHandle.h:331
IRBuilder.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SI
StandardInstrumentations SI(Debug, VerifyEach)
llvm::memtag::AllocaInfo
Definition: MemoryTaggingSupport.h:47
llvm::User::setOperand
void setOperand(unsigned i, Value *Val)
Definition: User.h:174
addRange
static void addRange(SmallVectorImpl< ConstantInt * > &EndPoints, ConstantInt *Low, ConstantInt *High)
Definition: Metadata.cpp:1043
CFG.h
llvm::MemIntrinsicBase::getDest
Value * getDest() const
This is just like getRawDest, but it strips off any cast instructions (including addrspacecast) that ...
Definition: IntrinsicInst.h:740
None.h
llvm::AnalysisUsage::setPreservesCFG
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:263
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::PostDominatorTree
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
Definition: PostDominators.h:28
llvm::Value::getType
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
llvm::ConstantInt::isZero
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Definition: Constants.h:194
uint32_t
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
LiveRegUnits.h
ValueHandle.h
llvm::memtag::StackInfoBuilder::visit
void visit(Instruction &Inst)
Definition: MemoryTaggingSupport.cpp:100
llvm::IRBuilderBase::CreateConstGEP1_32
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Definition: IRBuilder.h:1740
llvm::cl::Optional
@ Optional
Definition: CommandLine.h:115
llvm::ConstantInt::getZExtValue
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition: Constants.h:142
llvm::BasicBlock::front
const Instruction & front() const
Definition: BasicBlock.h:309
runOnFunction
static bool runOnFunction(Function &F, bool PostInlining)
Definition: EntryExitInstrumenter.cpp:69
llvm::IRBuilderBase::CreateBitOrPointerCast
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2030
llvm::Constant::getNullValue
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Definition: Constants.cpp:350
llvm::MemIntrinsicBase::getLength
Value * getLength() const
Definition: IntrinsicInst.h:731
llvm::memtag::alignAndPadAlloca
void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align)
Definition: MemoryTaggingSupport.cpp:150
Casting.h
Function.h
llvm::memtag::StackInfo::AllocasToInstrument
MapVector< AllocaInst *, AllocaInfo > AllocasToInstrument
Definition: MemoryTaggingSupport.h:55
llvm::IntrinsicInst
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:46
llvm::StackSafetyGlobalInfoWrapperPass
This pass performs the global (interprocedural) stack safety analysis (legacy pass manager).
Definition: StackSafetyAnalysis.h:150
AA
ScalarEvolutionExpressions.h
Instructions.h
AArch64Subtarget.h
llvm::AllocaInst::isUsedWithInAlloca
bool isUsedWithInAlloca() const
Return true if this alloca is used as an inalloca argument to a call.
Definition: Instructions.h:139
llvm::MemIntrinsic::isVolatile
bool isVolatile() const
Definition: IntrinsicInst.h:971
SmallVector.h
MachineInstrBuilder.h
llvm::createAArch64StackTaggingPass
FunctionPass * createAArch64StackTaggingPass(bool IsOptNone)
Definition: AArch64StackTagging.cpp:351
llvm::IRBuilderBase::CreateLShr
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition: IRBuilder.h:1310
Dominators.h
llvm::Module::getTargetTriple
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
Definition: Module.h:258
ClMergeInit
static cl::opt< bool > ClMergeInit("stack-tagging-merge-init", cl::Hidden, cl::init(true), cl::ZeroOrMore, cl::desc("merge stack variable initializers with tagging when possible"))
llvm::IRBuilderBase::CreateShl
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1289
llvm::AAResultsWrapperPass
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Definition: AliasAnalysis.h:1347
llvm::Instruction::getParent
const BasicBlock * getParent() const
Definition: Instruction.h:91
generate
We currently generate
Definition: README.txt:597
Tagging
AArch64 Stack Tagging
Definition: AArch64StackTagging.cpp:348
llvm::IRBuilderBase::CreateZExtOrTrunc
Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a ZExt or Trunc from the integer value V to DestTy.
Definition: IRBuilder.h:1870
MachineOperand.h
llvm::Module::getDataLayout
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Definition: Module.cpp:398
llvm::StackSafetyGlobalInfo
Definition: StackSafetyAnalysis.h:58
llvm::IntegerType::get
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition: Type.cpp:311
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
llvm::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition: PassAnalysisSupport.h:75
llvm::AllocaInst
an instruction to allocate memory on the stack
Definition: Instructions.h:58
llvm::cl::desc
Definition: CommandLine.h:405
raw_ostream.h
MachineFunction.h
InitializePasses.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
TargetRegisterInfo.h
Debug.h
llvm::IRBuilderBase::CreateCall
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2229
llvm::memtag::isStandardLifetime
bool isStandardLifetime(const SmallVectorImpl< IntrinsicInst * > &LifetimeStart, const SmallVectorImpl< IntrinsicInst * > &LifetimeEnd, const DominatorTree *DT, size_t MaxLifetimes)
Definition: MemoryTaggingSupport.cpp:76
llvm::MemoryLocation
Representation for a specific memory location.
Definition: MemoryLocation.h:210
llvm::sampleprof::Base
@ Base
Definition: Discriminator.h:58
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:37
llvm::SmallVectorImpl::insert
iterator insert(iterator I, T &&Elt)
Definition: SmallVector.h:792