13
13
#ifndef LLVM_CLANG_AST_APVALUE_H
14
14
#define LLVM_CLANG_AST_APVALUE_H
15
15
16
+ #include " clang/AST/CharUnits.h"
16
17
#include " clang/Basic/LLVM.h"
17
18
#include " llvm/ADT/APFixedPoint.h"
18
19
#include " llvm/ADT/APFloat.h"
@@ -29,7 +30,6 @@ template <typename T> class BasicReaderBase;
29
30
30
31
class AddrLabelExpr ;
31
32
class ASTContext ;
32
- class CharUnits ;
33
33
class CXXRecordDecl ;
34
34
class Decl ;
35
35
class DiagnosticBuilder ;
@@ -88,6 +88,59 @@ class DynamicAllocLValue {
88
88
89
89
static constexpr int NumLowBitsAvailable = 3 ;
90
90
};
91
+
92
+ /* TO_UPSTREAM(BoundsSafety) ON*/
93
+ // / Symbolic representation of a size forged pointer
94
+ class ForgedPtrLValue {
95
+ const ValueDecl *Base;
96
+
97
+ public:
98
+ ForgedPtrLValue () : Base(nullptr ) {}
99
+ explicit ForgedPtrLValue (const ValueDecl *Base) : Base(Base) {}
100
+ explicit operator bool () const { return Base; }
101
+
102
+ const ValueDecl *getBaseValueDecl () const { return Base; }
103
+
104
+ void *getOpaqueValue () { return const_cast <ValueDecl *>(Base); }
105
+ static ForgedPtrLValue getFromOpaqueValue (void *Value) {
106
+ ForgedPtrLValue V;
107
+ V.Base = reinterpret_cast <ValueDecl *>(Value);
108
+ return V;
109
+ }
110
+ };
111
+
112
+ // / This represents a pointer union that is either DynamicAllocLValue or
113
+ // / ForgedPtrLValue.
114
+ // /
115
+ // / This is a hack to be able to add ForgedPtrLValue as another pointer member
116
+ // / to the pointer union of APValue::LValueBase because it already has the
117
+ // / maximum number of members for the available low bits, i.e., 2.
118
+ // / DynamicAllocLValue and ValueDecl* have 3 low bits available and thus we can
119
+ // / use this one more remaining bit to encode ForgedPtrLValue.
120
+ class DynamicAllocOrForgedPtrLValue
121
+ : public llvm::PointerUnion<DynamicAllocLValue, ForgedPtrLValue> {
122
+
123
+ using BaseTy = llvm::PointerUnion<DynamicAllocLValue, ForgedPtrLValue>;
124
+
125
+ public:
126
+ DynamicAllocOrForgedPtrLValue () = default ;
127
+ DynamicAllocOrForgedPtrLValue (DynamicAllocLValue LV) : BaseTy(LV) {}
128
+ DynamicAllocOrForgedPtrLValue (ForgedPtrLValue LV) : BaseTy(LV) {}
129
+
130
+ explicit operator bool () const {
131
+ if (is<DynamicAllocLValue>()) {
132
+ return static_cast <bool >(get<DynamicAllocLValue>());
133
+ }
134
+ return static_cast <bool >(get<ForgedPtrLValue>());
135
+ }
136
+
137
+ static DynamicAllocOrForgedPtrLValue getFromOpaqueValue (void *Value) {
138
+ DynamicAllocOrForgedPtrLValue V;
139
+ V.Val .setFromOpaqueValue (Value);
140
+ return V;
141
+ }
142
+ };
143
+ /* TO_UPSTREAM(BoundsSafety) OFF*/
91
144
}
92
145
93
146
namespace llvm {
@@ -113,6 +166,28 @@ template<> struct PointerLikeTypeTraits<clang::DynamicAllocLValue> {
113
166
static constexpr int NumLowBitsAvailable =
114
167
clang::DynamicAllocLValue::NumLowBitsAvailable;
115
168
};
169
+
170
+ /* TO_UPSTREAM(BoundsSafety) ON*/
171
+ template <> struct PointerLikeTypeTraits <clang::ForgedPtrLValue> {
172
+ static void *getAsVoidPointer (clang::ForgedPtrLValue V) {
173
+ return V.getOpaqueValue ();
174
+ }
175
+ static clang::ForgedPtrLValue getFromVoidPointer (void *P) {
176
+ return clang::ForgedPtrLValue::getFromOpaqueValue (P);
177
+ }
178
+ static constexpr int NumLowBitsAvailable = 3 ;
179
+ };
180
+
181
+ template <> struct PointerLikeTypeTraits <clang::DynamicAllocOrForgedPtrLValue> {
182
+ static void *getAsVoidPointer (clang::DynamicAllocOrForgedPtrLValue V) {
183
+ return V.getOpaqueValue ();
184
+ }
185
+ static clang::DynamicAllocOrForgedPtrLValue getFromVoidPointer (void *P) {
186
+ return clang::DynamicAllocOrForgedPtrLValue::getFromOpaqueValue (P);
187
+ }
188
+ static constexpr int NumLowBitsAvailable = 2 ;
189
+ };
190
+ /* TO_UPSTREAM(BoundsSafety) OFF*/
116
191
}
117
192
118
193
namespace clang {
@@ -145,28 +220,64 @@ class APValue {
145
220
146
221
class LValueBase {
147
222
typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
148
- DynamicAllocLValue >
223
+ DynamicAllocOrForgedPtrLValue >
149
224
PtrTy;
150
225
226
+ template <class T >
227
+ static constexpr bool IsDAOrForgedV =
228
+ std::is_same<T, DynamicAllocLValue>::value ||
229
+ std::is_same<T, ForgedPtrLValue>::value;
230
+
231
+ template <class T , class U = T>
232
+ using EnableIfDAOrForged =
233
+ typename std::enable_if<IsDAOrForgedV<T>, U>::type;
234
+
235
+ template <class T , class U = T>
236
+ using EnableIfNotDANorForged =
237
+ typename std::enable_if<!IsDAOrForgedV<T>, U>::type;
238
+
151
239
public:
152
240
LValueBase () : Local{} {}
153
241
LValueBase (const ValueDecl *P, unsigned I = 0 , unsigned V = 0 );
154
242
LValueBase (const Expr *P, unsigned I = 0 , unsigned V = 0 );
155
243
static LValueBase getDynamicAlloc (DynamicAllocLValue LV, QualType Type);
156
244
static LValueBase getTypeInfo (TypeInfoLValue LV, QualType TypeInfo);
245
+ static LValueBase getForgedPtr (ForgedPtrLValue LV, QualType Type);
157
246
158
247
void Profile (llvm::FoldingSetNodeID &ID) const ;
159
248
160
- template <class T >
161
- bool is () const { return Ptr.is <T>(); }
249
+ template <class T > EnableIfNotDANorForged<T, bool > is () const {
250
+ return Ptr.is <T>();
251
+ }
162
252
163
- template <class T >
164
- T get () const { return Ptr.get <T>(); }
253
+ template <class T > EnableIfDAOrForged<T, bool > is () const {
254
+ if (!Ptr.is <DynamicAllocOrForgedPtrLValue>())
255
+ return false ;
256
+ return Ptr.get <DynamicAllocOrForgedPtrLValue>().is <T>();
257
+ }
165
258
166
- template <class T >
167
- T dyn_cast () const { return Ptr.dyn_cast <T>(); }
259
+ template <class T > EnableIfNotDANorForged<T> get () const {
260
+ return Ptr.get <T>();
261
+ }
262
+
263
+ template <class T > EnableIfDAOrForged<T> get () const {
264
+ assert (is<T>() && " Invalid accessor called" );
265
+ return Ptr.get <DynamicAllocOrForgedPtrLValue>().get <T>();
266
+ }
267
+
268
+ template <class T > EnableIfNotDANorForged<T> dyn_cast () const {
269
+ return Ptr.dyn_cast <T>();
270
+ }
271
+
272
+ template <class T > EnableIfDAOrForged<T> dyn_cast () const {
273
+ if (is<T>())
274
+ return Ptr.get <DynamicAllocOrForgedPtrLValue>().dyn_cast <T>();
275
+ return T ();
276
+ }
168
277
169
278
void *getOpaqueValue () const ;
279
+ // TO_UPSTREAM(BoundsSafety)
280
+ const ValueDecl *getValueDecl () const ;
170
281
171
282
bool isNull () const ;
172
283
@@ -176,6 +287,7 @@ class APValue {
176
287
unsigned getVersion () const ;
177
288
QualType getTypeInfoType () const ;
178
289
QualType getDynamicAllocType () const ;
290
+ QualType getForgedPtrAsArrayType () const ;
179
291
180
292
QualType getType () const ;
181
293
@@ -197,6 +309,8 @@ class APValue {
197
309
void *TypeInfoType;
198
310
// / The QualType, if this is a DynamicAllocLValue.
199
311
void *DynamicAllocType;
312
+ // / The QualType, if this is a ForgedPtrLValue.
313
+ void *ForgedPtrAsArrayType;
200
314
};
201
315
};
202
316
@@ -305,10 +419,45 @@ class APValue {
305
419
};
306
420
struct MemberPointerData ;
307
421
422
+ /* TO_UPSTREAM(BoundsSafety) ON */
423
+ struct LVBase {
424
+ APValue::LValueBase Base;
425
+ CharUnits Offset;
426
+ // BoundsSafety : While the base also holds a corresponding constant array type
427
+ // for forged pointer, we still keep track of forged size because the array
428
+ // size will be different from the actual forged size if it is not a multiple
429
+ // of element type size after a bitcast. The codegen doesn't round up/down
430
+ // the bounds to be a type-size multiple, we should keep it the same for
431
+ // constant emission. Once __builtin_forge_* has a type as an argument, we
432
+ // may consider round down the size with the element type size.
433
+ CharUnits ForgedSize;
434
+ // While 'Offset' is the offset within the LValue, 'ForgedOffset' is the
435
+ // offset of the base pointer of __builtin_unsafe_forge*. For example, in
436
+ // the following,
437
+ // '__bidi_indexable_unsafe_forge_bidi_indexable(base + N) + M'
438
+ // 'N' should be 'ForgedOffset' and 'M' should be 'Offset'. This way, the
439
+ // forged pointer itself becomes an LValue starting at base + 'ForgedOffset'.
440
+ CharUnits ForgedOffset;
441
+ unsigned PathLength;
442
+ bool IsNullPtr : 1 ;
443
+ bool IsOnePastTheEnd : 1 ;
444
+ bool IsForgeBidi : 1 ;
445
+ bool IsForgeSingle : 1 ;
446
+ bool IsForgeTerminatedBy : 1 ;
447
+ };
448
+
449
+ struct LVPlaceHolder {
450
+ LVBase Base;
451
+ LValuePathEntry Path[1 ];
452
+ };
453
+ /* TO_UPSTREAM(BoundsSafety) OFF */
454
+
308
455
// We ensure elsewhere that Data is big enough for LV and MemberPointerData.
309
456
typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
310
457
ComplexAPFloat, Vec, Arr, StructData,
311
- UnionData, AddrLabelDiffData> DataType;
458
+ UnionData, AddrLabelDiffData,
459
+ // TO_UPSTREAM(BoundsSafety)
460
+ LVPlaceHolder> DataType;
312
461
static const size_t DataSize = sizeof (DataType);
313
462
314
463
DataType Data;
@@ -487,12 +636,33 @@ class APValue {
487
636
const CharUnits &getLValueOffset () const {
488
637
return const_cast <APValue*>(this )->getLValueOffset ();
489
638
}
639
+
640
+ /* TO_UPSTREAM(BoundsSafety) ON */
641
+ CharUnits &getLValueForgedSize ();
642
+ const CharUnits &getLValueForgedSize () const {
643
+ return const_cast <APValue *>(this )->getLValueForgedSize ();
644
+ }
645
+
646
+ CharUnits &getLValueForgedOffset ();
647
+ const CharUnits &getLValueForgedOffset () const {
648
+ return const_cast <APValue *>(this )->getLValueForgedOffset ();
649
+ }
650
+
651
+ CharUnits getUnwrappedLValueOffset () const ;
652
+ /* TO_UPSTREAM(BoundsSafety) OFF */
653
+
490
654
bool isLValueOnePastTheEnd () const ;
491
655
bool hasLValuePath () const ;
492
656
ArrayRef<LValuePathEntry> getLValuePath () const ;
493
657
unsigned getLValueCallIndex () const ;
494
658
unsigned getLValueVersion () const ;
495
659
bool isNullPointer () const ;
660
+ /* TO_UPSTREAM(BoundsSafety) ON */
661
+ bool isLValueForgeBidi () const ;
662
+ bool isLValueForgeSingle () const ;
663
+ bool isLValueForgeTerminatedBy () const ;
664
+ bool isLValueForge () const ;
665
+ /* TO_UPSTREAM(BoundsSafety) OFF */
496
666
497
667
APValue &getVectorElt (unsigned I) {
498
668
assert (isVector () && " Invalid accessor" );
@@ -628,6 +798,12 @@ class APValue {
628
798
((AddrLabelDiffData *)(char *)&Data)->RHSExpr = RHSExpr;
629
799
}
630
800
801
+ /* TO_UPSTREAM(BoundsSafety) ON */
802
+ void setLValueForgedBidi (const CharUnits &Size, const CharUnits &Offset);
803
+ void setLValueForgedSingle (const CharUnits &Offset);
804
+ void setLValueForgedTerminatedBy (const CharUnits &Offset);
805
+ /* TO_UPSTREAM(BoundsSafety) OFF */
806
+
631
807
private:
632
808
void DestroyDataAndMakeUninit ();
633
809
void MakeInt () {
0 commit comments