1193326Sed//===-- CGValue.h - LLVM CodeGen wrappers for llvm::Value* ------*- C++ -*-===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed// These classes implement wrappers around llvm::Value in order to
11193326Sed// fully represent the range of values for C L- and R- values.
12193326Sed//
13193326Sed//===----------------------------------------------------------------------===//
14193326Sed
15280031Sdim#ifndef LLVM_CLANG_LIB_CODEGEN_CGVALUE_H
16280031Sdim#define LLVM_CLANG_LIB_CODEGEN_CGVALUE_H
17193326Sed
18212904Sdim#include "clang/AST/ASTContext.h"
19193326Sed#include "clang/AST/Type.h"
20249423Sdim#include "llvm/IR/Value.h"
21288943Sdim#include "llvm/IR/Type.h"
22296417Sdim#include "Address.h"
23193326Sed
24193326Sednamespace llvm {
25193326Sed  class Constant;
26249423Sdim  class MDNode;
27193326Sed}
28193326Sed
29193326Sednamespace clang {
30193326Sednamespace CodeGen {
31234353Sdim  class AggValueSlot;
32249423Sdim  struct CGBitFieldInfo;
33193326Sed
34193326Sed/// RValue - This trivial value class is used to represent the result of an
35193326Sed/// expression that is evaluated.  It can be one of three things: either a
36193326Sed/// simple LLVM SSA value, a pair of SSA values for complex numbers, or the
37193326Sed/// address of an aggregate value in memory.
38193326Sedclass RValue {
39207619Srdivacky  enum Flavor { Scalar, Complex, Aggregate };
40198092Srdivacky
41296417Sdim  // The shift to make to an aggregate's alignment to make it look
42296417Sdim  // like a pointer.
43296417Sdim  enum { AggAlignShift = 4 };
44296417Sdim
45207619Srdivacky  // Stores first value and flavor.
46207619Srdivacky  llvm::PointerIntPair<llvm::Value *, 2, Flavor> V1;
47207619Srdivacky  // Stores second value and volatility.
48207619Srdivacky  llvm::PointerIntPair<llvm::Value *, 1, bool> V2;
49207619Srdivacky
50193326Sedpublic:
51207619Srdivacky  bool isScalar() const { return V1.getInt() == Scalar; }
52207619Srdivacky  bool isComplex() const { return V1.getInt() == Complex; }
53207619Srdivacky  bool isAggregate() const { return V1.getInt() == Aggregate; }
54198092Srdivacky
55207619Srdivacky  bool isVolatileQualified() const { return V2.getInt(); }
56198092Srdivacky
57198893Srdivacky  /// getScalarVal() - Return the Value* of this scalar value.
58193326Sed  llvm::Value *getScalarVal() const {
59193326Sed    assert(isScalar() && "Not a scalar!");
60207619Srdivacky    return V1.getPointer();
61193326Sed  }
62193326Sed
63193326Sed  /// getComplexVal - Return the real/imag components of this complex value.
64193326Sed  ///
65193326Sed  std::pair<llvm::Value *, llvm::Value *> getComplexVal() const {
66207619Srdivacky    return std::make_pair(V1.getPointer(), V2.getPointer());
67193326Sed  }
68198092Srdivacky
69193326Sed  /// getAggregateAddr() - Return the Value* of the address of the aggregate.
70296417Sdim  Address getAggregateAddress() const {
71193326Sed    assert(isAggregate() && "Not an aggregate!");
72296417Sdim    auto align = reinterpret_cast<uintptr_t>(V2.getPointer()) >> AggAlignShift;
73296417Sdim    return Address(V1.getPointer(), CharUnits::fromQuantity(align));
74296417Sdim  }
75296417Sdim  llvm::Value *getAggregatePointer() const {
76296417Sdim    assert(isAggregate() && "Not an aggregate!");
77207619Srdivacky    return V1.getPointer();
78193326Sed  }
79198092Srdivacky
80296417Sdim  static RValue getIgnored() {
81296417Sdim    // FIXME: should we make this a more explicit state?
82296417Sdim    return get(nullptr);
83296417Sdim  }
84296417Sdim
85193326Sed  static RValue get(llvm::Value *V) {
86193326Sed    RValue ER;
87207619Srdivacky    ER.V1.setPointer(V);
88207619Srdivacky    ER.V1.setInt(Scalar);
89207619Srdivacky    ER.V2.setInt(false);
90193326Sed    return ER;
91193326Sed  }
92193326Sed  static RValue getComplex(llvm::Value *V1, llvm::Value *V2) {
93193326Sed    RValue ER;
94207619Srdivacky    ER.V1.setPointer(V1);
95207619Srdivacky    ER.V2.setPointer(V2);
96207619Srdivacky    ER.V1.setInt(Complex);
97207619Srdivacky    ER.V2.setInt(false);
98193326Sed    return ER;
99193326Sed  }
100193326Sed  static RValue getComplex(const std::pair<llvm::Value *, llvm::Value *> &C) {
101207619Srdivacky    return getComplex(C.first, C.second);
102193326Sed  }
103193326Sed  // FIXME: Aggregate rvalues need to retain information about whether they are
104193326Sed  // volatile or not.  Remove default to find all places that probably get this
105193326Sed  // wrong.
106296417Sdim  static RValue getAggregate(Address addr, bool isVolatile = false) {
107193326Sed    RValue ER;
108296417Sdim    ER.V1.setPointer(addr.getPointer());
109207619Srdivacky    ER.V1.setInt(Aggregate);
110296417Sdim
111296417Sdim    auto align = static_cast<uintptr_t>(addr.getAlignment().getQuantity());
112296417Sdim    ER.V2.setPointer(reinterpret_cast<llvm::Value*>(align << AggAlignShift));
113296417Sdim    ER.V2.setInt(isVolatile);
114193326Sed    return ER;
115193326Sed  }
116193326Sed};
117193326Sed
118249423Sdim/// Does an ARC strong l-value have precise lifetime?
119249423Sdimenum ARCPreciseLifetime_t {
120249423Sdim  ARCImpreciseLifetime, ARCPreciseLifetime
121249423Sdim};
122193326Sed
123296417Sdim/// The source of the alignment of an l-value; an expression of
124296417Sdim/// confidence in the alignment actually matching the estimate.
125296417Sdimenum class AlignmentSource {
126296417Sdim  /// The l-value was an access to a declared entity or something
127296417Sdim  /// equivalently strong, like the address of an array allocated by a
128296417Sdim  /// language runtime.
129296417Sdim  Decl,
130296417Sdim
131296417Sdim  /// The l-value was considered opaque, so the alignment was
132296417Sdim  /// determined from a type, but that type was an explicitly-aligned
133296417Sdim  /// typedef.
134296417Sdim  AttributedType,
135296417Sdim
136296417Sdim  /// The l-value was considered opaque, so the alignment was
137296417Sdim  /// determined from a type.
138296417Sdim  Type
139296417Sdim};
140296417Sdim
141296417Sdim/// Given that the base address has the given alignment source, what's
142296417Sdim/// our confidence in the alignment of the field?
143296417Sdimstatic inline AlignmentSource getFieldAlignmentSource(AlignmentSource Source) {
144296417Sdim  // For now, we don't distinguish fields of opaque pointers from
145296417Sdim  // top-level declarations, but maybe we should.
146296417Sdim  return AlignmentSource::Decl;
147296417Sdim}
148296417Sdim
149193326Sed/// LValue - This represents an lvalue references.  Because C/C++ allow
150193326Sed/// bitfields, this is not a simple LLVM pointer, it may be a pointer plus a
151193326Sed/// bitrange.
152193326Sedclass LValue {
153193326Sed  enum {
154193326Sed    Simple,       // This is a normal l-value, use getAddress().
155193326Sed    VectorElt,    // This is a vector element l-value (V[i]), use getVector*
156193326Sed    BitField,     // This is a bitfield l-value, use getBitfield*.
157276479Sdim    ExtVectorElt, // This is an extended vector subset, use getExtVectorComp
158276479Sdim    GlobalReg     // This is a register l-value, use getGlobalReg()
159193326Sed  } LVType;
160193326Sed
161193326Sed  llvm::Value *V;
162198092Srdivacky
163193326Sed  union {
164193326Sed    // Index into a vector subscript: V[i]
165193326Sed    llvm::Value *VectorIdx;
166193326Sed
167193326Sed    // ExtVector element subset: V.xyx
168193326Sed    llvm::Constant *VectorElts;
169198092Srdivacky
170193326Sed    // BitField start bit and size
171206275Srdivacky    const CGBitFieldInfo *BitFieldInfo;
172193326Sed  };
173193326Sed
174224145Sdim  QualType Type;
175224145Sdim
176198092Srdivacky  // 'const' is unused here
177198092Srdivacky  Qualifiers Quals;
178193326Sed
179234353Sdim  // The alignment to use when accessing this lvalue.  (For vector elements,
180234353Sdim  // this is the alignment of the whole vector.)
181239462Sdim  int64_t Alignment;
182212904Sdim
183193326Sed  // objective-c's ivar
184193326Sed  bool Ivar:1;
185193326Sed
186198092Srdivacky  // objective-c's ivar is an array
187198092Srdivacky  bool ObjIsArray:1;
188198092Srdivacky
189193326Sed  // LValue is non-gc'able for any reason, including being a parameter or local
190193326Sed  // variable.
191193326Sed  bool NonGC: 1;
192193326Sed
193193326Sed  // Lvalue is a global reference of an objective-c object
194193326Sed  bool GlobalObjCRef : 1;
195212904Sdim
196212904Sdim  // Lvalue is a thread local reference
197212904Sdim  bool ThreadLocalRef : 1;
198193326Sed
199249423Sdim  // Lvalue has ARC imprecise lifetime.  We store this inverted to try
200249423Sdim  // to make the default bitfield pattern all-zeroes.
201249423Sdim  bool ImpreciseLifetime : 1;
202249423Sdim
203296417Sdim  unsigned AlignSource : 2;
204296417Sdim
205296417Sdim  // This flag shows if a nontemporal load/stores should be used when accessing
206296417Sdim  // this lvalue.
207296417Sdim  bool Nontemporal : 1;
208296417Sdim
209198092Srdivacky  Expr *BaseIvarExp;
210218893Sdim
211249423Sdim  /// Used by struct-path-aware TBAA.
212249423Sdim  QualType TBAABaseType;
213249423Sdim  /// Offset relative to the base type.
214249423Sdim  uint64_t TBAAOffset;
215249423Sdim
216218893Sdim  /// TBAAInfo - TBAA information to attach to dereferences of this LValue.
217218893Sdim  llvm::MDNode *TBAAInfo;
218218893Sdim
219193326Sedprivate:
220234353Sdim  void Initialize(QualType Type, Qualifiers Quals,
221296417Sdim                  CharUnits Alignment, AlignmentSource AlignSource,
222276479Sdim                  llvm::MDNode *TBAAInfo = nullptr) {
223296417Sdim    assert((!Alignment.isZero() || Type->isIncompleteType()) &&
224296417Sdim           "initializing l-value with zero alignment!");
225224145Sdim    this->Type = Type;
226198092Srdivacky    this->Quals = Quals;
227234353Sdim    this->Alignment = Alignment.getQuantity();
228234353Sdim    assert(this->Alignment == Alignment.getQuantity() &&
229234353Sdim           "Alignment exceeds allowed max!");
230296417Sdim    this->AlignSource = unsigned(AlignSource);
231212904Sdim
232212904Sdim    // Initialize Objective-C flags.
233198092Srdivacky    this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
234249423Sdim    this->ImpreciseLifetime = false;
235296417Sdim    this->Nontemporal = false;
236212904Sdim    this->ThreadLocalRef = false;
237276479Sdim    this->BaseIvarExp = nullptr;
238249423Sdim
239249423Sdim    // Initialize fields for TBAA.
240249423Sdim    this->TBAABaseType = Type;
241249423Sdim    this->TBAAOffset = 0;
242218893Sdim    this->TBAAInfo = TBAAInfo;
243193326Sed  }
244198092Srdivacky
245193326Sedpublic:
246193326Sed  bool isSimple() const { return LVType == Simple; }
247193326Sed  bool isVectorElt() const { return LVType == VectorElt; }
248206275Srdivacky  bool isBitField() const { return LVType == BitField; }
249193326Sed  bool isExtVectorElt() const { return LVType == ExtVectorElt; }
250276479Sdim  bool isGlobalReg() const { return LVType == GlobalReg; }
251193326Sed
252198092Srdivacky  bool isVolatileQualified() const { return Quals.hasVolatile(); }
253198092Srdivacky  bool isRestrictQualified() const { return Quals.hasRestrict(); }
254198092Srdivacky  unsigned getVRQualifiers() const {
255198092Srdivacky    return Quals.getCVRQualifiers() & ~Qualifiers::Const;
256193326Sed  }
257198092Srdivacky
258224145Sdim  QualType getType() const { return Type; }
259224145Sdim
260224145Sdim  Qualifiers::ObjCLifetime getObjCLifetime() const {
261224145Sdim    return Quals.getObjCLifetime();
262224145Sdim  }
263224145Sdim
264193326Sed  bool isObjCIvar() const { return Ivar; }
265212904Sdim  void setObjCIvar(bool Value) { Ivar = Value; }
266212904Sdim
267198092Srdivacky  bool isObjCArray() const { return ObjIsArray; }
268212904Sdim  void setObjCArray(bool Value) { ObjIsArray = Value; }
269212904Sdim
270193326Sed  bool isNonGC () const { return NonGC; }
271212904Sdim  void setNonGC(bool Value) { NonGC = Value; }
272212904Sdim
273193326Sed  bool isGlobalObjCRef() const { return GlobalObjCRef; }
274212904Sdim  void setGlobalObjCRef(bool Value) { GlobalObjCRef = Value; }
275212904Sdim
276212904Sdim  bool isThreadLocalRef() const { return ThreadLocalRef; }
277212904Sdim  void setThreadLocalRef(bool Value) { ThreadLocalRef = Value;}
278212904Sdim
279249423Sdim  ARCPreciseLifetime_t isARCPreciseLifetime() const {
280249423Sdim    return ARCPreciseLifetime_t(!ImpreciseLifetime);
281249423Sdim  }
282249423Sdim  void setARCPreciseLifetime(ARCPreciseLifetime_t value) {
283249423Sdim    ImpreciseLifetime = (value == ARCImpreciseLifetime);
284249423Sdim  }
285296417Sdim  bool isNontemporal() const { return Nontemporal; }
286296417Sdim  void setNontemporal(bool Value) { Nontemporal = Value; }
287249423Sdim
288212904Sdim  bool isObjCWeak() const {
289212904Sdim    return Quals.getObjCGCAttr() == Qualifiers::Weak;
290212904Sdim  }
291212904Sdim  bool isObjCStrong() const {
292212904Sdim    return Quals.getObjCGCAttr() == Qualifiers::Strong;
293212904Sdim  }
294224145Sdim
295224145Sdim  bool isVolatile() const {
296224145Sdim    return Quals.hasVolatile();
297224145Sdim  }
298193326Sed
299198092Srdivacky  Expr *getBaseIvarExp() const { return BaseIvarExp; }
300198092Srdivacky  void setBaseIvarExp(Expr *V) { BaseIvarExp = V; }
301198092Srdivacky
302249423Sdim  QualType getTBAABaseType() const { return TBAABaseType; }
303249423Sdim  void setTBAABaseType(QualType T) { TBAABaseType = T; }
304249423Sdim
305249423Sdim  uint64_t getTBAAOffset() const { return TBAAOffset; }
306249423Sdim  void setTBAAOffset(uint64_t O) { TBAAOffset = O; }
307249423Sdim
308218893Sdim  llvm::MDNode *getTBAAInfo() const { return TBAAInfo; }
309218893Sdim  void setTBAAInfo(llvm::MDNode *N) { TBAAInfo = N; }
310218893Sdim
311212904Sdim  const Qualifiers &getQuals() const { return Quals; }
312212904Sdim  Qualifiers &getQuals() { return Quals; }
313212904Sdim
314198092Srdivacky  unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
315198092Srdivacky
316234353Sdim  CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); }
317234353Sdim  void setAlignment(CharUnits A) { Alignment = A.getQuantity(); }
318198092Srdivacky
319296417Sdim  AlignmentSource getAlignmentSource() const {
320296417Sdim    return AlignmentSource(AlignSource);
321296417Sdim  }
322296417Sdim  void setAlignmentSource(AlignmentSource Source) {
323296417Sdim    AlignSource = unsigned(Source);
324296417Sdim  }
325296417Sdim
326193326Sed  // simple lvalue
327296417Sdim  llvm::Value *getPointer() const {
328224145Sdim    assert(isSimple());
329296417Sdim    return V;
330224145Sdim  }
331296417Sdim  Address getAddress() const { return Address(getPointer(), getAlignment()); }
332296417Sdim  void setAddress(Address address) {
333296417Sdim    assert(isSimple());
334296417Sdim    V = address.getPointer();
335296417Sdim    Alignment = address.getAlignment().getQuantity();
336296417Sdim  }
337206275Srdivacky
338193326Sed  // vector elt lvalue
339296417Sdim  Address getVectorAddress() const {
340296417Sdim    return Address(getVectorPointer(), getAlignment());
341296417Sdim  }
342296417Sdim  llvm::Value *getVectorPointer() const { assert(isVectorElt()); return V; }
343193326Sed  llvm::Value *getVectorIdx() const { assert(isVectorElt()); return VectorIdx; }
344206275Srdivacky
345193326Sed  // extended vector elements.
346296417Sdim  Address getExtVectorAddress() const {
347296417Sdim    return Address(getExtVectorPointer(), getAlignment());
348296417Sdim  }
349296417Sdim  llvm::Value *getExtVectorPointer() const {
350296417Sdim    assert(isExtVectorElt());
351296417Sdim    return V;
352296417Sdim  }
353193326Sed  llvm::Constant *getExtVectorElts() const {
354193326Sed    assert(isExtVectorElt());
355193326Sed    return VectorElts;
356193326Sed  }
357206275Srdivacky
358193326Sed  // bitfield lvalue
359296417Sdim  Address getBitFieldAddress() const {
360296417Sdim    return Address(getBitFieldPointer(), getAlignment());
361193326Sed  }
362296417Sdim  llvm::Value *getBitFieldPointer() const { assert(isBitField()); return V; }
363206275Srdivacky  const CGBitFieldInfo &getBitFieldInfo() const {
364206275Srdivacky    assert(isBitField());
365206275Srdivacky    return *BitFieldInfo;
366193326Sed  }
367206275Srdivacky
368276479Sdim  // global register lvalue
369276479Sdim  llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; }
370276479Sdim
371296417Sdim  static LValue MakeAddr(Address address, QualType type,
372296417Sdim                         ASTContext &Context,
373296417Sdim                         AlignmentSource alignSource,
374276479Sdim                         llvm::MDNode *TBAAInfo = nullptr) {
375224145Sdim    Qualifiers qs = type.getQualifiers();
376224145Sdim    qs.setObjCGCAttr(Context.getObjCGCAttrKind(type));
377212904Sdim
378193326Sed    LValue R;
379193326Sed    R.LVType = Simple;
380296417Sdim    assert(address.getPointer()->getType()->isPointerTy());
381296417Sdim    R.V = address.getPointer();
382296417Sdim    R.Initialize(type, qs, address.getAlignment(), alignSource, TBAAInfo);
383193326Sed    return R;
384193326Sed  }
385198092Srdivacky
386296417Sdim  static LValue MakeVectorElt(Address vecAddress, llvm::Value *Idx,
387296417Sdim                              QualType type, AlignmentSource alignSource) {
388193326Sed    LValue R;
389193326Sed    R.LVType = VectorElt;
390296417Sdim    R.V = vecAddress.getPointer();
391193326Sed    R.VectorIdx = Idx;
392296417Sdim    R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
393296417Sdim                 alignSource);
394193326Sed    return R;
395193326Sed  }
396198092Srdivacky
397296417Sdim  static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts,
398296417Sdim                                 QualType type, AlignmentSource alignSource) {
399193326Sed    LValue R;
400193326Sed    R.LVType = ExtVectorElt;
401296417Sdim    R.V = vecAddress.getPointer();
402193326Sed    R.VectorElts = Elts;
403296417Sdim    R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
404296417Sdim                 alignSource);
405193326Sed    return R;
406193326Sed  }
407193326Sed
408207619Srdivacky  /// \brief Create a new object to represent a bit-field access.
409207619Srdivacky  ///
410249423Sdim  /// \param Addr - The base address of the bit-field sequence this
411249423Sdim  /// bit-field refers to.
412207619Srdivacky  /// \param Info - The information describing how to perform the bit-field
413207619Srdivacky  /// access.
414296417Sdim  static LValue MakeBitfield(Address Addr,
415224145Sdim                             const CGBitFieldInfo &Info,
416296417Sdim                             QualType type,
417296417Sdim                             AlignmentSource alignSource) {
418193326Sed    LValue R;
419193326Sed    R.LVType = BitField;
420296417Sdim    R.V = Addr.getPointer();
421206275Srdivacky    R.BitFieldInfo = &Info;
422296417Sdim    R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), alignSource);
423193326Sed    return R;
424193326Sed  }
425193326Sed
426296417Sdim  static LValue MakeGlobalReg(Address Reg, QualType type) {
427276479Sdim    LValue R;
428276479Sdim    R.LVType = GlobalReg;
429296417Sdim    R.V = Reg.getPointer();
430296417Sdim    R.Initialize(type, type.getQualifiers(), Reg.getAlignment(),
431296417Sdim                 AlignmentSource::Decl);
432276479Sdim    return R;
433276479Sdim  }
434276479Sdim
435234353Sdim  RValue asAggregateRValue() const {
436234353Sdim    return RValue::getAggregate(getAddress(), isVolatileQualified());
437193326Sed  }
438218893Sdim};
439198092Srdivacky
440218893Sdim/// An aggregate value slot.
441218893Sdimclass AggValueSlot {
442218893Sdim  /// The address.
443218893Sdim  llvm::Value *Addr;
444224145Sdim
445224145Sdim  // Qualifiers
446224145Sdim  Qualifiers Quals;
447226633Sdim
448234353Sdim  unsigned short Alignment;
449234353Sdim
450226633Sdim  /// DestructedFlag - This is set to true if some external code is
451226633Sdim  /// responsible for setting up a destructor for the slot.  Otherwise
452226633Sdim  /// the code which constructs it should push the appropriate cleanup.
453226633Sdim  bool DestructedFlag : 1;
454226633Sdim
455226633Sdim  /// ObjCGCFlag - This is set to true if writing to the memory in the
456226633Sdim  /// slot might require calling an appropriate Objective-C GC
457226633Sdim  /// barrier.  The exact interaction here is unnecessarily mysterious.
458226633Sdim  bool ObjCGCFlag : 1;
459218893Sdim
460226633Sdim  /// ZeroedFlag - This is set to true if the memory in the slot is
461226633Sdim  /// known to be zero before the assignment into it.  This means that
462226633Sdim  /// zero fields don't need to be set.
463226633Sdim  bool ZeroedFlag : 1;
464218893Sdim
465226633Sdim  /// AliasedFlag - This is set to true if the slot might be aliased
466226633Sdim  /// and it's not undefined behavior to access it through such an
467226633Sdim  /// alias.  Note that it's always undefined behavior to access a C++
468226633Sdim  /// object that's under construction through an alias derived from
469226633Sdim  /// outside the construction process.
470226633Sdim  ///
471226633Sdim  /// This flag controls whether calls that produce the aggregate
472226633Sdim  /// value may be evaluated directly into the slot, or whether they
473226633Sdim  /// must be evaluated into an unaliased temporary and then memcpy'ed
474226633Sdim  /// over.  Since it's invalid in general to memcpy a non-POD C++
475226633Sdim  /// object, it's important that this flag never be set when
476226633Sdim  /// evaluating an expression which constructs such an object.
477226633Sdim  bool AliasedFlag : 1;
478226633Sdim
479218893Sdimpublic:
480226633Sdim  enum IsAliased_t { IsNotAliased, IsAliased };
481226633Sdim  enum IsDestructed_t { IsNotDestructed, IsDestructed };
482226633Sdim  enum IsZeroed_t { IsNotZeroed, IsZeroed };
483226633Sdim  enum NeedsGCBarriers_t { DoesNotNeedGCBarriers, NeedsGCBarriers };
484226633Sdim
485218893Sdim  /// ignored - Returns an aggregate value slot indicating that the
486218893Sdim  /// aggregate value is being ignored.
487218893Sdim  static AggValueSlot ignored() {
488296417Sdim    return forAddr(Address::invalid(), Qualifiers(), IsNotDestructed,
489234353Sdim                   DoesNotNeedGCBarriers, IsNotAliased);
490193326Sed  }
491218893Sdim
492218893Sdim  /// forAddr - Make a slot for an aggregate value.
493218893Sdim  ///
494226633Sdim  /// \param quals - The qualifiers that dictate how the slot should
495226633Sdim  /// be initialied. Only 'volatile' and the Objective-C lifetime
496226633Sdim  /// qualifiers matter.
497224145Sdim  ///
498226633Sdim  /// \param isDestructed - true if something else is responsible
499226633Sdim  ///   for calling destructors on this object
500226633Sdim  /// \param needsGC - true if the slot is potentially located
501218893Sdim  ///   somewhere that ObjC GC calls should be emitted for
502296417Sdim  static AggValueSlot forAddr(Address addr,
503234353Sdim                              Qualifiers quals,
504226633Sdim                              IsDestructed_t isDestructed,
505226633Sdim                              NeedsGCBarriers_t needsGC,
506226633Sdim                              IsAliased_t isAliased,
507261991Sdim                              IsZeroed_t isZeroed = IsNotZeroed) {
508218893Sdim    AggValueSlot AV;
509296417Sdim    if (addr.isValid()) {
510296417Sdim      AV.Addr = addr.getPointer();
511296417Sdim      AV.Alignment = addr.getAlignment().getQuantity();
512296417Sdim    } else {
513296417Sdim      AV.Addr = nullptr;
514296417Sdim      AV.Alignment = 0;
515296417Sdim    }
516226633Sdim    AV.Quals = quals;
517226633Sdim    AV.DestructedFlag = isDestructed;
518226633Sdim    AV.ObjCGCFlag = needsGC;
519226633Sdim    AV.ZeroedFlag = isZeroed;
520226633Sdim    AV.AliasedFlag = isAliased;
521218893Sdim    return AV;
522218893Sdim  }
523218893Sdim
524239462Sdim  static AggValueSlot forLValue(const LValue &LV,
525239462Sdim                                IsDestructed_t isDestructed,
526226633Sdim                                NeedsGCBarriers_t needsGC,
527226633Sdim                                IsAliased_t isAliased,
528261991Sdim                                IsZeroed_t isZeroed = IsNotZeroed) {
529296417Sdim    return forAddr(LV.getAddress(),
530261991Sdim                   LV.getQuals(), isDestructed, needsGC, isAliased, isZeroed);
531218893Sdim  }
532218893Sdim
533226633Sdim  IsDestructed_t isExternallyDestructed() const {
534226633Sdim    return IsDestructed_t(DestructedFlag);
535218893Sdim  }
536226633Sdim  void setExternallyDestructed(bool destructed = true) {
537226633Sdim    DestructedFlag = destructed;
538218893Sdim  }
539218893Sdim
540224145Sdim  Qualifiers getQualifiers() const { return Quals; }
541224145Sdim
542218893Sdim  bool isVolatile() const {
543224145Sdim    return Quals.hasVolatile();
544218893Sdim  }
545218893Sdim
546249423Sdim  void setVolatile(bool flag) {
547249423Sdim    Quals.setVolatile(flag);
548249423Sdim  }
549249423Sdim
550224145Sdim  Qualifiers::ObjCLifetime getObjCLifetime() const {
551224145Sdim    return Quals.getObjCLifetime();
552224145Sdim  }
553224145Sdim
554226633Sdim  NeedsGCBarriers_t requiresGCollection() const {
555226633Sdim    return NeedsGCBarriers_t(ObjCGCFlag);
556218893Sdim  }
557296417Sdim
558296417Sdim  llvm::Value *getPointer() const {
559218893Sdim    return Addr;
560218893Sdim  }
561218893Sdim
562296417Sdim  Address getAddress() const {
563296417Sdim    return Address(Addr, getAlignment());
564296417Sdim  }
565296417Sdim
566218893Sdim  bool isIgnored() const {
567276479Sdim    return Addr == nullptr;
568218893Sdim  }
569218893Sdim
570234353Sdim  CharUnits getAlignment() const {
571234353Sdim    return CharUnits::fromQuantity(Alignment);
572234353Sdim  }
573234353Sdim
574226633Sdim  IsAliased_t isPotentiallyAliased() const {
575226633Sdim    return IsAliased_t(AliasedFlag);
576226633Sdim  }
577226633Sdim
578218893Sdim  RValue asRValue() const {
579296417Sdim    if (isIgnored()) {
580296417Sdim      return RValue::getIgnored();
581296417Sdim    } else {
582296417Sdim      return RValue::getAggregate(getAddress(), isVolatile());
583296417Sdim    }
584218893Sdim  }
585234353Sdim
586226633Sdim  void setZeroed(bool V = true) { ZeroedFlag = V; }
587226633Sdim  IsZeroed_t isZeroed() const {
588226633Sdim    return IsZeroed_t(ZeroedFlag);
589218893Sdim  }
590193326Sed};
591193326Sed
592193326Sed}  // end namespace CodeGen
593193326Sed}  // end namespace clang
594193326Sed
595193326Sed#endif
596