[llvm] [HWASan] Add hwasan-tag-bits flag (PR #191088)

Florian Mayer via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 13 16:47:43 PDT 2026


https://github.com/fmayer updated https://github.com/llvm/llvm-project/pull/191088

>From 724370374e3a92c76ca82015d9938216a82db85a Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Wed, 8 Apr 2026 17:25:15 -0700
Subject: [PATCH 1/6] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
 =?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.7
---
 .../Instrumentation/HWAddressSanitizer.cpp    |  7 +-
 .../HWAddressSanitizer/alloca.ll              | 75 +++++++++++++++++++
 2 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index a8900a3c4f43f..7cdb1c7c51caf 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -283,6 +283,11 @@ static cl::opt<bool> ClUsePageAliases("hwasan-experimental-use-page-aliases",
                                       cl::desc("Use page aliasing in HWASan"),
                                       cl::Hidden, cl::init(false));
 
+static cl::opt<bool> ClNonNegativePointers(
+    "hwasan-non-negative-pointers",
+    cl::desc("Don't use the top bit of the pointer for alloca tags"),
+    cl::Hidden, cl::init(false));
+
 STATISTIC(NumTotalFuncs, "Number of total funcs");
 STATISTIC(NumInstrumentedFuncs, "Number of instrumented funcs");
 STATISTIC(NumNoProfileSummaryFuncs, "Number of funcs without PS");
@@ -676,7 +681,7 @@ void HWAddressSanitizer::initializeModule() {
   InstrumentStack = shouldInstrumentStack(TargetTriple);
   DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
   PointerTagShift = IsX86_64 ? 57 : 56;
-  TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
+  TagMaskByte = IsX86_64 ? 0x3F : (ClNonNegativePointers ? 0x7F : 0xFF);
 
   Mapping.init(TargetTriple, InstrumentWithCalls, CompileKernel);
 
diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll b/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll
index 4ed068222cc24..4a1cfe2336078 100644
--- a/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll
+++ b/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll
@@ -4,6 +4,7 @@
 ;
 ; RUN: opt < %s -passes=hwasan -hwasan-mapping-offset-dynamic=ifunc -hwasan-with-frame-record=0 -S | FileCheck %s --check-prefixes=DYNAMIC-SHADOW
 ; RUN: opt < %s -passes=hwasan -hwasan-mapping-offset=0 -hwasan-with-frame-record=0 -S | FileCheck %s --check-prefixes=ZERO-BASED-SHADOW
+; RUN: opt < %s -passes=hwasan -hwasan-mapping-offset=0 -hwasan-with-frame-record=0  -hwasan-non-negative-pointers -S | FileCheck %s --check-prefixes=ZERO-BASED-SHADOW-NON-NEGATIVE
 
 
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
@@ -30,6 +31,15 @@ declare void @use32(ptr)
 ; ZERO-BASED-SHADOW: @llvm.compiler.used = appending global [2 x ptr] [ptr @hwasan.note, ptr @hwasan.dummy.global], section "llvm.metadata"
 ; ZERO-BASED-SHADOW: @__hwasan_shadow = external global [0 x i8]
 ;.
+; ZERO-BASED-SHADOW-NON-NEGATIVE: @llvm.used = appending global [1 x ptr] [ptr @hwasan.module_ctor], section "llvm.metadata"
+; ZERO-BASED-SHADOW-NON-NEGATIVE: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @hwasan.module_ctor, ptr @hwasan.module_ctor }]
+; ZERO-BASED-SHADOW-NON-NEGATIVE: @__start_hwasan_globals = external hidden constant [0 x i8]
+; ZERO-BASED-SHADOW-NON-NEGATIVE: @__stop_hwasan_globals = external hidden constant [0 x i8]
+; ZERO-BASED-SHADOW-NON-NEGATIVE: @hwasan.note = private constant { i32, i32, i32, [8 x i8], i32, i32 } { i32 8, i32 8, i32 3, [8 x i8] c"LLVM\00\00\00\00", i32 trunc (i64 sub (i64 ptrtoint (ptr @__start_hwasan_globals to i64), i64 ptrtoint (ptr @hwasan.note to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @__stop_hwasan_globals to i64), i64 ptrtoint (ptr @hwasan.note to i64)) to i32) }, section ".note.hwasan.globals", comdat($hwasan.module_ctor), align 4
+; ZERO-BASED-SHADOW-NON-NEGATIVE: @hwasan.dummy.global = private constant [0 x i8] zeroinitializer, section "hwasan_globals", comdat($hwasan.module_ctor), !associated [[META0:![0-9]+]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE: @llvm.compiler.used = appending global [2 x ptr] [ptr @hwasan.note, ptr @hwasan.dummy.global], section "llvm.metadata"
+; ZERO-BASED-SHADOW-NON-NEGATIVE: @__hwasan_shadow = external global [0 x i8]
+;.
 define void @test_alloca() sanitize_hwaddress !dbg !15 {
 ; DYNAMIC-SHADOW-LABEL: define void @test_alloca(
 ; DYNAMIC-SHADOW-SAME: ) #[[ATTR0:[0-9]+]] personality ptr @__hwasan_personality_thunk !dbg [[DBG8:![0-9]+]] {
@@ -101,6 +111,43 @@ define void @test_alloca() sanitize_hwaddress !dbg !15 {
 ; ZERO-BASED-SHADOW-NEXT:    call void @llvm.memset.p0.i64(ptr align 1 [[TMP19]], i8 [[TMP15]], i64 1, i1 false), !dbg [[DBG15]]
 ; ZERO-BASED-SHADOW-NEXT:    ret void, !dbg [[DBG15]]
 ;
+; ZERO-BASED-SHADOW-NON-NEGATIVE-LABEL: define void @test_alloca(
+; ZERO-BASED-SHADOW-NON-NEGATIVE-SAME: ) #[[ATTR0:[0-9]+]] personality ptr @__hwasan_personality_thunk !dbg [[DBG8:![0-9]+]] {
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:  entry:
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[DOTHWASAN_SHADOW:%.*]] = call ptr asm "", "=r,0"(ptr null)
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP0:%.*]] = call ptr @llvm.frameaddress.p0(i32 0)
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP2:%.*]] = lshr i64 [[TMP1]], 20
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP3:%.*]] = xor i64 [[TMP1]], [[TMP2]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[HWASAN_STACK_BASE_TAG:%.*]] = and i64 [[TMP3]], 127
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP4:%.*]] = lshr i64 [[TMP1]], 56
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[HWASAN_UAR_TAG:%.*]] = and i64 [[TMP4]], 127
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[X:%.*]] = alloca { i32, [12 x i8] }, align 16
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:      #dbg_value(!DIArgList(ptr [[X]], ptr [[X]]), [[META11:![0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_tag_offset, 0, DW_OP_LLVM_arg, 1, DW_OP_LLVM_tag_offset, 0, DW_OP_plus, DW_OP_deref), [[META13:![0-9]+]])
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP5:%.*]] = xor i64 [[HWASAN_STACK_BASE_TAG]], 0, !dbg [[DBG14:![0-9]+]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP6:%.*]] = ptrtoint ptr [[X]] to i64, !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP7:%.*]] = and i64 [[TMP6]], -9151314442816847873, !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP8:%.*]] = shl i64 [[TMP5]], 56, !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP9:%.*]] = or i64 [[TMP7]], [[TMP8]], !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[X_HWASAN:%.*]] = inttoptr i64 [[TMP9]] to ptr, !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP10:%.*]] = trunc i64 [[TMP5]] to i8, !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP11:%.*]] = ptrtoint ptr [[X]] to i64, !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP12:%.*]] = and i64 [[TMP11]], -9151314442816847873, !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP13:%.*]] = lshr i64 [[TMP12]], 4, !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP14:%.*]] = inttoptr i64 [[TMP13]] to ptr, !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP15:%.*]] = getelementptr i8, ptr [[TMP14]], i32 0, !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    store i8 4, ptr [[TMP15]], align 1, !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP16:%.*]] = getelementptr i8, ptr [[X]], i32 15, !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    store i8 [[TMP10]], ptr [[TMP16]], align 1, !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    call void @use32(ptr nonnull [[X_HWASAN]]), !dbg [[DBG14]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP17:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8, !dbg [[DBG15:![0-9]+]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP18:%.*]] = ptrtoint ptr [[X]] to i64, !dbg [[DBG15]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP19:%.*]] = and i64 [[TMP18]], -9151314442816847873, !dbg [[DBG15]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP20:%.*]] = lshr i64 [[TMP19]], 4, !dbg [[DBG15]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[TMP21:%.*]] = inttoptr i64 [[TMP20]] to ptr, !dbg [[DBG15]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    call void @llvm.memset.p0.i64(ptr align 1 [[TMP21]], i8 [[TMP17]], i64 1, i1 false), !dbg [[DBG15]]
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    ret void, !dbg [[DBG15]]
+;
 entry:
   %x = alloca i32, align 4
   call void @llvm.dbg.value(metadata !DIArgList(ptr %x, ptr %x), metadata !22, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_deref)), !dbg !21
