Skip to content

Commit

Permalink
[x86] Implement a tagged-globals backend feature.
Browse files Browse the repository at this point in the history
The feature tells the backend to allow tags in the upper bits of global
variable addresses.  These tags will be ignored by upcoming CPUs with
the Intel LAM feature but may be used in instrumentation passes (e.g.,
HWASan).

This patch implements the feature by using @GOTPCREL relocations instead
of direct references to the locally defined global.  Thus the full
tagged address can be loaded by a single instruction:
  movq global@GOTPCREL(%rip), %rax

Reviewed By: eugenis

Differential Revision: https://reviews.llvm.org/D111343
  • Loading branch information
morehouse committed Oct 18, 2021
1 parent 04dc687 commit 431a5d8
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 0 deletions.
7 changes: 7 additions & 0 deletions llvm/lib/Target/X86/X86.td
Expand Up @@ -374,6 +374,13 @@ def FeatureLVILoadHardening
"Insert LFENCE instructions to prevent data speculatively injected "
"into loads from being used maliciously.">;

def FeatureTaggedGlobals
: SubtargetFeature<
"tagged-globals", "AllowTaggedGlobals", "true",
"Use an instruction sequence for taking the address of a global "
"that allows a memory tag in the upper address bits. Currently "
"also requires -mrelax-relocations=no to work properly.">;

//===----------------------------------------------------------------------===//
// X86 Subtarget Tuning features
//===----------------------------------------------------------------------===//
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/X86/X86Subtarget.cpp
Expand Up @@ -67,6 +67,13 @@ X86Subtarget::classifyGlobalReference(const GlobalValue *GV) const {

unsigned char
X86Subtarget::classifyLocalReference(const GlobalValue *GV) const {
// Tagged globals have non-zero upper bits, which makes direct references
// require a 64-bit immediate. On the small code model this causes relocation
// errors, so we go through the GOT instead.
if (AllowTaggedGlobals && TM.getCodeModel() == CodeModel::Small &&
!isa_and_nonnull<Function>(GV))
return X86II::MO_GOTPCREL;

// If we're not PIC, it's not very interesting.
if (!isPositionIndependent())
return X86II::MO_NO_FLAG;
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/X86/X86Subtarget.h
Expand Up @@ -476,6 +476,10 @@ class X86Subtarget final : public X86GenSubtargetInfo {
/// loads from being used maliciously.
bool UseLVILoadHardening = false;

/// Use an instruction sequence for taking the address of a global that allows
/// a memory tag in the upper address bits.
bool AllowTaggedGlobals = false;

/// Use software floating point for code generation.
bool UseSoftFloat = false;

Expand Down Expand Up @@ -795,6 +799,7 @@ class X86Subtarget final : public X86GenSubtargetInfo {
bool preferMaskRegisters() const { return PreferMaskRegisters; }
bool useGLMDivSqrtCosts() const { return UseGLMDivSqrtCosts; }
bool useLVIControlFlowIntegrity() const { return UseLVIControlFlowIntegrity; }
bool allowTaggedGlobals() const { return AllowTaggedGlobals; }
bool useLVILoadHardening() const { return UseLVILoadHardening; }
bool useSpeculativeExecutionSideEffectSuppression() const {
return UseSpeculativeExecutionSideEffectSuppression;
Expand Down
45 changes: 45 additions & 0 deletions llvm/test/CodeGen/X86/tagged-globals-pic.ll
@@ -0,0 +1,45 @@
; RUN: llc --relocation-model=pic < %s | FileCheck %s

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@global = external global i32
declare void @func()

define i32* @global_addr() #0 {
; CHECK-LABEL: global_addr:
; CHECK: movq global@GOTPCREL(%rip), %rax
; CHECK: retq

ret i32* @global
}

define i32 @global_load() #0 {
; CHECK-LABEL: global_load:
; CHECK: movq global@GOTPCREL(%rip), [[REG:%r[0-9a-z]+]]
; CHECK: movl ([[REG]]), %eax
; CHECK: retq

%load = load i32, i32* @global
ret i32 %load
}

define void @global_store() #0 {
; CHECK-LABEL: global_store:
; CHECK: movq global@GOTPCREL(%rip), [[REG:%r[0-9a-z]+]]
; CHECK: movl $0, ([[REG]])
; CHECK: retq

store i32 0, i32* @global
ret void
}

define void ()* @func_addr() #0 {
; CHECK-LABEL: func_addr:
; CHECK: movq func@GOTPCREL(%rip), %rax
; CHECK: retq

ret void ()* @func
}

attributes #0 = { "target-features"="+tagged-globals" }
45 changes: 45 additions & 0 deletions llvm/test/CodeGen/X86/tagged-globals-static.ll
@@ -0,0 +1,45 @@
; RUN: llc --relocation-model=static < %s | FileCheck %s

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@global = external dso_local global i32
declare dso_local void @func()

define i32* @global_addr() #0 {
; CHECK-LABEL: global_addr:
; CHECK: movq global@GOTPCREL(%rip), %rax
; CHECK: retq

ret i32* @global
}

define i32 @global_load() #0 {
; CHECK-LABEL: global_load:
; CHECK: movq global@GOTPCREL(%rip), [[REG:%r[0-9a-z]+]]
; CHECK: movl ([[REG]]), %eax
; CHECK: retq

%load = load i32, i32* @global
ret i32 %load
}

define void @global_store() #0 {
; CHECK-LABEL: global_store:
; CHECK: movq global@GOTPCREL(%rip), [[REG:%r[0-9a-z]+]]
; CHECK: movl $0, ([[REG]])
; CHECK: retq

store i32 0, i32* @global
ret void
}

define void ()* @func_addr() #0 {
; CHECK-LABEL: func_addr:
; CHECK: movl $func, %eax
; CHECK: retq

ret void ()* @func
}

attributes #0 = { "target-features"="+tagged-globals" }

0 comments on commit 431a5d8

Please sign in to comment.