Skip to content

Commit b808de8

Browse files
[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 ahmedbougacha/llvm-project@cc7ba7e - ObjC isa signing ahmedbougacha/llvm-project@c9ce0d4 Also applies a fix from #75 Co-authored-by: Ahmed Bougacha <[email protected]>
1 parent dcad014 commit b808de8

File tree

2 files changed

+228
-11
lines changed

2 files changed

+228
-11
lines changed

clang/include/clang/AST/Type.h

Lines changed: 205 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
#include "clang/Basic/Diagnostic.h"
2626
#include "clang/Basic/ExceptionSpecificationType.h"
2727
#include "clang/Basic/LLVM.h"
28+
#include "clang/Basic/LangOptions.h"
2829
#include "clang/Basic/Linkage.h"
2930
#include "clang/Basic/PartialDiagnostic.h"
31+
#include "clang/Basic/PointerAuthOptions.h"
3032
#include "clang/Basic/SourceLocation.h"
3133
#include "clang/Basic/Specifiers.h"
3234
#include "clang/Basic/Visibility.h"
@@ -138,6 +140,166 @@ using CanQualType = CanQual<Type>;
138140
#define TYPE(Class, Base) class Class##Type;
139141
#include "clang/AST/TypeNodes.inc"
140142

143+
/// Pointer-authentication qualifiers.
144+
class PointerAuthQualifier {
145+
enum : uint32_t {
146+
EnabledShift = 0,
147+
EnabledBits = 1,
148+
EnabledMask = 1 << EnabledShift,
149+
AddressDiscriminatedShift = EnabledShift + EnabledBits,
150+
AddressDiscriminatedBits = 1,
151+
AddressDiscriminatedMask = 1 << AddressDiscriminatedShift,
152+
AuthenticationModeShift =
153+
AddressDiscriminatedShift + AddressDiscriminatedBits,
154+
AuthenticationModeBits = 2,
155+
AuthenticationModeMask = ((1 << AuthenticationModeBits) - 1)
156+
<< AuthenticationModeShift,
157+
IsaPointerShift = AuthenticationModeShift + AuthenticationModeBits,
158+
IsaPointerBits = 1,
159+
IsaPointerMask = ((1 << IsaPointerBits) - 1) << IsaPointerShift,
160+
AuthenticatesNullValuesShift = IsaPointerShift + IsaPointerBits,
161+
AuthenticatesNullValuesBits = 1,
162+
AuthenticatesNullValuesMask = ((1 << AuthenticatesNullValuesBits) - 1)
163+
<< AuthenticatesNullValuesShift,
164+
KeyShift = AuthenticatesNullValuesShift + AuthenticatesNullValuesBits,
165+
KeyBits = 10,
166+
KeyMask = ((1 << KeyBits) - 1) << KeyShift,
167+
DiscriminatorShift = KeyShift + KeyBits,
168+
DiscriminatorBits = 16,
169+
DiscriminatorMask = ((1u << DiscriminatorBits) - 1) << DiscriminatorShift,
170+
};
171+
172+
// bits: |0 |1 |2..3 |4 |5 |6..15| 16...31 |
173+
// |Enabled|Address|AuthenticationMode|ISA pointer|AuthenticatesNull|Key |Discriminator|
174+
uint32_t Data;
175+
176+
static_assert((EnabledBits + AddressDiscriminatedBits +
177+
AuthenticationModeBits + IsaPointerBits +
178+
AuthenticatesNullValuesBits + KeyBits + DiscriminatorBits) ==
179+
32,
180+
"PointerAuthQualifier should be exactly 32 bits");
181+
static_assert((EnabledMask + AddressDiscriminatedMask +
182+
AuthenticationModeMask + IsaPointerMask +
183+
AuthenticatesNullValuesMask + KeyMask + DiscriminatorMask) ==
184+
0xFFFFFFFF,
185+
"All masks should cover the entire bits");
186+
static_assert((EnabledMask ^ AddressDiscriminatedMask ^
187+
AuthenticationModeMask ^ IsaPointerMask ^
188+
AuthenticatesNullValuesMask ^ KeyMask ^ DiscriminatorMask) ==
189+
0xFFFFFFFF,
190+
"All masks should cover the entire bits");
191+
192+
PointerAuthQualifier(unsigned key, bool isAddressDiscriminated,
193+
unsigned extraDiscriminator,
194+
PointerAuthenticationMode authenticationMode,
195+
bool isIsaPointer, bool authenticatesNullValues)
196+
: Data(EnabledMask |
197+
(isAddressDiscriminated
198+
? static_cast<uint32_t>(AddressDiscriminatedMask)
199+
: 0) |
200+
(key << KeyShift) |
201+
(unsigned(authenticationMode) << AuthenticationModeShift) |
202+
(extraDiscriminator << DiscriminatorShift) |
203+
(isIsaPointer << IsaPointerShift) |
204+
(authenticatesNullValues << AuthenticatesNullValuesShift)) {
205+
assert(key <= KeyNoneInternal);
206+
assert(extraDiscriminator <= MaxDiscriminator);
207+
}
208+
209+
public:
210+
enum {
211+
KeyNoneInternal = (1u << KeyBits) - 1,
212+
213+
/// The maximum supported pointer-authentication key.
214+
MaxKey = KeyNoneInternal - 1,
215+
216+
/// The maximum supported pointer-authentication discriminator.
217+
MaxDiscriminator = (1u << DiscriminatorBits) - 1
218+
};
219+
220+
public:
221+
PointerAuthQualifier() : Data(0) {}
222+
223+
static PointerAuthQualifier
224+
Create(int key, bool isAddressDiscriminated, unsigned extraDiscriminator,
225+
PointerAuthenticationMode authenticationMode, bool isIsaPointer,
226+
bool authenticatesNullValues) {
227+
if (key == PointerAuthKeyNone)
228+
key = KeyNoneInternal;
229+
assert((key >= 0 && key <= KeyNoneInternal) && "out-of-range key value");
230+
return PointerAuthQualifier(key, isAddressDiscriminated,
231+
extraDiscriminator, authenticationMode,
232+
isIsaPointer, authenticatesNullValues);
233+
}
234+
235+
bool isPresent() const {
236+
return getAuthenticationMode() != PointerAuthenticationMode::None;
237+
}
238+
239+
explicit operator bool() const { return isPresent(); }
240+
241+
unsigned getKey() const {
242+
assert(isPresent());
243+
return (Data & KeyMask) >> KeyShift;
244+
}
245+
246+
bool hasKeyNone() const {
247+
return isPresent() && getKey() == KeyNoneInternal;
248+
}
249+
250+
bool isAddressDiscriminated() const {
251+
assert(isPresent());
252+
return (Data & AddressDiscriminatedMask) >> AddressDiscriminatedShift;
253+
}
254+
255+
unsigned getExtraDiscriminator() const {
256+
assert(isPresent());
257+
return (Data >> DiscriminatorShift);
258+
}
259+
260+
PointerAuthenticationMode getAuthenticationMode() const {
261+
return PointerAuthenticationMode((Data & AuthenticationModeMask) >>
262+
AuthenticationModeShift);
263+
}
264+
265+
bool isIsaPointer() const {
266+
assert(isPresent());
267+
return (Data & IsaPointerMask) >> IsaPointerShift;
268+
}
269+
270+
bool authenticatesNullValues() const {
271+
assert(isPresent());
272+
return (Data & AuthenticatesNullValuesMask) >>
273+
AuthenticatesNullValuesShift;
274+
}
275+
276+
PointerAuthQualifier withoutKeyNone() const {
277+
return hasKeyNone() ? PointerAuthQualifier() : *this;
278+
}
279+
280+
friend bool operator==(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) {
281+
return Lhs.Data == Rhs.Data;
282+
}
283+
friend bool operator!=(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) {
284+
return Lhs.Data != Rhs.Data;
285+
}
286+
287+
bool isEquivalent(PointerAuthQualifier Other) const {
288+
return withoutKeyNone() == Other.withoutKeyNone();
289+
}
290+
291+
uint32_t getAsOpaqueValue() const { return Data; }
292+
293+
// Deserialize pointer-auth qualifiers from an opaque representation.
294+
static PointerAuthQualifier fromOpaqueValue(uint32_t opaque) {
295+
PointerAuthQualifier result;
296+
result.Data = opaque;
297+
return result;
298+
}
299+
300+
void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Data); }
301+
};
302+
141303
/// The collection of all-type qualifiers we support.
142304
/// Clang supports five independent qualifiers:
143305
/// * C99: const, volatile, and restrict
@@ -193,19 +355,27 @@ class Qualifiers {
193355
FastMask = (1 << FastWidth) - 1
194356
};
195357

358+
Qualifiers() : Mask(0), PtrAuth() {}
359+
196360
/// Returns the common set of qualifiers while removing them from
197361
/// the given sets.
198362
static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) {
363+
Qualifiers Q;
364+
if (L.getPointerAuth().isEquivalent(R.getPointerAuth())) {
365+
Q.setPointerAuth(L.getPointerAuth().withoutKeyNone());
366+
PointerAuthQualifier Empty;
367+
L.setPointerAuth(Empty);
368+
R.setPointerAuth(Empty);
369+
}
370+
199371
// If both are only CVR-qualified, bit operations are sufficient.
200372
if (!(L.Mask & ~CVRMask) && !(R.Mask & ~CVRMask)) {
201-
Qualifiers Q;
202373
Q.Mask = L.Mask & R.Mask;
203374
L.Mask &= ~Q.Mask;
204375
R.Mask &= ~Q.Mask;
205376
return Q;
206377
}
207378

208-
Qualifiers Q;
209379
unsigned CommonCRV = L.getCVRQualifiers() & R.getCVRQualifiers();
210380
Q.addCVRQualifiers(CommonCRV);
211381
L.removeCVRQualifiers(CommonCRV);
@@ -250,15 +420,16 @@ class Qualifiers {
250420
}
251421

252422
// Deserialize qualifiers from an opaque representation.
253-
static Qualifiers fromOpaqueValue(unsigned opaque) {
423+
static Qualifiers fromOpaqueValue(uint64_t opaque) {
254424
Qualifiers Qs;
255-
Qs.Mask = opaque;
425+
Qs.Mask = uint32_t(opaque);
426+
Qs.PtrAuth = PointerAuthQualifier::fromOpaqueValue(uint32_t(opaque >> 32));
256427
return Qs;
257428
}
258429

259430
// Serialize these qualifiers into an opaque representation.
260-
unsigned getAsOpaqueValue() const {
261-
return Mask;
431+
uint64_t getAsOpaqueValue() const {
432+
return uint64_t(Mask) | (uint64_t(PtrAuth.getAsOpaqueValue()) << 32);
262433
}
263434

264435
bool hasConst() const { return Mask & Const; }
@@ -406,6 +577,10 @@ class Qualifiers {
406577
setAddressSpace(space);
407578
}
408579

580+
PointerAuthQualifier getPointerAuth() const { return PtrAuth; }
581+
void setPointerAuth(PointerAuthQualifier q) { PtrAuth = q; }
582+
void removePtrAuth() { PtrAuth = PointerAuthQualifier(); }
583+
409584
// Fast qualifiers are those that can be allocated directly
410585
// on a QualType object.
411586
bool hasFastQualifiers() const { return getFastQualifiers(); }
@@ -428,16 +603,16 @@ class Qualifiers {
428603

429604
/// Return true if the set contains any qualifiers which require an ExtQuals
430605
/// node to be allocated.
431-
bool hasNonFastQualifiers() const { return Mask & ~FastMask; }
606+
bool hasNonFastQualifiers() const { return (Mask & ~FastMask) || PtrAuth; }
432607
Qualifiers getNonFastQualifiers() const {
433608
Qualifiers Quals = *this;
434609
Quals.setFastQualifiers(0);
435610
return Quals;
436611
}
437612

438613
/// Return true if the set contains any qualifiers.
439-
bool hasQualifiers() const { return Mask; }
440-
bool empty() const { return !Mask; }
614+
bool hasQualifiers() const { return Mask || PtrAuth; }
615+
bool empty() const { return !hasQualifiers(); }
441616

442617
/// Add the qualifiers from the given set to this set.
443618
void addQualifiers(Qualifiers Q) {
@@ -454,6 +629,9 @@ class Qualifiers {
454629
if (Q.hasObjCLifetime())
455630
addObjCLifetime(Q.getObjCLifetime());
456631
}
632+
633+
if (Q.PtrAuth)
634+
PtrAuth = Q.PtrAuth;
457635
}
458636

459637
/// Remove the qualifiers from the given set from this set.
@@ -471,6 +649,9 @@ class Qualifiers {
471649
if (getAddressSpace() == Q.getAddressSpace())
472650
removeAddressSpace();
473651
}
652+
653+
if (PtrAuth == Q.PtrAuth)
654+
PtrAuth = PointerAuthQualifier();
474655
}
475656

476657
/// Add the qualifiers from the given set to this set, given that
@@ -482,7 +663,10 @@ class Qualifiers {
482663
!hasObjCGCAttr() || !qs.hasObjCGCAttr());
483664
assert(getObjCLifetime() == qs.getObjCLifetime() ||
484665
!hasObjCLifetime() || !qs.hasObjCLifetime());
666+
assert(!PtrAuth || !qs.PtrAuth || PtrAuth == qs.PtrAuth);
485667
Mask |= qs.Mask;
668+
if (qs.PtrAuth)
669+
PtrAuth = qs.PtrAuth;
486670
}
487671

488672
/// Returns true if address space A is equal to or a superset of B.
@@ -535,6 +719,8 @@ class Qualifiers {
535719
// be changed.
536720
(getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() ||
537721
!other.hasObjCGCAttr()) &&
722+
// Pointer-auth qualifiers must match exactly.
723+
PtrAuth == other.PtrAuth &&
538724
// ObjC lifetime qualifiers must match exactly.
539725
getObjCLifetime() == other.getObjCLifetime() &&
540726
// CVR qualifiers may subset.
@@ -567,8 +753,12 @@ class Qualifiers {
567753
/// another set of qualifiers, not considering qualifier compatibility.
568754
bool isStrictSupersetOf(Qualifiers Other) const;
569755

570-
bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
571-
bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
756+
bool operator==(Qualifiers Other) const {
757+
return Mask == Other.Mask && PtrAuth == Other.PtrAuth;
758+
}
759+
bool operator!=(Qualifiers Other) const {
760+
return Mask != Other.Mask || PtrAuth != Other.PtrAuth;
761+
}
572762

573763
explicit operator bool() const { return hasQualifiers(); }
574764

@@ -606,13 +796,17 @@ class Qualifiers {
606796

607797
void Profile(llvm::FoldingSetNodeID &ID) const {
608798
ID.AddInteger(Mask);
799+
PtrAuth.Profile(ID);
609800
}
610801

611802
private:
612803
// bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31|
613804
// |C R V|U|GCAttr|Lifetime|AddressSpace|
614805
uint32_t Mask = 0;
615806

807+
PointerAuthQualifier PtrAuth;
808+
static_assert(sizeof(PointerAuthQualifier) == sizeof(uint32_t),
809+
"PointerAuthQualifier must be 32 bits");
616810
static const uint32_t UMask = 0x8;
617811
static const uint32_t UShift = 3;
618812
static const uint32_t GCAttrMask = 0x30;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===--- PointerAuthOptions.h -----------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines options for configuring pointer-auth technologies
10+
// like ARMv8.3.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
15+
#define LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
16+
17+
namespace clang {
18+
19+
constexpr int PointerAuthKeyNone = -1;
20+
21+
} // end namespace clang
22+
23+
#endif

0 commit comments

Comments
 (0)