<div dir="ltr">Seems to cause "instruction does not dominate all uses errors" on Windows:<br><div><a href="http://lab.llvm.org:8011/builders/clang-x64-windows-msvc/builds/8811">http://lab.llvm.org:8011/builders/clang-x64-windows-msvc/builds/8811</a> </div><div>$ ":" "RUN: at line 1"<br>$ "c:\b\slave\clang-x64-windows-msvc\build\build\stage1\bin\opt.exe" "-stack-tagging" "-S" "-o" "-"<br># command stderr:<br>Instruction does not dominate all uses!<br>  %0 = bitcast { i32, [12 x i8] }* %x.tag to i8*<br>  call void @llvm.aarch64.settag(i8* %0, i64 16)<br>in function OneVar<br>LLVM ERROR: Broken function found, compilation aborted!<br></div><div><br></div><div>That's usually not a Windows-specific issue, so I wouldn't be surprised if there were issues elsewhere.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jul 17, 2019 at 12:23 PM Evgeniy Stepanov via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: eugenis<br>
Date: Wed Jul 17 12:24:12 2019<br>
New Revision: 366361<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=366361&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=366361&view=rev</a><br>
Log:<br>
Basic MTE stack tagging instrumentation.<br>
<br>
Summary:<br>
Use MTE intrinsics to tag stack variables in functions with<br>
sanitize_memtag attribute.<br>
<br>
Reviewers: pcc, vitalybuka, hctim, ostannard<br>
<br>
Subscribers: srhines, mgorny, javed.absar, hiraditya, llvm-commits<br>
<br>
Tags: #llvm<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D64173" rel="noreferrer" target="_blank">https://reviews.llvm.org/D64173</a><br>
<br>
Added:<br>
    llvm/trunk/lib/Target/AArch64/AArch64StackTagging.cpp<br>
    llvm/trunk/test/CodeGen/AArch64/stack-tagging-dbg.ll<br>
    llvm/trunk/test/CodeGen/AArch64/stack-tagging.ll<br>
Modified:<br>
    llvm/trunk/lib/Target/AArch64/AArch64.h<br>
    llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp<br>
    llvm/trunk/lib/Target/AArch64/CMakeLists.txt<br>
    llvm/trunk/test/CodeGen/AArch64/O0-pipeline.ll<br>
    llvm/trunk/test/CodeGen/AArch64/O3-pipeline.ll<br>
<br>
Modified: llvm/trunk/lib/Target/AArch64/AArch64.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64.h?rev=366361&r1=366360&r2=366361&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64.h?rev=366361&r1=366360&r2=366361&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/AArch64/AArch64.h (original)<br>
+++ llvm/trunk/lib/Target/AArch64/AArch64.h Wed Jul 17 12:24:12 2019<br>
@@ -56,6 +56,7 @@ InstructionSelector *<br>
 createAArch64InstructionSelector(const AArch64TargetMachine &,<br>
                                  AArch64Subtarget &, AArch64RegisterBankInfo &);<br>
 FunctionPass *createAArch64PreLegalizeCombiner();<br>
+FunctionPass *createAArch64StackTaggingPass();<br>
<br>
 void initializeAArch64A53Fix835769Pass(PassRegistry&);<br>
 void initializeAArch64A57FPLoadBalancingPass(PassRegistry&);<br>
@@ -78,6 +79,7 @@ void initializeAArch64StorePairSuppressP<br>
 void initializeFalkorHWPFFixPass(PassRegistry&);<br>
 void initializeFalkorMarkStridedAccessesLegacyPass(PassRegistry&);<br>
 void initializeLDTLSCleanupPass(PassRegistry&);<br>
+void initializeAArch64StackTaggingPass(PassRegistry&);<br>
 } // end namespace llvm<br>
<br>
 #endif<br>
