[HWASan] Use page aliasing on x86_64.

Userspace page aliasing allows us to use middle pointer bits for tags
without untagging them before syscalls or accesses.  This should enable
easier experimentation with HWASan on x86_64 platforms.

Currently stack, global, and secondary heap tagging are unsupported.
Only primary heap allocations get tagged.

Note that aliasing mode will not work properly in the presence of
fork(), since heap memory will be shared between the parent and child
processes.  This mode is non-ideal; we expect Intel LAM to enable full
HWASan support on x86_64 in the future.

Reviewed By: vitalybuka, eugenis

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

GitOrigin-RevId: 96a4167b4c7e7e43d11b98f30bed84e4a626281a
diff --git a/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index 1c368e7..07892bd 100644
--- a/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -708,7 +708,7 @@
 }
 
 void HWAddressSanitizer::untagPointerOperand(Instruction *I, Value *Addr) {
-  if (TargetTriple.isAArch64())
+  if (TargetTriple.isAArch64() || TargetTriple.getArch() == Triple::x86_64)
     return;
 
   IRBuilder<> IRB(I);
@@ -1004,6 +1004,7 @@
 
 // Remove tag from an address.
 Value *HWAddressSanitizer::untagPointer(IRBuilder<> &IRB, Value *PtrLong) {
+  assert(!UsePageAliases);
   Value *UntaggedPtrLong;
   if (CompileKernel) {
     // Kernel addresses have 0xFF in the most significant byte.
diff --git a/test/Instrumentation/HWAddressSanitizer/X86/atomic.ll b/test/Instrumentation/HWAddressSanitizer/X86/atomic.ll
index ce2c187..e85fc70 100644
--- a/test/Instrumentation/HWAddressSanitizer/X86/atomic.ll
+++ b/test/Instrumentation/HWAddressSanitizer/X86/atomic.ll
@@ -11,10 +11,7 @@
 
 ; CHECK: call void @__hwasan_store8(i64 %[[A]])
 
-; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %ptr to i64
-; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935
-; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i64*
-; CHECK: atomicrmw add i64* %[[UNTAGGED_PTR]], i64 1 seq_cst
+; CHECK: atomicrmw add i64* %ptr, i64 1 seq_cst
 ; CHECK: ret void
 
 entry:
@@ -28,10 +25,7 @@
 
 ; CHECK: call void @__hwasan_store8(i64 %[[A]])
 
-; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %ptr to i64
-; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935
-; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i64*
-; CHECK: cmpxchg i64* %[[UNTAGGED_PTR]], i64 %compare_to, i64 %new_value seq_cst seq_cst
+; CHECK: cmpxchg i64* %ptr, i64 %compare_to, i64 %new_value seq_cst seq_cst
 ; CHECK: ret void
 
 entry:
diff --git a/test/Instrumentation/HWAddressSanitizer/X86/basic.ll b/test/Instrumentation/HWAddressSanitizer/X86/basic.ll
index e93ebb7..59e73c5 100644
--- a/test/Instrumentation/HWAddressSanitizer/X86/basic.ll
+++ b/test/Instrumentation/HWAddressSanitizer/X86/basic.ll
@@ -15,10 +15,7 @@
 ; ABORT: call void @__hwasan_load1(i64 %[[A]])
 ; RECOVER: call void @__hwasan_load1_noabort(i64 %[[A]])
 
-; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64
-; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935
-; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8*
-; CHECK: %[[G:[^ ]*]] = load i8, i8* %[[UNTAGGED_PTR]], align 4
+; CHECK: %[[G:[^ ]*]] = load i8, i8* %a, align 4
 ; CHECK: ret i8 %[[G]]
 
 entry:
@@ -33,10 +30,7 @@
 ; ABORT: call void @__hwasan_loadN(i64 %[[A]], i64 5)
 ; RECOVER: call void @__hwasan_loadN_noabort(i64 %[[A]], i64 5)
 
-; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64
-; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935
-; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i40*
-; CHECK: %[[B:[^ ]*]] = load i40, i40* %[[UNTAGGED_PTR]]
+; CHECK: %[[B:[^ ]*]] = load i40, i40* %a
 ; CHECK: ret i40 %[[B]]
 
 entry:
@@ -51,10 +45,7 @@
 ; ABORT: call void @__hwasan_store1(i64 %[[A]])
 ; RECOVER: call void @__hwasan_store1_noabort(i64 %[[A]])
 
-; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64
-; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935
-; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8*
-; CHECK: store i8 %b, i8* %[[UNTAGGED_PTR]], align 4
+; CHECK: store i8 %b, i8* %a, align 4
 ; CHECK: ret void
 
 entry:
@@ -69,10 +60,7 @@
 ; ABORT: call void @__hwasan_storeN(i64 %[[A]], i64 5)
 ; RECOVER: call void @__hwasan_storeN_noabort(i64 %[[A]], i64 5)
 
-; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64
-; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935
-; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i40*
-; CHECK: store i40 %b, i40* %[[UNTAGGED_PTR]]
+; CHECK: store i40 %b, i40* %a
 ; CHECK: ret void
 
 entry:
@@ -87,10 +75,7 @@
 ; ABORT: call void @__hwasan_storeN(i64 %[[A]], i64 8)
 ; RECOVER: call void @__hwasan_storeN_noabort(i64 %[[A]], i64 8)
 
-; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %a to i64
-; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935
-; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i64*
-; CHECK: store i64 %b, i64* %[[UNTAGGED_PTR]], align 4
+; CHECK: store i64 %b, i64* %a, align 4
 ; CHECK: ret void
 
 entry:
diff --git a/test/Instrumentation/HWAddressSanitizer/X86/kernel.ll b/test/Instrumentation/HWAddressSanitizer/X86/kernel.ll
index 66e13da..7cea081 100644
--- a/test/Instrumentation/HWAddressSanitizer/X86/kernel.ll
+++ b/test/Instrumentation/HWAddressSanitizer/X86/kernel.ll
@@ -18,10 +18,7 @@
 ; ABORT: call void @__hwasan_load1(i64 %[[A]])
 ; RECOVER: call void @__hwasan_load1_noabort(i64 %[[A]])
 
-; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64
-; CHECK: %[[UNTAGGED:[^ ]*]] = or i64 %[[A]], -72057594037927936
-; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8*
-; CHECK: %[[G:[^ ]*]] = load i8, i8* %[[UNTAGGED_PTR]], align 4
+; CHECK: %[[G:[^ ]*]] = load i8, i8* %a, align 4
 ; CHECK: ret i8 %[[G]]
 
 entry:
diff --git a/test/Instrumentation/HWAddressSanitizer/X86/with-calls.ll b/test/Instrumentation/HWAddressSanitizer/X86/with-calls.ll
index c6fce2f..60d2f04 100644
--- a/test/Instrumentation/HWAddressSanitizer/X86/with-calls.ll
+++ b/test/Instrumentation/HWAddressSanitizer/X86/with-calls.ll
@@ -13,10 +13,7 @@
 ; ABORT: call void @__hwasan_load1(i64 %[[A]])
 ; RECOVER: call void @__hwasan_load1_noabort(i64 %[[A]])
 
-; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64
-; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935
-; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8*
-; CHECK: %[[B:[^ ]*]] = load i8, i8* %[[UNTAGGED_PTR]]
+; CHECK: %[[B:[^ ]*]] = load i8, i8* %a
 ; CHECK: ret i8 %[[B]]
 
 entry:
@@ -31,10 +28,7 @@
 ; ABORT: call void @__hwasan_loadN(i64 %[[A]], i64 5)
 ; RECOVER: call void @__hwasan_loadN_noabort(i64 %[[A]], i64 5)
 
-; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64
-; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935
-; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i40*
-; CHECK: %[[B:[^ ]*]] = load i40, i40* %[[UNTAGGED_PTR]]
+; CHECK: %[[B:[^ ]*]] = load i40, i40* %a
 ; CHECK: ret i40 %[[B]]
 
 entry:
@@ -49,10 +43,7 @@
 ; ABORT: call void @__hwasan_store1(i64 %[[A]])
 ; RECOVER: call void @__hwasan_store1_noabort(i64 %[[A]])
 
-; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64
-; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935
-; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8*
-; CHECK: store i8 %b, i8* %[[UNTAGGED_PTR]]
+; CHECK: store i8 %b, i8* %a
 ; CHECK: ret void
 
 entry:
@@ -67,10 +58,7 @@
 ; ABORT: call void @__hwasan_storeN(i64 %[[A]], i64 5)
 ; RECOVER: call void @__hwasan_storeN_noabort(i64 %[[A]], i64 5)
 
-; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64
-; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935
-; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i40*
-; CHECK: store i40 %b, i40* %[[UNTAGGED_PTR]]
+; CHECK: store i40 %b, i40* %a
 ; CHECK: ret void
 
 entry: