From 37e83bc6db3ad7d9a5d182694ebe71ebbc6120de Mon Sep 17 00:00:00 2001 From: Varun Gandhi Date: Wed, 6 Jan 2021 14:34:20 -0800 Subject: [PATCH] [NFC] Move readAPValue/writeAPValue up the inheritance hierarchy The implementation for (de)serialization of APValues can be shared between Clang and Swift, so we prefer pushing the methods up the inheritance hierarchy, instead of having the methods live in ASTReader/ASTWriter. Fixes rdar://72592937. Reviewed By: rjmccall Differential Revision: https://reviews.llvm.org/D94196 --- clang/include/clang/AST/APValue.h | 16 +- clang/include/clang/AST/AbstractBasicReader.h | 34 +++ clang/include/clang/AST/AbstractBasicWriter.h | 35 +++ clang/include/clang/AST/PropertiesBase.td | 308 +++++++++++++++++++++ .../include/clang/Serialization/ASTRecordReader.h | 2 +- .../include/clang/Serialization/ASTRecordWriter.h | 9 +- clang/include/clang/Serialization/ASTWriter.h | 5 + clang/lib/AST/APValue.cpp | 8 + clang/lib/Serialization/ASTReader.cpp | 159 ----------- clang/lib/Serialization/ASTWriter.cpp | 138 --------- clang/utils/TableGen/ClangASTPropertiesEmitter.cpp | 12 +- 11 files changed, 415 insertions(+), 311 deletions(-) diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index eded348..f9b1899 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -23,6 +23,10 @@ #include "llvm/Support/AlignOf.h" namespace clang { +namespace serialization { +template class BasicReaderBase; +} // end namespace serialization + class AddrLabelExpr; class ASTContext; class CharUnits; @@ -233,12 +237,20 @@ public: return llvm::hash_value(A.Value); } }; + class LValuePathSerializationHelper { + const void *ElemTy; + + public: + ArrayRef Path; + + LValuePathSerializationHelper(ArrayRef, QualType); + QualType getType(); + }; struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; - friend class ASTRecordReader; - friend class ASTWriter; + template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; friend class ASTNodeImporter; diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h index d7b3a9d..5505d66 100644 --- a/clang/include/clang/AST/AbstractBasicReader.h +++ b/clang/include/clang/AST/AbstractBasicReader.h @@ -177,6 +177,40 @@ public: return llvm::APInt(bitWidth, numWords, &data[0]); } + llvm::FixedPointSemantics readFixedPointSemantics() { + unsigned width = asImpl().readUInt32(); + unsigned scale = asImpl().readUInt32(); + unsigned tmp = asImpl().readUInt32(); + bool isSigned = tmp & 0x1; + bool isSaturated = tmp & 0x2; + bool hasUnsignedPadding = tmp & 0x4; + return llvm::FixedPointSemantics(width, scale, isSigned, isSaturated, + hasUnsignedPadding); + } + + APValue::LValuePathSerializationHelper readLValuePathSerializationHelper( + SmallVectorImpl &path) { + auto elemTy = asImpl().readQualType(); + unsigned pathLength = asImpl().readUInt32(); + for (unsigned i = 0; i < pathLength; ++i) { + if (elemTy->template getAs()) { + unsigned int_ = asImpl().readUInt32(); + Decl *decl = asImpl().template readDeclAs(); + if (auto *recordDecl = dyn_cast(decl)) + elemTy = getASTContext().getRecordType(recordDecl); + else + elemTy = cast(decl)->getType(); + path.push_back( + APValue::LValuePathEntry(APValue::BaseOrMemberType(decl, int_))); + } else { + elemTy = getASTContext().getAsArrayType(elemTy)->getElementType(); + path.push_back( + APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32())); + } + } + return APValue::LValuePathSerializationHelper(path, elemTy); + } + Qualifiers readQualifiers() { static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t), "update this if the value size changes"); diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h index 0a6730c..75aef734 100644 --- a/clang/include/clang/AST/AbstractBasicWriter.h +++ b/clang/include/clang/AST/AbstractBasicWriter.h @@ -9,6 +9,7 @@ #ifndef CLANG_AST_ABSTRACTBASICWRITER_H #define CLANG_AST_ABSTRACTBASICWRITER_H +#include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" namespace clang { @@ -121,6 +122,7 @@ template class DataStreamBasicWriter : public BasicWriterBase { protected: using BasicWriterBase::asImpl; + DataStreamBasicWriter(ASTContext &ctx) : BasicWriterBase(ctx) {} public: /// Implement property-find by ignoring it. We rely on properties being @@ -163,6 +165,39 @@ public: asImpl().writeUInt64(words[i]); } + void writeFixedPointSemantics(const llvm::FixedPointSemantics &sema) { + asImpl().writeUInt32(sema.getWidth()); + asImpl().writeUInt32(sema.getScale()); + asImpl().writeUInt32(sema.isSigned() | sema.isSaturated() << 1 | + sema.hasUnsignedPadding() << 2); + } + + void writeLValuePathSerializationHelper( + APValue::LValuePathSerializationHelper lvaluePath) { + ArrayRef path = lvaluePath.Path; + QualType elemTy = lvaluePath.getType(); + asImpl().writeQualType(elemTy); + asImpl().writeUInt32(path.size()); + auto &ctx = ((BasicWriterBase *)this)->getASTContext(); + for (auto elem : path) { + if (elemTy->getAs()) { + asImpl().writeUInt32(elem.getAsBaseOrMember().getInt()); + const Decl *baseOrMember = elem.getAsBaseOrMember().getPointer(); + if (const auto *recordDecl = dyn_cast(baseOrMember)) { + asImpl().writeDeclRef(recordDecl); + elemTy = ctx.getRecordType(recordDecl); + } else { + const auto *valueDecl = cast(baseOrMember); + asImpl().writeDeclRef(valueDecl); + elemTy = valueDecl->getType(); + } + } else { + asImpl().writeUInt32(elem.getAsArrayIndex()); + elemTy = ctx.getAsArrayType(elemTy)->getElementType(); + } + } + } + void writeQualifiers(Qualifiers value) { static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t), "update this if the value size changes"); diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index ba0f237..a087cb4 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -72,6 +72,8 @@ class CountPropertyType : PropertyType { def APInt : PropertyType<"llvm::APInt"> { let PassByReference = 1; } def APSInt : PropertyType<"llvm::APSInt"> { let PassByReference = 1; } +def APValue : PropertyType { let PassByReference = 1; } +def APValueKind : EnumPropertyType<"APValue::ValueKind">; def ArraySizeModifier : EnumPropertyType<"ArrayType::ArraySizeModifier">; def AttrKind : EnumPropertyType<"attr::Kind">; def AutoTypeKeyword : EnumPropertyType; @@ -109,7 +111,15 @@ def DeclRef : RefPropertyType<"Decl"> { let ConstWhenWriting = 1; } SubclassPropertyType<"ValueDecl", DeclRef>; def ElaboratedTypeKeyword : EnumPropertyType; def ExtParameterInfo : PropertyType<"FunctionProtoType::ExtParameterInfo">; +def FixedPointSemantics : PropertyType<"llvm::FixedPointSemantics"> { + let PassByReference = 1; +} def Identifier : RefPropertyType<"IdentifierInfo"> { let ConstWhenWriting = 1; } +def LValuePathEntry : PropertyType<"APValue::LValuePathEntry">; +def LValuePathSerializationHelper : + PropertyType<"APValue::LValuePathSerializationHelper"> { + let BufferElementTypes = [ LValuePathEntry ]; +} def NestedNameSpecifier : PropertyType<"NestedNameSpecifier *">; def NestedNameSpecifierKind : EnumPropertyType<"NestedNameSpecifier::SpecifierKind">; @@ -237,6 +247,304 @@ class PropertyTypeCase : HasProperties { string Name = name; } +// Type cases for APValue. +def : PropertyTypeKind; +let Class = PropertyTypeCase in { + def : Creator<[{ return APValue(); }]>; +} +let Class = PropertyTypeCase in { + def : Creator<[{ return APValue::IndeterminateValue(); }]>; +} +let Class = PropertyTypeCase in { + def : Property<"value", APSInt> { + let Read = [{ node.getInt() }]; + } + def : Creator<[{ return APValue(value); }]>; +} +let Class = PropertyTypeCase in { + def : Property<"semantics", UInt32> { + let Read = [{ + static_cast( + llvm::APFloatBase::SemanticsToEnum(node.getFloat().getSemantics())) + }]; + } + def : Property<"value", APInt> { + let Read = [{ node.getFloat().bitcastToAPInt() }]; + } + def : Creator<[{ + const llvm::fltSemantics &floatSema = llvm::APFloatBase::EnumToSemantics( + static_cast(semantics)); + return APValue(llvm::APFloat(floatSema, value)); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"semantics", FixedPointSemantics> { + let Read = [{ node.getFixedPoint().getSemantics() }]; + } + def : Property<"value", APSInt> { + let Read = [{ node.getFixedPoint().getValue() }]; + } + def : Creator<[{ + return APValue(llvm::APFixedPoint(std::move(value), semantics)); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"real", APSInt> { + let Read = [{ node.getComplexIntReal() }]; + } + def : Property<"imag", APSInt> { + let Read = [{ node.getComplexIntImag() }]; + } + def : Creator<[{ return APValue(real, imag); }]>; +} +let Class = PropertyTypeCase in { + def : ReadHelper<[{ + auto sema = llvm::APFloatBase::SemanticsToEnum( + node.getComplexFloatReal().getSemantics()); + assert(sema == llvm::APFloatBase::SemanticsToEnum( + node.getComplexFloatImag().getSemantics())); + }]>; + def : Property<"semantics", UInt32> { + let Read = [{ static_cast(sema) }]; + } + def : Property<"real", APInt> { + let Read = [{ node.getComplexFloatReal().bitcastToAPInt() }]; + } + def : Property<"imag", APInt> { + let Read = [{ node.getComplexFloatImag().bitcastToAPInt() }]; + } + def : Creator<[{ + const llvm::fltSemantics &sema = llvm::APFloatBase::EnumToSemantics( + static_cast(semantics)); + return APValue(llvm::APFloat(sema, real), + llvm::APFloat(sema, imag)); + }]>; +} +let Class = PropertyTypeCase in { + def : ReadHelper<[{ + SmallVector buffer; + unsigned len = node.getVectorLength(); + for (unsigned i = 0; i < len; ++i) + buffer.push_back(node.getVectorElt(i)); + }]>; + def : Property<"elements", Array> { + let Read = [{ buffer }]; + } + def : Creator<[{ + APValue result; + result.MakeVector(); + unsigned length = elements.size(); + (void)result.setVectorUninit(length); + for (unsigned i = 0; i < length; i++) + result.getVectorElt(i) = elements[i]; + return result; + }]>; +} +let Class = PropertyTypeCase in { + def : ReadHelper<[{ + SmallVector buffer{}; + unsigned initLength = node.getArrayInitializedElts(); + for (unsigned i = 0; i < initLength; ++i) + buffer.push_back(node.getArrayInitializedElt(i)); + if (node.hasArrayFiller()) + buffer.push_back(node.getArrayFiller()); + }]>; + def : Property<"totalLength", UInt32> { + let Read = [{ node.getArraySize() }]; + } + def : Property<"hasFiller", Bool> { + let Read = [{ node.hasArrayFiller() }]; + } + def : Property<"elements", Array> { + let Read = [{ buffer }]; + } + def : Creator<[{ + APValue result; + unsigned initLength = elements.size() - (hasFiller ? 1 : 0); + result.MakeArray(initLength, totalLength); + for (unsigned i = 0; i < initLength; ++i) + result.getArrayInitializedElt(i) = elements[i]; + if (hasFiller) + result.getArrayFiller() = elements.back(); + return result; + }]>; +} +let Class = PropertyTypeCase in { + def : ReadHelper<[{ + SmallVector structBases; + unsigned numBases = node.getStructNumBases(); + for (unsigned i = 0; i < numBases; ++i) + structBases.push_back(node.getStructBase(i)); + SmallVector structFields; + unsigned numFields = node.getStructNumFields(); + for (unsigned i = 0; i < numFields; ++i) + structFields.push_back(node.getStructField(i)); + }]>; + def : Property<"bases", Array> { + let Read = [{ structBases }]; + } + def : Property<"fields", Array> { + let Read = [{ structFields }]; + } + def : Creator<[{ + APValue result; + result.MakeStruct(bases.size(), fields.size()); + for (unsigned i = 0; i < bases.size(); ++i) + result.getStructBase(i) = bases[i]; + for (unsigned i = 0; i < fields.size(); ++i) + result.getStructField(i) = fields[i]; + return result; + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"fieldDecl", DeclRef> { + let Read = [{ node.getUnionField() }]; + } + def : Property<"value", APValue> { + let Read = [{ node.getUnionValue() }]; + } + def : Creator<[{ + return APValue(cast(fieldDecl), std::move(value)); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"lhs", StmtRef> { + let Read = [{ const_cast(node.getAddrLabelDiffLHS()) }]; + } + def : Property<"rhs", StmtRef> { + let Read = [{ const_cast(node.getAddrLabelDiffRHS()) }]; + } + def : Creator<[{ + return APValue(cast(lhs), cast(rhs)); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"isDerived", Bool> { + let Read = [{ node.isMemberPointerToDerivedMember() }]; + } + def : Property<"member", ValueDeclRef> { + let Read = [{ node.getMemberPointerDecl() }]; + } + def : Property<"memberPath", Array> { + let Read = [{ node.getMemberPointerPath() }]; + } + def : Creator<[{ + APValue result; + unsigned pathSize = memberPath.size(); + const CXXRecordDecl **pathArray = + result.setMemberPointerUninit(member, isDerived, pathSize).data(); + for (unsigned i = 0; i < pathSize; ++i) + pathArray[i] = memberPath[i]->getCanonicalDecl(); + return result; + }]>; +} +let Class = PropertyTypeCase in { + def : ReadHelper<[{ + auto lvalueBase = node.getLValueBase(); + const Expr *expr = + lvalueBase ? lvalueBase.dyn_cast() : nullptr; + bool lvalueBaseIsExpr = (bool) expr; + bool lvalueBaseIsTypeInfo = lvalueBase.is(); + QualType elemTy; + if (lvalueBase) { + if (lvalueBaseIsTypeInfo) { + elemTy = lvalueBase.getTypeInfoType(); + } else if (lvalueBaseIsExpr) { + elemTy = expr->getType(); + } else { + elemTy = lvalueBase.get()->getType(); + } + } + }]>; + def : Property<"hasLValuePath", Bool> { + let Read = [{ node.hasLValuePath() }]; + } + def : Property<"isLValueOnePastTheEnd", Bool> { + let Read = [{ node.isLValueOnePastTheEnd() }]; + } + def : Property<"isExpr", Bool> { + let Read = [{ lvalueBaseIsExpr }]; + } + def : Property<"isTypeInfo", Bool> { + let Read = [{ lvalueBaseIsTypeInfo }]; + } + def : Property<"hasBase", Bool> { + let Read = [{ static_cast(lvalueBase) }]; + } + def : Property<"isNullPtr", Bool> { + let Read = [{ node.isNullPointer() }]; + } + def : Property<"typeInfo", QualType> { + let Conditional = [{ hasBase && isTypeInfo }]; + let Read = [{ + QualType(node.getLValueBase().get().getType(), 0) + }]; + } + def : Property<"type", QualType> { + let Conditional = [{ hasBase && isTypeInfo }]; + let Read = [{ node.getLValueBase().getTypeInfoType() }]; + } + def : Property<"callIndex", UInt32> { + let Conditional = [{ hasBase && !isTypeInfo }]; + let Read = [{ node.getLValueBase().getCallIndex() }]; + } + def : Property<"version", UInt32> { + let Conditional = [{ hasBase && !isTypeInfo }]; + let Read = [{ node.getLValueBase().getVersion() }]; + } + def : Property<"stmt", StmtRef> { + let Conditional = [{ hasBase && !isTypeInfo && isExpr }]; + let Read = [{ const_cast(expr) }]; + } + def : Property<"decl", DeclRef> { + let Conditional = [{ hasBase && !isTypeInfo && !isExpr }]; + let Read = [{ lvalueBase.get() }]; + } + def : Property<"offsetQuantity", UInt32> { + let Read = [{ node.getLValueOffset().getQuantity() }]; + } + def : Property<"lvaluePath", LValuePathSerializationHelper> { + let Conditional = [{ hasLValuePath }]; + let Read = [{ + APValue::LValuePathSerializationHelper(node.getLValuePath(), elemTy) + }]; + } + def : Creator<[{ + (void)ctx; + APValue::LValueBase base; + QualType elemTy; + if (hasBase) { + if (isTypeInfo) { + base = APValue::LValueBase::getTypeInfo( + TypeInfoLValue(typeInfo.getValue().getTypePtr()), type.getValue()); + elemTy = base.getTypeInfoType(); + } else if (isExpr) { + base = APValue::LValueBase(cast(stmt.getValue()), + callIndex.getValue(), version.getValue()); + elemTy = base.get()->getType(); + } else { + base = APValue::LValueBase(cast(decl.getValue()), + callIndex.getValue(), version.getValue()); + elemTy = base.get()->getType(); + } + } + CharUnits offset = CharUnits::fromQuantity(offsetQuantity); + APValue result; + result.MakeLValue(); + if (!hasLValuePath) { + result.setLValue(base, offset, APValue::NoLValuePath{}, isNullPtr); + return result; + } + auto pathLength = lvaluePath->Path.size(); + APValue::LValuePathEntry *path = result.setLValueUninit( + base, offset, pathLength, isLValueOnePastTheEnd, isNullPtr).data(); + assert(lvaluePath->getType() == elemTy && "Unexpected type reference!"); + llvm::copy(lvaluePath->Path, path); + return result; + }]>; +} + // Type cases for DeclarationName. def : PropertyTypeKind; diff --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h index 3912ffe..b85609b 100644 --- a/clang/include/clang/Serialization/ASTRecordReader.h +++ b/clang/include/clang/Serialization/ASTRecordReader.h @@ -281,7 +281,7 @@ public: } /// Read an arbitrary constant value, advancing Idx. - APValue readAPValue(); + // APValue readAPValue(); (inherited) /// Read an integral value, advancing Idx. // llvm::APInt readAPInt(); (inherited) diff --git a/clang/include/clang/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h index e362463..0dc69bd 100644 --- a/clang/include/clang/Serialization/ASTRecordWriter.h +++ b/clang/include/clang/Serialization/ASTRecordWriter.h @@ -55,13 +55,14 @@ class ASTRecordWriter public: /// Construct a ASTRecordWriter that uses the default encoding scheme. - ASTRecordWriter(ASTWriter &Writer, ASTWriter::RecordDataImpl &Record) - : Writer(&Writer), Record(&Record) {} + ASTRecordWriter(ASTWriter &W, ASTWriter::RecordDataImpl &Record) + : DataStreamBasicWriter(W.getASTContext()), Writer(&W), Record(&Record) {} /// Construct a ASTRecordWriter that uses the same encoding scheme as another /// ASTRecordWriter. ASTRecordWriter(ASTRecordWriter &Parent, ASTWriter::RecordDataImpl &Record) - : Writer(Parent.Writer), Record(&Record) {} + : DataStreamBasicWriter(Parent.getASTContext()), Writer(Parent.Writer), + Record(&Record) {} /// Copying an ASTRecordWriter is almost certainly a bug. ASTRecordWriter(const ASTRecordWriter &) = delete; @@ -165,7 +166,7 @@ public: void AddAPFloat(const llvm::APFloat &Value); /// Emit an APvalue. - void AddAPValue(const APValue &Value); + void AddAPValue(const APValue &Value) { writeAPValue(Value); } /// Emit a reference to an identifier. void AddIdentifierRef(const IdentifierInfo *II) { diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 7a6664a..02fd72f 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -555,6 +555,11 @@ public: bool IncludeTimestamps = true); ~ASTWriter() override; + ASTContext &getASTContext() const { + assert(Context && "requested AST context when not writing AST"); + return *Context; + } + const LangOptions &getLangOpts() const; /// Get a timestamp for output into the AST file. The actual timestamp diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index c18f885..9a9233b 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -154,6 +154,14 @@ void APValue::LValuePathEntry::Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Value); } +APValue::LValuePathSerializationHelper::LValuePathSerializationHelper( + ArrayRef Path, QualType ElemTy) + : ElemTy((const void *)ElemTy.getTypePtrOrNull()), Path(Path) {} + +QualType APValue::LValuePathSerializationHelper::getType() { + return QualType::getFromOpaquePtr(ElemTy); +} + namespace { struct LVBase { APValue::LValueBase Base; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index b48b23c..eda286c 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -8941,165 +8941,6 @@ ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record, return SourceRange(beg, end); } -static llvm::FixedPointSemantics -ReadFixedPointSemantics(const SmallVectorImpl &Record, - unsigned &Idx) { - unsigned Width = Record[Idx++]; - unsigned Scale = Record[Idx++]; - uint64_t Tmp = Record[Idx++]; - bool IsSigned = Tmp & 0x1; - bool IsSaturated = Tmp & 0x2; - bool HasUnsignedPadding = Tmp & 0x4; - return llvm::FixedPointSemantics(Width, Scale, IsSigned, IsSaturated, - HasUnsignedPadding); -} - -APValue ASTRecordReader::readAPValue() { - auto Kind = static_cast(asImpl().readUInt32()); - switch (Kind) { - case APValue::None: - return APValue(); - case APValue::Indeterminate: - return APValue::IndeterminateValue(); - case APValue::Int: - return APValue(asImpl().readAPSInt()); - case APValue::Float: { - const llvm::fltSemantics &FloatSema = llvm::APFloatBase::EnumToSemantics( - static_cast(asImpl().readUInt32())); - return APValue(asImpl().readAPFloat(FloatSema)); - } - case APValue::FixedPoint: { - llvm::FixedPointSemantics FPSema = ReadFixedPointSemantics(Record, Idx); - return APValue(llvm::APFixedPoint(readAPInt(), FPSema)); - } - case APValue::ComplexInt: { - llvm::APSInt First = asImpl().readAPSInt(); - return APValue(std::move(First), asImpl().readAPSInt()); - } - case APValue::ComplexFloat: { - const llvm::fltSemantics &FloatSema = llvm::APFloatBase::EnumToSemantics( - static_cast(asImpl().readUInt32())); - llvm::APFloat First = readAPFloat(FloatSema); - return APValue(std::move(First), asImpl().readAPFloat(FloatSema)); - } - case APValue::Vector: { - APValue Result; - Result.MakeVector(); - unsigned Length = asImpl().readUInt32(); - (void)Result.setVectorUninit(Length); - for (unsigned LoopIdx = 0; LoopIdx < Length; LoopIdx++) - Result.getVectorElt(LoopIdx) = asImpl().readAPValue(); - return Result; - } - case APValue::Array: { - APValue Result; - unsigned InitLength = asImpl().readUInt32(); - unsigned TotalLength = asImpl().readUInt32(); - Result.MakeArray(InitLength, TotalLength); - for (unsigned LoopIdx = 0; LoopIdx < InitLength; LoopIdx++) - Result.getArrayInitializedElt(LoopIdx) = asImpl().readAPValue(); - if (Result.hasArrayFiller()) - Result.getArrayFiller() = asImpl().readAPValue(); - return Result; - } - case APValue::Struct: { - APValue Result; - unsigned BasesLength = asImpl().readUInt32(); - unsigned FieldsLength = asImpl().readUInt32(); - Result.MakeStruct(BasesLength, FieldsLength); - for (unsigned LoopIdx = 0; LoopIdx < BasesLength; LoopIdx++) - Result.getStructBase(LoopIdx) = asImpl().readAPValue(); - for (unsigned LoopIdx = 0; LoopIdx < FieldsLength; LoopIdx++) - Result.getStructField(LoopIdx) = asImpl().readAPValue(); - return Result; - } - case APValue::Union: { - auto *FDecl = asImpl().readDeclAs(); - APValue Value = asImpl().readAPValue(); - return APValue(FDecl, std::move(Value)); - } - case APValue::AddrLabelDiff: { - auto *LHS = cast(asImpl().readExpr()); - auto *RHS = cast(asImpl().readExpr()); - return APValue(LHS, RHS); - } - case APValue::MemberPointer: { - APValue Result; - bool IsDerived = asImpl().readUInt32(); - auto *Member = asImpl().readDeclAs(); - unsigned PathSize = asImpl().readUInt32(); - const CXXRecordDecl **PathArray = - Result.setMemberPointerUninit(Member, IsDerived, PathSize).data(); - for (unsigned LoopIdx = 0; LoopIdx < PathSize; LoopIdx++) - PathArray[LoopIdx] = - asImpl().readDeclAs()->getCanonicalDecl(); - return Result; - } - case APValue::LValue: { - uint64_t Bits = asImpl().readUInt32(); - bool HasLValuePath = Bits & 0x1; - bool IsLValueOnePastTheEnd = Bits & 0x2; - bool IsExpr = Bits & 0x4; - bool IsTypeInfo = Bits & 0x8; - bool IsNullPtr = Bits & 0x10; - bool HasBase = Bits & 0x20; - APValue::LValueBase Base; - QualType ElemTy; - assert((!IsExpr || !IsTypeInfo) && "LValueBase cannot be both"); - if (HasBase) { - if (!IsTypeInfo) { - unsigned CallIndex = asImpl().readUInt32(); - unsigned Version = asImpl().readUInt32(); - if (IsExpr) { - Base = APValue::LValueBase(asImpl().readExpr(), CallIndex, Version); - ElemTy = Base.get()->getType(); - } else { - Base = APValue::LValueBase(asImpl().readDeclAs(), - CallIndex, Version); - ElemTy = Base.get()->getType(); - } - } else { - QualType TypeInfo = asImpl().readType(); - QualType Type = asImpl().readType(); - Base = APValue::LValueBase::getTypeInfo( - TypeInfoLValue(TypeInfo.getTypePtr()), Type); - Base.getTypeInfoType(); - } - } - CharUnits Offset = CharUnits::fromQuantity(asImpl().readUInt32()); - unsigned PathLength = asImpl().readUInt32(); - APValue Result; - Result.MakeLValue(); - if (HasLValuePath) { - APValue::LValuePathEntry *Path = - Result - .setLValueUninit(Base, Offset, PathLength, IsLValueOnePastTheEnd, - IsNullPtr) - .data(); - for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) { - if (ElemTy->getAs()) { - unsigned Int = asImpl().readUInt32(); - Decl *D = asImpl().readDeclAs(); - if (auto *RD = dyn_cast(D)) - ElemTy = getASTContext().getRecordType(RD); - else - ElemTy = cast(D)->getType(); - Path[LoopIdx] = - APValue::LValuePathEntry(APValue::BaseOrMemberType(D, Int)); - } else { - ElemTy = getASTContext().getAsArrayType(ElemTy)->getElementType(); - Path[LoopIdx] = - APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32()); - } - } - } else - Result.setLValue(Base, Offset, APValue::NoLValuePath{}, IsNullPtr); - return Result; - } - } - llvm_unreachable("Invalid APValue::ValueKind"); -} - /// Read a floating-point value llvm::APFloat ASTRecordReader::readAPFloat(const llvm::fltSemantics &Sem) { return llvm::APFloat(Sem, readAPInt()); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 3a281e4..27d41df 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5121,144 +5121,6 @@ void ASTRecordWriter::AddAPFloat(const llvm::APFloat &Value) { AddAPInt(Value.bitcastToAPInt()); } -static void WriteFixedPointSemantics(ASTRecordWriter &Record, - llvm::FixedPointSemantics FPSema) { - Record.push_back(FPSema.getWidth()); - Record.push_back(FPSema.getScale()); - Record.push_back(FPSema.isSigned() | FPSema.isSaturated() << 1 | - FPSema.hasUnsignedPadding() << 2); -} - -void ASTRecordWriter::AddAPValue(const APValue &Value) { - APValue::ValueKind Kind = Value.getKind(); - push_back(static_cast(Kind)); - switch (Kind) { - case APValue::None: - case APValue::Indeterminate: - return; - case APValue::Int: - AddAPSInt(Value.getInt()); - return; - case APValue::Float: - push_back(static_cast( - llvm::APFloatBase::SemanticsToEnum(Value.getFloat().getSemantics()))); - AddAPFloat(Value.getFloat()); - return; - case APValue::FixedPoint: { - WriteFixedPointSemantics(*this, Value.getFixedPoint().getSemantics()); - AddAPSInt(Value.getFixedPoint().getValue()); - return; - } - case APValue::ComplexInt: { - AddAPSInt(Value.getComplexIntReal()); - AddAPSInt(Value.getComplexIntImag()); - return; - } - case APValue::ComplexFloat: { - assert(llvm::APFloatBase::SemanticsToEnum( - Value.getComplexFloatImag().getSemantics()) == - llvm::APFloatBase::SemanticsToEnum( - Value.getComplexFloatReal().getSemantics())); - push_back(static_cast(llvm::APFloatBase::SemanticsToEnum( - Value.getComplexFloatReal().getSemantics()))); - AddAPFloat(Value.getComplexFloatReal()); - AddAPFloat(Value.getComplexFloatImag()); - return; - } - case APValue::Vector: - push_back(Value.getVectorLength()); - for (unsigned Idx = 0; Idx < Value.getVectorLength(); Idx++) - AddAPValue(Value.getVectorElt(Idx)); - return; - case APValue::Array: - push_back(Value.getArrayInitializedElts()); - push_back(Value.getArraySize()); - for (unsigned Idx = 0; Idx < Value.getArrayInitializedElts(); Idx++) - AddAPValue(Value.getArrayInitializedElt(Idx)); - if (Value.hasArrayFiller()) - AddAPValue(Value.getArrayFiller()); - return; - case APValue::Struct: - push_back(Value.getStructNumBases()); - push_back(Value.getStructNumFields()); - for (unsigned Idx = 0; Idx < Value.getStructNumBases(); Idx++) - AddAPValue(Value.getStructBase(Idx)); - for (unsigned Idx = 0; Idx < Value.getStructNumFields(); Idx++) - AddAPValue(Value.getStructField(Idx)); - return; - case APValue::Union: - AddDeclRef(Value.getUnionField()); - AddAPValue(Value.getUnionValue()); - return; - case APValue::AddrLabelDiff: - AddStmt(const_cast(Value.getAddrLabelDiffLHS())); - AddStmt(const_cast(Value.getAddrLabelDiffRHS())); - return; - case APValue::MemberPointer: { - push_back(Value.isMemberPointerToDerivedMember()); - AddDeclRef(Value.getMemberPointerDecl()); - ArrayRef RecordPath = Value.getMemberPointerPath(); - push_back(RecordPath.size()); - for (auto Elem : RecordPath) - AddDeclRef(Elem); - return; - } - case APValue::LValue: { - push_back(Value.hasLValuePath() | Value.isLValueOnePastTheEnd() << 1 | - Value.getLValueBase().is() << 2 | - Value.getLValueBase().is() << 3 | - Value.isNullPointer() << 4 | - static_cast(Value.getLValueBase()) << 5); - QualType ElemTy; - if (Value.getLValueBase()) { - assert(!Value.getLValueBase().is() && - "in C++20 dynamic allocation are transient so they shouldn't " - "appear in the AST"); - if (!Value.getLValueBase().is()) { - push_back(Value.getLValueBase().getCallIndex()); - push_back(Value.getLValueBase().getVersion()); - if (const auto *E = Value.getLValueBase().dyn_cast()) { - AddStmt(const_cast(E)); - ElemTy = E->getType(); - } else { - AddDeclRef(Value.getLValueBase().get()); - ElemTy = Value.getLValueBase().get()->getType(); - } - } else { - AddTypeRef( - QualType(Value.getLValueBase().get().getType(), 0)); - AddTypeRef(Value.getLValueBase().getTypeInfoType()); - ElemTy = Value.getLValueBase().getTypeInfoType(); - } - } - push_back(Value.getLValueOffset().getQuantity()); - push_back(Value.getLValuePath().size()); - if (Value.hasLValuePath()) { - ArrayRef Path = Value.getLValuePath(); - for (auto Elem : Path) { - if (ElemTy->getAs()) { - push_back(Elem.getAsBaseOrMember().getInt()); - const Decl *BaseOrMember = Elem.getAsBaseOrMember().getPointer(); - if (const auto *RD = dyn_cast(BaseOrMember)) { - AddDeclRef(RD); - ElemTy = Writer->Context->getRecordType(RD); - } else { - const auto *VD = cast(BaseOrMember); - AddDeclRef(VD); - ElemTy = VD->getType(); - } - } else { - push_back(Elem.getAsArrayIndex()); - ElemTy = Writer->Context->getAsArrayType(ElemTy)->getElementType(); - } - } - } - } - return; - } - llvm_unreachable("Invalid APValue::ValueKind"); -} - void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record) { Record.push_back(getIdentifierRef(II)); } diff --git a/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp b/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp index 256ca42..caced02 100644 --- a/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp +++ b/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp @@ -708,15 +708,13 @@ ASTPropsEmitter::emitBasicReaderWriterTemplate(const ReaderWriterInfo &info) { // Emit the Basic{Reader,Writer}Base template. Out << "template \n" "class Basic" << info.ClassSuffix << "Base {\n"; - if (info.IsReader) - Out << " ASTContext &C;\n"; + Out << " ASTContext &C;\n"; Out << "protected:\n" - " Basic" << info.ClassSuffix << "Base" - << (info.IsReader ? "(ASTContext &ctx) : C(ctx)" : "()") - << " {}\n" + " Basic" + << info.ClassSuffix << "Base" << ("(ASTContext &ctx) : C(ctx)") + << " {}\n" "public:\n"; - if (info.IsReader) - Out << " ASTContext &getASTContext() { return C; }\n"; + Out << " ASTContext &getASTContext() { return C; }\n"; Out << " Impl &asImpl() { return static_cast(*this); }\n"; auto enterReaderWriterMethod = [&](StringRef cxxTypeName, -- 2.7.4