[clang] [clang-tools-extra] [PAC][clang] Define `PointerAuthQualifier` and `PointerAuthenticationMode` (PR #84384)
Daniil Kovalev via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 23 13:04:25 PDT 2024
https://github.com/kovdan01 updated https://github.com/llvm/llvm-project/pull/84384
>From ef23d427b48687b62da9e1062886ddfcc1649b6a Mon Sep 17 00:00:00 2001
From: John McCall <rjmccall at apple.com>
Date: Mon, 16 Dec 2019 20:31:25 -0500
Subject: [PATCH 1/9] Abstract serialization fixes for the Apple Clang changes.
---
clang/include/clang/AST/AbstractBasicReader.h | 4 ++--
clang/include/clang/AST/AbstractBasicWriter.h | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h
index 1f2797cc701458..ab036f1d445acc 100644
--- a/clang/include/clang/AST/AbstractBasicReader.h
+++ b/clang/include/clang/AST/AbstractBasicReader.h
@@ -213,9 +213,9 @@ class DataStreamBasicReader : public BasicReaderBase<Impl> {
}
Qualifiers readQualifiers() {
- static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t),
+ static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint64_t),
"update this if the value size changes");
- uint32_t value = asImpl().readUInt32();
+ uint64_t value = asImpl().readUInt64();
return Qualifiers::fromOpaqueValue(value);
}
diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h
index 07afa388de2c17..8e42fcaad1d388 100644
--- a/clang/include/clang/AST/AbstractBasicWriter.h
+++ b/clang/include/clang/AST/AbstractBasicWriter.h
@@ -196,9 +196,9 @@ class DataStreamBasicWriter : public BasicWriterBase<Impl> {
}
void writeQualifiers(Qualifiers value) {
- static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t),
+ static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint64_t),
"update this if the value size changes");
- asImpl().writeUInt32(value.getAsOpaqueValue());
+ asImpl().writeUInt64(value.getAsOpaqueValue());
}
void writeExceptionSpecInfo(
>From 9e296a1a69158419960c265f12f52523db0c8e2a Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 7 Mar 2024 15:34:24 +0300
Subject: [PATCH 2/9] [clang] Define `PointerAuthenticationMode` enum
---
clang/include/clang/Basic/LangOptions.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 862952d336ef31..6fe7472d8ad0ca 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -57,6 +57,13 @@ enum class ShaderStage {
Invalid,
};
+enum class PointerAuthenticationMode : unsigned {
+ None,
+ Strip,
+ SignAndStrip,
+ SignAndAuth
+};
+
/// Bitfields of LangOptions, split out from LangOptions in order to ensure that
/// this large collection of bitfields is a trivial class type.
class LangOptionsBase {
>From 71d7760aa9cc459d7bc0365fa079f64cb5704c96 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 7 Mar 2024 15:31:03 +0300
Subject: [PATCH 3/9] [clang] Define `PointerAuthQualifier` class
Includes changes from the following commits from the branch
https://github.com/ahmedbougacha/llvm-project/tree/eng/arm64e-upstream-llvmorg
- Initial support https://github.com/ahmedbougacha/llvm-project/commit/cc7ba7eb1814e9b254c7d94aa0b78cb0e21acfc5
- ObjC isa signing https://github.com/ahmedbougacha/llvm-project/commit/c9ce0d408f1d9aeffc7b86256334220aec6de5a3
Also applies a fix from https://github.com/access-softek/llvm-project/pull/75
Co-authored-by: Ahmed Bougacha <ahmed at bougacha.org>
---
clang/include/clang/AST/Type.h | 215 +++++++++++++++++-
.../include/clang/Basic/PointerAuthOptions.h | 23 ++
2 files changed, 227 insertions(+), 11 deletions(-)
create mode 100644 clang/include/clang/Basic/PointerAuthOptions.h
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 1942b0e67f65a3..1741a3017f7280 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -25,8 +25,10 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/PointerAuthOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/Visibility.h"
@@ -138,6 +140,165 @@ using CanQualType = CanQual<Type>;
#define TYPE(Class, Base) class Class##Type;
#include "clang/AST/TypeNodes.inc"
+/// Pointer-authentication qualifiers.
+class PointerAuthQualifier {
+ enum : uint32_t {
+ EnabledShift = 0,
+ EnabledBits = 1,
+ EnabledMask = 1 << EnabledShift,
+ AddressDiscriminatedShift = EnabledShift + EnabledBits,
+ AddressDiscriminatedBits = 1,
+ AddressDiscriminatedMask = 1 << AddressDiscriminatedShift,
+ AuthenticationModeShift =
+ AddressDiscriminatedShift + AddressDiscriminatedBits,
+ AuthenticationModeBits = 2,
+ AuthenticationModeMask = ((1 << AuthenticationModeBits) - 1)
+ << AuthenticationModeShift,
+ IsaPointerShift = AuthenticationModeShift + AuthenticationModeBits,
+ IsaPointerBits = 1,
+ IsaPointerMask = ((1 << IsaPointerBits) - 1) << IsaPointerShift,
+ AuthenticatesNullValuesShift = IsaPointerShift + IsaPointerBits,
+ AuthenticatesNullValuesBits = 1,
+ AuthenticatesNullValuesMask = ((1 << AuthenticatesNullValuesBits) - 1)
+ << AuthenticatesNullValuesShift,
+ KeyShift = AuthenticatesNullValuesShift + AuthenticatesNullValuesBits,
+ KeyBits = 10,
+ KeyMask = ((1 << KeyBits) - 1) << KeyShift,
+ DiscriminatorShift = KeyShift + KeyBits,
+ DiscriminatorBits = 16,
+ DiscriminatorMask = ((1u << DiscriminatorBits) - 1) << DiscriminatorShift,
+ };
+
+ // bits: |0 |1 |2..3 |4 |
+ // |Enabled|Address|AuthenticationMode|ISA pointer|
+ // bits: |5 |6..15| 16...31 |
+ // |AuthenticatesNull|Key |Discriminator|
+ uint32_t Data;
+
+ static_assert((EnabledBits + AddressDiscriminatedBits +
+ AuthenticationModeBits + IsaPointerBits +
+ AuthenticatesNullValuesBits + KeyBits + DiscriminatorBits) ==
+ 32,
+ "PointerAuthQualifier should be exactly 32 bits");
+ static_assert((EnabledMask + AddressDiscriminatedMask +
+ AuthenticationModeMask + IsaPointerMask +
+ AuthenticatesNullValuesMask + KeyMask + DiscriminatorMask) ==
+ 0xFFFFFFFF,
+ "All masks should cover the entire bits");
+ static_assert((EnabledMask ^ AddressDiscriminatedMask ^
+ AuthenticationModeMask ^ IsaPointerMask ^
+ AuthenticatesNullValuesMask ^ KeyMask ^ DiscriminatorMask) ==
+ 0xFFFFFFFF,
+ "All masks should cover the entire bits");
+
+ PointerAuthQualifier(unsigned key, bool isAddressDiscriminated,
+ unsigned extraDiscriminator,
+ PointerAuthenticationMode authenticationMode,
+ bool isIsaPointer, bool authenticatesNullValues)
+ : Data(EnabledMask |
+ (isAddressDiscriminated
+ ? static_cast<uint32_t>(AddressDiscriminatedMask)
+ : 0) |
+ (key << KeyShift) |
+ (unsigned(authenticationMode) << AuthenticationModeShift) |
+ (extraDiscriminator << DiscriminatorShift) |
+ (isIsaPointer << IsaPointerShift) |
+ (authenticatesNullValues << AuthenticatesNullValuesShift)) {
+ assert(key <= KeyNoneInternal);
+ assert(extraDiscriminator <= MaxDiscriminator);
+ }
+
+public:
+ enum {
+ KeyNoneInternal = (1u << KeyBits) - 1,
+
+ /// The maximum supported pointer-authentication key.
+ MaxKey = KeyNoneInternal - 1,
+
+ /// The maximum supported pointer-authentication discriminator.
+ MaxDiscriminator = (1u << DiscriminatorBits) - 1
+ };
+
+public:
+ PointerAuthQualifier() : Data(0) {}
+
+ static PointerAuthQualifier
+ Create(int key, bool isAddressDiscriminated, unsigned extraDiscriminator,
+ PointerAuthenticationMode authenticationMode, bool isIsaPointer,
+ bool authenticatesNullValues) {
+ if (key == PointerAuthKeyNone)
+ key = KeyNoneInternal;
+ assert((key >= 0 && key <= KeyNoneInternal) && "out-of-range key value");
+ return PointerAuthQualifier(key, isAddressDiscriminated, extraDiscriminator,
+ authenticationMode, isIsaPointer,
+ authenticatesNullValues);
+ }
+
+ bool isPresent() const {
+ return getAuthenticationMode() != PointerAuthenticationMode::None;
+ }
+
+ explicit operator bool() const { return isPresent(); }
+
+ unsigned getKey() const {
+ assert(isPresent());
+ return (Data & KeyMask) >> KeyShift;
+ }
+
+ bool hasKeyNone() const { return isPresent() && getKey() == KeyNoneInternal; }
+
+ bool isAddressDiscriminated() const {
+ assert(isPresent());
+ return (Data & AddressDiscriminatedMask) >> AddressDiscriminatedShift;
+ }
+
+ unsigned getExtraDiscriminator() const {
+ assert(isPresent());
+ return (Data >> DiscriminatorShift);
+ }
+
+ PointerAuthenticationMode getAuthenticationMode() const {
+ return PointerAuthenticationMode((Data & AuthenticationModeMask) >>
+ AuthenticationModeShift);
+ }
+
+ bool isIsaPointer() const {
+ assert(isPresent());
+ return (Data & IsaPointerMask) >> IsaPointerShift;
+ }
+
+ bool authenticatesNullValues() const {
+ assert(isPresent());
+ return (Data & AuthenticatesNullValuesMask) >> AuthenticatesNullValuesShift;
+ }
+
+ PointerAuthQualifier withoutKeyNone() const {
+ return hasKeyNone() ? PointerAuthQualifier() : *this;
+ }
+
+ friend bool operator==(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) {
+ return Lhs.Data == Rhs.Data;
+ }
+ friend bool operator!=(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) {
+ return Lhs.Data != Rhs.Data;
+ }
+
+ bool isEquivalent(PointerAuthQualifier Other) const {
+ return withoutKeyNone() == Other.withoutKeyNone();
+ }
+
+ uint32_t getAsOpaqueValue() const { return Data; }
+
+ // Deserialize pointer-auth qualifiers from an opaque representation.
+ static PointerAuthQualifier fromOpaqueValue(uint32_t opaque) {
+ PointerAuthQualifier result;
+ result.Data = opaque;
+ return result;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Data); }
+};
+
/// The collection of all-type qualifiers we support.
/// Clang supports five independent qualifiers:
/// * C99: const, volatile, and restrict
@@ -193,19 +354,27 @@ class Qualifiers {
FastMask = (1 << FastWidth) - 1
};
+ Qualifiers() : Mask(0), PtrAuth() {}
+
/// Returns the common set of qualifiers while removing them from
/// the given sets.
static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) {
+ Qualifiers Q;
+ if (L.getPointerAuth().isEquivalent(R.getPointerAuth())) {
+ Q.setPointerAuth(L.getPointerAuth().withoutKeyNone());
+ PointerAuthQualifier Empty;
+ L.setPointerAuth(Empty);
+ R.setPointerAuth(Empty);
+ }
+
// If both are only CVR-qualified, bit operations are sufficient.
if (!(L.Mask & ~CVRMask) && !(R.Mask & ~CVRMask)) {
- Qualifiers Q;
Q.Mask = L.Mask & R.Mask;
L.Mask &= ~Q.Mask;
R.Mask &= ~Q.Mask;
return Q;
}
- Qualifiers Q;
unsigned CommonCRV = L.getCVRQualifiers() & R.getCVRQualifiers();
Q.addCVRQualifiers(CommonCRV);
L.removeCVRQualifiers(CommonCRV);
@@ -250,15 +419,16 @@ class Qualifiers {
}
// Deserialize qualifiers from an opaque representation.
- static Qualifiers fromOpaqueValue(unsigned opaque) {
+ static Qualifiers fromOpaqueValue(uint64_t opaque) {
Qualifiers Qs;
- Qs.Mask = opaque;
+ Qs.Mask = uint32_t(opaque);
+ Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue(uint32_t(opaque >> 32));
return Qs;
}
// Serialize these qualifiers into an opaque representation.
- unsigned getAsOpaqueValue() const {
- return Mask;
+ uint64_t getAsOpaqueValue() const {
+ return uint64_t(Mask) | (uint64_t(PtrAuth.getAsOpaqueValue()) << 32);
}
bool hasConst() const { return Mask & Const; }
@@ -406,6 +576,10 @@ class Qualifiers {
setAddressSpace(space);
}
+ PointerAuthQualifier getPointerAuth() const { return PtrAuth; }
+ void setPointerAuth(PointerAuthQualifier q) { PtrAuth = q; }
+ void removePtrAuth() { PtrAuth = PointerAuthQualifier(); }
+
// Fast qualifiers are those that can be allocated directly
// on a QualType object.
bool hasFastQualifiers() const { return getFastQualifiers(); }
@@ -428,7 +602,7 @@ class Qualifiers {
/// Return true if the set contains any qualifiers which require an ExtQuals
/// node to be allocated.
- bool hasNonFastQualifiers() const { return Mask & ~FastMask; }
+ bool hasNonFastQualifiers() const { return (Mask & ~FastMask) || PtrAuth; }
Qualifiers getNonFastQualifiers() const {
Qualifiers Quals = *this;
Quals.setFastQualifiers(0);
@@ -436,8 +610,8 @@ class Qualifiers {
}
/// Return true if the set contains any qualifiers.
- bool hasQualifiers() const { return Mask; }
- bool empty() const { return !Mask; }
+ bool hasQualifiers() const { return Mask || PtrAuth; }
+ bool empty() const { return !hasQualifiers(); }
/// Add the qualifiers from the given set to this set.
void addQualifiers(Qualifiers Q) {
@@ -454,6 +628,9 @@ class Qualifiers {
if (Q.hasObjCLifetime())
addObjCLifetime(Q.getObjCLifetime());
}
+
+ if (Q.PtrAuth)
+ PtrAuth = Q.PtrAuth;
}
/// Remove the qualifiers from the given set from this set.
@@ -471,6 +648,9 @@ class Qualifiers {
if (getAddressSpace() == Q.getAddressSpace())
removeAddressSpace();
}
+
+ if (PtrAuth == Q.PtrAuth)
+ PtrAuth = PointerAuthQualifier();
}
/// Add the qualifiers from the given set to this set, given that
@@ -482,7 +662,10 @@ class Qualifiers {
!hasObjCGCAttr() || !qs.hasObjCGCAttr());
assert(getObjCLifetime() == qs.getObjCLifetime() ||
!hasObjCLifetime() || !qs.hasObjCLifetime());
+ assert(!PtrAuth || !qs.PtrAuth || PtrAuth == qs.PtrAuth);
Mask |= qs.Mask;
+ if (qs.PtrAuth)
+ PtrAuth = qs.PtrAuth;
}
/// Returns true if address space A is equal to or a superset of B.
@@ -535,6 +718,8 @@ class Qualifiers {
// be changed.
(getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() ||
!other.hasObjCGCAttr()) &&
+ // Pointer-auth qualifiers must match exactly.
+ PtrAuth == other.PtrAuth &&
// ObjC lifetime qualifiers must match exactly.
getObjCLifetime() == other.getObjCLifetime() &&
// CVR qualifiers may subset.
@@ -567,8 +752,12 @@ class Qualifiers {
/// another set of qualifiers, not considering qualifier compatibility.
bool isStrictSupersetOf(Qualifiers Other) const;
- bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
- bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
+ bool operator==(Qualifiers Other) const {
+ return Mask == Other.Mask && PtrAuth == Other.PtrAuth;
+ }
+ bool operator!=(Qualifiers Other) const {
+ return Mask != Other.Mask || PtrAuth != Other.PtrAuth;
+ }
explicit operator bool() const { return hasQualifiers(); }
@@ -606,6 +795,7 @@ class Qualifiers {
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddInteger(Mask);
+ PtrAuth.Profile(ID);
}
private:
@@ -613,6 +803,9 @@ class Qualifiers {
// |C R V|U|GCAttr|Lifetime|AddressSpace|
uint32_t Mask = 0;
+ PointerAuthQualifier PtrAuth;
+ static_assert(sizeof(PointerAuthQualifier) == sizeof(uint32_t),
+ "PointerAuthQualifier must be 32 bits");
static const uint32_t UMask = 0x8;
static const uint32_t UShift = 3;
static const uint32_t GCAttrMask = 0x30;
diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h
new file mode 100644
index 00000000000000..c69847ac704a41
--- /dev/null
+++ b/clang/include/clang/Basic/PointerAuthOptions.h
@@ -0,0 +1,23 @@
+//===--- PointerAuthOptions.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines options for configuring pointer-auth technologies
+// like ARMv8.3.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
+#define LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
+
+namespace clang {
+
+constexpr int PointerAuthKeyNone = -1;
+
+} // end namespace clang
+
+#endif
>From cbfde2159c0af8b472ab296c37dc1adf9fc4ad91 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Thu, 7 Mar 2024 17:54:20 +0300
Subject: [PATCH 4/9] [clang] Support `PointerAuthQualifier` in `QualType`
---
clang/include/clang/AST/ASTContext.h | 10 ++++++++++
clang/include/clang/AST/Type.h | 4 ++++
2 files changed, 14 insertions(+)
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index ff6b64c7f72d57..4fd214592d1f27 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2182,6 +2182,16 @@ class ASTContext : public RefCountedBase<ASTContext> {
return getQualifiedType(type.getUnqualifiedType(), Qs);
}
+ /// \brief Return a type with the given __ptrauth qualifier.
+ QualType getPointerAuthType(QualType type, PointerAuthQualifier pointerAuth) {
+ assert(!type.getPointerAuth());
+ assert(pointerAuth);
+
+ Qualifiers qs;
+ qs.setPointerAuth(pointerAuth);
+ return getQualifiedType(type, qs);
+ }
+
unsigned char getFixedPointScale(QualType Ty) const;
unsigned char getFixedPointIBits(QualType Ty) const;
llvm::FixedPointSemantics getFixedPointSemantics(QualType Ty) const;
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 1741a3017f7280..48a51dd851ac36 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1434,6 +1434,10 @@ class QualType {
// true when Type is objc's weak and weak is enabled but ARC isn't.
bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const;
+ PointerAuthQualifier getPointerAuth() const {
+ return getQualifiers().getPointerAuth();
+ }
+
enum PrimitiveDefaultInitializeKind {
/// The type does not fall into any of the following categories. Note that
/// this case is zero-valued so that values of this enum can be used as a
>From 3517033bd3a8b676abd649562bcfc7eb4d278d09 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Mon, 8 Apr 2024 18:12:18 +0300
Subject: [PATCH 5/9] Address review comments & enhance code style
---
clang/include/clang/AST/ASTContext.h | 10 ++--
clang/include/clang/AST/Type.h | 57 ++++++++++---------
.../include/clang/Basic/PointerAuthOptions.h | 2 +-
3 files changed, 36 insertions(+), 33 deletions(-)
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index f77726f332ea03..eeac5961b415b8 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2197,13 +2197,13 @@ class ASTContext : public RefCountedBase<ASTContext> {
}
/// \brief Return a type with the given __ptrauth qualifier.
- QualType getPointerAuthType(QualType type, PointerAuthQualifier pointerAuth) {
- assert(!type.getPointerAuth());
- assert(pointerAuth);
+ QualType getPointerAuthType(QualType Ty, PointerAuthQualifier PointerAuth) {
+ assert(!Ty.getPointerAuth());
+ assert(PointerAuth);
Qualifiers qs;
- qs.setPointerAuth(pointerAuth);
- return getQualifiedType(type, qs);
+ qs.setPointerAuth(PointerAuth);
+ return getQualifiedType(Ty, qs);
}
unsigned char getFixedPointScale(QualType Ty) const;
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index e5f11174cca9bc..4dd532c2420206 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -176,6 +176,8 @@ class PointerAuthQualifier {
// |AuthenticatesNull|Key |Discriminator|
uint32_t Data;
+ // The following static assertions check that each of the 32 bits is present
+ // exactly in one of the constants.
static_assert((EnabledBits + AddressDiscriminatedBits +
AuthenticationModeBits + IsaPointerBits +
AuthenticatesNullValuesBits + KeyBits + DiscriminatorBits) ==
@@ -192,21 +194,22 @@ class PointerAuthQualifier {
0xFFFFFFFF,
"All masks should cover the entire bits");
- PointerAuthQualifier(unsigned key, bool isAddressDiscriminated,
- unsigned extraDiscriminator,
- PointerAuthenticationMode authenticationMode,
- bool isIsaPointer, bool authenticatesNullValues)
+ PointerAuthQualifier(unsigned Key, bool IsAddressDiscriminated,
+ unsigned ExtraDiscriminator,
+ PointerAuthenticationMode AuthenticationMode,
+ bool IsIsaPointer, bool AuthenticatesNullValues)
: Data(EnabledMask |
- (isAddressDiscriminated
- ? static_cast<uint32_t>(AddressDiscriminatedMask)
+ (IsAddressDiscriminated
+ ? llvm::to_underlying(AddressDiscriminatedMask)
: 0) |
- (key << KeyShift) |
- (unsigned(authenticationMode) << AuthenticationModeShift) |
- (extraDiscriminator << DiscriminatorShift) |
- (isIsaPointer << IsaPointerShift) |
- (authenticatesNullValues << AuthenticatesNullValuesShift)) {
- assert(key <= KeyNoneInternal);
- assert(extraDiscriminator <= MaxDiscriminator);
+ (Key << KeyShift) |
+ (llvm::to_underlying(AuthenticationMode)
+ << AuthenticationModeShift) |
+ (ExtraDiscriminator << DiscriminatorShift) |
+ (IsIsaPointer << IsaPointerShift) |
+ (AuthenticatesNullValues << AuthenticatesNullValuesShift)) {
+ assert(Key <= KeyNoneInternal);
+ assert(ExtraDiscriminator <= MaxDiscriminator);
}
public:
@@ -224,15 +227,15 @@ class PointerAuthQualifier {
PointerAuthQualifier() : Data(0) {}
static PointerAuthQualifier
- Create(int key, bool isAddressDiscriminated, unsigned extraDiscriminator,
- PointerAuthenticationMode authenticationMode, bool isIsaPointer,
- bool authenticatesNullValues) {
- if (key == PointerAuthKeyNone)
- key = KeyNoneInternal;
- assert((key >= 0 && key <= KeyNoneInternal) && "out-of-range key value");
- return PointerAuthQualifier(key, isAddressDiscriminated, extraDiscriminator,
- authenticationMode, isIsaPointer,
- authenticatesNullValues);
+ Create(unsigned Key, bool IsAddressDiscriminated, unsigned ExtraDiscriminator,
+ PointerAuthenticationMode AuthenticationMode, bool IsIsaPointer,
+ bool AuthenticatesNullValues) {
+ if (Key == PointerAuthKeyNone)
+ Key = KeyNoneInternal;
+ assert(Key <= KeyNoneInternal && "out-of-range key value");
+ return PointerAuthQualifier(Key, IsAddressDiscriminated, ExtraDiscriminator,
+ AuthenticationMode, IsIsaPointer,
+ AuthenticatesNullValues);
}
bool isPresent() const {
@@ -291,9 +294,9 @@ class PointerAuthQualifier {
uint32_t getAsOpaqueValue() const { return Data; }
// Deserialize pointer-auth qualifiers from an opaque representation.
- static PointerAuthQualifier fromOpaqueValue(uint32_t opaque) {
+ static PointerAuthQualifier fromOpaqueValue(uint32_t Opaque) {
PointerAuthQualifier result;
- result.Data = opaque;
+ result.Data = Opaque;
return result;
}
@@ -420,10 +423,10 @@ class Qualifiers {
}
// Deserialize qualifiers from an opaque representation.
- static Qualifiers fromOpaqueValue(uint64_t opaque) {
+ static Qualifiers fromOpaqueValue(uint64_t Opaque) {
Qualifiers Qs;
- Qs.Mask = uint32_t(opaque);
- Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue(uint32_t(opaque >> 32));
+ Qs.Mask = uint32_t(Opaque);
+ Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue(uint32_t(Opaque >> 32));
return Qs;
}
diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h
index c69847ac704a41..e5cdcc31ebfb70 100644
--- a/clang/include/clang/Basic/PointerAuthOptions.h
+++ b/clang/include/clang/Basic/PointerAuthOptions.h
@@ -16,7 +16,7 @@
namespace clang {
-constexpr int PointerAuthKeyNone = -1;
+constexpr unsigned PointerAuthKeyNone = -1;
} // end namespace clang
>From cfb3afe19c698aaf41fb7b492503081989896434 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Tue, 16 Apr 2024 20:01:17 +0300
Subject: [PATCH 6/9] Address review comments
---
clang/include/clang/AST/ASTContext.h | 6 +++---
clang/include/clang/AST/Type.h | 12 +++++-------
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 52eaa5b36fead3..23959d4453ca54 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2201,9 +2201,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
assert(!Ty.getPointerAuth());
assert(PointerAuth);
- Qualifiers qs;
- qs.setPointerAuth(PointerAuth);
- return getQualifiedType(Ty, qs);
+ Qualifiers Qs;
+ Qs.setPointerAuth(PointerAuth);
+ return getQualifiedType(Ty, Qs);
}
unsigned char getFixedPointScale(QualType Ty) const;
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 4dd532c2420206..30b23de23f4c66 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -174,7 +174,7 @@ class PointerAuthQualifier {
// |Enabled|Address|AuthenticationMode|ISA pointer|
// bits: |5 |6..15| 16...31 |
// |AuthenticatesNull|Key |Discriminator|
- uint32_t Data;
+ uint32_t Data = 0;
// The following static assertions check that each of the 32 bits is present
// exactly in one of the constants.
@@ -224,7 +224,7 @@ class PointerAuthQualifier {
};
public:
- PointerAuthQualifier() : Data(0) {}
+ PointerAuthQualifier() = default;
static PointerAuthQualifier
Create(unsigned Key, bool IsAddressDiscriminated, unsigned ExtraDiscriminator,
@@ -295,9 +295,9 @@ class PointerAuthQualifier {
// Deserialize pointer-auth qualifiers from an opaque representation.
static PointerAuthQualifier fromOpaqueValue(uint32_t Opaque) {
- PointerAuthQualifier result;
- result.Data = Opaque;
- return result;
+ PointerAuthQualifier Result;
+ Result.Data = Opaque;
+ return Result;
}
void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Data); }
@@ -358,8 +358,6 @@ class Qualifiers {
FastMask = (1 << FastWidth) - 1
};
- Qualifiers() : Mask(0), PtrAuth() {}
-
/// Returns the common set of qualifiers while removing them from
/// the given sets.
static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) {
>From df81082d6f0210b02e72a3237ab7c03715d23488 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Tue, 16 Apr 2024 20:11:22 +0300
Subject: [PATCH 7/9] Do not use `uint32_t(Opaque)` for getting 32 upper bits
of `Opaque`
---
clang/include/clang/AST/Type.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 30b23de23f4c66..6cae078d89e5b9 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -52,6 +52,7 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
+#include <limits>
#include <optional>
#include <string>
#include <type_traits>
@@ -423,8 +424,9 @@ class Qualifiers {
// Deserialize qualifiers from an opaque representation.
static Qualifiers fromOpaqueValue(uint64_t Opaque) {
Qualifiers Qs;
- Qs.Mask = uint32_t(Opaque);
- Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue(uint32_t(Opaque >> 32));
+ constexpr uint32_t U32Max = std::numeric_limits<uint32_t>::max();
+ Qs.Mask = Opaque & U32Max;
+ Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue((Opaque >> 32) & U32Max);
return Qs;
}
>From e3cb910ebce1ffa187816a20ce52e6303799665a Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Wed, 17 Apr 2024 21:56:24 +0300
Subject: [PATCH 8/9] [clang-tidy] Use only fast qualifiers to re-construct
`QualType`
---
.../bugprone/EasilySwappableParametersCheck.cpp | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp
index 84e99c7fafc74b..10868129e76da9 100644
--- a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp
@@ -967,7 +967,8 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
// Get out the qualifiers of the original type. This will always be
// re-applied to the WorkType to ensure it is the same qualification as the
// original From was.
- auto QualifiersToApply = From.split().Quals.getAsOpaqueValue();
+ auto FastQualifiersToApply = static_cast<unsigned>(
+ From.split().Quals.getAsOpaqueValue() & Qualifiers::FastMask);
// LValue->RValue is irrelevant for the check, because it is a thing to be
// done at a call site, and will be performed if need be performed.
@@ -993,7 +994,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
// "const double -> double".
LLVM_DEBUG(llvm::dbgs()
<< "--- approximateStdConv. Conversion between numerics.\n");
- WorkType = QualType{ToBuiltin, QualifiersToApply};
+ WorkType = QualType{ToBuiltin, FastQualifiersToApply};
}
const auto *FromEnum = WorkType->getAs<EnumType>();
@@ -1002,7 +1003,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
// Unscoped enumerations (or enumerations in C) convert to numerics.
LLVM_DEBUG(llvm::dbgs()
<< "--- approximateStdConv. Unscoped enum to numeric.\n");
- WorkType = QualType{ToBuiltin, QualifiersToApply};
+ WorkType = QualType{ToBuiltin, FastQualifiersToApply};
} else if (FromNumeric && ToEnum && ToEnum->isUnscopedEnumerationType()) {
// Numeric types convert to enumerations only in C.
if (Ctx.getLangOpts().CPlusPlus) {
@@ -1013,7 +1014,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
LLVM_DEBUG(llvm::dbgs()
<< "--- approximateStdConv. Numeric to unscoped enum.\n");
- WorkType = QualType{ToEnum, QualifiersToApply};
+ WorkType = QualType{ToEnum, FastQualifiersToApply};
}
// Check for pointer conversions.
@@ -1022,14 +1023,14 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
if (FromPtr && ToPtr) {
if (ToPtr->isVoidPointerType()) {
LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. To void pointer.\n");
- WorkType = QualType{ToPtr, QualifiersToApply};
+ WorkType = QualType{ToPtr, FastQualifiersToApply};
}
const auto *FromRecordPtr = FromPtr->getPointeeCXXRecordDecl();
const auto *ToRecordPtr = ToPtr->getPointeeCXXRecordDecl();
if (isDerivedToBase(FromRecordPtr, ToRecordPtr)) {
LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived* to Base*\n");
- WorkType = QualType{ToPtr, QualifiersToApply};
+ WorkType = QualType{ToPtr, FastQualifiersToApply};
}
}
@@ -1039,7 +1040,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
const auto *ToRecord = To->getAsCXXRecordDecl();
if (isDerivedToBase(FromRecord, ToRecord)) {
LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived To Base.\n");
- WorkType = QualType{ToRecord->getTypeForDecl(), QualifiersToApply};
+ WorkType = QualType{ToRecord->getTypeForDecl(), FastQualifiersToApply};
}
if (Ctx.getLangOpts().CPlusPlus17 && FromPtr && ToPtr) {
@@ -1054,7 +1055,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
!ToFunctionPtr->hasNoexceptExceptionSpec()) {
LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. noexcept function "
"pointer to non-noexcept.\n");
- WorkType = QualType{ToPtr, QualifiersToApply};
+ WorkType = QualType{ToPtr, FastQualifiersToApply};
}
}
>From 53485b1e7f7c60253b8734e95ae9b9a04e9e7a95 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Tue, 23 Apr 2024 22:23:12 +0300
Subject: [PATCH 9/9] Store PtrAuth inside Mask to enhance performance
---
clang/include/clang/AST/Type.h | 112 +++++++++++++++++----------------
1 file changed, 59 insertions(+), 53 deletions(-)
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 6cae078d89e5b9..dff02d4861b3db 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -52,7 +52,6 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
-#include <limits>
#include <optional>
#include <string>
#include <type_traits>
@@ -211,6 +210,8 @@ class PointerAuthQualifier {
(AuthenticatesNullValues << AuthenticatesNullValuesShift)) {
assert(Key <= KeyNoneInternal);
assert(ExtraDiscriminator <= MaxDiscriminator);
+ assert((Data == 0) ==
+ (getAuthenticationMode() == PointerAuthenticationMode::None));
}
public:
@@ -240,7 +241,9 @@ class PointerAuthQualifier {
}
bool isPresent() const {
- return getAuthenticationMode() != PointerAuthenticationMode::None;
+ assert((Data == 0) ==
+ (getAuthenticationMode() == PointerAuthenticationMode::None));
+ return Data != 0;
}
explicit operator bool() const { return isPresent(); }
@@ -298,6 +301,8 @@ class PointerAuthQualifier {
static PointerAuthQualifier fromOpaqueValue(uint32_t Opaque) {
PointerAuthQualifier Result;
Result.Data = Opaque;
+ assert((Result.Data == 0) ==
+ (Result.getAuthenticationMode() == PointerAuthenticationMode::None));
return Result;
}
@@ -312,8 +317,9 @@ class PointerAuthQualifier {
/// * Objective C: the GC attributes (none, weak, or strong)
class Qualifiers {
public:
- enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ.
- Const = 0x1,
+ enum TQ : uint64_t {
+ // NOTE: These flags must be kept in sync with DeclSpec::TQ.
+ Const = 0x1,
Restrict = 0x2,
Volatile = 0x4,
CVRMask = Const | Volatile | Restrict
@@ -347,7 +353,7 @@ class Qualifiers {
OCL_Autoreleasing
};
- enum {
+ enum : uint64_t {
/// The maximum supported address space number.
/// 23 bits should be enough for anyone.
MaxAddressSpace = 0x7fffffu,
@@ -363,8 +369,11 @@ class Qualifiers {
/// the given sets.
static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) {
Qualifiers Q;
- if (L.getPointerAuth().isEquivalent(R.getPointerAuth())) {
- Q.setPointerAuth(L.getPointerAuth().withoutKeyNone());
+ PointerAuthQualifier LPtrAuth = L.getPointerAuth();
+ if (LPtrAuth.isPresent() &&
+ LPtrAuth.getKey() != PointerAuthQualifier::KeyNoneInternal &&
+ LPtrAuth == R.getPointerAuth()) {
+ Q.setPointerAuth(LPtrAuth);
PointerAuthQualifier Empty;
L.setPointerAuth(Empty);
R.setPointerAuth(Empty);
@@ -422,18 +431,14 @@ class Qualifiers {
}
// Deserialize qualifiers from an opaque representation.
- static Qualifiers fromOpaqueValue(uint64_t Opaque) {
+ static Qualifiers fromOpaqueValue(uint64_t opaque) {
Qualifiers Qs;
- constexpr uint32_t U32Max = std::numeric_limits<uint32_t>::max();
- Qs.Mask = Opaque & U32Max;
- Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue((Opaque >> 32) & U32Max);
+ Qs.Mask = opaque;
return Qs;
}
// Serialize these qualifiers into an opaque representation.
- uint64_t getAsOpaqueValue() const {
- return uint64_t(Mask) | (uint64_t(PtrAuth.getAsOpaqueValue()) << 32);
- }
+ uint64_t getAsOpaqueValue() const { return Mask; }
bool hasConst() const { return Mask & Const; }
bool hasOnlyConst() const { return Mask == Const; }
@@ -580,9 +585,19 @@ class Qualifiers {
setAddressSpace(space);
}
- PointerAuthQualifier getPointerAuth() const { return PtrAuth; }
- void setPointerAuth(PointerAuthQualifier q) { PtrAuth = q; }
- void removePtrAuth() { PtrAuth = PointerAuthQualifier(); }
+ bool hasPointerAuth() const { return Mask & PtrAuthMask; }
+ PointerAuthQualifier getPointerAuth() const {
+ return PointerAuthQualifier::fromOpaqueValue(Mask >> PtrAuthShift);
+ }
+ void setPointerAuth(PointerAuthQualifier Q) {
+ Mask = (Mask & ~PtrAuthMask) |
+ (uint64_t(Q.getAsOpaqueValue()) << PtrAuthShift);
+ }
+ void removePointerAuth() { Mask &= ~PtrAuthMask; }
+ void addPointerAuth(PointerAuthQualifier Q) {
+ assert(Q.isPresent());
+ setPointerAuth(Q);
+ }
// Fast qualifiers are those that can be allocated directly
// on a QualType object.
@@ -606,7 +621,7 @@ class Qualifiers {
/// Return true if the set contains any qualifiers which require an ExtQuals
/// node to be allocated.
- bool hasNonFastQualifiers() const { return (Mask & ~FastMask) || PtrAuth; }
+ bool hasNonFastQualifiers() const { return Mask & ~FastMask; }
Qualifiers getNonFastQualifiers() const {
Qualifiers Quals = *this;
Quals.setFastQualifiers(0);
@@ -614,8 +629,8 @@ class Qualifiers {
}
/// Return true if the set contains any qualifiers.
- bool hasQualifiers() const { return Mask || PtrAuth; }
- bool empty() const { return !hasQualifiers(); }
+ bool hasQualifiers() const { return Mask; }
+ bool empty() const { return !Mask; }
/// Add the qualifiers from the given set to this set.
void addQualifiers(Qualifiers Q) {
@@ -631,10 +646,9 @@ class Qualifiers {
addObjCGCAttr(Q.getObjCGCAttr());
if (Q.hasObjCLifetime())
addObjCLifetime(Q.getObjCLifetime());
+ if (Q.hasPointerAuth())
+ addPointerAuth(Q.getPointerAuth());
}
-
- if (Q.PtrAuth)
- PtrAuth = Q.PtrAuth;
}
/// Remove the qualifiers from the given set from this set.
@@ -651,10 +665,9 @@ class Qualifiers {
removeObjCLifetime();
if (getAddressSpace() == Q.getAddressSpace())
removeAddressSpace();
+ if (getPointerAuth() == Q.getPointerAuth())
+ removePointerAuth();
}
-
- if (PtrAuth == Q.PtrAuth)
- PtrAuth = PointerAuthQualifier();
}
/// Add the qualifiers from the given set to this set, given that
@@ -666,10 +679,9 @@ class Qualifiers {
!hasObjCGCAttr() || !qs.hasObjCGCAttr());
assert(getObjCLifetime() == qs.getObjCLifetime() ||
!hasObjCLifetime() || !qs.hasObjCLifetime());
- assert(!PtrAuth || !qs.PtrAuth || PtrAuth == qs.PtrAuth);
+ assert(!hasPointerAuth() || !qs.hasPointerAuth() ||
+ getPointerAuth() == qs.getPointerAuth());
Mask |= qs.Mask;
- if (qs.PtrAuth)
- PtrAuth = qs.PtrAuth;
}
/// Returns true if address space A is equal to or a superset of B.
@@ -723,7 +735,7 @@ class Qualifiers {
(getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() ||
!other.hasObjCGCAttr()) &&
// Pointer-auth qualifiers must match exactly.
- PtrAuth == other.PtrAuth &&
+ getPointerAuth() == other.getPointerAuth() &&
// ObjC lifetime qualifiers must match exactly.
getObjCLifetime() == other.getObjCLifetime() &&
// CVR qualifiers may subset.
@@ -756,12 +768,8 @@ class Qualifiers {
/// another set of qualifiers, not considering qualifier compatibility.
bool isStrictSupersetOf(Qualifiers Other) const;
- bool operator==(Qualifiers Other) const {
- return Mask == Other.Mask && PtrAuth == Other.PtrAuth;
- }
- bool operator!=(Qualifiers Other) const {
- return Mask != Other.Mask || PtrAuth != Other.PtrAuth;
- }
+ bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
+ bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
explicit operator bool() const { return hasQualifiers(); }
@@ -797,28 +805,26 @@ class Qualifiers {
void print(raw_ostream &OS, const PrintingPolicy &Policy,
bool appendSpaceIfNonEmpty = false) const;
- void Profile(llvm::FoldingSetNodeID &ID) const {
- ID.AddInteger(Mask);
- PtrAuth.Profile(ID);
- }
+ void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Mask); }
private:
- // bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31|
- // |C R V|U|GCAttr|Lifetime|AddressSpace|
- uint32_t Mask = 0;
-
- PointerAuthQualifier PtrAuth;
+ // bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31|32 ... 63|
+ // |C R V|U|GCAttr|Lifetime|AddressSpace| PtrAuth |
+ uint64_t Mask = 0;
static_assert(sizeof(PointerAuthQualifier) == sizeof(uint32_t),
"PointerAuthQualifier must be 32 bits");
- static const uint32_t UMask = 0x8;
- static const uint32_t UShift = 3;
- static const uint32_t GCAttrMask = 0x30;
- static const uint32_t GCAttrShift = 4;
- static const uint32_t LifetimeMask = 0x1C0;
- static const uint32_t LifetimeShift = 6;
- static const uint32_t AddressSpaceMask =
+
+ static constexpr uint64_t UMask = 0x8;
+ static constexpr uint64_t UShift = 3;
+ static constexpr uint64_t GCAttrMask = 0x30;
+ static constexpr uint64_t GCAttrShift = 4;
+ static constexpr uint64_t LifetimeMask = 0x1C0;
+ static constexpr uint64_t LifetimeShift = 6;
+ static constexpr uint64_t AddressSpaceMask =
~(CVRMask | UMask | GCAttrMask | LifetimeMask);
- static const uint32_t AddressSpaceShift = 9;
+ static constexpr uint64_t AddressSpaceShift = 9;
+ static constexpr uint64_t PtrAuthShift = 32;
+ static constexpr uint64_t PtrAuthMask = uint64_t(0xffffffff) << PtrAuthShift;
};
class QualifiersAndAtomic {
More information about the cfe-commits
mailing list