@@ -120,6 +167,12 @@ define void @test_vscale_alloca() sanitize_hwaddress {
 ; ZERO-BASED-SHADOW-NEXT:    [[X:%.*]] = alloca <vscale x 4 x i64>, align 32
 ; ZERO-BASED-SHADOW-NEXT:    call void @use32(ptr nonnull [[X]])
 ; ZERO-BASED-SHADOW-NEXT:    ret void
+;
+; ZERO-BASED-SHADOW-NON-NEGATIVE-LABEL: define void @test_vscale_alloca(
+; ZERO-BASED-SHADOW-NON-NEGATIVE-SAME: ) #[[ATTR0]] {
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    [[X:%.*]] = alloca <vscale x 4 x i64>, align 32
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    call void @use32(ptr nonnull [[X]])
+; ZERO-BASED-SHADOW-NON-NEGATIVE-NEXT:    ret void
 ;
   %x = alloca <vscale x 4 x i64>
   call void @use32(ptr nonnull %x)
@@ -158,6 +211,11 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
 ; ZERO-BASED-SHADOW: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) }
 ; ZERO-BASED-SHADOW: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
 ;.
+; ZERO-BASED-SHADOW-NON-NEGATIVE: attributes #[[ATTR0]] = { sanitize_hwaddress }
+; ZERO-BASED-SHADOW-NON-NEGATIVE: attributes #[[ATTR1:[0-9]+]] = { nounwind }
+; ZERO-BASED-SHADOW-NON-NEGATIVE: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) }
+; ZERO-BASED-SHADOW-NON-NEGATIVE: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
+;.
 ; DYNAMIC-SHADOW: [[META0]] = !{ptr @hwasan.note}
 ; DYNAMIC-SHADOW: [[META1:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: [[META2:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: [[META3:![0-9]+]], splitDebugInlining: false, nameTableKind: None)
 ; DYNAMIC-SHADOW: [[META2]] = !DIFile(filename: "{{.*}}alloca.cpp", directory: {{.*}})
@@ -192,3 +250,20 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
 ; ZERO-BASED-SHADOW: [[DBG14]] = !DILocation(line: 7, column: 5, scope: [[DBG8]])
 ; ZERO-BASED-SHADOW: [[DBG15]] = !DILocation(line: 8, column: 1, scope: [[DBG8]])
 ;.
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[META0]] = !{ptr @hwasan.note}
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[META1:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: [[META2:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: [[META3:![0-9]+]], splitDebugInlining: false, nameTableKind: None)
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[META2]] = !DIFile(filename: "{{.*}}alloca.cpp", directory: {{.*}})
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[META3]] = !{}
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[META4:![0-9]+]] = !{i32 7, !"Dwarf Version", i32 4}
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[META5:![0-9]+]] = !{i32 2, !"Debug Info Version", i32 3}
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[META6:![0-9]+]] = !{i32 4, !"nosanitize_hwaddress", i32 1}
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[META7:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[DBG8]] = distinct !DISubprogram(name: "test_alloca", linkageName: "_Z11test_allocav", scope: [[META2]], file: [[META2]], line: 4, type: [[META9:![0-9]+]], scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META1]], retainedNodes: [[META3]])
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[META9]] = !DISubroutineType(types: [[META10:![0-9]+]])
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[META10]] = !{null}
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[META11]] = !DILocalVariable(name: "x", scope: [[DBG8]], file: [[META2]], line: 5, type: [[META12:![0-9]+]])
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[META12]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[META13]] = !DILocation(line: 0, scope: [[DBG8]])
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[DBG14]] = !DILocation(line: 7, column: 5, scope: [[DBG8]])
+; ZERO-BASED-SHADOW-NON-NEGATIVE: [[DBG15]] = !DILocation(line: 8, column: 1, scope: [[DBG8]])
+;.

