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