Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 1 | //===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file implements the APValue class. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "clang/AST/APValue.h" |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 14 | #include "clang/AST/ASTContext.h" |
Ken Dyck | 0299083 | 2010-01-15 12:37:54 +0000 | [diff] [blame] | 15 | #include "clang/AST/CharUnits.h" |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 16 | #include "clang/AST/DeclCXX.h" |
| 17 | #include "clang/AST/Expr.h" |
| 18 | #include "clang/AST/Type.h" |
David Blaikie | 76bd3c8 | 2011-09-23 05:35:21 +0000 | [diff] [blame] | 19 | #include "llvm/Support/ErrorHandling.h" |
Chandler Carruth | 3a02247 | 2012-12-04 09:13:33 +0000 | [diff] [blame] | 20 | #include "llvm/Support/raw_ostream.h" |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 21 | using namespace clang; |
| 22 | |
Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 23 | /// The identity of a type_info object depends on the canonical unqualified |
| 24 | /// type only. |
| 25 | TypeInfoLValue::TypeInfoLValue(const Type *T) |
| 26 | : T(T->getCanonicalTypeUnqualified().getTypePtr()) {} |
| 27 | |
| 28 | void TypeInfoLValue::print(llvm::raw_ostream &Out, |
| 29 | const PrintingPolicy &Policy) const { |
| 30 | Out << "typeid("; |
| 31 | QualType(getType(), 0).print(Out, Policy); |
| 32 | Out << ")"; |
| 33 | } |
| 34 | |
| 35 | static_assert( |
| 36 | 1 << llvm::PointerLikeTypeTraits<TypeInfoLValue>::NumLowBitsAvailable <= |
Richard Smith | 7748376 | 2019-05-17 07:28:41 +0000 | [diff] [blame] | 37 | alignof(Type), |
Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 38 | "Type is insufficiently aligned"); |
| 39 | |
| 40 | APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V) |
| 41 | : Ptr(P), Local{I, V} {} |
| 42 | APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V) |
| 43 | : Ptr(P), Local{I, V} {} |
| 44 | |
| 45 | APValue::LValueBase APValue::LValueBase::getTypeInfo(TypeInfoLValue LV, |
| 46 | QualType TypeInfo) { |
| 47 | LValueBase Base; |
| 48 | Base.Ptr = LV; |
| 49 | Base.TypeInfoType = TypeInfo.getAsOpaquePtr(); |
| 50 | return Base; |
| 51 | } |
| 52 | |
| 53 | unsigned APValue::LValueBase::getCallIndex() const { |
| 54 | return is<TypeInfoLValue>() ? 0 : Local.CallIndex; |
| 55 | } |
| 56 | |
| 57 | unsigned APValue::LValueBase::getVersion() const { |
| 58 | return is<TypeInfoLValue>() ? 0 : Local.Version; |
| 59 | } |
| 60 | |
| 61 | QualType APValue::LValueBase::getTypeInfoType() const { |
| 62 | assert(is<TypeInfoLValue>() && "not a type_info lvalue"); |
| 63 | return QualType::getFromOpaquePtr(TypeInfoType); |
| 64 | } |
| 65 | |
| 66 | namespace clang { |
| 67 | bool operator==(const APValue::LValueBase &LHS, |
| 68 | const APValue::LValueBase &RHS) { |
| 69 | if (LHS.Ptr != RHS.Ptr) |
| 70 | return false; |
| 71 | if (LHS.is<TypeInfoLValue>()) |
| 72 | return true; |
| 73 | return LHS.Local.CallIndex == RHS.Local.CallIndex && |
| 74 | LHS.Local.Version == RHS.Local.Version; |
| 75 | } |
| 76 | } |
| 77 | |
Ken Dyck | 0299083 | 2010-01-15 12:37:54 +0000 | [diff] [blame] | 78 | namespace { |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 79 | struct LVBase { |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 80 | APValue::LValueBase Base; |
Ken Dyck | 0299083 | 2010-01-15 12:37:54 +0000 | [diff] [blame] | 81 | CharUnits Offset; |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 82 | unsigned PathLength; |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 83 | bool IsNullPtr : 1; |
| 84 | bool IsOnePastTheEnd : 1; |
Ken Dyck | 0299083 | 2010-01-15 12:37:54 +0000 | [diff] [blame] | 85 | }; |
| 86 | } |
| 87 | |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 88 | void *APValue::LValueBase::getOpaqueValue() const { |
| 89 | return Ptr.getOpaqueValue(); |
| 90 | } |
| 91 | |
| 92 | bool APValue::LValueBase::isNull() const { |
| 93 | return Ptr.isNull(); |
| 94 | } |
| 95 | |
| 96 | APValue::LValueBase::operator bool () const { |
| 97 | return static_cast<bool>(Ptr); |
| 98 | } |
| 99 | |
| 100 | clang::APValue::LValueBase |
| 101 | llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() { |
| 102 | return clang::APValue::LValueBase( |
Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 103 | DenseMapInfo<const ValueDecl*>::getEmptyKey()); |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 104 | } |
| 105 | |
| 106 | clang::APValue::LValueBase |
| 107 | llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() { |
| 108 | return clang::APValue::LValueBase( |
Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 109 | DenseMapInfo<const ValueDecl*>::getTombstoneKey()); |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 110 | } |
| 111 | |
Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 112 | namespace clang { |
| 113 | llvm::hash_code hash_value(const APValue::LValueBase &Base) { |
Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 114 | if (Base.is<TypeInfoLValue>()) |
| 115 | return llvm::hash_value(Base.getOpaqueValue()); |
Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 116 | return llvm::hash_combine(Base.getOpaqueValue(), Base.getCallIndex(), |
| 117 | Base.getVersion()); |
| 118 | } |
| 119 | } |
| 120 | |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 121 | unsigned llvm::DenseMapInfo<clang::APValue::LValueBase>::getHashValue( |
| 122 | const clang::APValue::LValueBase &Base) { |
Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 123 | return hash_value(Base); |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | bool llvm::DenseMapInfo<clang::APValue::LValueBase>::isEqual( |
| 127 | const clang::APValue::LValueBase &LHS, |
| 128 | const clang::APValue::LValueBase &RHS) { |
| 129 | return LHS == RHS; |
| 130 | } |
| 131 | |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 132 | struct APValue::LV : LVBase { |
| 133 | static const unsigned InlinePathSpace = |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 134 | (DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry); |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 135 | |
| 136 | /// Path - The sequence of base classes, fields and array indices to follow to |
| 137 | /// walk from Base to the subobject. When performing GCC-style folding, there |
| 138 | /// may not be such a path. |
| 139 | union { |
| 140 | LValuePathEntry Path[InlinePathSpace]; |
| 141 | LValuePathEntry *PathPtr; |
| 142 | }; |
| 143 | |
| 144 | LV() { PathLength = (unsigned)-1; } |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 145 | ~LV() { resizePath(0); } |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 146 | |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 147 | void resizePath(unsigned Length) { |
| 148 | if (Length == PathLength) |
| 149 | return; |
| 150 | if (hasPathPtr()) |
| 151 | delete [] PathPtr; |
| 152 | PathLength = Length; |
| 153 | if (hasPathPtr()) |
| 154 | PathPtr = new LValuePathEntry[Length]; |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 155 | } |
| 156 | |
| 157 | bool hasPath() const { return PathLength != (unsigned)-1; } |
| 158 | bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; } |
| 159 | |
| 160 | LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; } |
Richard Smith | bcb4eb2 | 2011-11-07 07:31:09 +0000 | [diff] [blame] | 161 | const LValuePathEntry *getPath() const { |
| 162 | return hasPathPtr() ? PathPtr : Path; |
| 163 | } |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 164 | }; |
| 165 | |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 166 | namespace { |
| 167 | struct MemberPointerBase { |
| 168 | llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember; |
| 169 | unsigned PathLength; |
| 170 | }; |
| 171 | } |
| 172 | |
| 173 | struct APValue::MemberPointerData : MemberPointerBase { |
| 174 | static const unsigned InlinePathSpace = |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 175 | (DataSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*); |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 176 | typedef const CXXRecordDecl *PathElem; |
| 177 | union { |
| 178 | PathElem Path[InlinePathSpace]; |
| 179 | PathElem *PathPtr; |
| 180 | }; |
| 181 | |
| 182 | MemberPointerData() { PathLength = 0; } |
| 183 | ~MemberPointerData() { resizePath(0); } |
| 184 | |
| 185 | void resizePath(unsigned Length) { |
| 186 | if (Length == PathLength) |
| 187 | return; |
| 188 | if (hasPathPtr()) |
| 189 | delete [] PathPtr; |
| 190 | PathLength = Length; |
| 191 | if (hasPathPtr()) |
| 192 | PathPtr = new PathElem[Length]; |
| 193 | } |
| 194 | |
| 195 | bool hasPathPtr() const { return PathLength > InlinePathSpace; } |
| 196 | |
| 197 | PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; } |
| 198 | const PathElem *getPath() const { |
| 199 | return hasPathPtr() ? PathPtr : Path; |
| 200 | } |
| 201 | }; |
| 202 | |
Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 203 | // FIXME: Reduce the malloc traffic here. |
| 204 | |
| 205 | APValue::Arr::Arr(unsigned NumElts, unsigned Size) : |
| 206 | Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]), |
| 207 | NumElts(NumElts), ArrSize(Size) {} |
| 208 | APValue::Arr::~Arr() { delete [] Elts; } |
| 209 | |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 210 | APValue::StructData::StructData(unsigned NumBases, unsigned NumFields) : |
| 211 | Elts(new APValue[NumBases+NumFields]), |
| 212 | NumBases(NumBases), NumFields(NumFields) {} |
| 213 | APValue::StructData::~StructData() { |
| 214 | delete [] Elts; |
| 215 | } |
| 216 | |
Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 217 | APValue::UnionData::UnionData() : Field(nullptr), Value(new APValue) {} |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 218 | APValue::UnionData::~UnionData () { |
| 219 | delete Value; |
| 220 | } |
| 221 | |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 222 | APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { |
| 223 | switch (RHS.getKind()) { |
| 224 | case Uninitialized: |
| 225 | break; |
| 226 | case Int: |
| 227 | MakeInt(); |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 228 | setInt(RHS.getInt()); |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 229 | break; |
| 230 | case Float: |
| 231 | MakeFloat(); |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 232 | setFloat(RHS.getFloat()); |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 233 | break; |
Leonard Chan | 86285d2 | 2019-01-16 18:53:05 +0000 | [diff] [blame] | 234 | case FixedPoint: { |
| 235 | APFixedPoint FXCopy = RHS.getFixedPoint(); |
| 236 | MakeFixedPoint(std::move(FXCopy)); |
| 237 | break; |
| 238 | } |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 239 | case Vector: |
| 240 | MakeVector(); |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 241 | setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts, |
Dan Gohman | 145f3f1 | 2010-04-19 16:39:44 +0000 | [diff] [blame] | 242 | RHS.getVectorLength()); |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 243 | break; |
| 244 | case ComplexInt: |
| 245 | MakeComplexInt(); |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 246 | setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag()); |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 247 | break; |
| 248 | case ComplexFloat: |
| 249 | MakeComplexFloat(); |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 250 | setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag()); |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 251 | break; |
| 252 | case LValue: |
| 253 | MakeLValue(); |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 254 | if (RHS.hasLValuePath()) |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 255 | setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(), |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 256 | RHS.isLValueOnePastTheEnd(), RHS.isNullPointer()); |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 257 | else |
Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 258 | setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(), |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 259 | RHS.isNullPointer()); |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 260 | break; |
| 261 | case Array: |
| 262 | MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize()); |
Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 263 | for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I) |
| 264 | getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I); |
| 265 | if (RHS.hasArrayFiller()) |
| 266 | getArrayFiller() = RHS.getArrayFiller(); |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 267 | break; |
| 268 | case Struct: |
| 269 | MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields()); |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 270 | for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I) |
| 271 | getStructBase(I) = RHS.getStructBase(I); |
| 272 | for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I) |
| 273 | getStructField(I) = RHS.getStructField(I); |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 274 | break; |
| 275 | case Union: |
| 276 | MakeUnion(); |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 277 | setUnion(RHS.getUnionField(), RHS.getUnionValue()); |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 278 | break; |
| 279 | case MemberPointer: |
| 280 | MakeMemberPointer(RHS.getMemberPointerDecl(), |
| 281 | RHS.isMemberPointerToDerivedMember(), |
| 282 | RHS.getMemberPointerPath()); |
| 283 | break; |
| 284 | case AddrLabelDiff: |
| 285 | MakeAddrLabelDiff(); |
Eli Friedman | fd5e54d | 2012-01-04 23:13:47 +0000 | [diff] [blame] | 286 | setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS()); |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 287 | break; |
Eli Friedman | fd5e54d | 2012-01-04 23:13:47 +0000 | [diff] [blame] | 288 | } |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 289 | } |
| 290 | |
Daniel Dunbar | b743157 | 2012-03-08 20:28:55 +0000 | [diff] [blame] | 291 | void APValue::DestroyDataAndMakeUninit() { |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 292 | if (Kind == Int) |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 293 | ((APSInt*)(char*)Data.buffer)->~APSInt(); |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 294 | else if (Kind == Float) |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 295 | ((APFloat*)(char*)Data.buffer)->~APFloat(); |
Leonard Chan | 86285d2 | 2019-01-16 18:53:05 +0000 | [diff] [blame] | 296 | else if (Kind == FixedPoint) |
| 297 | ((APFixedPoint *)(char *)Data.buffer)->~APFixedPoint(); |
Nate Begeman | 1e31b16 | 2009-01-18 01:01:34 +0000 | [diff] [blame] | 298 | else if (Kind == Vector) |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 299 | ((Vec*)(char*)Data.buffer)->~Vec(); |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 300 | else if (Kind == ComplexInt) |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 301 | ((ComplexAPSInt*)(char*)Data.buffer)->~ComplexAPSInt(); |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 302 | else if (Kind == ComplexFloat) |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 303 | ((ComplexAPFloat*)(char*)Data.buffer)->~ComplexAPFloat(); |
Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 304 | else if (Kind == LValue) |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 305 | ((LV*)(char*)Data.buffer)->~LV(); |
Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 306 | else if (Kind == Array) |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 307 | ((Arr*)(char*)Data.buffer)->~Arr(); |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 308 | else if (Kind == Struct) |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 309 | ((StructData*)(char*)Data.buffer)->~StructData(); |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 310 | else if (Kind == Union) |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 311 | ((UnionData*)(char*)Data.buffer)->~UnionData(); |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 312 | else if (Kind == MemberPointer) |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 313 | ((MemberPointerData*)(char*)Data.buffer)->~MemberPointerData(); |
Eli Friedman | fd5e54d | 2012-01-04 23:13:47 +0000 | [diff] [blame] | 314 | else if (Kind == AddrLabelDiff) |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 315 | ((AddrLabelDiffData*)(char*)Data.buffer)->~AddrLabelDiffData(); |
Nate Begeman | 1e31b16 | 2009-01-18 01:01:34 +0000 | [diff] [blame] | 316 | Kind = Uninitialized; |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 317 | } |
| 318 | |
Manuel Klimek | a732899 | 2013-06-03 13:51:33 +0000 | [diff] [blame] | 319 | bool APValue::needsCleanup() const { |
| 320 | switch (getKind()) { |
| 321 | case Uninitialized: |
| 322 | case AddrLabelDiff: |
| 323 | return false; |
| 324 | case Struct: |
| 325 | case Union: |
| 326 | case Array: |
| 327 | case Vector: |
| 328 | return true; |
| 329 | case Int: |
| 330 | return getInt().needsCleanup(); |
| 331 | case Float: |
| 332 | return getFloat().needsCleanup(); |
Leonard Chan | 86285d2 | 2019-01-16 18:53:05 +0000 | [diff] [blame] | 333 | case FixedPoint: |
| 334 | return getFixedPoint().getValue().needsCleanup(); |
Manuel Klimek | a732899 | 2013-06-03 13:51:33 +0000 | [diff] [blame] | 335 | case ComplexFloat: |
| 336 | assert(getComplexFloatImag().needsCleanup() == |
| 337 | getComplexFloatReal().needsCleanup() && |
| 338 | "In _Complex float types, real and imaginary values always have the " |
| 339 | "same size."); |
| 340 | return getComplexFloatReal().needsCleanup(); |
| 341 | case ComplexInt: |
| 342 | assert(getComplexIntImag().needsCleanup() == |
| 343 | getComplexIntReal().needsCleanup() && |
| 344 | "In _Complex int types, real and imaginary values must have the " |
| 345 | "same size."); |
| 346 | return getComplexIntReal().needsCleanup(); |
| 347 | case LValue: |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 348 | return reinterpret_cast<const LV *>(Data.buffer)->hasPathPtr(); |
Manuel Klimek | a732899 | 2013-06-03 13:51:33 +0000 | [diff] [blame] | 349 | case MemberPointer: |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 350 | return reinterpret_cast<const MemberPointerData *>(Data.buffer) |
| 351 | ->hasPathPtr(); |
Manuel Klimek | a732899 | 2013-06-03 13:51:33 +0000 | [diff] [blame] | 352 | } |
Benjamin Kramer | d1b7cd7 | 2013-06-03 21:26:13 +0000 | [diff] [blame] | 353 | llvm_unreachable("Unknown APValue kind!"); |
Manuel Klimek | a732899 | 2013-06-03 13:51:33 +0000 | [diff] [blame] | 354 | } |
| 355 | |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 356 | void APValue::swap(APValue &RHS) { |
| 357 | std::swap(Kind, RHS.Kind); |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 358 | char TmpData[DataSize]; |
| 359 | memcpy(TmpData, Data.buffer, DataSize); |
| 360 | memcpy(Data.buffer, RHS.Data.buffer, DataSize); |
| 361 | memcpy(RHS.Data.buffer, TmpData, DataSize); |
Richard Smith | 4e9e523 | 2012-03-10 00:28:11 +0000 | [diff] [blame] | 362 | } |
| 363 | |
Yaron Keren | cdae941 | 2016-01-29 19:38:18 +0000 | [diff] [blame] | 364 | LLVM_DUMP_METHOD void APValue::dump() const { |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 365 | dump(llvm::errs()); |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 366 | llvm::errs() << '\n'; |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 367 | } |
| 368 | |
| 369 | static double GetApproxValue(const llvm::APFloat &F) { |
| 370 | llvm::APFloat V = F; |
| 371 | bool ignored; |
Stephan Bergmann | 17c7f70 | 2016-12-14 11:57:17 +0000 | [diff] [blame] | 372 | V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven, |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 373 | &ignored); |
| 374 | return V.convertToDouble(); |
| 375 | } |
| 376 | |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 377 | void APValue::dump(raw_ostream &OS) const { |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 378 | switch (getKind()) { |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 379 | case Uninitialized: |
| 380 | OS << "Uninitialized"; |
| 381 | return; |
| 382 | case Int: |
| 383 | OS << "Int: " << getInt(); |
| 384 | return; |
| 385 | case Float: |
| 386 | OS << "Float: " << GetApproxValue(getFloat()); |
| 387 | return; |
Leonard Chan | 86285d2 | 2019-01-16 18:53:05 +0000 | [diff] [blame] | 388 | case FixedPoint: |
| 389 | OS << "FixedPoint : " << getFixedPoint(); |
| 390 | return; |
Nate Begeman | 1e31b16 | 2009-01-18 01:01:34 +0000 | [diff] [blame] | 391 | case Vector: |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 392 | OS << "Vector: "; |
| 393 | getVectorElt(0).dump(OS); |
| 394 | for (unsigned i = 1; i != getVectorLength(); ++i) { |
| 395 | OS << ", "; |
| 396 | getVectorElt(i).dump(OS); |
| 397 | } |
Nate Begeman | 1e31b16 | 2009-01-18 01:01:34 +0000 | [diff] [blame] | 398 | return; |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 399 | case ComplexInt: |
| 400 | OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag(); |
| 401 | return; |
| 402 | case ComplexFloat: |
| 403 | OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal()) |
| 404 | << ", " << GetApproxValue(getComplexFloatImag()); |
Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 405 | return; |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 406 | case LValue: |
| 407 | OS << "LValue: <todo>"; |
| 408 | return; |
Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 409 | case Array: |
| 410 | OS << "Array: "; |
| 411 | for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) { |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 412 | getArrayInitializedElt(I).dump(OS); |
Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 413 | if (I != getArraySize() - 1) OS << ", "; |
| 414 | } |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 415 | if (hasArrayFiller()) { |
| 416 | OS << getArraySize() - getArrayInitializedElts() << " x "; |
| 417 | getArrayFiller().dump(OS); |
| 418 | } |
Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 419 | return; |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 420 | case Struct: |
| 421 | OS << "Struct "; |
| 422 | if (unsigned N = getStructNumBases()) { |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 423 | OS << " bases: "; |
| 424 | getStructBase(0).dump(OS); |
| 425 | for (unsigned I = 1; I != N; ++I) { |
| 426 | OS << ", "; |
| 427 | getStructBase(I).dump(OS); |
| 428 | } |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 429 | } |
| 430 | if (unsigned N = getStructNumFields()) { |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 431 | OS << " fields: "; |
| 432 | getStructField(0).dump(OS); |
| 433 | for (unsigned I = 1; I != N; ++I) { |
| 434 | OS << ", "; |
| 435 | getStructField(I).dump(OS); |
| 436 | } |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 437 | } |
| 438 | return; |
| 439 | case Union: |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 440 | OS << "Union: "; |
| 441 | getUnionValue().dump(OS); |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 442 | return; |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 443 | case MemberPointer: |
| 444 | OS << "MemberPointer: <todo>"; |
| 445 | return; |
Eli Friedman | fd5e54d | 2012-01-04 23:13:47 +0000 | [diff] [blame] | 446 | case AddrLabelDiff: |
| 447 | OS << "AddrLabelDiff: <todo>"; |
| 448 | return; |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 449 | } |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 450 | llvm_unreachable("Unknown APValue kind!"); |
Chris Lattner | 981f33b | 2008-11-16 07:46:48 +0000 | [diff] [blame] | 451 | } |
| 452 | |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 453 | void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ |
| 454 | switch (getKind()) { |
Jeffrey Yasskin | d2af962 | 2011-07-18 16:43:53 +0000 | [diff] [blame] | 455 | case APValue::Uninitialized: |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 456 | Out << "<uninitialized>"; |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 457 | return; |
Jeffrey Yasskin | d2af962 | 2011-07-18 16:43:53 +0000 | [diff] [blame] | 458 | case APValue::Int: |
Richard Smith | 5614ca7 | 2012-03-23 23:55:39 +0000 | [diff] [blame] | 459 | if (Ty->isBooleanType()) |
| 460 | Out << (getInt().getBoolValue() ? "true" : "false"); |
| 461 | else |
| 462 | Out << getInt(); |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 463 | return; |
Jeffrey Yasskin | d2af962 | 2011-07-18 16:43:53 +0000 | [diff] [blame] | 464 | case APValue::Float: |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 465 | Out << GetApproxValue(getFloat()); |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 466 | return; |
Leonard Chan | 86285d2 | 2019-01-16 18:53:05 +0000 | [diff] [blame] | 467 | case APValue::FixedPoint: |
| 468 | Out << getFixedPoint(); |
| 469 | return; |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 470 | case APValue::Vector: { |
| 471 | Out << '{'; |
| 472 | QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); |
| 473 | getVectorElt(0).printPretty(Out, Ctx, ElemTy); |
| 474 | for (unsigned i = 1; i != getVectorLength(); ++i) { |
Jeffrey Yasskin | d2af962 | 2011-07-18 16:43:53 +0000 | [diff] [blame] | 475 | Out << ", "; |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 476 | getVectorElt(i).printPretty(Out, Ctx, ElemTy); |
Jeffrey Yasskin | d2af962 | 2011-07-18 16:43:53 +0000 | [diff] [blame] | 477 | } |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 478 | Out << '}'; |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 479 | return; |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 480 | } |
Jeffrey Yasskin | d2af962 | 2011-07-18 16:43:53 +0000 | [diff] [blame] | 481 | case APValue::ComplexInt: |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 482 | Out << getComplexIntReal() << "+" << getComplexIntImag() << "i"; |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 483 | return; |
Jeffrey Yasskin | d2af962 | 2011-07-18 16:43:53 +0000 | [diff] [blame] | 484 | case APValue::ComplexFloat: |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 485 | Out << GetApproxValue(getComplexFloatReal()) << "+" |
| 486 | << GetApproxValue(getComplexFloatImag()) << "i"; |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 487 | return; |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 488 | case APValue::LValue: { |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 489 | bool IsReference = Ty->isReferenceType(); |
| 490 | QualType InnerTy |
| 491 | = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType(); |
Douglas Gregor | 0b7bc7f | 2013-01-29 01:26:43 +0000 | [diff] [blame] | 492 | if (InnerTy.isNull()) |
| 493 | InnerTy = Ty; |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 494 | |
Richard Smith | 128719c | 2018-09-13 22:47:33 +0000 | [diff] [blame] | 495 | LValueBase Base = getLValueBase(); |
| 496 | if (!Base) { |
| 497 | if (isNullPointer()) { |
| 498 | Out << (Ctx.getLangOpts().CPlusPlus11 ? "nullptr" : "0"); |
| 499 | } else if (IsReference) { |
| 500 | Out << "*(" << InnerTy.stream(Ctx.getPrintingPolicy()) << "*)" |
| 501 | << getLValueOffset().getQuantity(); |
| 502 | } else { |
| 503 | Out << "(" << Ty.stream(Ctx.getPrintingPolicy()) << ")" |
| 504 | << getLValueOffset().getQuantity(); |
| 505 | } |
| 506 | return; |
| 507 | } |
| 508 | |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 509 | if (!hasLValuePath()) { |
| 510 | // No lvalue path: just print the offset. |
| 511 | CharUnits O = getLValueOffset(); |
| 512 | CharUnits S = Ctx.getTypeSizeInChars(InnerTy); |
| 513 | if (!O.isZero()) { |
| 514 | if (IsReference) |
| 515 | Out << "*("; |
| 516 | if (O % S) { |
| 517 | Out << "(char*)"; |
| 518 | S = CharUnits::One(); |
| 519 | } |
| 520 | Out << '&'; |
| 521 | } else if (!IsReference) |
| 522 | Out << '&'; |
| 523 | |
| 524 | if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) |
| 525 | Out << *VD; |
Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 526 | else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) { |
| 527 | TI.print(Out, Ctx.getPrintingPolicy()); |
| 528 | } else { |
Richard Trieu | ddd01ce | 2014-06-09 22:53:25 +0000 | [diff] [blame] | 529 | assert(Base.get<const Expr *>() != nullptr && |
| 530 | "Expecting non-null Expr"); |
Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 531 | Base.get<const Expr*>()->printPretty(Out, nullptr, |
| 532 | Ctx.getPrintingPolicy()); |
Richard Trieu | ddd01ce | 2014-06-09 22:53:25 +0000 | [diff] [blame] | 533 | } |
| 534 | |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 535 | if (!O.isZero()) { |
| 536 | Out << " + " << (O / S); |
| 537 | if (IsReference) |
| 538 | Out << ')'; |
| 539 | } |
| 540 | return; |
| 541 | } |
| 542 | |
| 543 | // We have an lvalue path. Print it out nicely. |
| 544 | if (!IsReference) |
| 545 | Out << '&'; |
| 546 | else if (isLValueOnePastTheEnd()) |
| 547 | Out << "*(&"; |
| 548 | |
| 549 | QualType ElemTy; |
| 550 | if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) { |
| 551 | Out << *VD; |
| 552 | ElemTy = VD->getType(); |
Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 553 | } else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) { |
| 554 | TI.print(Out, Ctx.getPrintingPolicy()); |
| 555 | ElemTy = Base.getTypeInfoType(); |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 556 | } else { |
| 557 | const Expr *E = Base.get<const Expr*>(); |
Richard Trieu | ddd01ce | 2014-06-09 22:53:25 +0000 | [diff] [blame] | 558 | assert(E != nullptr && "Expecting non-null Expr"); |
Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 559 | E->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 560 | ElemTy = E->getType(); |
| 561 | } |
| 562 | |
| 563 | ArrayRef<LValuePathEntry> Path = getLValuePath(); |
Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 564 | const CXXRecordDecl *CastToBase = nullptr; |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 565 | for (unsigned I = 0, N = Path.size(); I != N; ++I) { |
| 566 | if (ElemTy->getAs<RecordType>()) { |
| 567 | // The lvalue refers to a class type, so the next path entry is a base |
| 568 | // or member. |
Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 569 | const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer(); |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 570 | if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) { |
| 571 | CastToBase = RD; |
| 572 | ElemTy = Ctx.getRecordType(RD); |
| 573 | } else { |
| 574 | const ValueDecl *VD = cast<ValueDecl>(BaseOrMember); |
| 575 | Out << "."; |
| 576 | if (CastToBase) |
| 577 | Out << *CastToBase << "::"; |
| 578 | Out << *VD; |
| 579 | ElemTy = VD->getType(); |
| 580 | } |
| 581 | } else { |
| 582 | // The lvalue must refer to an array. |
Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 583 | Out << '[' << Path[I].getAsArrayIndex() << ']'; |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 584 | ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType(); |
| 585 | } |
| 586 | } |
| 587 | |
| 588 | // Handle formatting of one-past-the-end lvalues. |
| 589 | if (isLValueOnePastTheEnd()) { |
| 590 | // FIXME: If CastToBase is non-0, we should prefix the output with |
| 591 | // "(CastToBase*)". |
| 592 | Out << " + 1"; |
| 593 | if (IsReference) |
| 594 | Out << ')'; |
| 595 | } |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 596 | return; |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 597 | } |
| 598 | case APValue::Array: { |
| 599 | const ArrayType *AT = Ctx.getAsArrayType(Ty); |
| 600 | QualType ElemTy = AT->getElementType(); |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 601 | Out << '{'; |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 602 | if (unsigned N = getArrayInitializedElts()) { |
| 603 | getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy); |
| 604 | for (unsigned I = 1; I != N; ++I) { |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 605 | Out << ", "; |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 606 | if (I == 10) { |
| 607 | // Avoid printing out the entire contents of large arrays. |
| 608 | Out << "..."; |
| 609 | break; |
| 610 | } |
| 611 | getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy); |
| 612 | } |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 613 | } |
| 614 | Out << '}'; |
| 615 | return; |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 616 | } |
| 617 | case APValue::Struct: { |
| 618 | Out << '{'; |
| 619 | const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl(); |
| 620 | bool First = true; |
| 621 | if (unsigned N = getStructNumBases()) { |
| 622 | const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD); |
| 623 | CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin(); |
| 624 | for (unsigned I = 0; I != N; ++I, ++BI) { |
| 625 | assert(BI != CD->bases_end()); |
| 626 | if (!First) |
| 627 | Out << ", "; |
| 628 | getStructBase(I).printPretty(Out, Ctx, BI->getType()); |
| 629 | First = false; |
| 630 | } |
| 631 | } |
Aaron Ballman | e8a8bae | 2014-03-08 20:12:42 +0000 | [diff] [blame] | 632 | for (const auto *FI : RD->fields()) { |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 633 | if (!First) |
| 634 | Out << ", "; |
David Blaikie | 2d7c57e | 2012-04-30 02:36:29 +0000 | [diff] [blame] | 635 | if (FI->isUnnamedBitfield()) continue; |
| 636 | getStructField(FI->getFieldIndex()). |
| 637 | printPretty(Out, Ctx, FI->getType()); |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 638 | First = false; |
| 639 | } |
| 640 | Out << '}'; |
| 641 | return; |
| 642 | } |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 643 | case APValue::Union: |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 644 | Out << '{'; |
| 645 | if (const FieldDecl *FD = getUnionField()) { |
| 646 | Out << "." << *FD << " = "; |
| 647 | getUnionValue().printPretty(Out, Ctx, FD->getType()); |
| 648 | } |
| 649 | Out << '}'; |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 650 | return; |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 651 | case APValue::MemberPointer: |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 652 | // FIXME: This is not enough to unambiguously identify the member in a |
| 653 | // multiple-inheritance scenario. |
| 654 | if (const ValueDecl *VD = getMemberPointerDecl()) { |
| 655 | Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD; |
| 656 | return; |
| 657 | } |
| 658 | Out << "0"; |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 659 | return; |
Eli Friedman | fd5e54d | 2012-01-04 23:13:47 +0000 | [diff] [blame] | 660 | case APValue::AddrLabelDiff: |
| 661 | Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName(); |
| 662 | Out << " - "; |
| 663 | Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName(); |
| 664 | return; |
Jeffrey Yasskin | d2af962 | 2011-07-18 16:43:53 +0000 | [diff] [blame] | 665 | } |
Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 666 | llvm_unreachable("Unknown APValue kind!"); |
Jeffrey Yasskin | d2af962 | 2011-07-18 16:43:53 +0000 | [diff] [blame] | 667 | } |
| 668 | |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 669 | std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { |
| 670 | std::string Result; |
| 671 | llvm::raw_string_ostream Out(Result); |
| 672 | printPretty(Out, Ctx, Ty); |
Eli Friedman | 375f09f | 2011-12-16 22:12:23 +0000 | [diff] [blame] | 673 | Out.flush(); |
Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 674 | return Result; |
Jeffrey Yasskin | d2af962 | 2011-07-18 16:43:53 +0000 | [diff] [blame] | 675 | } |
| 676 | |
Hans Wennborg | dd1ea8a | 2019-03-06 10:26:19 +0000 | [diff] [blame] | 677 | bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy, |
| 678 | const ASTContext &Ctx) const { |
| 679 | if (isInt()) { |
| 680 | Result = getInt(); |
| 681 | return true; |
| 682 | } |
| 683 | |
| 684 | if (isLValue() && isNullPointer()) { |
| 685 | Result = Ctx.MakeIntValue(Ctx.getTargetNullPointerValue(SrcTy), SrcTy); |
| 686 | return true; |
| 687 | } |
| 688 | |
| 689 | if (isLValue() && !getLValueBase()) { |
| 690 | Result = Ctx.MakeIntValue(getLValueOffset().getQuantity(), SrcTy); |
| 691 | return true; |
| 692 | } |
| 693 | |
| 694 | return false; |
| 695 | } |
| 696 | |
Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 697 | const APValue::LValueBase APValue::getLValueBase() const { |
Ken Dyck | 0299083 | 2010-01-15 12:37:54 +0000 | [diff] [blame] | 698 | assert(isLValue() && "Invalid accessor"); |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 699 | return ((const LV*)(const void*)Data.buffer)->Base; |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 700 | } |
| 701 | |
| 702 | bool APValue::isLValueOnePastTheEnd() const { |
| 703 | assert(isLValue() && "Invalid accessor"); |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 704 | return ((const LV*)(const void*)Data.buffer)->IsOnePastTheEnd; |
Ken Dyck | 0299083 | 2010-01-15 12:37:54 +0000 | [diff] [blame] | 705 | } |
| 706 | |
Richard Smith | 0b0a0b6 | 2011-10-29 20:57:55 +0000 | [diff] [blame] | 707 | CharUnits &APValue::getLValueOffset() { |
| 708 | assert(isLValue() && "Invalid accessor"); |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 709 | return ((LV*)(void*)Data.buffer)->Offset; |
Ken Dyck | 0299083 | 2010-01-15 12:37:54 +0000 | [diff] [blame] | 710 | } |
| 711 | |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 712 | bool APValue::hasLValuePath() const { |
Ken Dyck | 0299083 | 2010-01-15 12:37:54 +0000 | [diff] [blame] | 713 | assert(isLValue() && "Invalid accessor"); |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 714 | return ((const LV*)(const char*)Data.buffer)->hasPath(); |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 715 | } |
| 716 | |
| 717 | ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const { |
| 718 | assert(isLValue() && hasLValuePath() && "Invalid accessor"); |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 719 | const LV &LVal = *((const LV*)(const char*)Data.buffer); |
Craig Topper | 5fc8fc2 | 2014-08-27 06:28:36 +0000 | [diff] [blame] | 720 | return llvm::makeArrayRef(LVal.getPath(), LVal.PathLength); |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 721 | } |
| 722 | |
Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 723 | unsigned APValue::getLValueCallIndex() const { |
| 724 | assert(isLValue() && "Invalid accessor"); |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 725 | return ((const LV*)(const char*)Data.buffer)->Base.getCallIndex(); |
| 726 | } |
| 727 | |
| 728 | unsigned APValue::getLValueVersion() const { |
| 729 | assert(isLValue() && "Invalid accessor"); |
| 730 | return ((const LV*)(const char*)Data.buffer)->Base.getVersion(); |
Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 731 | } |
| 732 | |
Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 733 | bool APValue::isNullPointer() const { |
| 734 | assert(isLValue() && "Invalid usage"); |
| 735 | return ((const LV*)(const char*)Data.buffer)->IsNullPtr; |
| 736 | } |
| 737 | |
Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 738 | void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 739 | bool IsNullPtr) { |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 740 | assert(isLValue() && "Invalid accessor"); |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 741 | LV &LVal = *((LV*)(char*)Data.buffer); |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 742 | LVal.Base = B; |
| 743 | LVal.IsOnePastTheEnd = false; |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 744 | LVal.Offset = O; |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 745 | LVal.resizePath((unsigned)-1); |
Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 746 | LVal.IsNullPtr = IsNullPtr; |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 747 | } |
| 748 | |
Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 749 | void APValue::setLValue(LValueBase B, const CharUnits &O, |
Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 750 | ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 751 | bool IsNullPtr) { |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 752 | assert(isLValue() && "Invalid accessor"); |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 753 | LV &LVal = *((LV*)(char*)Data.buffer); |
Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 754 | LVal.Base = B; |
| 755 | LVal.IsOnePastTheEnd = IsOnePastTheEnd; |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 756 | LVal.Offset = O; |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 757 | LVal.resizePath(Path.size()); |
Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 758 | memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); |
Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 759 | LVal.IsNullPtr = IsNullPtr; |
Ken Dyck | 0299083 | 2010-01-15 12:37:54 +0000 | [diff] [blame] | 760 | } |
| 761 | |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 762 | const ValueDecl *APValue::getMemberPointerDecl() const { |
| 763 | assert(isMemberPointer() && "Invalid accessor"); |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 764 | const MemberPointerData &MPD = |
| 765 | *((const MemberPointerData *)(const char *)Data.buffer); |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 766 | return MPD.MemberAndIsDerivedMember.getPointer(); |
| 767 | } |
| 768 | |
| 769 | bool APValue::isMemberPointerToDerivedMember() const { |
| 770 | assert(isMemberPointer() && "Invalid accessor"); |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 771 | const MemberPointerData &MPD = |
| 772 | *((const MemberPointerData *)(const char *)Data.buffer); |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 773 | return MPD.MemberAndIsDerivedMember.getInt(); |
| 774 | } |
| 775 | |
| 776 | ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const { |
| 777 | assert(isMemberPointer() && "Invalid accessor"); |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 778 | const MemberPointerData &MPD = |
| 779 | *((const MemberPointerData *)(const char *)Data.buffer); |
Craig Topper | 5fc8fc2 | 2014-08-27 06:28:36 +0000 | [diff] [blame] | 780 | return llvm::makeArrayRef(MPD.getPath(), MPD.PathLength); |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 781 | } |
| 782 | |
Ken Dyck | 0299083 | 2010-01-15 12:37:54 +0000 | [diff] [blame] | 783 | void APValue::MakeLValue() { |
| 784 | assert(isUninit() && "Bad state change"); |
Benjamin Kramer | a939c23 | 2014-03-15 18:54:13 +0000 | [diff] [blame] | 785 | static_assert(sizeof(LV) <= DataSize, "LV too big"); |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 786 | new ((void*)(char*)Data.buffer) LV(); |
Ken Dyck | 0299083 | 2010-01-15 12:37:54 +0000 | [diff] [blame] | 787 | Kind = LValue; |
| 788 | } |
Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 789 | |
| 790 | void APValue::MakeArray(unsigned InitElts, unsigned Size) { |
| 791 | assert(isUninit() && "Bad state change"); |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 792 | new ((void*)(char*)Data.buffer) Arr(InitElts, Size); |
Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 793 | Kind = Array; |
| 794 | } |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 795 | |
| 796 | void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, |
| 797 | ArrayRef<const CXXRecordDecl*> Path) { |
| 798 | assert(isUninit() && "Bad state change"); |
Richard Smith | 7073a2d | 2014-01-10 00:40:45 +0000 | [diff] [blame] | 799 | MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData; |
Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 800 | Kind = MemberPointer; |
| 801 | MPD->MemberAndIsDerivedMember.setPointer(Member); |
| 802 | MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); |
| 803 | MPD->resizePath(Path.size()); |
| 804 | memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*)); |
| 805 | } |