[llvm] r320217 - Hardware-assisted AddressSanitizer (llvm part).

Evgeniy Stepanov via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 8 16:21:42 PST 2017


Author: eugenis
Date: Fri Dec  8 16:21:41 2017
New Revision: 320217

URL: http://llvm.org/viewvc/llvm-project?rev=320217&view=rev
Log:
Hardware-assisted AddressSanitizer (llvm part).

Summary:
This is LLVM instrumentation for the new HWASan tool. It is basically
a stripped down copy of ASan at this point, w/o stack or global
support. Instrumenation adds a global constructor + runtime callbacks
for every load and store.

HWASan comes with its own IR attribute.

A brief design document can be found in
clang/docs/HardwareAssistedAddressSanitizerDesign.rst (submitted earlier).

Reviewers: kcc, pcc, alekseyshl

Subscribers: srhines, mehdi_amini, mgorny, javed.absar, eraman, llvm-commits, hiraditya

Differential Revision: https://reviews.llvm.org/D40932

Added:
    llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
    llvm/trunk/test/Instrumentation/HWAddressSanitizer/
    llvm/trunk/test/Instrumentation/HWAddressSanitizer/atomic.ll
    llvm/trunk/test/Instrumentation/HWAddressSanitizer/basic.ll
Modified:
    llvm/trunk/docs/BitCodeFormat.rst
    llvm/trunk/docs/LangRef.rst
    llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
    llvm/trunk/include/llvm/IR/Attributes.td
    llvm/trunk/include/llvm/InitializePasses.h
    llvm/trunk/include/llvm/Transforms/Instrumentation.h
    llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp
    llvm/trunk/lib/Analysis/ValueTracking.cpp
    llvm/trunk/lib/AsmParser/LLLexer.cpp
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/AsmParser/LLToken.h
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/trunk/lib/CodeGen/ShrinkWrap.cpp
    llvm/trunk/lib/IR/Attributes.cpp
    llvm/trunk/lib/IR/Verifier.cpp
    llvm/trunk/lib/Transforms/IPO/ForceFunctionAttrs.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
    llvm/trunk/lib/Transforms/Instrumentation/CMakeLists.txt
    llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp
    llvm/trunk/lib/Transforms/Scalar/GVN.cpp
    llvm/trunk/test/Bitcode/attributes.ll
    llvm/trunk/test/Transforms/GVN/no_speculative_loads_with_asan.ll
    llvm/trunk/test/Transforms/Inline/attributes.ll
    llvm/trunk/test/Transforms/InstCombine/lifetime-asan.ll
    llvm/trunk/test/Transforms/NewGVN/no_speculative_loads_with_asan.ll
    llvm/trunk/test/Transforms/SimplifyCFG/no_speculative_loads_with_asan.ll

Modified: llvm/trunk/docs/BitCodeFormat.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/BitCodeFormat.rst?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/docs/BitCodeFormat.rst (original)
+++ llvm/trunk/docs/BitCodeFormat.rst Fri Dec  8 16:21:41 2017
@@ -1054,6 +1054,7 @@ The integer codes are mapped to well-kno
 * code 52: ``writeonly``
 * code 53: ``speculatable``
 * code 54: ``strictfp``
+* code 55: ``sanitize_hwaddress``
 
 .. note::
   The ``allocsize`` attribute has a special encoding for its arguments. Its two

Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Fri Dec  8 16:21:41 2017
@@ -1597,6 +1597,10 @@ example:
 ``sanitize_thread``
     This attribute indicates that ThreadSanitizer checks
     (dynamic thread safety analysis) are enabled for this function.
