LLVM  17.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/SmallVector.h"
18 #include "llvm/ADT/Statistic.h"
20 #include "llvm/Analysis/CFG.h"
21 #include "llvm/Analysis/LoopInfo.h"
38 #include "llvm/IR/DebugLoc.h"
39 #include "llvm/IR/Dominators.h"
40 #include "llvm/IR/Function.h"
42 #include "llvm/IR/IRBuilder.h"
43 #include "llvm/IR/InstIterator.h"
44 #include "llvm/IR/Instruction.h"
45 #include "llvm/IR/Instructions.h"
46 #include "llvm/IR/IntrinsicInst.h"
47 #include "llvm/IR/IntrinsicsAArch64.h"
48 #include "llvm/IR/Metadata.h"
49 #include "llvm/IR/ValueHandle.h"
50 #include "llvm/InitializePasses.h"
51 #include "llvm/Pass.h"
52 #include "llvm/Support/Casting.h"
53 #include "llvm/Support/Debug.h"
57 #include <cassert>
58 #include <iterator>
59 #include <memory>
60 #include <utility>
61 
62 using namespace llvm;
63 
64 #define DEBUG_TYPE "aarch64-stack-tagging"
65 
67  "stack-tagging-merge-init", cl::Hidden, cl::init(true),
68  cl::desc("merge stack variable initializers with tagging when possible"));
69 
70 static cl::opt<bool>
71  ClUseStackSafety("stack-tagging-use-stack-safety", cl::Hidden,
72  cl::init(true),
73  cl::desc("Use Stack Safety analysis results"));
74 
75 static cl::opt<unsigned> ClScanLimit("stack-tagging-merge-init-scan-limit",
76  cl::init(40), cl::Hidden);
77 
78 static cl::opt<unsigned>
79  ClMergeInitSizeLimit("stack-tagging-merge-init-size-limit", cl::init(272),
80  cl::Hidden);
81 
83  "stack-tagging-max-lifetimes-for-alloca", cl::Hidden, cl::init(3),
85  cl::desc("How many lifetime ends to handle for a single alloca."),
86  cl::Optional);
87 
88 static const Align kTagGranuleSize = Align(16);
89 
90 namespace {
91 
92 class InitializerBuilder {
93  uint64_t Size;
94  const DataLayout *DL;
95  Value *BasePtr;
96  Function *SetTagFn;
97  Function *SetTagZeroFn;
98  Function *StgpFn;
99 
100  // List of initializers sorted by start offset.
101  struct Range {
102  uint64_t Start, End;
103  Instruction *Inst;
104  };
106  // 8-aligned offset => 8-byte initializer
107  // Missing keys are zero initialized.
108  std::map<uint64_t, Value *> Out;
109 
110 public:
111  InitializerBuilder(uint64_t Size, const DataLayout *DL, Value *BasePtr,
112  Function *SetTagFn, Function *SetTagZeroFn,
113  Function *StgpFn)
114  : Size(Size), DL(DL), BasePtr(BasePtr), SetTagFn(SetTagFn),
115  SetTagZeroFn(SetTagZeroFn), StgpFn(StgpFn) {}
116 
117  bool addRange(uint64_t Start, uint64_t End, Instruction *Inst) {
118  auto I =
119  llvm::lower_bound(Ranges, Start, [](const Range &LHS, uint64_t RHS) {
120  return LHS.End <= RHS;
121  });
122  if (I != Ranges.end() && End > I->Start) {
123  // Overlap - bail.
124  return false;
125  }
126  Ranges.insert(I, {Start, End, Inst});
127  return true;
128  }
129 
130  bool addStore(uint64_t Offset, StoreInst *SI, const DataLayout *DL) {
131  int64_t StoreSize = DL->getTypeStoreSize(SI->getOperand(0)->getType());
132  if (!addRange(Offset, Offset + StoreSize, SI))
133  return false;
134  IRBuilder<> IRB(SI);
135  applyStore(IRB, Offset, Offset + StoreSize, SI->getOperand(0));
136  return true;
137  }
138 
139  bool addMemSet(uint64_t Offset, MemSetInst *MSI) {
140  uint64_t StoreSize = cast<ConstantInt>(MSI->getLength())->getZExtValue();
141  if (!addRange(Offset, Offset + StoreSize, MSI))
142  return false;
143  IRBuilder<> IRB(MSI);
144  applyMemSet(IRB, Offset, Offset + StoreSize,
145  cast<ConstantInt>(MSI->getValue()));
146  return true;
147  }
148 
149  void applyMemSet(IRBuilder<> &IRB, int64_t Start, int64_t End,
150  ConstantInt *V) {
151  // Out[] does not distinguish between zero and undef, and we already know
152  // that this memset does not overlap with any other initializer. Nothing to
153  // do for memset(0).
154  if (V->isZero())
155  return;
156  for (int64_t Offset = Start - Start % 8; Offset < End; Offset += 8) {
157  uint64_t Cst = 0x0101010101010101UL;
158  int LowBits = Offset < Start ? (Start - Offset) * 8 : 0;
159  if (LowBits)
160  Cst = (Cst >> LowBits) << LowBits;
161  int HighBits = End - Offset < 8 ? (8 - (End - Offset)) * 8 : 0;
162  if (HighBits)
163  Cst = (Cst << HighBits) >> HighBits;
164  ConstantInt *C =
165  ConstantInt::get(IRB.getInt64Ty(), Cst * V->getZExtValue());
166 
167  Value *&CurrentV = Out[Offset];
168  if (!CurrentV) {
169  CurrentV = C;
170  } else {
171  CurrentV = IRB.CreateOr(CurrentV, C);
172  }
173  }
174  }
175 
176  // Take a 64-bit slice of the value starting at the given offset (in bytes).
177  // Offset can be negative. Pad with zeroes on both sides when necessary.
178  Value *sliceValue(IRBuilder<> &IRB, Value *V, int64_t Offset) {
179  if (Offset > 0) {
180  V = IRB.CreateLShr(V, Offset * 8);
181  V = IRB.CreateZExtOrTrunc(V, IRB.getInt64Ty());
182  } else if (Offset < 0) {
183  V = IRB.CreateZExtOrTrunc(V, IRB.getInt64Ty());
184  V = IRB.CreateShl(V, -Offset * 8);
185  } else {
186  V = IRB.CreateZExtOrTrunc(V, IRB.getInt64Ty());
187  }
188  return V;
189  }
190 
191  void applyStore(IRBuilder<> &IRB, int64_t Start, int64_t End,
192  Value *StoredValue) {
193  StoredValue = flatten(IRB, StoredValue);
194  for (int64_t Offset = Start - Start % 8; Offset < End; Offset += 8) {
195  Value *V = sliceValue(IRB, StoredValue, Offset - Start);
196  Value *&CurrentV = Out[Offset];
197  if (!CurrentV) {
198  CurrentV = V;
199  } else {
200  CurrentV = IRB.CreateOr(CurrentV, V);
201  }
202  }
203  }
204 
205  void generate(IRBuilder<> &IRB) {
206  LLVM_DEBUG(dbgs() << "Combined initializer\n");
207  // No initializers => the entire allocation is undef.
208  if (Ranges.empty()) {
209  emitUndef(IRB, 0, Size);
210  return;
211  }
212 
213  // Look through 8-byte initializer list 16 bytes at a time;
214  // If one of the two 8-byte halfs is non-zero non-undef, emit STGP.
215  // Otherwise, emit zeroes up to next available item.
216  uint64_t LastOffset = 0;
217  for (uint64_t Offset = 0; Offset < Size; Offset += 16) {
218  auto I1 = Out.find(Offset);
219  auto I2 = Out.find(Offset + 8);
220  if (I1 == Out.end() && I2 == Out.end())
221  continue;
222 
223  if (Offset > LastOffset)
224  emitZeroes(IRB, LastOffset, Offset - LastOffset);
225 
226  Value *Store1 = I1 == Out.end() ? Constant::getNullValue(IRB.getInt64Ty())
227  : I1->second;
228  Value *Store2 = I2 == Out.end() ? Constant::getNullValue(IRB.getInt64Ty())
229  : I2->second;
230  emitPair(IRB, Offset, Store1, Store2);
231  LastOffset = Offset + 16;
232  }
233 
234  // memset(0) does not update Out[], therefore the tail can be either undef
235  // or zero.
236  if (LastOffset < Size)
237  emitZeroes(IRB, LastOffset, Size - LastOffset);
238 
239  for (const auto &R : Ranges) {
240  R.Inst->eraseFromParent();
241  }
242  }
243 
244  void emitZeroes(IRBuilder<> &IRB, uint64_t Offset, uint64_t Size) {
245  LLVM_DEBUG(dbgs() << " [" << Offset << ", " << Offset + Size
246  << ") zero\n");
247  Value *Ptr = BasePtr;
248  if (Offset)
249  Ptr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), Ptr, Offset);
250  IRB.CreateCall(SetTagZeroFn,
251  {Ptr, ConstantInt::get(IRB.getInt64Ty(), Size)});
252  }
253 
254  void emitUndef(IRBuilder<> &IRB, uint64_t Offset, uint64_t Size) {
255  LLVM_DEBUG(dbgs() << " [" << Offset << ", " << Offset + Size
256  << ") undef\n");
257  Value *Ptr = BasePtr;
258  if (Offset)
259  Ptr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), Ptr, Offset);
260  IRB.CreateCall(SetTagFn, {Ptr, ConstantInt::get(IRB.getInt64Ty(), Size)});
261  }
262 
263  void emitPair(IRBuilder<> &IRB, uint64_t Offset, Value *A, Value *B) {
264  LLVM_DEBUG(dbgs() << " [" << Offset << ", " << Offset + 16 << "):\n");
265  LLVM_DEBUG(dbgs() << " " << *A << "\n " << *B << "\n");
266  Value *Ptr = BasePtr;
267  if (Offset)
268  Ptr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), Ptr, Offset);
269  IRB.CreateCall(StgpFn, {Ptr, A, B});
270  }
271 
272  Value *flatten(IRBuilder<> &IRB, Value *V) {
273  if (V->getType()->isIntegerTy())
274  return V;
275  // vector of pointers -> vector of ints
276  if (VectorType *VecTy = dyn_cast<VectorType>(V->getType())) {
277  LLVMContext &Ctx = IRB.getContext();
278  Type *EltTy = VecTy->getElementType();
279  if (EltTy->isPointerTy()) {
280  uint32_t EltSize = DL->getTypeSizeInBits(EltTy);
281  auto *NewTy = FixedVectorType::get(
282  IntegerType::get(Ctx, EltSize),
283  cast<FixedVectorType>(VecTy)->getNumElements());
284  V = IRB.CreatePointerCast(V, NewTy);
285  }
286  }
287  return IRB.CreateBitOrPointerCast(
288  V, IRB.getIntNTy(DL->getTypeStoreSize(V->getType()) * 8));
289  }
290 };
291 
292 class AArch64StackTagging : public FunctionPass {
293  const bool MergeInit;
294  const bool UseStackSafety;
295 
296 public:
297  static char ID; // Pass ID, replacement for typeid
298 
299  AArch64StackTagging(bool IsOptNone = false)
300  : FunctionPass(ID),
301  MergeInit(ClMergeInit.getNumOccurrences() ? ClMergeInit : !IsOptNone),
302  UseStackSafety(ClUseStackSafety.getNumOccurrences() ? ClUseStackSafety
303  : !IsOptNone) {
305  }
306 
307  void tagAlloca(AllocaInst *AI, Instruction *InsertBefore, Value *Ptr,
308  uint64_t Size);
309  void untagAlloca(AllocaInst *AI, Instruction *InsertBefore, uint64_t Size);
310 
311  Instruction *collectInitializers(Instruction *StartInst, Value *StartPtr,
312  uint64_t Size, InitializerBuilder &IB);
313 
314  Instruction *insertBaseTaggedPointer(
316  const DominatorTree *DT);
317  bool runOnFunction(Function &F) override;
318 
319  StringRef getPassName() const override { return "AArch64 Stack Tagging"; }
320 
321 private:
322  Function *F = nullptr;
323  Function *SetTagFunc = nullptr;
324  const DataLayout *DL = nullptr;
325  AAResults *AA = nullptr;
326  const StackSafetyGlobalInfo *SSI = nullptr;
327 
328  void getAnalysisUsage(AnalysisUsage &AU) const override {
329  AU.setPreservesCFG();
330  if (UseStackSafety)
332  if (MergeInit)
334  }
335 };
336 
337 } // end anonymous namespace
338 
339 char AArch64StackTagging::ID = 0;
340 
341 INITIALIZE_PASS_BEGIN(AArch64StackTagging, DEBUG_TYPE, "AArch64 Stack Tagging",
342  false, false)
345 INITIALIZE_PASS_END(AArch64StackTagging, DEBUG_TYPE, "AArch64 Stack Tagging",
347 
349  return new AArch64StackTagging(IsOptNone);
350 }
351 
352 Instruction *AArch64StackTagging::collectInitializers(Instruction *StartInst,
353  Value *StartPtr,
354  uint64_t Size,
355  InitializerBuilder &IB) {
356  MemoryLocation AllocaLoc{StartPtr, Size};
357  Instruction *LastInst = StartInst;
358  BasicBlock::iterator BI(StartInst);
359 
360  unsigned Count = 0;
361  for (; Count < ClScanLimit && !BI->isTerminator(); ++BI) {
362  if (!isa<DbgInfoIntrinsic>(*BI))
363  ++Count;
364 
365  if (isNoModRef(AA->getModRefInfo(&*BI, AllocaLoc)))
366  continue;
367 
368  if (!isa<StoreInst>(BI) && !isa<MemSetInst>(BI)) {
369  // If the instruction is readnone, ignore it, otherwise bail out. We
370  // don't even allow readonly here because we don't want something like:
371  // A[1] = 2; strlen(A); A[2] = 2; -> memcpy(A, ...); strlen(A).
372  if (BI->mayWriteToMemory() || BI->mayReadFromMemory())
373  break;
374  continue;
375  }
376 
377  if (StoreInst *NextStore = dyn_cast<StoreInst>(BI)) {
378  if (!NextStore->isSimple())
379  break;
380 
381  // Check to see if this store is to a constant offset from the start ptr.
382  std::optional<int64_t> Offset =
383  isPointerOffset(StartPtr, NextStore->getPointerOperand(), *DL);
384  if (!Offset)
385  break;
386 
387  if (!IB.addStore(*Offset, NextStore, DL))
388  break;
389  LastInst = NextStore;
390  } else {
391  MemSetInst *MSI = cast<MemSetInst>(BI);
392 
393  if (MSI->isVolatile() || !isa<ConstantInt>(MSI->getLength()))
394  break;
395 
396  if (!isa<ConstantInt>(MSI->getValue()))
397  break;
398 
399  // Check to see if this store is to a constant offset from the start ptr.
400  std::optional<int64_t> Offset =
401  isPointerOffset(StartPtr, MSI->getDest(), *DL);
402  if (!Offset)
403  break;
404 
405  if (!IB.addMemSet(*Offset, MSI))
406  break;
407  LastInst = MSI;
408  }
409  }
410  return LastInst;
411 }
412 
413 void AArch64StackTagging::tagAlloca(AllocaInst *AI, Instruction *InsertBefore,
414  Value *Ptr, uint64_t Size) {
415  auto SetTagZeroFunc =
416  Intrinsic::getDeclaration(F->getParent(), Intrinsic::aarch64_settag_zero);
417  auto StgpFunc =
418  Intrinsic::getDeclaration(F->getParent(), Intrinsic::aarch64_stgp);
419 
420  InitializerBuilder IB(Size, DL, Ptr, SetTagFunc, SetTagZeroFunc, StgpFunc);
421  bool LittleEndian =
423  // Current implementation of initializer merging assumes little endianness.
424  if (MergeInit && !F->hasOptNone() && LittleEndian &&
425  Size < ClMergeInitSizeLimit) {
426  LLVM_DEBUG(dbgs() << "collecting initializers for " << *AI
427  << ", size = " << Size << "\n");
428  InsertBefore = collectInitializers(InsertBefore, Ptr, Size, IB);
429  }
430 
431  IRBuilder<> IRB(InsertBefore);
432  IB.generate(IRB);
433 }
434 
435 void AArch64StackTagging::untagAlloca(AllocaInst *AI, Instruction *InsertBefore,
436  uint64_t Size) {
437  IRBuilder<> IRB(InsertBefore);
438  IRB.CreateCall(SetTagFunc, {IRB.CreatePointerCast(AI, IRB.getInt8PtrTy()),
439  ConstantInt::get(IRB.getInt64Ty(), Size)});
440 }
441 
442 Instruction *AArch64StackTagging::insertBaseTaggedPointer(
443  const MapVector<AllocaInst *, memtag::AllocaInfo> &AllocasToInstrument,
444  const DominatorTree *DT) {
445  BasicBlock *PrologueBB = nullptr;
446  // Try sinking IRG as deep as possible to avoid hurting shrink wrap.
447  for (auto &I : AllocasToInstrument) {
448  const memtag::AllocaInfo &Info = I.second;
449  AllocaInst *AI = Info.AI;
450  if (!PrologueBB) {
451  PrologueBB = AI->getParent();
452  continue;
453  }
454  PrologueBB = DT->findNearestCommonDominator(PrologueBB, AI->getParent());
455  }
456  assert(PrologueBB);
457 
458  IRBuilder<> IRB(&PrologueBB->front());
459  Function *IRG_SP =
460  Intrinsic::getDeclaration(F->getParent(), Intrinsic::aarch64_irg_sp);
461  Instruction *Base =
462  IRB.CreateCall(IRG_SP, {Constant::getNullValue(IRB.getInt64Ty())});
463  Base->setName("basetag");
464  return Base;
465 }
466 
467 // FIXME: check for MTE extension
469  if (!Fn.hasFnAttribute(Attribute::SanitizeMemTag))
470  return false;
471 
472  if (UseStackSafety)
473  SSI = &getAnalysis<StackSafetyGlobalInfoWrapperPass>().getResult();
474  F = &Fn;
475  DL = &Fn.getParent()->getDataLayout();
476  if (MergeInit)
477  AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
478 
479  memtag::StackInfoBuilder SIB(SSI);
480  for (Instruction &I : instructions(F))
481  SIB.visit(I);
482  memtag::StackInfo &SInfo = SIB.get();
483 
484  if (SInfo.AllocasToInstrument.empty())
485  return false;
486 
487  std::unique_ptr<DominatorTree> DeleteDT;
488  DominatorTree *DT = nullptr;
489  if (auto *P = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
490  DT = &P->getDomTree();
491 
492  if (DT == nullptr) {
493  DeleteDT = std::make_unique<DominatorTree>(*F);
494  DT = DeleteDT.get();
495  }
496 
497  std::unique_ptr<PostDominatorTree> DeletePDT;
498  PostDominatorTree *PDT = nullptr;
499  if (auto *P = getAnalysisIfAvailable<PostDominatorTreeWrapperPass>())
500  PDT = &P->getPostDomTree();
501 
502  if (PDT == nullptr) {
503  DeletePDT = std::make_unique<PostDominatorTree>(*F);
504  PDT = DeletePDT.get();
505  }
506 
507  std::unique_ptr<LoopInfo> DeleteLI;
508  LoopInfo *LI = nullptr;
509  if (auto *LIWP = getAnalysisIfAvailable<LoopInfoWrapperPass>()) {
510  LI = &LIWP->getLoopInfo();
511  } else {
512  DeleteLI = std::make_unique<LoopInfo>(*DT);
513  LI = DeleteLI.get();
514  }
515 
516  SetTagFunc =
517  Intrinsic::getDeclaration(F->getParent(), Intrinsic::aarch64_settag);
518 
519  Instruction *Base = insertBaseTaggedPointer(SInfo.AllocasToInstrument, DT);
520 
521  int NextTag = 0;
522  for (auto &I : SInfo.AllocasToInstrument) {
523  memtag::AllocaInfo &Info = I.second;
524  assert(Info.AI && SIB.isInterestingAlloca(*Info.AI));
525  TrackingVH<Instruction> OldAI = Info.AI;
527  AllocaInst *AI = Info.AI;
528  int Tag = NextTag;
529  NextTag = (NextTag + 1) % 16;
530  // Replace alloca with tagp(alloca).
531  IRBuilder<> IRB(Info.AI->getNextNode());
533  F->getParent(), Intrinsic::aarch64_tagp, {Info.AI->getType()});
534  Instruction *TagPCall =
535  IRB.CreateCall(TagP, {Constant::getNullValue(Info.AI->getType()), Base,
536  ConstantInt::get(IRB.getInt64Ty(), Tag)});
537  if (Info.AI->hasName())
538  TagPCall->setName(Info.AI->getName() + ".tag");
539  Info.AI->replaceAllUsesWith(TagPCall);
540  TagPCall->setOperand(0, Info.AI);
541 
542  // Calls to functions that may return twice (e.g. setjmp) confuse the
543  // postdominator analysis, and will leave us to keep memory tagged after
544  // function return. Work around this by always untagging at every return
545  // statement if return_twice functions are called.
546  bool StandardLifetime =
547  SInfo.UnrecognizedLifetimes.empty() &&
548  memtag::isStandardLifetime(Info.LifetimeStart, Info.LifetimeEnd, DT, LI,
549  ClMaxLifetimes) &&
550  !SInfo.CallsReturnTwice;
551  if (StandardLifetime) {
552  IntrinsicInst *Start = Info.LifetimeStart[0];
553  uint64_t Size =
554  cast<ConstantInt>(Start->getArgOperand(0))->getZExtValue();
555  Size = alignTo(Size, kTagGranuleSize);
556  tagAlloca(AI, Start->getNextNode(), Start->getArgOperand(1), Size);
557 
558  auto TagEnd = [&](Instruction *Node) { untagAlloca(AI, Node, Size); };
559  if (!DT || !PDT ||
560  !memtag::forAllReachableExits(*DT, *PDT, *LI, Start, Info.LifetimeEnd,
561  SInfo.RetVec, TagEnd)) {
562  for (auto *End : Info.LifetimeEnd)
563  End->eraseFromParent();
564  }
565  } else {
566  uint64_t Size = *Info.AI->getAllocationSize(*DL);
567  Value *Ptr = IRB.CreatePointerCast(TagPCall, IRB.getInt8PtrTy());
568  tagAlloca(AI, &*IRB.GetInsertPoint(), Ptr, Size);
569  for (auto *RI : SInfo.RetVec) {
570  untagAlloca(AI, RI, Size);
571  }
572  // We may have inserted tag/untag outside of any lifetime interval.
573  // Remove all lifetime intrinsics for this alloca.
574  for (auto *II : Info.LifetimeStart)
575  II->eraseFromParent();
576  for (auto *II : Info.LifetimeEnd)
577  II->eraseFromParent();
578  }
579 
580  // Fixup debug intrinsics to point to the new alloca.
581  for (auto *DVI : Info.DbgVariableIntrinsics)
582  DVI->replaceVariableLocationOp(OldAI, Info.AI);
583  }
584 
585  // If we have instrumented at least one alloca, all unrecognized lifetime
586  // intrinsics have to go.
587  for (auto *I : SInfo.UnrecognizedLifetimes)
588  I->eraseFromParent();
589 
590  return true;
591 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:77
llvm::alignTo
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
StackSafetyAnalysis.h
MachineInstr.h
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::initializeAArch64StackTaggingPass
void initializeAArch64StackTaggingPass(PassRegistry &)
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:70
AArch64.h
llvm::IRBuilderBase::getInt64Ty
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Definition: IRBuilder.h:517
llvm::memtag::StackInfo
Definition: MemoryTaggingSupport.h:57
llvm::DataLayout
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:114
llvm::AArch64PACKey::ID
ID
Definition: AArch64BaseInfo.h:824
llvm::dxil::ParameterKind::I1
@ I1
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:249
InstIterator.h
DEBUG_TYPE
#define DEBUG_TYPE
Definition: AArch64StackTagging.cpp:64
flatten
loop flatten
Definition: LoopFlatten.cpp:994
llvm::Function
Definition: Function.h:59
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:1923
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:1199
Statistic.h
llvm::memtag::StackInfo::CallsReturnTwice
bool CallsReturnTwice
Definition: MemoryTaggingSupport.h:61
llvm::IRBuilder<>
MapVector.h
ValueTracking.h
Local.h
llvm::IRBuilderBase::CreateOr
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1412
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::memtag::forAllReachableExits
bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI, const Instruction *Start, const SmallVectorImpl< IntrinsicInst * > &Ends, const SmallVectorImpl< Instruction * > &RetVec, llvm::function_ref< void(Instruction *)> Callback)
Definition: MemoryTaggingSupport.cpp:44
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:138
ClUseStackSafety
static cl::opt< bool > ClUseStackSafety("stack-tagging-use-stack-safety", cl::Hidden, cl::init(true), cl::desc("Use Stack Safety analysis results"))
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
ClMergeInit
static cl::opt< bool > ClMergeInit("stack-tagging-merge-init", cl::Hidden, cl::init(true), cl::desc("merge stack variable initializers with tagging when possible"))
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:103
llvm::cl::ReallyHidden
@ ReallyHidden
Definition: CommandLine.h:139
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
DepthFirstIterator.h
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:275
llvm::MemSetBase::getValue
Value * getValue() const
Definition: IntrinsicInst.h:940
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:60
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
Instruction.h
llvm::Triple::isLittleEndian
bool isLittleEndian() const
Tests whether the target triple is little endian.
Definition: Triple.cpp:1745
LHS
Value * LHS
Definition: X86PartialReduction.cpp:75
llvm::ConstantInt
This is the shared class of boolean and integer constants.
Definition: Constants.h:78
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:24
llvm::AAResults
Definition: AliasAnalysis.h:294
PostDominators.h
llvm::memtag::StackInfoBuilder
Definition: MemoryTaggingSupport.h:64
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::ARM_PROC::A
@ A
Definition: ARMBaseInfo.h:34
llvm::AAResults::getModRefInfo
ModRefInfo getModRefInfo(const Instruction *I, const std::optional< MemoryLocation > &OptLoc)
Check whether or not an instruction may read or write the optionally specified memory location.
Definition: AliasAnalysis.h:488
llvm::IRBuilderBase::getIntNTy
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
Definition: IRBuilder.h:525
SI
@ SI
Definition: SIInstrInfo.cpp:7993
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
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:88
llvm::Instruction
Definition: Instruction.h:41
llvm::IRBuilderBase::getInt8Ty
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
Definition: IRBuilder.h:502
llvm::IRBuilderBase::getContext
LLVMContext & getContext() const
Definition: IRBuilder.h:176
llvm::Value::setName
void setName(const Twine &Name)
Change the name of the value.
Definition: Value.cpp:375
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:887
DebugLoc.h
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
Align
uint64_t Align
Definition: ELFObjHandler.cpp:82
llvm::FixedVectorType::get
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition: Type.cpp:686
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
llvm::isPointerOffset
std::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:7501
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 and llvm.memset.inline intrinsics.
Definition: IntrinsicInst.h:1080
llvm::IRBuilderBase::CreatePointerCast
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2054
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:59
LoopInfo.h
llvm::Type::isIntegerTy
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:222
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:640
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:301
llvm::IRBuilderBase::GetInsertPoint
BasicBlock::iterator GetInsertPoint() const
Definition: IRBuilder.h:175
uint64_t
llvm::GlobalValue::getParent
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:652
llvm::memtag::StackInfo::UnrecognizedLifetimes
SmallVector< Instruction *, 4 > UnrecognizedLifetimes
Definition: MemoryTaggingSupport.h:59
INITIALIZE_PASS_DEPENDENCY
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::AArch64PACKey::IB
@ IB
Definition: AArch64BaseInfo.h:826
llvm::IRBuilderBase::getInt8PtrTy
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
Definition: IRBuilder.h:560
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:445
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())
Ptr
@ Ptr
Definition: TargetLibraryInfo.cpp:62
llvm::memtag::AllocaInfo
Definition: MemoryTaggingSupport.h:50
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:1102
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:833
llvm::LoopInfo
Definition: LoopInfo.h:1108
llvm::AnalysisUsage::setPreservesCFG
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:265
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::Offset
@ Offset
Definition: DWP.cpp:406
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:193
uint32_t
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
LiveRegUnits.h
ValueHandle.h
llvm::IRBuilderBase::CreateConstGEP1_32
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Definition: IRBuilder.h:1796
llvm::Intrinsic::getDeclaration
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
Definition: Function.cpp:1502
llvm::cl::Optional
@ Optional
Definition: CommandLine.h:114
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:141
llvm::BasicBlock::front
const Instruction & front() const
Definition: BasicBlock.h:326
llvm::memtag::isStandardLifetime
bool isStandardLifetime(const SmallVectorImpl< IntrinsicInst * > &LifetimeStart, const SmallVectorImpl< IntrinsicInst * > &LifetimeEnd, const DominatorTree *DT, const LoopInfo *LI, size_t MaxLifetimes)
Definition: MemoryTaggingSupport.cpp:87
runOnFunction
static bool runOnFunction(Function &F, bool PostInlining)
Definition: EntryExitInstrumenter.cpp:85
llvm::IRBuilderBase::CreateBitOrPointerCast
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2086
llvm::Constant::getNullValue
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Definition: Constants.cpp:356
llvm::MemIntrinsicBase::getLength
Value * getLength() const
Definition: IntrinsicInst.h:824
llvm::memtag::alignAndPadAlloca
void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align)
Definition: MemoryTaggingSupport.cpp:180
Casting.h
Function.h
llvm::memtag::StackInfo::AllocasToInstrument
MapVector< AllocaInst *, AllocaInfo > AllocasToInstrument
Definition: MemoryTaggingSupport.h:58
llvm::DominatorTree::findNearestCommonDominator
Instruction * findNearestCommonDominator(Instruction *I1, Instruction *I2) const
Find the nearest instruction I that dominates both I1 and I2, in the sense that a result produced bef...
Definition: Dominators.cpp:358
llvm::IntrinsicInst
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:47
llvm::StackSafetyGlobalInfoWrapperPass
This pass performs the global (interprocedural) stack safety analysis (legacy pass manager).
Definition: StackSafetyAnalysis.h:150
ScalarEvolutionExpressions.h
Instructions.h
AArch64Subtarget.h
llvm::MemIntrinsic::isVolatile
bool isVolatile() const
Definition: IntrinsicInst.h:1057
SmallVector.h
MachineInstrBuilder.h
llvm::IRBuilderBase::CreateCall
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=std::nullopt, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2293
llvm::createAArch64StackTaggingPass
FunctionPass * createAArch64StackTaggingPass(bool IsOptNone)
Definition: AArch64StackTagging.cpp:348
llvm::IRBuilderBase::CreateLShr
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition: IRBuilder.h:1352
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
llvm::IRBuilderBase::CreateShl
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1331
llvm::AAResultsWrapperPass
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Definition: AliasAnalysis.h:933
llvm::Instruction::getParent
const BasicBlock * getParent() const
Definition: Instruction.h:90
generate
We currently generate
Definition: README.txt:597
llvm::logicalview::LVWarningKind::Ranges
@ Ranges
Tagging
AArch64 Stack Tagging
Definition: AArch64StackTagging.cpp:345
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:1926
MachineOperand.h
llvm::isNoModRef
bool isNoModRef(const ModRefInfo MRI)
Definition: ModRef.h:39
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:313
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:411
raw_ostream.h
MachineFunction.h
InitializePasses.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
TargetRegisterInfo.h
Debug.h
llvm::MemoryLocation
Representation for a specific memory location.
Definition: MemoryLocation.h:211
llvm::sampleprof::Base
@ Base
Definition: Discriminator.h:58