<br>
Added: llvm/trunk/lib/Target/AArch64/AArch64StackTagging.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64StackTagging.cpp?rev=366361&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64StackTagging.cpp?rev=366361&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/AArch64/AArch64StackTagging.cpp (added)<br>
+++ llvm/trunk/lib/Target/AArch64/AArch64StackTagging.cpp Wed Jul 17 12:24:12 2019<br>
@@ -0,0 +1,345 @@<br>
+//===- AArch64StackTagging.cpp - Stack tagging in IR --===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "AArch64.h"<br>
+#include "AArch64InstrInfo.h"<br>
+#include "AArch64Subtarget.h"<br>
+#include "AArch64TargetMachine.h"<br>
+#include "llvm/ADT/DenseMap.h"<br>
+#include "llvm/ADT/DepthFirstIterator.h"<br>
+#include "llvm/ADT/MapVector.h"<br>
+#include "llvm/ADT/None.h"<br>
+#include "llvm/ADT/Optional.h"<br>
+#include "llvm/ADT/SmallVector.h"<br>
+#include "llvm/ADT/Statistic.h"<br>
+#include "llvm/Analysis/LoopInfo.h"<br>
+#include "llvm/Analysis/ScalarEvolution.h"<br>
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"<br>
+#include "llvm/Analysis/ValueTracking.h"<br>
+#include "llvm/CodeGen/LiveRegUnits.h"<br>
+#include "llvm/CodeGen/MachineBasicBlock.h"<br>
+#include "llvm/CodeGen/MachineFunction.h"<br>
+#include "llvm/CodeGen/MachineFunctionPass.h"<br>
+#include "llvm/CodeGen/MachineInstr.h"<br>
+#include "llvm/CodeGen/MachineInstrBuilder.h"<br>
+#include "llvm/CodeGen/MachineLoopInfo.h"<br>
+#include "llvm/CodeGen/MachineOperand.h"<br>
+#include "llvm/CodeGen/MachineRegisterInfo.h"<br>
+#include "llvm/CodeGen/TargetPassConfig.h"<br>
+#include "llvm/CodeGen/TargetRegisterInfo.h"<br>
+#include "llvm/IR/DebugLoc.h"<br>
+#include "llvm/IR/Dominators.h"<br>
+#include "llvm/IR/Function.h"<br>
+#include "llvm/IR/GetElementPtrTypeIterator.h"<br>
+#include "llvm/IR/Instruction.h"<br>
+#include "llvm/IR/Instructions.h"<br>
+#include "llvm/IR/IntrinsicInst.h"<br>
+#include "llvm/IR/Metadata.h"<br>
+#include "llvm/Pass.h"<br>
+#include "llvm/Support/Casting.h"<br>
+#include "llvm/Support/Debug.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+#include "llvm/Transforms/Utils/Local.h"<br>
+#include <cassert><br>
+#include <iterator><br>
+#include <utility><br>
+<br>
+using namespace llvm;<br>
+<br>
+#define DEBUG_TYPE "stack-tagging"<br>
+<br>
+static constexpr unsigned kTagGranuleSize = 16;<br>
+<br>
+namespace {<br>
+class AArch64StackTagging : public FunctionPass {<br>
+  struct AllocaInfo {<br>
+    AllocaInst *AI;<br>
+    SmallVector<IntrinsicInst *, 2> LifetimeStart;<br>
+    SmallVector<IntrinsicInst *, 2> LifetimeEnd;<br>
+    SmallVector<DbgVariableIntrinsic *, 2> DbgVariableIntrinsics;<br>
+    int Tag; // -1 for non-tagged allocations<br>
+  };<br>
+<br>
+public:<br>
+  static char ID; // Pass ID, replacement for typeid<br>
+<br>
+  AArch64StackTagging() : FunctionPass(ID) {<br>
+    initializeAArch64StackTaggingPass(*PassRegistry::getPassRegistry());<br>
+  }<br>
+<br>
+  bool isInterestingAlloca(const AllocaInst &AI);<br>
+  void alignAndPadAlloca(AllocaInfo &Info);<br>
+<br>
+  void tagAlloca(AllocaInst *AI, Instruction *InsertBefore, Value *Ptr,<br>
+                 uint64_t Size);<br>
+  void untagAlloca(AllocaInst *AI, Instruction *InsertBefore, uint64_t Size);<br>
+<br>
+  Instruction *<br>
+  insertBaseTaggedPointer(const MapVector<AllocaInst *, AllocaInfo> &Allocas,<br>
+                          const DominatorTree *DT);<br>
+  bool runOnFunction(Function &F) override;<br>
+<br>
+  StringRef getPassName() const override { return "AArch64 Stack Tagging"; }<br>
+<br>
+private:<br>
+  Function *F;<br>
+  Function *SetTagFunc;<br>
+  const DataLayout *DL;<br>
+<br>
+  void getAnalysisUsage(AnalysisUsage &AU) const override {<br>
+    AU.setPreservesCFG();<br>
+  }<br>
+};<br>
+<br>
+} // end anonymous namespace<br>
+<br>
+char AArch64StackTagging::ID = 0;<br>
+<br>
+INITIALIZE_PASS_BEGIN(AArch64StackTagging, DEBUG_TYPE, "AArch64 Stack Tagging",<br>
+                      false, false)<br>
+INITIALIZE_PASS_END(AArch64StackTagging, DEBUG_TYPE, "AArch64 Stack Tagging",<br>
+                    false, false)<br>
+<br>
+FunctionPass *llvm::createAArch64StackTaggingPass() {<br>
+  return new AArch64StackTagging();<br>
+}<br>
+<br>
+bool AArch64StackTagging::isInterestingAlloca(const AllocaInst &AI) {<br>
+  // FIXME: support dynamic allocas<br>
+  bool IsInteresting =<br>
+      AI.getAllocatedType()->isSized() && AI.isStaticAlloca() &&<br>
+      // alloca() may be called with 0 size, ignore it.<br>
+      AI.getAllocationSizeInBits(*DL).getValue() > 0 &&<br>
+      // inalloca allocas are not treated as static, and we don't want<br>
+      // dynamic alloca instrumentation for them as well.<br>
+      !AI.isUsedWithInAlloca() &&<br>
+      // swifterror allocas are register promoted by ISel<br>
+      !AI.isSwiftError();<br>
+  return IsInteresting;<br>
+}<br>
+<br>
+void AArch64StackTagging::tagAlloca(AllocaInst *AI, Instruction *InsertBefore,<br>
+                                    Value *Ptr, uint64_t Size) {<br>
+  IRBuilder<> IRB(InsertBefore);<br>
+  IRB.CreateCall(SetTagFunc, {Ptr, ConstantInt::get(IRB.getInt64Ty(), Size)});<br>
+}<br>
+<br>
+void AArch64StackTagging::untagAlloca(AllocaInst *AI, Instruction *InsertBefore,<br>
+                                      uint64_t Size) {<br>
+  IRBuilder<> IRB(InsertBefore);<br>
+  IRB.CreateCall(SetTagFunc, {IRB.CreatePointerCast(AI, IRB.getInt8PtrTy()),<br>
+                              ConstantInt::get(IRB.getInt64Ty(), Size)});<br>
+}<br>
+<br>
+Instruction *AArch64StackTagging::insertBaseTaggedPointer(<br>
+    const MapVector<AllocaInst *, AllocaInfo> &Allocas,<br>
+    const DominatorTree *DT) {<br>
+  BasicBlock *PrologueBB = nullptr;<br>
+  // Try sinking IRG as deep as possible to avoid hurting shrink wrap.<br>
+  for (auto &I : Allocas) {<br>
+    const AllocaInfo &Info = I.second;<br>
+    AllocaInst *AI = Info.AI;<br>
+    if (Info.Tag < 0)<br>
+      continue;<br>
+    if (!PrologueBB) {<br>
+      PrologueBB = AI->getParent();<br>
+      continue;<br>
+    }<br>
+    PrologueBB = DT->findNearestCommonDominator(PrologueBB, AI->getParent());<br>
+  }<br>
+  assert(PrologueBB);<br>
+<br>
+  IRBuilder<> IRB(&PrologueBB->front());<br>
+  Function *IRG_SP =<br>
+      Intrinsic::getDeclaration(F->getParent(), Intrinsic::aarch64_irg_sp);<br>
+  Instruction *Base =<br>
+      IRB.CreateCall(IRG_SP, {Constant::getNullValue(IRB.getInt64Ty())});<br>
+  Base->setName("basetag");<br>
+  return Base;<br>
+}<br>
+<br>
+void AArch64StackTagging::alignAndPadAlloca(AllocaInfo &Info) {<br>
+  unsigned NewAlignment = std::max(Info.AI->getAlignment(), kTagGranuleSize);<br>
+  Info.AI->setAlignment(NewAlignment);<br>
+<br>
+  uint64_t Size = Info.AI->getAllocationSizeInBits(*DL).getValue() / 8;<br>
+  uint64_t AlignedSize = alignTo(Size, kTagGranuleSize);<br>
+  if (Size == AlignedSize)<br>
+    return;<br>
+<br>
+  // Add padding to the alloca.<br>
+  Type *AllocatedType =<br>
+      Info.AI->isArrayAllocation()<br>
+          ? ArrayType::get(<br>
+                Info.AI->getAllocatedType(),<br>
+                dyn_cast<ConstantInt>(Info.AI->getArraySize())->getZExtValue())<br>
+          : Info.AI->getAllocatedType();<br>
+  Type *PaddingType =<br>
+      ArrayType::get(Type::getInt8Ty(F->getContext()), AlignedSize - Size);<br>
+  Type *TypeWithPadding = StructType::get(AllocatedType, PaddingType);<br>
+  auto *NewAI = new AllocaInst(<br>
+      TypeWithPadding, Info.AI->getType()->getAddressSpace(), nullptr, "", Info.AI);<br>
+  NewAI->takeName(Info.AI);<br>
+  NewAI->setAlignment(Info.AI->getAlignment());<br>
+  NewAI->setUsedWithInAlloca(Info.AI->isUsedWithInAlloca());<br>
+  NewAI->setSwiftError(Info.AI->isSwiftError());<br>
+  NewAI->copyMetadata(*Info.AI);<br>
+<br>
+  auto *NewPtr = new BitCastInst(NewAI, Info.AI->getType(), "", Info.AI);<br>
+  Info.AI->replaceAllUsesWith(NewPtr);<br>
+  Info.AI->eraseFromParent();<br>
+  Info.AI = NewAI;<br>
+}<br>
+<br>
+// FIXME: check for MTE extension<br>
+bool AArch64StackTagging::runOnFunction(Function &Fn) {<br>
+  if (!Fn.hasFnAttribute(Attribute::SanitizeMemTag))<br>
+    return false;<br>
+<br>
+  F = &Fn;<br>
+  DL = &Fn.getParent()->getDataLayout();<br>
+<br>
+  MapVector<AllocaInst *, AllocaInfo> Allocas; // need stable iteration order<br>
+  SmallVector<Instruction *, 8> RetVec;<br>
+  DenseMap<Value *, AllocaInst *> AllocaForValue;<br>
+  SmallVector<Instruction *, 4> UnrecognizedLifetimes;<br>
+<br>
+  for (auto &BB : *F) {<br>
+    for (BasicBlock::iterator IT = BB.begin(); IT != BB.end(); ++IT) {<br>
+      Instruction *I = &*IT;<br>
+      if (auto *AI = dyn_cast<AllocaInst>(I)) {<br>
+        Allocas[AI].AI = AI;<br>
+        continue;<br>
+      }<br>
+<br>
+      if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(I)) {<br>
+        if (auto *AI =<br>
+                dyn_cast_or_null<AllocaInst>(DVI->getVariableLocation())) {<br>
+          Allocas[AI].DbgVariableIntrinsics.push_back(DVI);<br>
+        }<br>
+        continue;<br>
+      }<br>
+<br>
+      auto *II = dyn_cast<IntrinsicInst>(I);<br>
+      if (II && (II->getIntrinsicID() == Intrinsic::lifetime_start ||<br>
+                 II->getIntrinsicID() == Intrinsic::lifetime_end)) {<br>
+        AllocaInst *AI =<br>
+            llvm::findAllocaForValue(II->getArgOperand(1), AllocaForValue);<br>
+        if (!AI) {<br>
+          UnrecognizedLifetimes.push_back(I);<br>
+          continue;<br>
+        }<br>
+        if (II->getIntrinsicID() == Intrinsic::lifetime_start)<br>
+          Allocas[AI].LifetimeStart.push_back(II);<br>
+        else<br>
+          Allocas[AI].LifetimeEnd.push_back(II);<br>
+      }<br>
+<br>
+      if (isa<ReturnInst>(I) || isa<ResumeInst>(I) || isa<CleanupReturnInst>(I))<br>
+        RetVec.push_back(I);<br>
+    }<br>
+  }<br>
+<br>
+  if (Allocas.empty())<br>
+    return false;<br>
+<br>
+  int NextTag = 0;<br>
+  int NumInterestingAllocas = 0;<br>
+  for (auto &I : Allocas) {<br>
+    AllocaInfo &Info = I.second;<br>
+    assert(Info.AI);<br>
+<br>
+    if (!isInterestingAlloca(*Info.AI)) {<br>
+      Info.Tag = -1;<br>
+      continue;<br>
+    }<br>
+<br>
+    alignAndPadAlloca(Info);<br>
+    NumInterestingAllocas++;<br>
+    Info.Tag = NextTag;<br>
+    NextTag = (NextTag + 1) % 16;<br>
+  }<br>
+<br>
+  if (NumInterestingAllocas == 0)<br>
+    return true;<br>
+<br>
+  SetTagFunc =<br>
+      Intrinsic::getDeclaration(F->getParent(), Intrinsic::aarch64_settag);<br>
+<br>
+  // Compute DT only if the function has the attribute, there are more than 1<br>
+  // interesting allocas, and it is not available for free.<br>
+  Instruction *Base;<br>
+  if (NumInterestingAllocas > 1) {<br>
+    auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();<br>
+    if (DTWP) {<br>
+      Base = insertBaseTaggedPointer(Allocas, &DTWP->getDomTree());<br>
+    } else {<br>
+      DominatorTree DT(*F);<br>
+      Base = insertBaseTaggedPointer(Allocas, &DT);<br>
+    }<br>
+  } else {<br>
+    Base = insertBaseTaggedPointer(Allocas, nullptr);<br>
+  }<br>
+<br>
+  for (auto &I : Allocas) {<br>
+    const AllocaInfo &Info = I.second;<br>
+    AllocaInst *AI = Info.AI;<br>
+    if (Info.Tag < 0)<br>
+      continue;<br>
+<br>
+    // Replace alloca with tagp(alloca).<br>
+    IRBuilder<> IRB(Info.AI->getNextNode());<br>
+    Function *TagP = Intrinsic::getDeclaration(<br>
+        F->getParent(), Intrinsic::aarch64_tagp, {Info.AI->getType()});<br>
+    Instruction *TagPCall =<br>
+        IRB.CreateCall(TagP, {Constant::getNullValue(Info.AI->getType()), Base,<br>
+                              ConstantInt::get(IRB.getInt64Ty(), Info.Tag)});<br>
+    if (Info.AI->hasName())<br>
+      TagPCall->setName(Info.AI->getName() + ".tag");<br>
+    Info.AI->replaceAllUsesWith(TagPCall);<br>
+    TagPCall->setOperand(0, Info.AI);<br>
+<br>
+    if (UnrecognizedLifetimes.empty() && Info.LifetimeStart.size() == 1 &&<br>
+        Info.LifetimeEnd.size() == 1) {<br>
+      IntrinsicInst *Start = Info.LifetimeStart[0];<br>
+      uint64_t Size =<br>
+          dyn_cast<ConstantInt>(Start->getArgOperand(0))->getZExtValue();<br>
+      Size = alignTo(Size, kTagGranuleSize);<br>
+      tagAlloca(AI, Start->getNextNode(), Start->getArgOperand(1), Size);<br>
+      untagAlloca(AI, Info.LifetimeEnd[0], Size);<br>
+    } else {<br>
+      uint64_t Size = Info.AI->getAllocationSizeInBits(*DL).getValue() / 8;<br>
+      tagAlloca(AI, TagPCall->getNextNode(),<br>
+                IRB.CreatePointerCast(TagPCall, IRB.getInt8PtrTy()), Size);<br>
+      for (auto &RI : RetVec) {<br>
+        untagAlloca(AI, RI, Size);<br>
+      }<br>
+      // We may have inserted tag/untag outside of any lifetime interval.<br>
+      // Remove all lifetime intrinsics for this alloca.<br>
+      for (auto &II : Info.LifetimeStart)<br>
+        II->eraseFromParent();<br>
+      for (auto &II : Info.LifetimeEnd)<br>
+        II->eraseFromParent();<br>
+    }<br>
+<br>
+    // Fixup debug intrinsics to point to the new alloca.<br>
+    for (auto DVI : Info.DbgVariableIntrinsics)<br>
+      DVI->setArgOperand(<br>
+          0,<br>
+          MetadataAsValue::get(F->getContext(), LocalAsMetadata::get(Info.AI)));<br>
+  }<br>
+<br>
+  // If we have instrumented at least one alloca, all unrecognized lifetime<br>
+  // instrinsics have to go.<br>
+  for (auto &I : UnrecognizedLifetimes)<br>
+    I->eraseFromParent();<br>
+<br>
+  return true;<br>
+}<br>
<br>
Modified: llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp?rev=366361&r1=366360&r2=366361&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp?rev=366361&r1=366360&r2=366361&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp (original)<br>
+++ llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp Wed Jul 17 12:24:12 2019<br>
@@ -179,6 +179,7 @@ extern "C" void LLVMInitializeAArch64Tar<br>
   initializeFalkorMarkStridedAccessesLegacyPass(*PR);<br>
   initializeLDTLSCleanupPass(*PR);<br>
   initializeAArch64SpeculationHardeningPass(*PR);<br>
