| Daniel Dunbar | 2eecaab | 2008-08-23 03:10:25 +0000 | [diff] [blame] | 1 | //===-- CGValue.h - LLVM CodeGen wrappers for llvm::Value* ------*- C++ -*-===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // These classes implement wrappers around llvm::Value in order to | 
|  | 11 | // fully represent the range of values for C L- and R- values. | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
|  | 15 | #ifndef CLANG_CODEGEN_CGVALUE_H | 
|  | 16 | #define CLANG_CODEGEN_CGVALUE_H | 
|  | 17 |  | 
|  | 18 | #include "clang/AST/Type.h" | 
|  | 19 |  | 
| Daniel Dunbar | 46f45b9 | 2008-09-09 01:06:48 +0000 | [diff] [blame] | 20 | namespace llvm { | 
|  | 21 | class Constant; | 
|  | 22 | class Value; | 
|  | 23 | } | 
|  | 24 |  | 
| Daniel Dunbar | 2eecaab | 2008-08-23 03:10:25 +0000 | [diff] [blame] | 25 | namespace clang { | 
| Daniel Dunbar | 85c59ed | 2008-08-29 08:11:39 +0000 | [diff] [blame] | 26 | class ObjCPropertyRefExpr; | 
|  | 27 |  | 
| Daniel Dunbar | 2eecaab | 2008-08-23 03:10:25 +0000 | [diff] [blame] | 28 | namespace CodeGen { | 
|  | 29 |  | 
|  | 30 | /// RValue - This trivial value class is used to represent the result of an | 
|  | 31 | /// expression that is evaluated.  It can be one of three things: either a | 
|  | 32 | /// simple LLVM SSA value, a pair of SSA values for complex numbers, or the | 
|  | 33 | /// address of an aggregate value in memory. | 
|  | 34 | class RValue { | 
|  | 35 | llvm::Value *V1, *V2; | 
|  | 36 | // TODO: Encode this into the low bit of pointer for more efficient | 
|  | 37 | // return-by-value. | 
|  | 38 | enum { Scalar, Complex, Aggregate } Flavor; | 
|  | 39 |  | 
|  | 40 | // FIXME: Aggregate rvalues need to retain information about whether they are | 
|  | 41 | // volatile or not. | 
|  | 42 | public: | 
|  | 43 |  | 
|  | 44 | bool isScalar() const { return Flavor == Scalar; } | 
|  | 45 | bool isComplex() const { return Flavor == Complex; } | 
|  | 46 | bool isAggregate() const { return Flavor == Aggregate; } | 
|  | 47 |  | 
|  | 48 | /// getScalar() - Return the Value* of this scalar value. | 
|  | 49 | llvm::Value *getScalarVal() const { | 
|  | 50 | assert(isScalar() && "Not a scalar!"); | 
|  | 51 | return V1; | 
|  | 52 | } | 
|  | 53 |  | 
|  | 54 | /// getComplexVal - Return the real/imag components of this complex value. | 
|  | 55 | /// | 
|  | 56 | std::pair<llvm::Value *, llvm::Value *> getComplexVal() const { | 
|  | 57 | return std::pair<llvm::Value *, llvm::Value *>(V1, V2); | 
|  | 58 | } | 
|  | 59 |  | 
|  | 60 | /// getAggregateAddr() - Return the Value* of the address of the aggregate. | 
|  | 61 | llvm::Value *getAggregateAddr() const { | 
|  | 62 | assert(isAggregate() && "Not an aggregate!"); | 
|  | 63 | return V1; | 
|  | 64 | } | 
|  | 65 |  | 
|  | 66 | static RValue get(llvm::Value *V) { | 
|  | 67 | RValue ER; | 
|  | 68 | ER.V1 = V; | 
|  | 69 | ER.Flavor = Scalar; | 
|  | 70 | return ER; | 
|  | 71 | } | 
|  | 72 | static RValue getComplex(llvm::Value *V1, llvm::Value *V2) { | 
|  | 73 | RValue ER; | 
|  | 74 | ER.V1 = V1; | 
|  | 75 | ER.V2 = V2; | 
|  | 76 | ER.Flavor = Complex; | 
|  | 77 | return ER; | 
|  | 78 | } | 
|  | 79 | static RValue getComplex(const std::pair<llvm::Value *, llvm::Value *> &C) { | 
|  | 80 | RValue ER; | 
|  | 81 | ER.V1 = C.first; | 
|  | 82 | ER.V2 = C.second; | 
|  | 83 | ER.Flavor = Complex; | 
|  | 84 | return ER; | 
|  | 85 | } | 
|  | 86 | static RValue getAggregate(llvm::Value *V) { | 
|  | 87 | RValue ER; | 
|  | 88 | ER.V1 = V; | 
|  | 89 | ER.Flavor = Aggregate; | 
|  | 90 | return ER; | 
|  | 91 | } | 
|  | 92 | }; | 
|  | 93 |  | 
|  | 94 |  | 
|  | 95 | /// LValue - This represents an lvalue references.  Because C/C++ allow | 
|  | 96 | /// bitfields, this is not a simple LLVM pointer, it may be a pointer plus a | 
|  | 97 | /// bitrange. | 
|  | 98 | class LValue { | 
|  | 99 | // FIXME: alignment? | 
|  | 100 |  | 
|  | 101 | enum { | 
|  | 102 | Simple,       // This is a normal l-value, use getAddress(). | 
|  | 103 | VectorElt,    // This is a vector element l-value (V[i]), use getVector* | 
|  | 104 | BitField,     // This is a bitfield l-value, use getBitfield*. | 
| Daniel Dunbar | 85c59ed | 2008-08-29 08:11:39 +0000 | [diff] [blame] | 105 | ExtVectorElt, // This is an extended vector subset, use getExtVectorComp | 
|  | 106 | PropertyRef   // This is an Objective-C property reference, use | 
|  | 107 | // getPropertyRefExpr | 
| Daniel Dunbar | 2eecaab | 2008-08-23 03:10:25 +0000 | [diff] [blame] | 108 | } LVType; | 
| Fariborz Jahanian | 5862650 | 2008-11-19 00:59:10 +0000 | [diff] [blame] | 109 |  | 
|  | 110 | enum ObjCType { | 
|  | 111 | None = 0,	// object with no gc attribute. | 
|  | 112 | Weak,	// __weak object expression | 
|  | 113 | Strong      // __strong object expression | 
|  | 114 | }; | 
| Daniel Dunbar | 2eecaab | 2008-08-23 03:10:25 +0000 | [diff] [blame] | 115 |  | 
|  | 116 | llvm::Value *V; | 
|  | 117 |  | 
|  | 118 | union { | 
|  | 119 | // Index into a vector subscript: V[i] | 
|  | 120 | llvm::Value *VectorIdx; | 
|  | 121 |  | 
|  | 122 | // ExtVector element subset: V.xyx | 
|  | 123 | llvm::Constant *VectorElts; | 
|  | 124 |  | 
|  | 125 | // BitField start bit and size | 
|  | 126 | struct { | 
|  | 127 | unsigned short StartBit; | 
|  | 128 | unsigned short Size; | 
|  | 129 | bool IsSigned; | 
|  | 130 | } BitfieldData; | 
| Daniel Dunbar | 85c59ed | 2008-08-29 08:11:39 +0000 | [diff] [blame] | 131 |  | 
|  | 132 | // Obj-C property reference expression | 
|  | 133 | const ObjCPropertyRefExpr *PropertyRefExpr; | 
| Daniel Dunbar | 2eecaab | 2008-08-23 03:10:25 +0000 | [diff] [blame] | 134 | }; | 
|  | 135 |  | 
|  | 136 | bool Volatile:1; | 
|  | 137 | // FIXME: set but never used, what effect should it have? | 
|  | 138 | bool Restrict:1; | 
| Fariborz Jahanian | 5862650 | 2008-11-19 00:59:10 +0000 | [diff] [blame] | 139 |  | 
| Fariborz Jahanian | d1cc804 | 2008-11-20 20:53:20 +0000 | [diff] [blame^] | 140 | // objective-c's ivar | 
|  | 141 | bool Ivar:1; | 
|  | 142 |  | 
| Fariborz Jahanian | 5862650 | 2008-11-19 00:59:10 +0000 | [diff] [blame] | 143 | // objective-c's gc attributes | 
|  | 144 | unsigned ObjCType : 2; | 
| Fariborz Jahanian | d1cc804 | 2008-11-20 20:53:20 +0000 | [diff] [blame^] | 145 |  | 
| Daniel Dunbar | 2eecaab | 2008-08-23 03:10:25 +0000 | [diff] [blame] | 146 |  | 
|  | 147 | private: | 
|  | 148 | static void SetQualifiers(unsigned Qualifiers, LValue& R) { | 
|  | 149 | R.Volatile = (Qualifiers&QualType::Volatile)!=0; | 
|  | 150 | R.Restrict = (Qualifiers&QualType::Restrict)!=0; | 
| Fariborz Jahanian | 6dc2317 | 2008-11-18 21:45:40 +0000 | [diff] [blame] | 151 | // FIXME: Convenient place to set objc flags to 0. This | 
|  | 152 | // should really be done in a user-defined constructor instead. | 
| Fariborz Jahanian | 5862650 | 2008-11-19 00:59:10 +0000 | [diff] [blame] | 153 | R.ObjCType = None; | 
| Fariborz Jahanian | d1cc804 | 2008-11-20 20:53:20 +0000 | [diff] [blame^] | 154 | R.Ivar = false; | 
| Daniel Dunbar | 2eecaab | 2008-08-23 03:10:25 +0000 | [diff] [blame] | 155 | } | 
| Fariborz Jahanian | 6d657c4 | 2008-11-18 20:18:11 +0000 | [diff] [blame] | 156 |  | 
| Daniel Dunbar | 2eecaab | 2008-08-23 03:10:25 +0000 | [diff] [blame] | 157 | public: | 
|  | 158 | bool isSimple() const { return LVType == Simple; } | 
|  | 159 | bool isVectorElt() const { return LVType == VectorElt; } | 
|  | 160 | bool isBitfield() const { return LVType == BitField; } | 
|  | 161 | bool isExtVectorElt() const { return LVType == ExtVectorElt; } | 
| Daniel Dunbar | 85c59ed | 2008-08-29 08:11:39 +0000 | [diff] [blame] | 162 | bool isPropertyRef() const { return LVType == PropertyRef; } | 
|  | 163 |  | 
| Daniel Dunbar | 2eecaab | 2008-08-23 03:10:25 +0000 | [diff] [blame] | 164 | bool isVolatileQualified() const { return Volatile; } | 
|  | 165 | bool isRestrictQualified() const { return Restrict; } | 
| Fariborz Jahanian | 6d657c4 | 2008-11-18 20:18:11 +0000 | [diff] [blame] | 166 |  | 
| Fariborz Jahanian | d1cc804 | 2008-11-20 20:53:20 +0000 | [diff] [blame^] | 167 | bool isObjCIvar() const { return Ivar; } | 
| Fariborz Jahanian | dbd32c2 | 2008-11-19 17:34:06 +0000 | [diff] [blame] | 168 | bool isObjCWeak() const { return ObjCType == Weak; } | 
|  | 169 | bool isObjCStrong() const { return ObjCType == Strong; } | 
| Fariborz Jahanian | 6d657c4 | 2008-11-18 20:18:11 +0000 | [diff] [blame] | 170 |  | 
| Fariborz Jahanian | d1cc804 | 2008-11-20 20:53:20 +0000 | [diff] [blame^] | 171 | static void SetObjCIvar(LValue& R) { | 
|  | 172 | R.Ivar = true; | 
|  | 173 | } | 
|  | 174 |  | 
| Fariborz Jahanian | 0c43f26 | 2008-11-19 18:38:10 +0000 | [diff] [blame] | 175 | static void SetObjCType(bool isWeak, bool isStrong, LValue& R) { | 
|  | 176 | assert(!(isWeak == true && isStrong == true)); | 
|  | 177 | if (isWeak) | 
| Fariborz Jahanian | 5862650 | 2008-11-19 00:59:10 +0000 | [diff] [blame] | 178 | R.ObjCType = Weak; | 
| Fariborz Jahanian | 0c43f26 | 2008-11-19 18:38:10 +0000 | [diff] [blame] | 179 | else if (isStrong) | 
| Fariborz Jahanian | 5862650 | 2008-11-19 00:59:10 +0000 | [diff] [blame] | 180 | R.ObjCType = Strong; | 
| Fariborz Jahanian | 6d657c4 | 2008-11-18 20:18:11 +0000 | [diff] [blame] | 181 | } | 
|  | 182 |  | 
| Daniel Dunbar | 2eecaab | 2008-08-23 03:10:25 +0000 | [diff] [blame] | 183 | // simple lvalue | 
|  | 184 | llvm::Value *getAddress() const { assert(isSimple()); return V; } | 
|  | 185 | // vector elt lvalue | 
|  | 186 | llvm::Value *getVectorAddr() const { assert(isVectorElt()); return V; } | 
|  | 187 | llvm::Value *getVectorIdx() const { assert(isVectorElt()); return VectorIdx; } | 
|  | 188 | // extended vector elements. | 
|  | 189 | llvm::Value *getExtVectorAddr() const { assert(isExtVectorElt()); return V; } | 
|  | 190 | llvm::Constant *getExtVectorElts() const { | 
|  | 191 | assert(isExtVectorElt()); | 
|  | 192 | return VectorElts; | 
|  | 193 | } | 
|  | 194 | // bitfield lvalue | 
|  | 195 | llvm::Value *getBitfieldAddr() const { assert(isBitfield()); return V; } | 
|  | 196 | unsigned short getBitfieldStartBit() const { | 
|  | 197 | assert(isBitfield()); | 
|  | 198 | return BitfieldData.StartBit; | 
|  | 199 | } | 
|  | 200 | unsigned short getBitfieldSize() const { | 
|  | 201 | assert(isBitfield()); | 
|  | 202 | return BitfieldData.Size; | 
|  | 203 | } | 
|  | 204 | bool isBitfieldSigned() const { | 
|  | 205 | assert(isBitfield()); | 
|  | 206 | return BitfieldData.IsSigned; | 
|  | 207 | } | 
| Daniel Dunbar | 85c59ed | 2008-08-29 08:11:39 +0000 | [diff] [blame] | 208 | // property ref lvalue | 
|  | 209 | const ObjCPropertyRefExpr *getPropertyRefExpr() const { | 
|  | 210 | assert(isPropertyRef()); | 
|  | 211 | return PropertyRefExpr; | 
|  | 212 | } | 
| Daniel Dunbar | 2eecaab | 2008-08-23 03:10:25 +0000 | [diff] [blame] | 213 |  | 
|  | 214 | static LValue MakeAddr(llvm::Value *V, unsigned Qualifiers) { | 
|  | 215 | LValue R; | 
|  | 216 | R.LVType = Simple; | 
|  | 217 | R.V = V; | 
|  | 218 | SetQualifiers(Qualifiers,R); | 
|  | 219 | return R; | 
|  | 220 | } | 
|  | 221 |  | 
|  | 222 | static LValue MakeVectorElt(llvm::Value *Vec, llvm::Value *Idx, | 
|  | 223 | unsigned Qualifiers) { | 
|  | 224 | LValue R; | 
|  | 225 | R.LVType = VectorElt; | 
|  | 226 | R.V = Vec; | 
|  | 227 | R.VectorIdx = Idx; | 
|  | 228 | SetQualifiers(Qualifiers,R); | 
|  | 229 | return R; | 
|  | 230 | } | 
|  | 231 |  | 
|  | 232 | static LValue MakeExtVectorElt(llvm::Value *Vec, llvm::Constant *Elts, | 
|  | 233 | unsigned Qualifiers) { | 
|  | 234 | LValue R; | 
|  | 235 | R.LVType = ExtVectorElt; | 
|  | 236 | R.V = Vec; | 
|  | 237 | R.VectorElts = Elts; | 
|  | 238 | SetQualifiers(Qualifiers,R); | 
|  | 239 | return R; | 
|  | 240 | } | 
|  | 241 |  | 
|  | 242 | static LValue MakeBitfield(llvm::Value *V, unsigned short StartBit, | 
|  | 243 | unsigned short Size, bool IsSigned, | 
|  | 244 | unsigned Qualifiers) { | 
|  | 245 | LValue R; | 
|  | 246 | R.LVType = BitField; | 
|  | 247 | R.V = V; | 
|  | 248 | R.BitfieldData.StartBit = StartBit; | 
|  | 249 | R.BitfieldData.Size = Size; | 
|  | 250 | R.BitfieldData.IsSigned = IsSigned; | 
|  | 251 | SetQualifiers(Qualifiers,R); | 
|  | 252 | return R; | 
|  | 253 | } | 
| Daniel Dunbar | 85c59ed | 2008-08-29 08:11:39 +0000 | [diff] [blame] | 254 |  | 
| Daniel Dunbar | f951719 | 2008-10-17 23:02:24 +0000 | [diff] [blame] | 255 | // FIXME: It is probably bad that we aren't emitting the target when | 
|  | 256 | // we build the lvalue. However, this complicates the code a bit, | 
|  | 257 | // and I haven't figured out how to make it go wrong yet. | 
| Daniel Dunbar | 85c59ed | 2008-08-29 08:11:39 +0000 | [diff] [blame] | 258 | static LValue MakePropertyRef(const ObjCPropertyRefExpr *E, | 
|  | 259 | unsigned Qualifiers) { | 
|  | 260 | LValue R; | 
|  | 261 | R.LVType = PropertyRef; | 
|  | 262 | R.PropertyRefExpr = E; | 
|  | 263 | SetQualifiers(Qualifiers,R); | 
|  | 264 | return R; | 
|  | 265 | } | 
| Daniel Dunbar | 2eecaab | 2008-08-23 03:10:25 +0000 | [diff] [blame] | 266 | }; | 
|  | 267 |  | 
|  | 268 | }  // end namespace CodeGen | 
|  | 269 | }  // end namespace clang | 
|  | 270 |  | 
|  | 271 | #endif |