1 | //===-- CGValue.h - LLVM CodeGen wrappers for llvm::Value* ------*- 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 | // These classes implement wrappers around llvm::Value in order to |
10 | // fully represent the range of values for C L- and R- values. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_CLANG_LIB_CODEGEN_CGVALUE_H |
15 | #define LLVM_CLANG_LIB_CODEGEN_CGVALUE_H |
16 | |
17 | #include "Address.h" |
18 | #include "CodeGenTBAA.h" |
19 | #include "EHScopeStack.h" |
20 | #include "clang/AST/ASTContext.h" |
21 | #include "clang/AST/Type.h" |
22 | #include "llvm/IR/Type.h" |
23 | #include "llvm/IR/Value.h" |
24 | |
25 | namespace llvm { |
26 | class Constant; |
27 | class MDNode; |
28 | } |
29 | |
30 | namespace clang { |
31 | namespace CodeGen { |
32 | class AggValueSlot; |
33 | class CGBuilderTy; |
34 | class CodeGenFunction; |
35 | struct CGBitFieldInfo; |
36 | |
37 | /// RValue - This trivial value class is used to represent the result of an |
38 | /// expression that is evaluated. It can be one of three things: either a |
39 | /// simple LLVM SSA value, a pair of SSA values for complex numbers, or the |
40 | /// address of an aggregate value in memory. |
41 | class RValue { |
42 | friend struct DominatingValue<RValue>; |
43 | |
44 | enum FlavorEnum { Scalar, Complex, Aggregate }; |
45 | |
46 | union { |
47 | // Stores first and second value. |
48 | struct { |
49 | llvm::Value *first; |
50 | llvm::Value *second; |
51 | } Vals; |
52 | |
53 | // Stores aggregate address. |
54 | Address AggregateAddr; |
55 | }; |
56 | |
57 | unsigned IsVolatile : 1; |
58 | unsigned Flavor : 2; |
59 | |
60 | public: |
61 | RValue() : Vals{.first: nullptr, .second: nullptr}, Flavor(Scalar) {} |
62 | |
63 | bool isScalar() const { return Flavor == Scalar; } |
64 | bool isComplex() const { return Flavor == Complex; } |
65 | bool isAggregate() const { return Flavor == Aggregate; } |
66 | |
67 | bool isVolatileQualified() const { return IsVolatile; } |
68 | |
69 | /// getScalarVal() - Return the Value* of this scalar value. |
70 | llvm::Value *getScalarVal() const { |
71 | assert(isScalar() && "Not a scalar!" ); |
72 | return Vals.first; |
73 | } |
74 | |
75 | /// getComplexVal - Return the real/imag components of this complex value. |
76 | /// |
77 | std::pair<llvm::Value *, llvm::Value *> getComplexVal() const { |
78 | return std::make_pair(x: Vals.first, y: Vals.second); |
79 | } |
80 | |
81 | /// getAggregateAddr() - Return the Value* of the address of the aggregate. |
82 | Address getAggregateAddress() const { |
83 | assert(isAggregate() && "Not an aggregate!" ); |
84 | return AggregateAddr; |
85 | } |
86 | |
87 | llvm::Value *getAggregatePointer(QualType PointeeType, |
88 | CodeGenFunction &CGF) const { |
89 | return getAggregateAddress().getBasePointer(); |
90 | } |
91 | |
92 | static RValue getIgnored() { |
93 | // FIXME: should we make this a more explicit state? |
94 | return get(V: nullptr); |
95 | } |
96 | |
97 | static RValue get(llvm::Value *V) { |
98 | RValue ER; |
99 | ER.Vals.first = V; |
100 | ER.Flavor = Scalar; |
101 | ER.IsVolatile = false; |
102 | return ER; |
103 | } |
104 | static RValue get(Address Addr, CodeGenFunction &CGF) { |
105 | return RValue::get(V: Addr.emitRawPointer(CGF)); |
106 | } |
107 | static RValue getComplex(llvm::Value *V1, llvm::Value *V2) { |
108 | RValue ER; |
109 | ER.Vals = {.first: V1, .second: V2}; |
110 | ER.Flavor = Complex; |
111 | ER.IsVolatile = false; |
112 | return ER; |
113 | } |
114 | static RValue getComplex(const std::pair<llvm::Value *, llvm::Value *> &C) { |
115 | return getComplex(V1: C.first, V2: C.second); |
116 | } |
117 | // FIXME: Aggregate rvalues need to retain information about whether they are |
118 | // volatile or not. Remove default to find all places that probably get this |
119 | // wrong. |
120 | |
121 | /// Convert an Address to an RValue. If the Address is not |
122 | /// signed, create an RValue using the unsigned address. Otherwise, resign the |
123 | /// address using the provided type. |
124 | static RValue getAggregate(Address addr, bool isVolatile = false) { |
125 | RValue ER; |
126 | ER.AggregateAddr = addr; |
127 | ER.Flavor = Aggregate; |
128 | ER.IsVolatile = isVolatile; |
129 | return ER; |
130 | } |
131 | }; |
132 | |
133 | /// Does an ARC strong l-value have precise lifetime? |
134 | enum ARCPreciseLifetime_t { |
135 | ARCImpreciseLifetime, ARCPreciseLifetime |
136 | }; |
137 | |
138 | /// The source of the alignment of an l-value; an expression of |
139 | /// confidence in the alignment actually matching the estimate. |
140 | enum class AlignmentSource { |
141 | /// The l-value was an access to a declared entity or something |
142 | /// equivalently strong, like the address of an array allocated by a |
143 | /// language runtime. |
144 | Decl, |
145 | |
146 | /// The l-value was considered opaque, so the alignment was |
147 | /// determined from a type, but that type was an explicitly-aligned |
148 | /// typedef. |
149 | AttributedType, |
150 | |
151 | /// The l-value was considered opaque, so the alignment was |
152 | /// determined from a type. |
153 | Type |
154 | }; |
155 | |
156 | /// Given that the base address has the given alignment source, what's |
157 | /// our confidence in the alignment of the field? |
158 | static inline AlignmentSource getFieldAlignmentSource(AlignmentSource Source) { |
159 | // For now, we don't distinguish fields of opaque pointers from |
160 | // top-level declarations, but maybe we should. |
161 | return AlignmentSource::Decl; |
162 | } |
163 | |
164 | class LValueBaseInfo { |
165 | AlignmentSource AlignSource; |
166 | |
167 | public: |
168 | explicit LValueBaseInfo(AlignmentSource Source = AlignmentSource::Type) |
169 | : AlignSource(Source) {} |
170 | AlignmentSource getAlignmentSource() const { return AlignSource; } |
171 | void setAlignmentSource(AlignmentSource Source) { AlignSource = Source; } |
172 | |
173 | void mergeForCast(const LValueBaseInfo &Info) { |
174 | setAlignmentSource(Info.getAlignmentSource()); |
175 | } |
176 | }; |
177 | |
178 | /// LValue - This represents an lvalue references. Because C/C++ allow |
179 | /// bitfields, this is not a simple LLVM pointer, it may be a pointer plus a |
180 | /// bitrange. |
181 | class LValue { |
182 | enum { |
183 | Simple, // This is a normal l-value, use getAddress(). |
184 | VectorElt, // This is a vector element l-value (V[i]), use getVector* |
185 | BitField, // This is a bitfield l-value, use getBitfield*. |
186 | ExtVectorElt, // This is an extended vector subset, use getExtVectorComp |
187 | GlobalReg, // This is a register l-value, use getGlobalReg() |
188 | MatrixElt // This is a matrix element, use getVector* |
189 | } LVType; |
190 | |
191 | union { |
192 | Address Addr = Address::invalid(); |
193 | llvm::Value *V; |
194 | }; |
195 | |
196 | union { |
197 | // Index into a vector subscript: V[i] |
198 | llvm::Value *VectorIdx; |
199 | |
200 | // ExtVector element subset: V.xyx |
201 | llvm::Constant *VectorElts; |
202 | |
203 | // BitField start bit and size |
204 | const CGBitFieldInfo *BitFieldInfo; |
205 | }; |
206 | |
207 | QualType Type; |
208 | |
209 | // 'const' is unused here |
210 | Qualifiers Quals; |
211 | |
212 | // objective-c's ivar |
213 | bool Ivar:1; |
214 | |
215 | // objective-c's ivar is an array |
216 | bool ObjIsArray:1; |
217 | |
218 | // LValue is non-gc'able for any reason, including being a parameter or local |
219 | // variable. |
220 | bool NonGC: 1; |
221 | |
222 | // Lvalue is a global reference of an objective-c object |
223 | bool GlobalObjCRef : 1; |
224 | |
225 | // Lvalue is a thread local reference |
226 | bool ThreadLocalRef : 1; |
227 | |
228 | // Lvalue has ARC imprecise lifetime. We store this inverted to try |
229 | // to make the default bitfield pattern all-zeroes. |
230 | bool ImpreciseLifetime : 1; |
231 | |
232 | // This flag shows if a nontemporal load/stores should be used when accessing |
233 | // this lvalue. |
234 | bool Nontemporal : 1; |
235 | |
236 | // The pointer is known not to be null. |
237 | bool IsKnownNonNull : 1; |
238 | |
239 | LValueBaseInfo BaseInfo; |
240 | TBAAAccessInfo TBAAInfo; |
241 | |
242 | Expr *BaseIvarExp; |
243 | |
244 | private: |
245 | void Initialize(QualType Type, Qualifiers Quals, Address Addr, |
246 | LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { |
247 | this->Type = Type; |
248 | this->Quals = Quals; |
249 | const unsigned MaxAlign = 1U << 31; |
250 | CharUnits Alignment = Addr.getAlignment(); |
251 | assert((isGlobalReg() || !Alignment.isZero() || Type->isIncompleteType()) && |
252 | "initializing l-value with zero alignment!" ); |
253 | if (Alignment.getQuantity() > MaxAlign) { |
254 | assert(false && "Alignment exceeds allowed max!" ); |
255 | Alignment = CharUnits::fromQuantity(Quantity: MaxAlign); |
256 | } |
257 | this->Addr = Addr; |
258 | this->BaseInfo = BaseInfo; |
259 | this->TBAAInfo = TBAAInfo; |
260 | |
261 | // Initialize Objective-C flags. |
262 | this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false; |
263 | this->ImpreciseLifetime = false; |
264 | this->Nontemporal = false; |
265 | this->ThreadLocalRef = false; |
266 | this->IsKnownNonNull = false; |
267 | this->BaseIvarExp = nullptr; |
268 | } |
269 | |
270 | void initializeSimpleLValue(Address Addr, QualType Type, |
271 | LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, |
272 | ASTContext &Context) { |
273 | Qualifiers QS = Type.getQualifiers(); |
274 | QS.setObjCGCAttr(Context.getObjCGCAttrKind(Ty: Type)); |
275 | LVType = Simple; |
276 | Initialize(Type, Quals: QS, Addr, BaseInfo, TBAAInfo); |
277 | assert(Addr.getBasePointer()->getType()->isPointerTy()); |
278 | } |
279 | |
280 | public: |
281 | bool isSimple() const { return LVType == Simple; } |
282 | bool isVectorElt() const { return LVType == VectorElt; } |
283 | bool isBitField() const { return LVType == BitField; } |
284 | bool isExtVectorElt() const { return LVType == ExtVectorElt; } |
285 | bool isGlobalReg() const { return LVType == GlobalReg; } |
286 | bool isMatrixElt() const { return LVType == MatrixElt; } |
287 | |
288 | bool isVolatileQualified() const { return Quals.hasVolatile(); } |
289 | bool isRestrictQualified() const { return Quals.hasRestrict(); } |
290 | unsigned getVRQualifiers() const { |
291 | return Quals.getCVRQualifiers() & ~Qualifiers::Const; |
292 | } |
293 | |
294 | QualType getType() const { return Type; } |
295 | |
296 | Qualifiers::ObjCLifetime getObjCLifetime() const { |
297 | return Quals.getObjCLifetime(); |
298 | } |
299 | |
300 | bool isObjCIvar() const { return Ivar; } |
301 | void setObjCIvar(bool Value) { Ivar = Value; } |
302 | |
303 | bool isObjCArray() const { return ObjIsArray; } |
304 | void setObjCArray(bool Value) { ObjIsArray = Value; } |
305 | |
306 | bool isNonGC () const { return NonGC; } |
307 | void setNonGC(bool Value) { NonGC = Value; } |
308 | |
309 | bool isGlobalObjCRef() const { return GlobalObjCRef; } |
310 | void setGlobalObjCRef(bool Value) { GlobalObjCRef = Value; } |
311 | |
312 | bool isThreadLocalRef() const { return ThreadLocalRef; } |
313 | void setThreadLocalRef(bool Value) { ThreadLocalRef = Value;} |
314 | |
315 | ARCPreciseLifetime_t isARCPreciseLifetime() const { |
316 | return ARCPreciseLifetime_t(!ImpreciseLifetime); |
317 | } |
318 | void setARCPreciseLifetime(ARCPreciseLifetime_t value) { |
319 | ImpreciseLifetime = (value == ARCImpreciseLifetime); |
320 | } |
321 | bool isNontemporal() const { return Nontemporal; } |
322 | void setNontemporal(bool Value) { Nontemporal = Value; } |
323 | |
324 | bool isObjCWeak() const { |
325 | return Quals.getObjCGCAttr() == Qualifiers::Weak; |
326 | } |
327 | bool isObjCStrong() const { |
328 | return Quals.getObjCGCAttr() == Qualifiers::Strong; |
329 | } |
330 | |
331 | bool isVolatile() const { |
332 | return Quals.hasVolatile(); |
333 | } |
334 | |
335 | Expr *getBaseIvarExp() const { return BaseIvarExp; } |
336 | void setBaseIvarExp(Expr *V) { BaseIvarExp = V; } |
337 | |
338 | TBAAAccessInfo getTBAAInfo() const { return TBAAInfo; } |
339 | void setTBAAInfo(TBAAAccessInfo Info) { TBAAInfo = Info; } |
340 | |
341 | const Qualifiers &getQuals() const { return Quals; } |
342 | Qualifiers &getQuals() { return Quals; } |
343 | |
344 | LangAS getAddressSpace() const { return Quals.getAddressSpace(); } |
345 | |
346 | CharUnits getAlignment() const { return Addr.getAlignment(); } |
347 | void setAlignment(CharUnits A) { Addr.setAlignment(A); } |
348 | |
349 | LValueBaseInfo getBaseInfo() const { return BaseInfo; } |
350 | void setBaseInfo(LValueBaseInfo Info) { BaseInfo = Info; } |
351 | |
352 | KnownNonNull_t isKnownNonNull() const { |
353 | return (KnownNonNull_t)IsKnownNonNull; |
354 | } |
355 | LValue setKnownNonNull() { |
356 | IsKnownNonNull = true; |
357 | return *this; |
358 | } |
359 | |
360 | // simple lvalue |
361 | llvm::Value *getPointer(CodeGenFunction &CGF) const { |
362 | assert(isSimple()); |
363 | return Addr.getBasePointer(); |
364 | } |
365 | llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { |
366 | assert(isSimple()); |
367 | return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; |
368 | } |
369 | |
370 | Address getAddress(CodeGenFunction &CGF) const { |
371 | // FIXME: remove parameter. |
372 | return Addr; |
373 | } |
374 | |
375 | void setAddress(Address address) { Addr = address; } |
376 | |
377 | // vector elt lvalue |
378 | Address getVectorAddress() const { |
379 | assert(isVectorElt()); |
380 | return Addr; |
381 | } |
382 | llvm::Value *getRawVectorPointer(CodeGenFunction &CGF) const { |
383 | assert(isVectorElt()); |
384 | return Addr.emitRawPointer(CGF); |
385 | } |
386 | llvm::Value *getVectorPointer() const { |
387 | assert(isVectorElt()); |
388 | return Addr.getBasePointer(); |
389 | } |
390 | llvm::Value *getVectorIdx() const { |
391 | assert(isVectorElt()); |
392 | return VectorIdx; |
393 | } |
394 | |
395 | Address getMatrixAddress() const { |
396 | assert(isMatrixElt()); |
397 | return Addr; |
398 | } |
399 | llvm::Value *getMatrixPointer() const { |
400 | assert(isMatrixElt()); |
401 | return Addr.getBasePointer(); |
402 | } |
403 | llvm::Value *getMatrixIdx() const { |
404 | assert(isMatrixElt()); |
405 | return VectorIdx; |
406 | } |
407 | |
408 | // extended vector elements. |
409 | Address getExtVectorAddress() const { |
410 | assert(isExtVectorElt()); |
411 | return Addr; |
412 | } |
413 | llvm::Value *getRawExtVectorPointer(CodeGenFunction &CGF) const { |
414 | assert(isExtVectorElt()); |
415 | return Addr.emitRawPointer(CGF); |
416 | } |
417 | llvm::Constant *getExtVectorElts() const { |
418 | assert(isExtVectorElt()); |
419 | return VectorElts; |
420 | } |
421 | |
422 | // bitfield lvalue |
423 | Address getBitFieldAddress() const { |
424 | assert(isBitField()); |
425 | return Addr; |
426 | } |
427 | llvm::Value *getRawBitFieldPointer(CodeGenFunction &CGF) const { |
428 | assert(isBitField()); |
429 | return Addr.emitRawPointer(CGF); |
430 | } |
431 | |
432 | const CGBitFieldInfo &getBitFieldInfo() const { |
433 | assert(isBitField()); |
434 | return *BitFieldInfo; |
435 | } |
436 | |
437 | // global register lvalue |
438 | llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; } |
439 | |
440 | static LValue MakeAddr(Address Addr, QualType type, ASTContext &Context, |
441 | LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { |
442 | LValue R; |
443 | R.LVType = Simple; |
444 | R.initializeSimpleLValue(Addr, Type: type, BaseInfo, TBAAInfo, Context); |
445 | R.Addr = Addr; |
446 | assert(Addr.getType()->isPointerTy()); |
447 | return R; |
448 | } |
449 | |
450 | static LValue MakeVectorElt(Address vecAddress, llvm::Value *Idx, |
451 | QualType type, LValueBaseInfo BaseInfo, |
452 | TBAAAccessInfo TBAAInfo) { |
453 | LValue R; |
454 | R.LVType = VectorElt; |
455 | R.VectorIdx = Idx; |
456 | R.Initialize(Type: type, Quals: type.getQualifiers(), Addr: vecAddress, BaseInfo, TBAAInfo); |
457 | return R; |
458 | } |
459 | |
460 | static LValue MakeExtVectorElt(Address Addr, llvm::Constant *Elts, |
461 | QualType type, LValueBaseInfo BaseInfo, |
462 | TBAAAccessInfo TBAAInfo) { |
463 | LValue R; |
464 | R.LVType = ExtVectorElt; |
465 | R.VectorElts = Elts; |
466 | R.Initialize(Type: type, Quals: type.getQualifiers(), Addr, BaseInfo, TBAAInfo); |
467 | return R; |
468 | } |
469 | |
470 | /// Create a new object to represent a bit-field access. |
471 | /// |
472 | /// \param Addr - The base address of the bit-field sequence this |
473 | /// bit-field refers to. |
474 | /// \param Info - The information describing how to perform the bit-field |
475 | /// access. |
476 | static LValue MakeBitfield(Address Addr, const CGBitFieldInfo &Info, |
477 | QualType type, LValueBaseInfo BaseInfo, |
478 | TBAAAccessInfo TBAAInfo) { |
479 | LValue R; |
480 | R.LVType = BitField; |
481 | R.BitFieldInfo = &Info; |
482 | R.Initialize(Type: type, Quals: type.getQualifiers(), Addr, BaseInfo, TBAAInfo); |
483 | return R; |
484 | } |
485 | |
486 | static LValue MakeGlobalReg(llvm::Value *V, CharUnits alignment, |
487 | QualType type) { |
488 | LValue R; |
489 | R.LVType = GlobalReg; |
490 | R.Initialize(Type: type, Quals: type.getQualifiers(), Addr: Address::invalid(), |
491 | BaseInfo: LValueBaseInfo(AlignmentSource::Decl), TBAAInfo: TBAAAccessInfo()); |
492 | R.V = V; |
493 | return R; |
494 | } |
495 | |
496 | static LValue MakeMatrixElt(Address matAddress, llvm::Value *Idx, |
497 | QualType type, LValueBaseInfo BaseInfo, |
498 | TBAAAccessInfo TBAAInfo) { |
499 | LValue R; |
500 | R.LVType = MatrixElt; |
501 | R.VectorIdx = Idx; |
502 | R.Initialize(Type: type, Quals: type.getQualifiers(), Addr: matAddress, BaseInfo, TBAAInfo); |
503 | return R; |
504 | } |
505 | |
506 | RValue asAggregateRValue(CodeGenFunction &CGF) const { |
507 | return RValue::getAggregate(addr: getAddress(CGF), isVolatile: isVolatileQualified()); |
508 | } |
509 | }; |
510 | |
511 | /// An aggregate value slot. |
512 | class AggValueSlot { |
513 | /// The address. |
514 | Address Addr; |
515 | |
516 | // Qualifiers |
517 | Qualifiers Quals; |
518 | |
519 | /// DestructedFlag - This is set to true if some external code is |
520 | /// responsible for setting up a destructor for the slot. Otherwise |
521 | /// the code which constructs it should push the appropriate cleanup. |
522 | bool DestructedFlag : 1; |
523 | |
524 | /// ObjCGCFlag - This is set to true if writing to the memory in the |
525 | /// slot might require calling an appropriate Objective-C GC |
526 | /// barrier. The exact interaction here is unnecessarily mysterious. |
527 | bool ObjCGCFlag : 1; |
528 | |
529 | /// ZeroedFlag - This is set to true if the memory in the slot is |
530 | /// known to be zero before the assignment into it. This means that |
531 | /// zero fields don't need to be set. |
532 | bool ZeroedFlag : 1; |
533 | |
534 | /// AliasedFlag - This is set to true if the slot might be aliased |
535 | /// and it's not undefined behavior to access it through such an |
536 | /// alias. Note that it's always undefined behavior to access a C++ |
537 | /// object that's under construction through an alias derived from |
538 | /// outside the construction process. |
539 | /// |
540 | /// This flag controls whether calls that produce the aggregate |
541 | /// value may be evaluated directly into the slot, or whether they |
542 | /// must be evaluated into an unaliased temporary and then memcpy'ed |
543 | /// over. Since it's invalid in general to memcpy a non-POD C++ |
544 | /// object, it's important that this flag never be set when |
545 | /// evaluating an expression which constructs such an object. |
546 | bool AliasedFlag : 1; |
547 | |
548 | /// This is set to true if the tail padding of this slot might overlap |
549 | /// another object that may have already been initialized (and whose |
550 | /// value must be preserved by this initialization). If so, we may only |
551 | /// store up to the dsize of the type. Otherwise we can widen stores to |
552 | /// the size of the type. |
553 | bool OverlapFlag : 1; |
554 | |
555 | /// If is set to true, sanitizer checks are already generated for this address |
556 | /// or not required. For instance, if this address represents an object |
557 | /// created in 'new' expression, sanitizer checks for memory is made as a part |
558 | /// of 'operator new' emission and object constructor should not generate |
559 | /// them. |
560 | bool SanitizerCheckedFlag : 1; |
561 | |
562 | AggValueSlot(Address Addr, Qualifiers Quals, bool DestructedFlag, |
563 | bool ObjCGCFlag, bool ZeroedFlag, bool AliasedFlag, |
564 | bool OverlapFlag, bool SanitizerCheckedFlag) |
565 | : Addr(Addr), Quals(Quals), DestructedFlag(DestructedFlag), |
566 | ObjCGCFlag(ObjCGCFlag), ZeroedFlag(ZeroedFlag), |
567 | AliasedFlag(AliasedFlag), OverlapFlag(OverlapFlag), |
568 | SanitizerCheckedFlag(SanitizerCheckedFlag) {} |
569 | |
570 | public: |
571 | enum IsAliased_t { IsNotAliased, IsAliased }; |
572 | enum IsDestructed_t { IsNotDestructed, IsDestructed }; |
573 | enum IsZeroed_t { IsNotZeroed, IsZeroed }; |
574 | enum Overlap_t { DoesNotOverlap, MayOverlap }; |
575 | enum NeedsGCBarriers_t { DoesNotNeedGCBarriers, NeedsGCBarriers }; |
576 | enum IsSanitizerChecked_t { IsNotSanitizerChecked, IsSanitizerChecked }; |
577 | |
578 | /// ignored - Returns an aggregate value slot indicating that the |
579 | /// aggregate value is being ignored. |
580 | static AggValueSlot ignored() { |
581 | return forAddr(addr: Address::invalid(), quals: Qualifiers(), isDestructed: IsNotDestructed, |
582 | needsGC: DoesNotNeedGCBarriers, isAliased: IsNotAliased, mayOverlap: DoesNotOverlap); |
583 | } |
584 | |
585 | /// forAddr - Make a slot for an aggregate value. |
586 | /// |
587 | /// \param quals - The qualifiers that dictate how the slot should |
588 | /// be initialied. Only 'volatile' and the Objective-C lifetime |
589 | /// qualifiers matter. |
590 | /// |
591 | /// \param isDestructed - true if something else is responsible |
592 | /// for calling destructors on this object |
593 | /// \param needsGC - true if the slot is potentially located |
594 | /// somewhere that ObjC GC calls should be emitted for |
595 | static AggValueSlot forAddr(Address addr, |
596 | Qualifiers quals, |
597 | IsDestructed_t isDestructed, |
598 | NeedsGCBarriers_t needsGC, |
599 | IsAliased_t isAliased, |
600 | Overlap_t mayOverlap, |
601 | IsZeroed_t isZeroed = IsNotZeroed, |
602 | IsSanitizerChecked_t isChecked = IsNotSanitizerChecked) { |
603 | if (addr.isValid()) |
604 | addr.setKnownNonNull(); |
605 | return AggValueSlot(addr, quals, isDestructed, needsGC, isZeroed, isAliased, |
606 | mayOverlap, isChecked); |
607 | } |
608 | |
609 | static AggValueSlot |
610 | forLValue(const LValue &LV, CodeGenFunction &CGF, IsDestructed_t isDestructed, |
611 | NeedsGCBarriers_t needsGC, IsAliased_t isAliased, |
612 | Overlap_t mayOverlap, IsZeroed_t isZeroed = IsNotZeroed, |
613 | IsSanitizerChecked_t isChecked = IsNotSanitizerChecked) { |
614 | return forAddr(addr: LV.getAddress(CGF), quals: LV.getQuals(), isDestructed, needsGC, |
615 | isAliased, mayOverlap, isZeroed, isChecked); |
616 | } |
617 | |
618 | IsDestructed_t isExternallyDestructed() const { |
619 | return IsDestructed_t(DestructedFlag); |
620 | } |
621 | void setExternallyDestructed(bool destructed = true) { |
622 | DestructedFlag = destructed; |
623 | } |
624 | |
625 | Qualifiers getQualifiers() const { return Quals; } |
626 | |
627 | bool isVolatile() const { |
628 | return Quals.hasVolatile(); |
629 | } |
630 | |
631 | void setVolatile(bool flag) { |
632 | if (flag) |
633 | Quals.addVolatile(); |
634 | else |
635 | Quals.removeVolatile(); |
636 | } |
637 | |
638 | Qualifiers::ObjCLifetime getObjCLifetime() const { |
639 | return Quals.getObjCLifetime(); |
640 | } |
641 | |
642 | NeedsGCBarriers_t requiresGCollection() const { |
643 | return NeedsGCBarriers_t(ObjCGCFlag); |
644 | } |
645 | |
646 | llvm::Value *getPointer(QualType PointeeTy, CodeGenFunction &CGF) const; |
647 | |
648 | llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { |
649 | return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; |
650 | } |
651 | |
652 | Address getAddress() const { |
653 | return Addr; |
654 | } |
655 | |
656 | bool isIgnored() const { return !Addr.isValid(); } |
657 | |
658 | CharUnits getAlignment() const { |
659 | return Addr.getAlignment(); |
660 | } |
661 | |
662 | IsAliased_t isPotentiallyAliased() const { |
663 | return IsAliased_t(AliasedFlag); |
664 | } |
665 | |
666 | Overlap_t mayOverlap() const { |
667 | return Overlap_t(OverlapFlag); |
668 | } |
669 | |
670 | bool isSanitizerChecked() const { |
671 | return SanitizerCheckedFlag; |
672 | } |
673 | |
674 | RValue asRValue() const { |
675 | if (isIgnored()) { |
676 | return RValue::getIgnored(); |
677 | } else { |
678 | return RValue::getAggregate(addr: getAddress(), isVolatile: isVolatile()); |
679 | } |
680 | } |
681 | |
682 | void setZeroed(bool V = true) { ZeroedFlag = V; } |
683 | IsZeroed_t isZeroed() const { |
684 | return IsZeroed_t(ZeroedFlag); |
685 | } |
686 | |
687 | /// Get the preferred size to use when storing a value to this slot. This |
688 | /// is the type size unless that might overlap another object, in which |
689 | /// case it's the dsize. |
690 | CharUnits getPreferredSize(ASTContext &Ctx, QualType Type) const { |
691 | return mayOverlap() ? Ctx.getTypeInfoDataSizeInChars(T: Type).Width |
692 | : Ctx.getTypeSizeInChars(T: Type); |
693 | } |
694 | }; |
695 | |
696 | } // end namespace CodeGen |
697 | } // end namespace clang |
698 | |
699 | #endif |
700 | |