#ifndef CLANG_CODEGEN_CGVALUE_H
#define CLANG_CODEGEN_CGVALUE_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
namespace llvm {
class Constant;
class Value;
}
namespace clang {
namespace CodeGen {
class AggValueSlot;
class CGBitFieldInfo;
class RValue {
enum Flavor { Scalar, Complex, Aggregate };
llvm::PointerIntPair<llvm::Value *, 2, Flavor> V1;
llvm::PointerIntPair<llvm::Value *, 1, bool> V2;
public:
bool isScalar() const { return V1.getInt() == Scalar; }
bool isComplex() const { return V1.getInt() == Complex; }
bool isAggregate() const { return V1.getInt() == Aggregate; }
bool isVolatileQualified() const { return V2.getInt(); }
llvm::Value *getScalarVal() const {
assert(isScalar() && "Not a scalar!");
return V1.getPointer();
}
std::pair<llvm::Value *, llvm::Value *> getComplexVal() const {
return std::make_pair(V1.getPointer(), V2.getPointer());
}
llvm::Value *getAggregateAddr() const {
assert(isAggregate() && "Not an aggregate!");
return V1.getPointer();
}
static RValue get(llvm::Value *V) {
RValue ER;
ER.V1.setPointer(V);
ER.V1.setInt(Scalar);
ER.V2.setInt(false);
return ER;
}
static RValue getComplex(llvm::Value *V1, llvm::Value *V2) {
RValue ER;
ER.V1.setPointer(V1);
ER.V2.setPointer(V2);
ER.V1.setInt(Complex);
ER.V2.setInt(false);
return ER;
}
static RValue getComplex(const std::pair<llvm::Value *, llvm::Value *> &C) {
return getComplex(C.first, C.second);
}
static RValue getAggregate(llvm::Value *V, bool Volatile = false) {
RValue ER;
ER.V1.setPointer(V);
ER.V1.setInt(Aggregate);
ER.V2.setInt(Volatile);
return ER;
}
};
class LValue {
enum {
Simple, VectorElt, BitField, ExtVectorElt } LVType;
llvm::Value *V;
union {
llvm::Value *VectorIdx;
llvm::Constant *VectorElts;
const CGBitFieldInfo *BitFieldInfo;
};
QualType Type;
Qualifiers Quals;
unsigned short Alignment;
bool Ivar:1;
bool ObjIsArray:1;
bool NonGC: 1;
bool GlobalObjCRef : 1;
bool ThreadLocalRef : 1;
Expr *BaseIvarExp;
llvm::MDNode *TBAAInfo;
private:
void Initialize(QualType Type, Qualifiers Quals,
CharUnits Alignment = CharUnits(),
llvm::MDNode *TBAAInfo = 0) {
this->Type = Type;
this->Quals = Quals;
this->Alignment = Alignment.getQuantity();
assert(this->Alignment == Alignment.getQuantity() &&
"Alignment exceeds allowed max!");
this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
this->ThreadLocalRef = false;
this->BaseIvarExp = 0;
this->TBAAInfo = TBAAInfo;
}
public:
bool isSimple() const { return LVType == Simple; }
bool isVectorElt() const { return LVType == VectorElt; }
bool isBitField() const { return LVType == BitField; }
bool isExtVectorElt() const { return LVType == ExtVectorElt; }
bool isVolatileQualified() const { return Quals.hasVolatile(); }
bool isRestrictQualified() const { return Quals.hasRestrict(); }
unsigned getVRQualifiers() const {
return Quals.getCVRQualifiers() & ~Qualifiers::Const;
}
QualType getType() const { return Type; }
Qualifiers::ObjCLifetime getObjCLifetime() const {
return Quals.getObjCLifetime();
}
bool isObjCIvar() const { return Ivar; }
void setObjCIvar(bool Value) { Ivar = Value; }
bool isObjCArray() const { return ObjIsArray; }
void setObjCArray(bool Value) { ObjIsArray = Value; }
bool isNonGC () const { return NonGC; }
void setNonGC(bool Value) { NonGC = Value; }
bool isGlobalObjCRef() const { return GlobalObjCRef; }
void setGlobalObjCRef(bool Value) { GlobalObjCRef = Value; }
bool isThreadLocalRef() const { return ThreadLocalRef; }
void setThreadLocalRef(bool Value) { ThreadLocalRef = Value;}
bool isObjCWeak() const {
return Quals.getObjCGCAttr() == Qualifiers::Weak;
}
bool isObjCStrong() const {
return Quals.getObjCGCAttr() == Qualifiers::Strong;
}
bool isVolatile() const {
return Quals.hasVolatile();
}
Expr *getBaseIvarExp() const { return BaseIvarExp; }
void setBaseIvarExp(Expr *V) { BaseIvarExp = V; }
llvm::MDNode *getTBAAInfo() const { return TBAAInfo; }
void setTBAAInfo(llvm::MDNode *N) { TBAAInfo = N; }
const Qualifiers &getQuals() const { return Quals; }
Qualifiers &getQuals() { return Quals; }
unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); }
void setAlignment(CharUnits A) { Alignment = A.getQuantity(); }
llvm::Value *getAddress() const { assert(isSimple()); return V; }
void setAddress(llvm::Value *address) {
assert(isSimple());
V = address;
}
llvm::Value *getVectorAddr() const { assert(isVectorElt()); return V; }
llvm::Value *getVectorIdx() const { assert(isVectorElt()); return VectorIdx; }
llvm::Value *getExtVectorAddr() const { assert(isExtVectorElt()); return V; }
llvm::Constant *getExtVectorElts() const {
assert(isExtVectorElt());
return VectorElts;
}
llvm::Value *getBitFieldBaseAddr() const {
assert(isBitField());
return V;
}
const CGBitFieldInfo &getBitFieldInfo() const {
assert(isBitField());
return *BitFieldInfo;
}
static LValue MakeAddr(llvm::Value *address, QualType type,
CharUnits alignment, ASTContext &Context,
llvm::MDNode *TBAAInfo = 0) {
Qualifiers qs = type.getQualifiers();
qs.setObjCGCAttr(Context.getObjCGCAttrKind(type));
LValue R;
R.LVType = Simple;
R.V = address;
R.Initialize(type, qs, alignment, TBAAInfo);
return R;
}
static LValue MakeVectorElt(llvm::Value *Vec, llvm::Value *Idx,
QualType type) {
LValue R;
R.LVType = VectorElt;
R.V = Vec;
R.VectorIdx = Idx;
R.Initialize(type, type.getQualifiers());
return R;
}
static LValue MakeExtVectorElt(llvm::Value *Vec, llvm::Constant *Elts,
QualType type) {
LValue R;
R.LVType = ExtVectorElt;
R.V = Vec;
R.VectorElts = Elts;
R.Initialize(type, type.getQualifiers());
return R;
}
static LValue MakeBitfield(llvm::Value *BaseValue,
const CGBitFieldInfo &Info,
QualType type) {
LValue R;
R.LVType = BitField;
R.V = BaseValue;
R.BitFieldInfo = &Info;
R.Initialize(type, type.getQualifiers());
return R;
}
RValue asAggregateRValue() const {
return RValue::getAggregate(getAddress(), isVolatileQualified());
}
};
class AggValueSlot {
llvm::Value *Addr;
Qualifiers Quals;
unsigned short Alignment;
bool DestructedFlag : 1;
bool ObjCGCFlag : 1;
bool ZeroedFlag : 1;
bool AliasedFlag : 1;
public:
enum IsAliased_t { IsNotAliased, IsAliased };
enum IsDestructed_t { IsNotDestructed, IsDestructed };
enum IsZeroed_t { IsNotZeroed, IsZeroed };
enum NeedsGCBarriers_t { DoesNotNeedGCBarriers, NeedsGCBarriers };
static AggValueSlot ignored() {
return forAddr(0, CharUnits(), Qualifiers(), IsNotDestructed,
DoesNotNeedGCBarriers, IsNotAliased);
}
static AggValueSlot forAddr(llvm::Value *addr, CharUnits align,
Qualifiers quals,
IsDestructed_t isDestructed,
NeedsGCBarriers_t needsGC,
IsAliased_t isAliased,
IsZeroed_t isZeroed = IsNotZeroed) {
AggValueSlot AV;
AV.Addr = addr;
AV.Alignment = align.getQuantity();
AV.Quals = quals;
AV.DestructedFlag = isDestructed;
AV.ObjCGCFlag = needsGC;
AV.ZeroedFlag = isZeroed;
AV.AliasedFlag = isAliased;
return AV;
}
static AggValueSlot forLValue(LValue LV, IsDestructed_t isDestructed,
NeedsGCBarriers_t needsGC,
IsAliased_t isAliased,
IsZeroed_t isZeroed = IsNotZeroed) {
return forAddr(LV.getAddress(), LV.getAlignment(),
LV.getQuals(), isDestructed, needsGC, isAliased, isZeroed);
}
IsDestructed_t isExternallyDestructed() const {
return IsDestructed_t(DestructedFlag);
}
void setExternallyDestructed(bool destructed = true) {
DestructedFlag = destructed;
}
Qualifiers getQualifiers() const { return Quals; }
bool isVolatile() const {
return Quals.hasVolatile();
}
Qualifiers::ObjCLifetime getObjCLifetime() const {
return Quals.getObjCLifetime();
}
NeedsGCBarriers_t requiresGCollection() const {
return NeedsGCBarriers_t(ObjCGCFlag);
}
llvm::Value *getAddr() const {
return Addr;
}
bool isIgnored() const {
return Addr == 0;
}
CharUnits getAlignment() const {
return CharUnits::fromQuantity(Alignment);
}
IsAliased_t isPotentiallyAliased() const {
return IsAliased_t(AliasedFlag);
}
RValue asRValue() const {
return RValue::getAggregate(getAddr(), isVolatile());
}
void setZeroed(bool V = true) { ZeroedFlag = V; }
IsZeroed_t isZeroed() const {
return IsZeroed_t(ZeroedFlag);
}
};
} }
#endif