+  initializeAArch64StackTaggingPass(*PR);<br>
 }<br>
<br>
 //===----------------------------------------------------------------------===//<br>
@@ -446,6 +447,8 @@ void AArch64PassConfig::addIRPasses() {<br>
     // invariant.<br>
     addPass(createLICMPass());<br>
   }<br>
+<br>
+  addPass(createAArch64StackTaggingPass());<br>
 }<br>
<br>
 // Pass Pipeline Configuration<br>
<br>
Modified: llvm/trunk/lib/Target/AArch64/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/CMakeLists.txt?rev=366361&r1=366360&r2=366361&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/CMakeLists.txt?rev=366361&r1=366360&r2=366361&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/AArch64/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/Target/AArch64/CMakeLists.txt Wed Jul 17 12:24:12 2019<br>
@@ -55,6 +55,7 @@ add_llvm_target(AArch64CodeGen<br>
   AArch64RegisterInfo.cpp<br>
   AArch64SelectionDAGInfo.cpp<br>
   AArch64SpeculationHardening.cpp<br>
+  AArch64StackTagging.cpp<br>
   AArch64StorePairSuppress.cpp<br>
   AArch64Subtarget.cpp<br>
   AArch64TargetMachine.cpp<br>
<br>
Modified: llvm/trunk/test/CodeGen/AArch64/O0-pipeline.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/O0-pipeline.ll?rev=366361&r1=366360&r2=366361&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/O0-pipeline.ll?rev=366361&r1=366360&r2=366361&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/AArch64/O0-pipeline.ll (original)<br>
+++ llvm/trunk/test/CodeGen/AArch64/O0-pipeline.ll Wed Jul 17 12:24:12 2019<br>
@@ -25,6 +25,7 @@<br>
 ; CHECK-NEXT:       Instrument function entry/exit with calls to e.g. mcount() (post inlining)<br>
 ; CHECK-NEXT:       Scalarize Masked Memory Intrinsics<br>
 ; CHECK-NEXT:       Expand reduction intrinsics<br>
+; CHECK-NEXT:       AArch64 Stack Tagging<br>
 ; CHECK-NEXT:     Rewrite Symbols<br>
 ; CHECK-NEXT:     FunctionPass Manager<br>
 ; CHECK-NEXT:       Dominator Tree Construction<br>
<br>
Modified: llvm/trunk/test/CodeGen/AArch64/O3-pipeline.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/O3-pipeline.ll?rev=366361&r1=366360&r2=366361&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/O3-pipeline.ll?rev=366361&r1=366360&r2=366361&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/AArch64/O3-pipeline.ll (original)<br>
+++ llvm/trunk/test/CodeGen/AArch64/O3-pipeline.ll Wed Jul 17 12:24:12 2019<br>
@@ -55,6 +55,7 @@<br>
 ; CHECK-NEXT:       Interleaved Load Combine Pass<br>
 ; CHECK-NEXT:       Dominator Tree Construction<br>
 ; CHECK-NEXT:       Interleaved Access Pass<br>
+; CHECK-NEXT:       AArch64 Stack Tagging<br>
 ; CHECK-NEXT:       Natural Loop Information<br>
 ; CHECK-NEXT:       CodeGen Prepare<br>
 ; CHECK-NEXT:     Rewrite Symbols<br>
<br>
Added: llvm/trunk/test/CodeGen/AArch64/stack-tagging-dbg.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/stack-tagging-dbg.ll?rev=366361&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/stack-tagging-dbg.ll?rev=366361&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/AArch64/stack-tagging-dbg.ll (added)<br>
+++ llvm/trunk/test/CodeGen/AArch64/stack-tagging-dbg.ll Wed Jul 17 12:24:12 2019<br>
@@ -0,0 +1,37 @@<br>
+; RUN: opt < %s -stack-tagging -S -o - | FileCheck %s<br>
+<br>
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"<br>
+target triple = "aarch64--linux-android"<br>
+<br>
+declare void @use32(i32*)<br>
+declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone speculatable<br>
+<br>
+; Debug intrinsics use the new alloca directly, not through a GEP or a tagp.<br>
+define void @DbgIntrinsics() sanitize_memtag {<br>
+entry:<br>
+  %x = alloca i32, align 4<br>
+  call void @llvm.dbg.declare(metadata i32* %x, metadata !6, metadata !DIExpression()), !dbg !10<br>
+  store i32 42, i32* %x, align 4<br>
+  call void @use32(i32* %x)<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @DbgIntrinsics(<br>
+; CHECK:  [[X:%.*]] = alloca { i32, [12 x i8] }, align 16<br>
+; CHECK:  call void @llvm.dbg.declare(metadata { i32, [12 x i8] }* [[X]],<br>
+<br>
+<br>
+!<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{!0}<br>
+!llvm.module.flags = !{!8, !9}<br>
+<br>
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 9.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)<br>
+!1 = !DIFile(filename: "stack-tagging.cc", directory: "/tmp")<br>
+!2 = !{}<br>
+!3 = distinct !DISubprogram(name: "DbgIntrinsics", linkageName: "DbgIntrinsics", scope: !1, file: !1, line: 3, type: !4, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)<br>
+!4 = !DISubroutineType(types: !5)<br>
+!5 = !{null}<br>
+!6 = !DILocalVariable(name: "x", scope: !3, file: !1, line: 4, type: !7)<br>
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)<br>
+!8 = !{i32 2, !"Dwarf Version", i32 4}<br>
+!9 = !{i32 2, !"Debug Info Version", i32 3}<br>
+!10 = !DILocation(line: 1, column: 2, scope: !3)<br>
<br>
Added: llvm/trunk/test/CodeGen/AArch64/stack-tagging.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/stack-tagging.ll?rev=366361&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/stack-tagging.ll?rev=366361&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/AArch64/stack-tagging.ll (added)<br>
+++ llvm/trunk/test/CodeGen/AArch64/stack-tagging.ll Wed Jul 17 12:24:12 2019<br>
@@ -0,0 +1,187 @@<br>
+; RUN: opt < %s -stack-tagging -S -o - | FileCheck %s<br>
+<br>
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"<br>
+target triple = "aarch64--linux-android"<br>
+<br>
+declare void @use8(i8*)<br>
+declare void @use32(i32*)<br>
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)<br>
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)<br>
+<br>
+define void @OneVar() sanitize_memtag {<br>
+entry:<br>
+  %x = alloca i32, align 4<br>
+  call void @use32(i32* %x)<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @OneVar(<br>
+; CHECK:  [[BASE:%.*]] = call i8* @llvm.aarch64.irg.sp(i64 0)<br>
+; CHECK:  [[X:%.*]] = alloca { i32, [12 x i8] }, align 16<br>
+; CHECK:  [[TX:%.*]] = call { i32, [12 x i8] }* @llvm.aarch64.tagp.{{.*}}({ i32, [12 x i8] }* [[X]], i8* [[BASE]], i64 0)<br>
+; CHECK:  [[TX8:%.*]] = bitcast { i32, [12 x i8] }* [[TX]] to i8*<br>
+; CHECK:  call void @llvm.aarch64.settag(i8* [[TX8]], i64 16)<br>
+; CHECK:  [[GEP32:%.*]] = bitcast { i32, [12 x i8] }* [[TX]] to i32*<br>
+; CHECK:  call void @use32(i32* [[GEP32]])<br>
+; CHECK:  [[GEP8:%.*]] = bitcast { i32, [12 x i8] }* [[X]] to i8*<br>
+; CHECK:  call void @llvm.aarch64.settag(i8* [[GEP8]], i64 16)<br>
+; CHECK:  ret void<br>
+<br>
+<br>
+define void @ManyVars() sanitize_memtag {<br>
+entry:<br>
+  %x1 = alloca i32, align 4<br>
+  %x2 = alloca i8, align 4<br>
+  %x3 = alloca i32, i32 11, align 4<br>
+  call void @use32(i32* %x1)<br>
+  call void @use8(i8* %x2)<br>
+  call void @use32(i32* %x3)<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @ManyVars(<br>
+; CHECK:  alloca { i32, [12 x i8] }, align 16<br>
+; CHECK:  call { i32, [12 x i8] }* @llvm.aarch64.tagp.{{.*}}({ i32, [12 x i8] }* {{.*}}, i64 0)<br>
+; CHECK:  call void @llvm.aarch64.settag(i8* {{.*}}, i64 16)<br>
+; CHECK:  alloca { i8, [15 x i8] }, align 16<br>
+; CHECK:  call { i8, [15 x i8] }* @llvm.aarch64.tagp.{{.*}}({ i8, [15 x i8] }* {{.*}}, i64 1)<br>
+; CHECK:  call void @llvm.aarch64.settag(i8* {{.*}}, i64 16)<br>
+; CHECK:  alloca { [11 x i32], [4 x i8] }, align 16<br>
+; CHECK:  call { [11 x i32], [4 x i8] }* @llvm.aarch64.tagp.{{.*}}({ [11 x i32], [4 x i8] }* {{.*}}, i64 2)<br>
+; CHECK:  call void @llvm.aarch64.settag(i8* {{.*}}, i64 48)<br>
+<br>
+; CHECK:  call void @use32(<br>
+; CHECK:  call void @use8(<br>
+; CHECK:  call void @use32(<br>
+<br>
+; CHECK:  call void @llvm.aarch64.settag(i8* {{.*}}, i64 16)<br>
+; CHECK:  call void @llvm.aarch64.settag(i8* {{.*}}, i64 16)<br>
+; CHECK:  call void @llvm.aarch64.settag(i8* {{.*}}, i64 48)<br>
+; CHECK-NEXT:  ret void<br>
+<br>
+<br>
+define void @Scope(i32 %b) sanitize_memtag {<br>
+entry:<br>
+  %x = alloca i32, align 4<br>
+  %tobool = icmp eq i32 %b, 0<br>
+  br i1 %tobool, label %if.end, label %if.then<br>
+<br>
+if.then:<br>
+  %0 = bitcast i32* %x to i8*<br>
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0)<br>
+  call void @use8(i8* %0) #3<br>
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0)<br>
+  br label %if.end<br>
+<br>
+if.end:<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @Scope(<br>
+; CHECK:  br i1<br>
+; CHECK:  call void @llvm.lifetime.start.p0i8(<br>
+; CHECK:  call void @llvm.aarch64.settag(<br>
+; CHECK:  call void @use8(<br>
+; CHECK:  call void @llvm.aarch64.settag(<br>
+; CHECK:  call void @llvm.lifetime.end.p0i8(<br>
+; CHECK:  br label<br>
+; CHECK:  ret void<br>
+<br>
+<br>
+; Spooked by the multiple lifetime ranges, StackTagging remove all of them and sets tags on entry and exit.<br>
+define void @BadScope(i32 %b) sanitize_memtag {<br>
+entry:<br>
+  %x = alloca i32, align 4<br>
+  %tobool = icmp eq i32 %b, 0<br>
+  br i1 %tobool, label %if.end, label %if.then<br>
+<br>
+if.then:<br>
+  %0 = bitcast i32* %x to i8*<br>
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0)<br>
+  call void @use8(i8* %0) #3<br>
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0)<br>
+<br>
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0)<br>
+  call void @use8(i8* %0) #3<br>
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0)<br>
+  br label %if.end<br>
+<br>
+if.end:<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @BadScope(<br>
+; CHECK:       call void @llvm.aarch64.settag(i8* {{.*}}, i64 16)<br>
+; CHECK:       br i1<br>
+; CHECK:       call void @use8(i8*<br>
+; CHECK-NEXT:  call void @use8(i8*<br>
+; CHECK:       br label<br>
+; CHECK:       call void @llvm.aarch64.settag(i8* {{.*}}, i64 16)<br>
+; CHECK-NEXT:  ret void<br>
+<br>
+define void @DynamicAllocas(i32 %cnt) sanitize_memtag {<br>
+entry:<br>
+  %x = alloca i32, i32 %cnt, align 4<br>
+  br label %l<br>
+l:<br>
+  %y = alloca i32, align 4<br>
+  call void @use32(i32* %x)<br>
+  call void @use32(i32* %y)<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @DynamicAllocas(<br>
+; CHECK-NOT: @llvm.aarch64.irg.sp<br>
+; CHECK:     %x = alloca i32, i32 %cnt, align 4<br>
+; CHECK-NOT: @llvm.aarch64.irg.sp<br>
+; CHECK:     alloca i32, align 4<br>
+; CHECK-NOT: @llvm.aarch64.irg.sp<br>
+; CHECK:     ret void<br>
+<br>
+; If we can't trace one of the lifetime markers to a single alloca, fall back<br>
+; to poisoning all allocas at the beginning of the function.<br>
+; Each alloca must be poisoned only once.<br>
+define void @UnrecognizedLifetime(i8 %v) sanitize_memtag {<br>
+entry:<br>
+  %x = alloca i32, align 4<br>
+  %y = alloca i32, align 4<br>
+  %z = alloca i32, align 4<br>
+  %cx = bitcast i32* %x to i8*<br>
+  %cy = bitcast i32* %y to i8*<br>
+  %cz = bitcast i32* %z to i8*<br>
+  %tobool = icmp eq i8 %v, 0<br>
+  %xy = select i1 %tobool, i32* %x, i32* %y<br>
+  %cxcy = select i1 %tobool, i8* %cx, i8* %cy<br>
+  br label %another_bb<br>
+<br>
+another_bb:<br>
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %cz)<br>
+  store i32 7, i32* %z<br>
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %cz)<br>
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %cz)<br>
+  store i32 7, i32* %z<br>
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %cz)<br>
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %cxcy)<br>
+  store i32 8, i32* %xy<br>
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %cxcy)<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @UnrecognizedLifetime(<br>
+; CHECK: call i8* @llvm.aarch64.irg.sp(i64 0)<br>
+; CHECK: alloca { i32, [12 x i8] }, align 16<br>
+; CHECK: call { i32, [12 x i8] }* @llvm.aarch64.tagp<br>
+; CHECK: call void @llvm.aarch64.settag(<br>
+; CHECK: alloca { i32, [12 x i8] }, align 16<br>
+; CHECK: call { i32, [12 x i8] }* @llvm.aarch64.tagp<br>
+; CHECK: call void @llvm.aarch64.settag(<br>
+; CHECK: alloca { i32, [12 x i8] }, align 16<br>
+; CHECK: call { i32, [12 x i8] }* @llvm.aarch64.tagp<br>
+; CHECK: call void @llvm.aarch64.settag(<br>
+; CHECK: store i32<br>
+; CHECK: store i32<br>
+; CHECK: store i32<br>
+; CHECK: call void @llvm.aarch64.settag(<br>
+; CHECK: call void @llvm.aarch64.settag(<br>
+; CHECK: call void @llvm.aarch64.settag(<br>
+; CHECK: ret void<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>