+``sanitize_hwaddress``
+    This attribute indicates that HWAddressSanitizer checks
+    (dynamic address safety analysis based on tagged pointers) are enabled for
+    this function.
 ``speculatable``
     This function attribute indicates that the function does not have any
     effects besides calculating its result and does not have undefined behavior.

Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
+++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Fri Dec  8 16:21:41 2017
@@ -560,6 +560,7 @@ enum AttributeKindCodes {
   ATTR_KIND_WRITEONLY = 52,
   ATTR_KIND_SPECULATABLE = 53,
   ATTR_KIND_STRICT_FP = 54,
+  ATTR_KIND_SANITIZE_HWADDRESS = 55,
 };
 
 enum ComdatSelectionKindCodes {

Modified: llvm/trunk/include/llvm/IR/Attributes.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Attributes.td?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Attributes.td (original)
+++ llvm/trunk/include/llvm/IR/Attributes.td Fri Dec  8 16:21:41 2017
@@ -164,6 +164,9 @@ def SanitizeThread : EnumAttr<"sanitize_
 /// MemorySanitizer is on.
 def SanitizeMemory : EnumAttr<"sanitize_memory">;
 
+/// HWAddressSanitizer is on.
+def SanitizeHWAddress : EnumAttr<"sanitize_hwaddress">;
+
 /// Argument is swift error.
 def SwiftError : EnumAttr<"swifterror">;
 
@@ -200,6 +203,7 @@ class CompatRule<string F> {
 def : CompatRule<"isEqual<SanitizeAddressAttr>">;
 def : CompatRule<"isEqual<SanitizeThreadAttr>">;
 def : CompatRule<"isEqual<SanitizeMemoryAttr>">;
+def : CompatRule<"isEqual<SanitizeHWAddressAttr>">;
 def : CompatRule<"isEqual<SafeStackAttr>">;
 
 class MergeRule<string F> {

Modified: llvm/trunk/include/llvm/InitializePasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/include/llvm/InitializePasses.h (original)
+++ llvm/trunk/include/llvm/InitializePasses.h Fri Dec  8 16:21:41 2017
@@ -360,6 +360,7 @@ void initializeStripNonDebugSymbolsPass(
 void initializeStripNonLineTableDebugInfoPass(PassRegistry&);
 void initializeStripSymbolsPass(PassRegistry&);
 void initializeStructurizeCFGPass(PassRegistry&);
+void initializeHWAddressSanitizerPass(PassRegistry&);
 void initializeTailCallElimPass(PassRegistry&);
 void initializeTailDuplicatePassPass(PassRegistry&);
 void initializeTargetLibraryInfoWrapperPassPass(PassRegistry&);

Modified: llvm/trunk/include/llvm/Transforms/Instrumentation.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Instrumentation.h?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Instrumentation.h (original)
+++ llvm/trunk/include/llvm/Transforms/Instrumentation.h Fri Dec  8 16:21:41 2017
@@ -133,6 +133,8 @@ ModulePass *createAddressSanitizerModule
 FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0,
                                         bool Recover = false);
 
+FunctionPass *createHWAddressSanitizerPass();
+
 // Insert ThreadSanitizer (race detection) instrumentation
 FunctionPass *createThreadSanitizerPass();
 

Modified: llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp Fri Dec  8 16:21:41 2017
@@ -306,8 +306,10 @@ unsigned MemoryDependenceResults::getLoa
       return 0;
 
     if (LIOffs + NewLoadByteSize > MemLocEnd &&
-        LI->getParent()->getParent()->hasFnAttribute(
-            Attribute::SanitizeAddress))
+        (LI->getParent()->getParent()->hasFnAttribute(
+             Attribute::SanitizeAddress) ||
+         LI->getParent()->getParent()->hasFnAttribute(
+             Attribute::SanitizeHWAddress)))
       // We will be reading past the location accessed by the original program.
       // While this is safe in a regular build, Address Safety analysis tools
       // may start reporting false warnings. So, don't do widening.

Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Fri Dec  8 16:21:41 2017
@@ -3511,7 +3511,8 @@ bool llvm::isSafeToSpeculativelyExecute(
         // Speculative load may create a race that did not exist in the source.
         LI->getFunction()->hasFnAttribute(Attribute::SanitizeThread) ||
         // Speculative load may load data from dirty regions.
-        LI->getFunction()->hasFnAttribute(Attribute::SanitizeAddress))
+        LI->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
+        LI->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
       return false;
     const DataLayout &DL = LI->getModule()->getDataLayout();
     return isDereferenceableAndAlignedPointer(LI->getPointerOperand(),

Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLLexer.cpp Fri Dec  8 16:21:41 2017
@@ -664,6 +664,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(strictfp);
   KEYWORD(safestack);
   KEYWORD(sanitize_address);
+  KEYWORD(sanitize_hwaddress);
   KEYWORD(sanitize_thread);
   KEYWORD(sanitize_memory);
   KEYWORD(swifterror);

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Fri Dec  8 16:21:41 2017
@@ -1144,6 +1144,8 @@ bool LLParser::ParseFnAttributeValuePair
     case lltok::kw_safestack: B.addAttribute(Attribute::SafeStack); break;
     case lltok::kw_sanitize_address:
       B.addAttribute(Attribute::SanitizeAddress); break;
+    case lltok::kw_sanitize_hwaddress:
+      B.addAttribute(Attribute::SanitizeHWAddress); break;
     case lltok::kw_sanitize_thread:
       B.addAttribute(Attribute::SanitizeThread); break;
     case lltok::kw_sanitize_memory:
@@ -1468,6 +1470,7 @@ bool LLParser::ParseOptionalParamAttrs(A
     case lltok::kw_optsize:
     case lltok::kw_returns_twice:
     case lltok::kw_sanitize_address:
+    case lltok::kw_sanitize_hwaddress:
     case lltok::kw_sanitize_memory:
     case lltok::kw_sanitize_thread:
     case lltok::kw_ssp:
@@ -1560,6 +1563,7 @@ bool LLParser::ParseOptionalReturnAttrs(
     case lltok::kw_optsize:
     case lltok::kw_returns_twice:
     case lltok::kw_sanitize_address:
+    case lltok::kw_sanitize_hwaddress:
     case lltok::kw_sanitize_memory:
     case lltok::kw_sanitize_thread:
     case lltok::kw_ssp:

Modified: llvm/trunk/lib/AsmParser/LLToken.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLToken.h (original)
+++ llvm/trunk/lib/AsmParser/LLToken.h Fri Dec  8 16:21:41 2017
@@ -172,6 +172,7 @@ enum Kind {
   kw_alwaysinline,
   kw_argmemonly,
   kw_sanitize_address,
+  kw_sanitize_hwaddress,
   kw_builtin,
   kw_byval,
   kw_inalloca,

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Fri Dec  8 16:21:41 2017
@@ -1156,6 +1156,7 @@ static uint64_t getRawAttributeMask(Attr
   case Attribute::WriteOnly:       return 1ULL << 53;
   case Attribute::Speculatable:    return 1ULL << 54;
   case Attribute::StrictFP:        return 1ULL << 55;
+  case Attribute::SanitizeHWAddress: return 1ULL << 56;
   case Attribute::Dereferenceable:
     llvm_unreachable("dereferenceable attribute not supported in raw format");
     break;
@@ -1368,6 +1369,8 @@ static Attribute::AttrKind getAttrFromCo
     return Attribute::StructRet;
   case bitc::ATTR_KIND_SANITIZE_ADDRESS:
     return Attribute::SanitizeAddress;
+  case bitc::ATTR_KIND_SANITIZE_HWADDRESS:
+    return Attribute::SanitizeHWAddress;
   case bitc::ATTR_KIND_SANITIZE_THREAD:
     return Attribute::SanitizeThread;
   case bitc::ATTR_KIND_SANITIZE_MEMORY:

Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Fri Dec  8 16:21:41 2017
@@ -663,6 +663,8 @@ static uint64_t getAttrKindEncoding(Attr
     return bitc::ATTR_KIND_STRUCT_RET;
   case Attribute::SanitizeAddress:
     return bitc::ATTR_KIND_SANITIZE_ADDRESS;
+  case Attribute::SanitizeHWAddress:
+    return bitc::ATTR_KIND_SANITIZE_HWADDRESS;
   case Attribute::SanitizeThread:
     return bitc::ATTR_KIND_SANITIZE_THREAD;
   case Attribute::SanitizeMemory:

Modified: llvm/trunk/lib/CodeGen/ShrinkWrap.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ShrinkWrap.cpp?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/ShrinkWrap.cpp (original)
+++ llvm/trunk/lib/CodeGen/ShrinkWrap.cpp Fri Dec  8 16:21:41 2017
@@ -558,16 +558,17 @@ bool ShrinkWrap::isShrinkWrapEnabled(con
   switch (EnableShrinkWrapOpt) {
   case cl::BOU_UNSET:
     return TFI->enableShrinkWrapping(MF) &&
-      // Windows with CFI has some limitations that make it impossible
-      // to use shrink-wrapping.
-      !MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
-      // Sanitizers look at the value of the stack at the location
-      // of the crash. Since a crash can happen anywhere, the
-      // frame must be lowered before anything else happen for the
-      // sanitizers to be able to get a correct stack frame.
-      !(MF.getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
-        MF.getFunction()->hasFnAttribute(Attribute::SanitizeThread) ||
-        MF.getFunction()->hasFnAttribute(Attribute::SanitizeMemory));
+           // Windows with CFI has some limitations that make it impossible
+           // to use shrink-wrapping.
+           !MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
+           // Sanitizers look at the value of the stack at the location
+           // of the crash. Since a crash can happen anywhere, the
+           // frame must be lowered before anything else happen for the
+           // sanitizers to be able to get a correct stack frame.
+           !(MF.getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
+             MF.getFunction()->hasFnAttribute(Attribute::SanitizeThread) ||
+             MF.getFunction()->hasFnAttribute(Attribute::SanitizeMemory) ||
+             MF.getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress));
   // If EnableShrinkWrap is set, it takes precedence on whatever the
   // target sets. The rational is that we assume we want to test
   // something related to shrink-wrapping.

Modified: llvm/trunk/lib/IR/Attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Attributes.cpp?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Attributes.cpp (original)
+++ llvm/trunk/lib/IR/Attributes.cpp Fri Dec  8 16:21:41 2017
@@ -245,6 +245,8 @@ std::string Attribute::getAsString(bool
 
   if (hasAttribute(Attribute::SanitizeAddress))
     return "sanitize_address";
+  if (hasAttribute(Attribute::SanitizeHWAddress))
+    return "sanitize_hwaddress";
   if (hasAttribute(Attribute::AlwaysInline))
     return "alwaysinline";
   if (hasAttribute(Attribute::ArgMemOnly))

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Fri Dec  8 16:21:41 2017
@@ -1375,6 +1375,7 @@ static bool isFuncOnlyAttr(Attribute::At
   case Attribute::NonLazyBind:
   case Attribute::ReturnsTwice:
   case Attribute::SanitizeAddress:
+  case Attribute::SanitizeHWAddress:
   case Attribute::SanitizeThread:
   case Attribute::SanitizeMemory:
   case Attribute::MinSize:

Modified: llvm/trunk/lib/Transforms/IPO/ForceFunctionAttrs.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/ForceFunctionAttrs.cpp?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/ForceFunctionAttrs.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/ForceFunctionAttrs.cpp Fri Dec  8 16:21:41 2017
@@ -52,6 +52,7 @@ static Attribute::AttrKind parseAttrKind
       .Case("returns_twice", Attribute::ReturnsTwice)
       .Case("safestack", Attribute::SafeStack)
       .Case("sanitize_address", Attribute::SanitizeAddress)
+      .Case("sanitize_hwaddress", Attribute::SanitizeHWAddress)
       .Case("sanitize_memory", Attribute::SanitizeMemory)
       .Case("sanitize_thread", Attribute::SanitizeThread)
       .Case("ssp", Attribute::StackProtect)

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Fri Dec  8 16:21:41 2017
@@ -3607,7 +3607,8 @@ Instruction *InstCombiner::visitCallInst
   case Intrinsic::lifetime_start:
     // Asan needs to poison memory to detect invalid access which is possible
     // even for empty lifetime range.
-    if (II->getFunction()->hasFnAttribute(Attribute::SanitizeAddress))
+    if (II->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
+        II->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
       break;
 
     if (removeTriviallyEmptyRange(*II, Intrinsic::lifetime_start,

Modified: llvm/trunk/lib/Transforms/Instrumentation/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/CMakeLists.txt?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/CMakeLists.txt (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/CMakeLists.txt Fri Dec  8 16:21:41 2017
@@ -12,6 +12,7 @@ add_llvm_library(LLVMInstrumentation
   SanitizerCoverage.cpp
   ThreadSanitizer.cpp
   EfficiencySanitizer.cpp
+  HWAddressSanitizer.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms

Added: llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp?rev=320217&view=auto
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp (added)
+++ llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp Fri Dec  8 16:21:41 2017
@@ -0,0 +1,282 @@
+//===- HWAddressSanitizer.cpp - detector of uninitialized reads -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// This file is a part of HWAddressSanitizer, an address sanity checker
+/// based on tagged addressing.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/InstVisitor.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Transforms/Instrumentation.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "hwasan"
+
+static const char *const kHwasanModuleCtorName = "hwasan.module_ctor";
+static const char *const kHwasanInitName = "__hwasan_init";
+
+// Accesses sizes are powers of two: 1, 2, 4, 8, 16.
+static const size_t kNumberOfAccessSizes = 5;
+
+static cl::opt<std::string> ClMemoryAccessCallbackPrefix(
+    "hwasan-memory-access-callback-prefix",
+    cl::desc("Prefix for memory access callbacks"), cl::Hidden,
+    cl::init("__hwasan_"));
+
+static cl::opt<bool> ClInstrumentReads("hwasan-instrument-reads",
+                                       cl::desc("instrument read instructions"),
+                                       cl::Hidden, cl::init(true));
+
+static cl::opt<bool> ClInstrumentWrites(
+    "hwasan-instrument-writes", cl::desc("instrument write instructions"),
+    cl::Hidden, cl::init(true));
+
+static cl::opt<bool> ClInstrumentAtomics(
+    "hwasan-instrument-atomics",
+    cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden,
+    cl::init(true));
+
+namespace {
+
+/// \brief An instrumentation pass implementing detection of addressability bugs
+/// using tagged pointers.
+class HWAddressSanitizer : public FunctionPass {
+public:
+  // Pass identification, replacement for typeid.
+  static char ID;
+
+  HWAddressSanitizer() : FunctionPass(ID) {}
+
+  StringRef getPassName() const override { return "HWAddressSanitizer"; }
+
+  bool runOnFunction(Function &F) override;
+  bool doInitialization(Module &M) override;
+
+  void initializeCallbacks(Module &M);
+  bool instrumentMemAccess(Instruction *I);
+  Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite,
+                                   uint64_t *TypeSize, unsigned *Alignment,
+                                   Value **MaybeMask);
+
+private:
+  LLVMContext *C;
+  Type *IntptrTy;
+
+  Function *HwasanCtorFunction;
+
+  Function *HwasanMemoryAccessCallback[2][kNumberOfAccessSizes];
+  Function *HwasanMemoryAccessCallbackSized[2];
+};
+
+} // end anonymous namespace
+
+char HWAddressSanitizer::ID = 0;
+
+INITIALIZE_PASS_BEGIN(
+    HWAddressSanitizer, "hwasan",
+    "HWAddressSanitizer: detect memory bugs using tagged addressing.", false, false)
+INITIALIZE_PASS_END(
+    HWAddressSanitizer, "hwasan",
+    "HWAddressSanitizer: detect memory bugs using tagged addressing.", false, false)
+
+FunctionPass *llvm::createHWAddressSanitizerPass() {
+  return new HWAddressSanitizer();
+}
+
+/// \brief Module-level initialization.
+///
+/// inserts a call to __hwasan_init to the module's constructor list.
+bool HWAddressSanitizer::doInitialization(Module &M) {
+  DEBUG(dbgs() << "Init " << M.getName() << "\n");
+  auto &DL = M.getDataLayout();
+
+  Triple TargetTriple(M.getTargetTriple());
+
+  C = &(M.getContext());
+  IRBuilder<> IRB(*C);
+  IntptrTy = IRB.getIntPtrTy(DL);
+
+  std::tie(HwasanCtorFunction, std::ignore) =
+      createSanitizerCtorAndInitFunctions(M, kHwasanModuleCtorName,
+                                          kHwasanInitName,
+                                          /*InitArgTypes=*/{},
+                                          /*InitArgs=*/{});
+  appendToGlobalCtors(M, HwasanCtorFunction, 0);
+  return true;
+}
+
+void HWAddressSanitizer::initializeCallbacks(Module &M) {
+  IRBuilder<> IRB(*C);
+  for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
+    const std::string TypeStr = AccessIsWrite ? "store" : "load";
+
+    HwasanMemoryAccessCallbackSized[AccessIsWrite] =
+        checkSanitizerInterfaceFunction(M.getOrInsertFunction(
+            ClMemoryAccessCallbackPrefix + TypeStr,
+            FunctionType::get(IRB.getVoidTy(), {IntptrTy, IntptrTy}, false)));
+
+    for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
+         AccessSizeIndex++) {
+      HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
+          checkSanitizerInterfaceFunction(M.getOrInsertFunction(
+              ClMemoryAccessCallbackPrefix + TypeStr +
+                  itostr(1ULL << AccessSizeIndex),
+              FunctionType::get(IRB.getVoidTy(), {IntptrTy}, false)));
+    }
+  }
+}
+
+Value *HWAddressSanitizer::isInterestingMemoryAccess(Instruction *I,
+                                                   bool *IsWrite,
+                                                   uint64_t *TypeSize,
+                                                   unsigned *Alignment,
+                                                   Value **MaybeMask) {
+  // Skip memory accesses inserted by another instrumentation.
+  if (I->getMetadata("nosanitize")) return nullptr;
+
+  Value *PtrOperand = nullptr;
+  const DataLayout &DL = I->getModule()->getDataLayout();
+  if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
+    if (!ClInstrumentReads) return nullptr;
+    *IsWrite = false;
+    *TypeSize = DL.getTypeStoreSizeInBits(LI->getType());
+    *Alignment = LI->getAlignment();
+    PtrOperand = LI->getPointerOperand();
+  } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
+    if (!ClInstrumentWrites) return nullptr;
+    *IsWrite = true;
+    *TypeSize = DL.getTypeStoreSizeInBits(SI->getValueOperand()->getType());
+    *Alignment = SI->getAlignment();
+    PtrOperand = SI->getPointerOperand();
+  } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
+    if (!ClInstrumentAtomics) return nullptr;
+    *IsWrite = true;
+    *TypeSize = DL.getTypeStoreSizeInBits(RMW->getValOperand()->getType());
+    *Alignment = 0;
+    PtrOperand = RMW->getPointerOperand();
+  } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) {
+    if (!ClInstrumentAtomics) return nullptr;
+    *IsWrite = true;
+    *TypeSize = DL.getTypeStoreSizeInBits(XCHG->getCompareOperand()->getType());
+    *Alignment = 0;
+    PtrOperand = XCHG->getPointerOperand();
+  }
+
+  if (PtrOperand) {
+    // Do not instrument acesses from different address spaces; we cannot deal
+    // with them.
+    Type *PtrTy = cast<PointerType>(PtrOperand->getType()->getScalarType());
+    if (PtrTy->getPointerAddressSpace() != 0)
+      return nullptr;
+
+    // Ignore swifterror addresses.
+    // swifterror memory addresses are mem2reg promoted by instruction
+    // selection. As such they cannot have regular uses like an instrumentation
+    // function and it makes no sense to track them as memory.
+    if (PtrOperand->isSwiftError())
+      return nullptr;
+  }
+
+  return PtrOperand;
+}
+
+static size_t TypeSizeToSizeIndex(uint32_t TypeSize) {
+  size_t Res = countTrailingZeros(TypeSize / 8);
+  assert(Res < kNumberOfAccessSizes);
+  return Res;
+}
+
+bool HWAddressSanitizer::instrumentMemAccess(Instruction *I) {
+  DEBUG(dbgs() << "Instrumenting: " << *I << "\n");
+  bool IsWrite = false;
+  unsigned Alignment = 0;
+  uint64_t TypeSize = 0;
+  Value *MaybeMask = nullptr;
+  Value *Addr =
+      isInterestingMemoryAccess(I, &IsWrite, &TypeSize, &Alignment, &MaybeMask);
+
+  if (!Addr)
+    return false;
+
+  if (MaybeMask)
+    return false; //FIXME
+
+  IRBuilder<> IRB(I);
+  Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
+  if (isPowerOf2_64(TypeSize) &&
+      (TypeSize / 8 <= (1UL << (kNumberOfAccessSizes - 1)))) {
+    size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize);
+    IRB.CreateCall(HwasanMemoryAccessCallback[IsWrite][AccessSizeIndex],
+                   AddrLong);
+  } else {
+    IRB.CreateCall(HwasanMemoryAccessCallbackSized[IsWrite],
+                   {AddrLong, ConstantInt::get(IntptrTy, TypeSize / 8)});
+  }
+
+  return true;
+}
+
+bool HWAddressSanitizer::runOnFunction(Function &F) {
+  if (&F == HwasanCtorFunction)
+    return false;
+
+  if (!F.hasFnAttribute(Attribute::SanitizeHWAddress))
+    return false;
+
+  DEBUG(dbgs() << "Function: " << F.getName() << "\n");
+
+  initializeCallbacks(*F.getParent());
+
+  bool Changed = false;
+  SmallVector<Instruction*, 16> ToInstrument;
+  for (auto &BB : F) {
+    for (auto &Inst : BB) {
+      Value *MaybeMask = nullptr;
+      bool IsWrite;
+      unsigned Alignment;
+      uint64_t TypeSize;
+      Value *Addr = isInterestingMemoryAccess(&Inst, &IsWrite, &TypeSize,
+                                              &Alignment, &MaybeMask);
+      if (Addr || isa<MemIntrinsic>(Inst))
+        ToInstrument.push_back(&Inst);
+    }
+  }
+
+  for (auto Inst : ToInstrument)
+    Changed |= instrumentMemAccess(Inst);
+
+  return Changed;
+}

Modified: llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp Fri Dec  8 16:21:41 2017
@@ -66,6 +66,7 @@ void llvm::initializeInstrumentation(Pas
   initializePGOMemOPSizeOptLegacyPassPass(Registry);
   initializeInstrProfilingLegacyPassPass(Registry);
   initializeMemorySanitizerPass(Registry);
+  initializeHWAddressSanitizerPass(Registry);
   initializeThreadSanitizerPass(Registry);
   initializeSanitizerCoverageModulePass(Registry);
   initializeDataFlowSanitizerPass(Registry);

Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Fri Dec  8 16:21:41 2017
@@ -1299,7 +1299,10 @@ static void reportLoadElim(LoadInst *LI,
 /// non-local by performing PHI construction.
 bool GVN::processNonLocalLoad(LoadInst *LI) {
   // non-local speculations are not allowed under asan.
-  if (LI->getParent()->getParent()->hasFnAttribute(Attribute::SanitizeAddress))
+  if (LI->getParent()->getParent()->hasFnAttribute(
+          Attribute::SanitizeAddress) ||
+      LI->getParent()->getParent()->hasFnAttribute(
+          Attribute::SanitizeHWAddress))
     return false;
 
   // Step 1: Find the non-local dependencies of the load.

Modified: llvm/trunk/test/Bitcode/attributes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/attributes.ll?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/test/Bitcode/attributes.ll (original)
+++ llvm/trunk/test/Bitcode/attributes.ll Fri Dec  8 16:21:41 2017
@@ -204,7 +204,7 @@ define void @f34()
 ; CHECK: define void @f34()
 {
         call void @nobuiltin() nobuiltin
-; CHECK: call void @nobuiltin() #34
+; CHECK: call void @nobuiltin() #35
         ret void;
 }
 
@@ -339,6 +339,12 @@ define void @f57() speculatable {
   ret void
 }
 
+; CHECK: define void @f58() #34
+define void @f58() sanitize_hwaddress
+{
+        ret void;
+}
+
 ; CHECK: attributes #0 = { noreturn }
 ; CHECK: attributes #1 = { nounwind }
 ; CHECK: attributes #2 = { readnone }
@@ -373,4 +379,5 @@ define void @f57() speculatable {
 ; CHECK: attributes #31 = { allocsize(0,1) }
 ; CHECK: attributes #32 = { writeonly }
 ; CHECK: attributes #33 = { speculatable }
-; CHECK: attributes #34 = { nobuiltin }
+; CHECK: attributes #34 = { sanitize_hwaddress }
+; CHECK: attributes #35 = { nobuiltin }

Added: llvm/trunk/test/Instrumentation/HWAddressSanitizer/atomic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/HWAddressSanitizer/atomic.ll?rev=320217&view=auto
==============================================================================
--- llvm/trunk/test/Instrumentation/HWAddressSanitizer/atomic.ll (added)
+++ llvm/trunk/test/Instrumentation/HWAddressSanitizer/atomic.ll Fri Dec  8 16:21:41 2017
@@ -0,0 +1,26 @@
+; Test basic address sanitizer instrumentation.
+;
+; RUN: opt < %s -hwasan -S | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-android"
+
+define void @atomicrmw(i64* %ptr) sanitize_hwaddress {
+; CHECK-LABEL: @atomicrmw(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %ptr to i64
+; CHECK: call void @__hwasan_store8(i64 %[[A]])
+
+entry:
+  %0 = atomicrmw add i64* %ptr, i64 1 seq_cst
+  ret void
+}
+
+define void @cmpxchg(i64* %ptr, i64 %compare_to, i64 %new_value) sanitize_hwaddress {
+; CHECK-LABEL: @cmpxchg(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %ptr to i64
+; CHECK: call void @__hwasan_store8(i64 %[[A]])
+
+entry:
+  %0 = cmpxchg i64* %ptr, i64 %compare_to, i64 %new_value seq_cst seq_cst
+  ret void
+}

Added: llvm/trunk/test/Instrumentation/HWAddressSanitizer/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/HWAddressSanitizer/basic.ll?rev=320217&view=auto
==============================================================================
--- llvm/trunk/test/Instrumentation/HWAddressSanitizer/basic.ll (added)
+++ llvm/trunk/test/Instrumentation/HWAddressSanitizer/basic.ll Fri Dec  8 16:21:41 2017
@@ -0,0 +1,190 @@
+; Test basic address sanitizer instrumentation.
+;
+; RUN: opt < %s -hwasan -S | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-android"
+
+define i8 @test_load8(i8* %a) sanitize_hwaddress {
+; CHECK-LABEL: @test_load8(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64
+; CHECK: call void @__hwasan_load1(i64 %[[A]])
+; CHECK: %[[B:[^ ]*]] = load i8, i8* %a
+; CHECK: ret i8 %[[B]]
+
+entry:
+  %b = load i8, i8* %a, align 4
+  ret i8 %b
+}
+
+define i16 @test_load16(i16* %a) sanitize_hwaddress {
+; CHECK-LABEL: @test_load16(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i16* %a to i64
+; CHECK: call void @__hwasan_load2(i64 %[[A]])
+; CHECK: %[[B:[^ ]*]] = load i16, i16* %a
+; CHECK: ret i16 %[[B]]
+
+entry:
+  %b = load i16, i16* %a, align 4
+  ret i16 %b
+}
+
+define i32 @test_load32(i32* %a) sanitize_hwaddress {
+; CHECK-LABEL: @test_load32(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i32* %a to i64
+; CHECK: call void @__hwasan_load4(i64 %[[A]])
+; CHECK: %[[B:[^ ]*]] = load i32, i32* %a
+; CHECK: ret i32 %[[B]]
+
+entry:
+  %b = load i32, i32* %a, align 4
+  ret i32 %b
+}
+
+define i64 @test_load64(i64* %a) sanitize_hwaddress {
+; CHECK-LABEL: @test_load64(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %a to i64
+; CHECK: call void @__hwasan_load8(i64 %[[A]])
+; CHECK: %[[B:[^ ]*]] = load i64, i64* %a
+; CHECK: ret i64 %[[B]]
+
+entry:
+  %b = load i64, i64* %a, align 8
+  ret i64 %b
+}
+
+define i128 @test_load128(i128* %a) sanitize_hwaddress {
+; CHECK-LABEL: @test_load128(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i128* %a to i64
+; CHECK: call void @__hwasan_load16(i64 %[[A]])
+; CHECK: %[[B:[^ ]*]] = load i128, i128* %a
+; CHECK: ret i128 %[[B]]
+
+entry:
+  %b = load i128, i128* %a, align 16
+  ret i128 %b
+}
+
+define i40 @test_load40(i40* %a) sanitize_hwaddress {
+; CHECK-LABEL: @test_load40(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64
+; CHECK: call void @__hwasan_load(i64 %[[A]], i64 5)
+; CHECK: %[[B:[^ ]*]] = load i40, i40* %a
+; CHECK: ret i40 %[[B]]
+
+entry:
+  %b = load i40, i40* %a, align 4
+  ret i40 %b
+}
+
+define void @test_store8(i8* %a, i8 %b) sanitize_hwaddress {
+; CHECK-LABEL: @test_store8(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64
+; CHECK: call void @__hwasan_store1(i64 %[[A]])
+; CHECK: store i8 %b, i8* %a
+; CHECK: ret void
+
+entry:
+  store i8 %b, i8* %a, align 4
+  ret void
+}
+
+define void @test_store16(i16* %a, i16 %b) sanitize_hwaddress {
+; CHECK-LABEL: @test_store16(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i16* %a to i64
+; CHECK: call void @__hwasan_store2(i64 %[[A]])
+; CHECK: store i16 %b, i16* %a
+; CHECK: ret void
+
+entry:
+  store i16 %b, i16* %a, align 4
+  ret void
+}
+
+define void @test_store32(i32* %a, i32 %b) sanitize_hwaddress {
+; CHECK-LABEL: @test_store32(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i32* %a to i64
+; CHECK: call void @__hwasan_store4(i64 %[[A]])
+; CHECK: store i32 %b, i32* %a
+; CHECK: ret void
+
+entry:
+  store i32 %b, i32* %a, align 4
+  ret void
+}
+
+define void @test_store64(i64* %a, i64 %b) sanitize_hwaddress {
+; CHECK-LABEL: @test_store64(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %a to i64
+; CHECK: call void @__hwasan_store8(i64 %[[A]])
+; CHECK: store i64 %b, i64* %a
+; CHECK: ret void
+
+entry:
+  store i64 %b, i64* %a, align 4
+  ret void
+}
+
+define void @test_store128(i128* %a, i128 %b) sanitize_hwaddress {
+; CHECK-LABEL: @test_store128(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i128* %a to i64
+; CHECK: call void @__hwasan_store16(i64 %[[A]])
+; CHECK: store i128 %b, i128* %a
+; CHECK: ret void
+
+entry:
+  store i128 %b, i128* %a, align 4
+  ret void
+}
+
+define void @test_store40(i40* %a, i40 %b) sanitize_hwaddress {
+; CHECK-LABEL: @test_store40(
+; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64
+; CHECK: call void @__hwasan_store(i64 %[[A]], i64 5)
+; CHECK: store i40 %b, i40* %a
+; CHECK: ret void
+
+entry:
+  store i40 %b, i40* %a, align 4
+  ret void
+}
+
+define i8 @test_load_noattr(i8* %a) {
+; CHECK-LABEL: @test_load_noattr(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %[[B:[^ ]*]] = load i8, i8* %a
+; CHECK-NEXT: ret i8 %[[B]]
+
+entry:
+  %b = load i8, i8* %a, align 4
+  ret i8 %b
+}
+
+define i8 @test_load_notmyattr(i8* %a) sanitize_address {
+; CHECK-LABEL: @test_load_notmyattr(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %[[B:[^ ]*]] = load i8, i8* %a
+; CHECK-NEXT: ret i8 %[[B]]
+
+entry:
+  %b = load i8, i8* %a, align 4
+  ret i8 %b
+}
+
+define i8 @test_load_addrspace(i8 addrspace(256)* %a) sanitize_hwaddress {
+; CHECK-LABEL: @test_load_addrspace(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %[[B:[^ ]*]] = load i8, i8 addrspace(256)* %a
+; CHECK-NEXT: ret i8 %[[B]]
+
+entry:
+  %b = load i8, i8 addrspace(256)* %a, align 4
+  ret i8 %b
+}
+
+; CHECK: declare void @__hwasan_init()
+
+; CHECK:      define internal void @hwasan.module_ctor() {
+; CHECK-NEXT:   call void @__hwasan_init()
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }

Modified: llvm/trunk/test/Transforms/GVN/no_speculative_loads_with_asan.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/no_speculative_loads_with_asan.ll?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/GVN/no_speculative_loads_with_asan.ll (original)
+++ llvm/trunk/test/Transforms/GVN/no_speculative_loads_with_asan.ll Fri Dec  8 16:21:41 2017
@@ -53,3 +53,30 @@ define i32 @TestAsan() sanitize_address
 ; CHECK-NOT: %[[LOAD:[^ ]+]] = load i32
 ; CHECK: {{.*}} = phi
 
+
+define i32 @TestHWAsan() sanitize_hwaddress {
+  %1 = tail call noalias i8* @_Znam(i64 2)
+  %2 = getelementptr inbounds i8, i8* %1, i64 1
+  store i8 0, i8* %2, align 1
+  store i8 0, i8* %1, align 1
+  %3 = bitcast i8* %1 to i16*
+  %4 = load i16, i16* %3, align 4
+  %5 = icmp eq i16 %4, 0
+  br i1 %5, label %11, label %6
+
+; <label>:6                                       ; preds = %0
+  %7 = getelementptr inbounds i8, i8* %1, i64 2
+  %8 = bitcast i8* %7 to i16*
+  %9 = load i16, i16* %8, align 2
+  %10 = sext i16 %9 to i32
+  br label %11
+
+; <label>:11                                      ; preds = %0, %6
+  %12 = phi i32 [ %10, %6 ], [ 0, %0 ]
+  ret i32 %12
+}
+
+; CHECK-LABEL: @TestHWAsan
+; CHECK-NOT: %[[LOAD:[^ ]+]] = load i32
+; CHECK: {{.*}} = phi
+

Modified: llvm/trunk/test/Transforms/Inline/attributes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/attributes.ll?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Inline/attributes.ll (original)
+++ llvm/trunk/test/Transforms/Inline/attributes.ll Fri Dec  8 16:21:41 2017
@@ -10,6 +10,10 @@ define i32 @sanitize_address_callee(i32
   ret i32 %i
 }
 
+define i32 @sanitize_hwaddress_callee(i32 %i) sanitize_hwaddress {
+  ret i32 %i
+}
+
 define i32 @sanitize_thread_callee(i32 %i) sanitize_thread {
   ret i32 %i
 }
@@ -30,6 +34,10 @@ define i32 @alwaysinline_sanitize_addres
   ret i32 %i
 }
 
+define i32 @alwaysinline_sanitize_hwaddress_callee(i32 %i) alwaysinline sanitize_hwaddress {
+  ret i32 %i
+}
+
 define i32 @alwaysinline_sanitize_thread_callee(i32 %i) alwaysinline sanitize_thread {
   ret i32 %i
 }
@@ -59,6 +67,17 @@ define i32 @test_no_sanitize_address(i32
 ; CHECK-NEXT: ret i32
 }
 
+define i32 @test_no_sanitize_hwaddress(i32 %arg) {
+  %x1 = call i32 @noattr_callee(i32 %arg)
+  %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1)
+  %x3 = call i32 @alwaysinline_callee(i32 %x2)
+  %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3)
+  ret i32 %x4
+; CHECK-LABEL: @test_no_sanitize_hwaddress(
+; CHECK-NEXT: @sanitize_hwaddress_callee
+; CHECK-NEXT: ret i32
+}
+
 define i32 @test_no_sanitize_memory(i32 %arg) {
   %x1 = call i32 @noattr_callee(i32 %arg)
   %x2 = call i32 @sanitize_memory_callee(i32 %x1)
@@ -97,6 +116,17 @@ define i32 @test_sanitize_address(i32 %a
 ; CHECK-NEXT: @noattr_callee
 ; CHECK-NEXT: ret i32
 }
+
+define i32 @test_sanitize_hwaddress(i32 %arg) sanitize_hwaddress {
+  %x1 = call i32 @noattr_callee(i32 %arg)
+  %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1)
+  %x3 = call i32 @alwaysinline_callee(i32 %x2)
+  %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3)
+  ret i32 %x4
+; CHECK-LABEL: @test_sanitize_hwaddress(
+; CHECK-NEXT: @noattr_callee
+; CHECK-NEXT: ret i32
+}
 
 define i32 @test_sanitize_memory(i32 %arg) sanitize_memory {
   %x1 = call i32 @noattr_callee(i32 %arg)

Modified: llvm/trunk/test/Transforms/InstCombine/lifetime-asan.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/lifetime-asan.ll?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/lifetime-asan.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/lifetime-asan.ll Fri Dec  8 16:21:41 2017
@@ -19,6 +19,20 @@ entry:
   ret void
 }
 
+define void @hwasan() sanitize_hwaddress {
+entry:
+  ; CHECK-LABEL: @hwasan(
+  %text = alloca i8, align 1
+
+  call void @llvm.lifetime.start.p0i8(i64 1, i8* %text)
+  call void @llvm.lifetime.end.p0i8(i64 1, i8* %text)
+  ; CHECK: call void @llvm.lifetime.start
+  ; CHECK-NEXT: call void @llvm.lifetime.end
+
+  call void @foo(i8* %text) ; Keep alloca alive
+
+  ret void
+}
 
 define void @no_asan() {
 entry:

Modified: llvm/trunk/test/Transforms/NewGVN/no_speculative_loads_with_asan.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/no_speculative_loads_with_asan.ll?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/no_speculative_loads_with_asan.ll (original)
+++ llvm/trunk/test/Transforms/NewGVN/no_speculative_loads_with_asan.ll Fri Dec  8 16:21:41 2017
@@ -53,3 +53,29 @@ define i32 @TestAsan() sanitize_address
 ; CHECK-NOT: %[[LOAD:[^ ]+]] = load i32
 ; CHECK: {{.*}} = phi
 
+define i32 @TestHWAsan() sanitize_hwaddress {
+  %1 = tail call noalias i8* @_Znam(i64 2)
+  %2 = getelementptr inbounds i8, i8* %1, i64 1
+  store i8 0, i8* %2, align 1
+  store i8 0, i8* %1, align 1
+  %3 = bitcast i8* %1 to i16*
+  %4 = load i16, i16* %3, align 4
+  %5 = icmp eq i16 %4, 0
+  br i1 %5, label %11, label %6
+
+; <label>:6                                       ; preds = %0
+  %7 = getelementptr inbounds i8, i8* %1, i64 2
+  %8 = bitcast i8* %7 to i16*
+  %9 = load i16, i16* %8, align 2
+  %10 = sext i16 %9 to i32
+  br label %11
+
+; <label>:11                                      ; preds = %0, %6
+  %12 = phi i32 [ %10, %6 ], [ 0, %0 ]
+  ret i32 %12
+}
+
+; CHECK-LABEL: @TestHWAsan
+; CHECK-NOT: %[[LOAD:[^ ]+]] = load i32
+; CHECK: {{.*}} = phi
+

Modified: llvm/trunk/test/Transforms/SimplifyCFG/no_speculative_loads_with_asan.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/no_speculative_loads_with_asan.ll?rev=320217&r1=320216&r2=320217&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/no_speculative_loads_with_asan.ll (original)
+++ llvm/trunk/test/Transforms/SimplifyCFG/no_speculative_loads_with_asan.ll Fri Dec  8 16:21:41 2017
@@ -38,3 +38,22 @@ return:
 ; CHECK: br label
 ; CHECK: ret i32
 }
+
+define i32 @TestHWAsan(i32 %cond) nounwind readonly uwtable sanitize_hwaddress {
+entry:
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %return, label %if.then
+
+if.then:                                          ; preds = %entry
+  %0 = load i32, i32* @g, align 4
+  br label %return
+
+return:                                           ; preds = %entry, %if.then
+  %retval = phi i32 [ %0, %if.then ], [ 0, %entry ]
+  ret i32 %retval
+; CHECK-LABEL: @TestHWAsan
+; CHECK: br i1
+; CHECK: load i32, i32* @g
+; CHECK: br label
+; CHECK: ret i32
+}




More information about the llvm-commits mailing list