forked from OSchip/llvm-project
AArch64: Add a tagged-globals backend feature.
This feature instructs the backend to allow locally defined global variable addresses to contain a pointer tag in bits 56-63 that will be ignored by the hardware (i.e. TBI), but may be used by an instrumentation pass such as HWASAN. It works by adding a MOVK instruction to the regular ADRP/ADD sequence that sets bits 48-63 to the corresponding bits of the global, with the linker bounds check disabled on the ADRP instruction to prevent the tag from causing a link failure. This implementation of the feature omits the MOVK when loading from or storing to a global, which is sufficient for TBI. If the same approach is extended to MTE, assuming that 0 is not configured as a catch-all tag, we will most likely also need the MOVK in this case in order to avoid a tag mismatch. Differential Revision: https://reviews.llvm.org/D65364 llvm-svn: 367475
This commit is contained in:
parent
33773d5cfc
commit
09f39967a2
|
@ -355,6 +355,11 @@ def FeatureETE : SubtargetFeature<"ete", "HasETE",
|
|||
def FeatureTME : SubtargetFeature<"tme", "HasTME",
|
||||
"true", "Enable Transactional Memory Extension" >;
|
||||
|
||||
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">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Architectures.
|
||||
//
|
||||
|
|
|
@ -539,6 +539,23 @@ bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB,
|
|||
BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg)
|
||||
.add(MI.getOperand(1));
|
||||
|
||||
if (MI.getOperand(1).getTargetFlags() & AArch64II::MO_TAGGED) {
|
||||
// MO_TAGGED on the page indicates a tagged address. Set the tag now.
|
||||
// We do so by creating a MOVK that sets bits 48-63 of the register to
|
||||
// (global address + 0x100000000 - PC) >> 48. This assumes that we're in
|
||||
// the small code model so we can assume a binary size of <= 4GB, which
|
||||
// makes the untagged PC relative offset positive. The binary must also be
|
||||
// loaded into address range [0, 2^48). Both of these properties need to
|
||||
// be ensured at runtime when using tagged addresses.
|
||||
auto Tag = MI.getOperand(1);
|
||||
Tag.setTargetFlags(AArch64II::MO_PREL | AArch64II::MO_G3);
|
||||
Tag.setOffset(0x100000000);
|
||||
BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MOVKXi), DstReg)
|
||||
.addReg(DstReg)
|
||||
.add(Tag)
|
||||
.addImm(48);
|
||||
}
|
||||
|
||||
MachineInstrBuilder MIB2 =
|
||||
BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADDXri))
|
||||
.add(MI.getOperand(0))
|
||||
|
|
|
@ -4739,7 +4739,8 @@ AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
|
|||
{MO_COFFSTUB, "aarch64-coffstub"},
|
||||
{MO_GOT, "aarch64-got"}, {MO_NC, "aarch64-nc"},
|
||||
{MO_S, "aarch64-s"}, {MO_TLS, "aarch64-tls"},
|
||||
{MO_DLLIMPORT, "aarch64-dllimport"}};
|
||||
{MO_DLLIMPORT, "aarch64-dllimport"},
|
||||
{MO_PREL, "aarch64-prel"}};
|
||||
return makeArrayRef(TargetFlags);
|
||||
}
|
||||
|
||||
|
|
|
@ -148,6 +148,8 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
|
|||
RefFlags |= AArch64MCExpr::VK_TLSDESC;
|
||||
break;
|
||||
}
|
||||
} else if (MO.getTargetFlags() & AArch64II::MO_PREL) {
|
||||
RefFlags |= AArch64MCExpr::VK_PREL;
|
||||
} else {
|
||||
// No modifier means this is a generic reference, classified as absolute for
|
||||
// the cases where it matters (:abs_g0: etc).
|
||||
|
|
|
@ -229,6 +229,13 @@ AArch64Subtarget::ClassifyGlobalReference(const GlobalValue *GV,
|
|||
GV->hasExternalWeakLinkage())
|
||||
return AArch64II::MO_GOT;
|
||||
|
||||
// References to tagged globals are marked with MO_NC | MO_TAGGED to indicate
|
||||
// that their nominal addresses are tagged and outside of the code model. In
|
||||
// AArch64ExpandPseudo::expandMI we emit an additional instruction to set the
|
||||
// tag if necessary based on MO_TAGGED.
|
||||
if (AllowTaggedGlobals && !isa<FunctionType>(GV->getValueType()))
|
||||
return AArch64II::MO_NC | AArch64II::MO_TAGGED;
|
||||
|
||||
return AArch64II::MO_NO_FLAG;
|
||||
}
|
||||
|
||||
|
|
|
@ -191,6 +191,7 @@ protected:
|
|||
bool UseEL1ForTP = false;
|
||||
bool UseEL2ForTP = false;
|
||||
bool UseEL3ForTP = false;
|
||||
bool AllowTaggedGlobals = false;
|
||||
uint8_t MaxInterleaveFactor = 2;
|
||||
uint8_t VectorInsertExtractBaseCost = 3;
|
||||
uint16_t CacheLineSize = 0;
|
||||
|
|
|
@ -627,6 +627,14 @@ namespace AArch64II {
|
|||
/// MO_S - Indicates that the bits of the symbol operand represented by
|
||||
/// MO_G0 etc are signed.
|
||||
MO_S = 0x100,
|
||||
|
||||
/// MO_PREL - Indicates that the bits of the symbol operand represented by
|
||||
/// MO_G0 etc are PC relative.
|
||||
MO_PREL = 0x200,
|
||||
|
||||
/// MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag
|
||||
/// in bits 56-63.
|
||||
MO_TAGGED = 0x400,
|
||||
};
|
||||
} // end namespace AArch64II
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
; RUN: llc < %s | FileCheck %s
|
||||
|
||||
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
|
||||
target triple = "aarch64-unknown-linux-android"
|
||||
|
||||
@global = external hidden global i32
|
||||
declare void @func()
|
||||
|
||||
define i32* @global_addr() #0 {
|
||||
; CHECK: global_addr:
|
||||
; CHECK: adrp x0, :pg_hi21_nc:global
|
||||
; CHECK: movk x0, #:prel_g3:global+4294967296
|
||||
; CHECK: add x0, x0, :lo12:global
|
||||
ret i32* @global
|
||||
}
|
||||
|
||||
define i32 @global_load() #0 {
|
||||
; CHECK: global_load:
|
||||
; CHECK: adrp x8, :pg_hi21_nc:global
|
||||
; CHECK: ldr w0, [x8, :lo12:global]
|
||||
%load = load i32, i32* @global
|
||||
ret i32 %load
|
||||
}
|
||||
|
||||
define void ()* @func_addr() #0 {
|
||||
; CHECK: func_addr:
|
||||
; CHECK: adrp x0, func
|
||||
; CHECK: add x0, x0, :lo12:func
|
||||
ret void ()* @func
|
||||
}
|
||||
|
||||
attributes #0 = { "target-features"="+tagged-globals" }
|
Loading…
Reference in New Issue