>From 1e892613f2ed6452aedf3bf820419751f835ac31 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Mon, 13 Apr 2026 14:25:45 -0700
Subject: [PATCH 2/6] review comment

Created using spr 1.3.7
---
 .../Transforms/Instrumentation/HWAddressSanitizer.cpp  | 10 ++++++----
 llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index 7cdb1c7c51caf..97a25bebd4a3a 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -283,10 +283,10 @@ static cl::opt<bool> ClUsePageAliases("hwasan-experimental-use-page-aliases",
                                       cl::desc("Use page aliasing in HWASan"),
                                       cl::Hidden, cl::init(false));
 
-static cl::opt<bool> ClNonNegativePointers(
-    "hwasan-non-negative-pointers",
+static cl::opt<uint64_t> ClTagMask(
+    "hwasan-tag-mask",
     cl::desc("Don't use the top bit of the pointer for alloca tags"),
-    cl::Hidden, cl::init(false));
+    cl::Hidden, cl::init(0));
 
 STATISTIC(NumTotalFuncs, "Number of total funcs");
 STATISTIC(NumInstrumentedFuncs, "Number of instrumented funcs");
@@ -681,7 +681,9 @@ void HWAddressSanitizer::initializeModule() {
   InstrumentStack = shouldInstrumentStack(TargetTriple);
   DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
   PointerTagShift = IsX86_64 ? 57 : 56;
-  TagMaskByte = IsX86_64 ? 0x3F : (ClNonNegativePointers ? 0x7F : 0xFF);
+  TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
+  if (ClTagMask)
+    TagMaskByte &= ClTagMask;
 
   Mapping.init(TargetTriple, InstrumentWithCalls, CompileKernel);
 
diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll b/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll
index 4a1cfe2336078..4a3529de05634 100644
--- a/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll
+++ b/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll
@@ -4,7 +4,7 @@
 ;
 ; RUN: opt < %s -passes=hwasan -hwasan-mapping-offset-dynamic=ifunc -hwasan-with-frame-record=0 -S | FileCheck %s --check-prefixes=DYNAMIC-SHADOW
 ; RUN: opt < %s -passes=hwasan -hwasan-mapping-offset=0 -hwasan-with-frame-record=0 -S | FileCheck %s --check-prefixes=ZERO-BASED-SHADOW
-; RUN: opt < %s -passes=hwasan -hwasan-mapping-offset=0 -hwasan-with-frame-record=0  -hwasan-non-negative-pointers -S | FileCheck %s --check-prefixes=ZERO-BASED-SHADOW-NON-NEGATIVE
+; RUN: opt < %s -passes=hwasan -hwasan-mapping-offset=0 -hwasan-with-frame-record=0  -hwasan-tag-mask=127 -S | FileCheck %s --check-prefixes=ZERO-BASED-SHADOW-NON-NEGATIVE
 
 
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"

>From d40b5089f496bc9b097dcfaeea0376fbf0e9021e Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Mon, 13 Apr 2026 14:43:04 -0700
Subject: [PATCH 3/6] error handling

Created using spr 1.3.7
---
 .../Instrumentation/HWAddressSanitizer.cpp      | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index 97a25bebd4a3a..ec9ea6f72f322 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -52,6 +52,7 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MD5.h"
 #include "llvm/Support/RandomNumberGenerator.h"
 #include "llvm/Support/raw_ostream.h"
@@ -283,10 +284,10 @@ static cl::opt<bool> ClUsePageAliases("hwasan-experimental-use-page-aliases",
                                       cl::desc("Use page aliasing in HWASan"),
                                       cl::Hidden, cl::init(false));
 
-static cl::opt<uint64_t> ClTagMask(
-    "hwasan-tag-mask",
-    cl::desc("Don't use the top bit of the pointer for alloca tags"),
-    cl::Hidden, cl::init(0));
+static cl::opt<uint64_t>
+    ClTagMask("hwasan-tag-mask",
+              cl::desc("Don't use the top bit of the pointer for alloca tags"),
+              cl::Hidden, cl::init(0));
 
 STATISTIC(NumTotalFuncs, "Number of total funcs");
 STATISTIC(NumInstrumentedFuncs, "Number of instrumented funcs");
@@ -682,8 +683,14 @@ void HWAddressSanitizer::initializeModule() {
   DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
   PointerTagShift = IsX86_64 ? 57 : 56;
   TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
-  if (ClTagMask)
+  if (ClTagMask) {
+    if ((TagMaskByte + 1) & TagMaskByte)
+      reportFatalUsageError(
+          "-hwasan-tag-mask must be one less than a power of two.");
+    if (TagMaskByte < 16)
+      reportFatalUsageError("-hwasan-tag-mask must >= 16");
     TagMaskByte &= ClTagMask;
+  }
 
   Mapping.init(TargetTriple, InstrumentWithCalls, CompileKernel);
 

>From 98366c90e3fe935d3255c02a1dff14f8bf839ec0 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Mon, 13 Apr 2026 15:23:12 -0700
Subject: [PATCH 4/6] api

Created using spr 1.3.7
---
 .../Instrumentation/HWAddressSanitizer.cpp        | 15 ++++++---------
 .../Instrumentation/HWAddressSanitizer/alloca.ll  |  2 +-
 2 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index 47b108806a272..5522923a7461f 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -284,8 +284,8 @@ static cl::opt<bool> ClUsePageAliases("hwasan-experimental-use-page-aliases",
                                       cl::desc("Use page aliasing in HWASan"),
                                       cl::Hidden, cl::init(false));
 
-static cl::opt<uint64_t> ClTagMask(
-    "hwasan-tag-mask",
+static cl::opt<uint64_t> ClTagBits(
+    "hwasan-tag-bits",
     cl::desc("Additional masking for tags. This gets applied after "
              "the architecture specific mask for the ignored pointer bits. "
              "Must be > 16 and one less than a power of two."),
@@ -685,13 +685,10 @@ void HWAddressSanitizer::initializeModule() {
   DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
   PointerTagShift = IsX86_64 ? 57 : 56;
   TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
-  if (ClTagMask) {
-    if ((TagMaskByte + 1) & TagMaskByte)
-      reportFatalUsageError(
-          "-hwasan-tag-mask must be one less than a power of two.");
-    if (TagMaskByte < 16)
-      reportFatalUsageError("-hwasan-tag-mask must >= 16");
-    TagMaskByte &= ClTagMask;
+  if (ClTagBits) {
+    if (TagMaskByte < 4)
+      reportFatalUsageError("need more than 4 bits of tag to have non-short-granule tags");
+    TagMaskByte &= (1 << ClTagBits) - 1;
   }
 
   Mapping.init(TargetTriple, InstrumentWithCalls, CompileKernel);
diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll b/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll
index 4a3529de05634..34a5e5727375d 100644
--- a/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll
+++ b/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll
@@ -4,7 +4,7 @@
 ;
 ; RUN: opt < %s -passes=hwasan -hwasan-mapping-offset-dynamic=ifunc -hwasan-with-frame-record=0 -S | FileCheck %s --check-prefixes=DYNAMIC-SHADOW
 ; RUN: opt < %s -passes=hwasan -hwasan-mapping-offset=0 -hwasan-with-frame-record=0 -S | FileCheck %s --check-prefixes=ZERO-BASED-SHADOW
-; RUN: opt < %s -passes=hwasan -hwasan-mapping-offset=0 -hwasan-with-frame-record=0  -hwasan-tag-mask=127 -S | FileCheck %s --check-prefixes=ZERO-BASED-SHADOW-NON-NEGATIVE
+; RUN: opt < %s -passes=hwasan -hwasan-mapping-offset=0 -hwasan-with-frame-record=0  -hwasan-tag-bits=7 -S | FileCheck %s --check-prefixes=ZERO-BASED-SHADOW-NON-NEGATIVE
 
 
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"

>From f93dc89999be1d941924f953a865a3e461fe9c21 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Mon, 13 Apr 2026 15:24:36 -0700
Subject: [PATCH 5/6] doc

Created using spr 1.3.7
---
 llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index 5522923a7461f..6640673ddf83d 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -286,9 +286,7 @@ static cl::opt<bool> ClUsePageAliases("hwasan-experimental-use-page-aliases",
 
 static cl::opt<uint64_t> ClTagBits(
     "hwasan-tag-bits",
-    cl::desc("Additional masking for tags. This gets applied after "
-             "the architecture specific mask for the ignored pointer bits. "
-             "Must be > 16 and one less than a power of two."),
+    cl::desc("Restrict tag to at most N bits. Needs to be > 4."),
     cl::Hidden, cl::init(0));
 
 STATISTIC(NumTotalFuncs, "Number of total funcs");

>From d61441ff8c0987b72f1693cb64f5eb80ec14a706 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Mon, 13 Apr 2026 15:25:19 -0700
Subject: [PATCH 6/6] fmt

Created using spr 1.3.7
---
 .../Transforms/Instrumentation/HWAddressSanitizer.cpp | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index 6640673ddf83d..50eecdb168161 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -284,10 +284,10 @@ static cl::opt<bool> ClUsePageAliases("hwasan-experimental-use-page-aliases",
                                       cl::desc("Use page aliasing in HWASan"),
                                       cl::Hidden, cl::init(false));
 
-static cl::opt<uint64_t> ClTagBits(
-    "hwasan-tag-bits",
-    cl::desc("Restrict tag to at most N bits. Needs to be > 4."),
-    cl::Hidden, cl::init(0));
+static cl::opt<uint64_t>
+    ClTagBits("hwasan-tag-bits",
+              cl::desc("Restrict tag to at most N bits. Needs to be > 4."),
+              cl::Hidden, cl::init(0));
 
 STATISTIC(NumTotalFuncs, "Number of total funcs");
 STATISTIC(NumInstrumentedFuncs, "Number of instrumented funcs");
@@ -685,7 +685,8 @@ void HWAddressSanitizer::initializeModule() {
   TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
   if (ClTagBits) {
     if (TagMaskByte < 4)
-      reportFatalUsageError("need more than 4 bits of tag to have non-short-granule tags");
+      reportFatalUsageError(
+          "need more than 4 bits of tag to have non-short-granule tags");
     TagMaskByte &= (1 << ClTagBits) - 1;
   }
 



More information about the llvm-commits mailing list