[NFC] Move readAPValue/writeAPValue up the inheritance hierarchy
authorVarun Gandhi <varun_gandhi@apple.com>
Wed, 6 Jan 2021 22:34:20 +0000 (14:34 -0800)
committerVarun Gandhi <varun_gandhi@apple.com>
Thu, 7 Jan 2021 00:44:50 +0000 (16:44 -0800)
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
clang/include/clang/AST/AbstractBasicReader.h
clang/include/clang/AST/AbstractBasicWriter.h
clang/include/clang/AST/PropertiesBase.td
clang/include/clang/Serialization/ASTRecordReader.h
clang/include/clang/Serialization/ASTRecordWriter.h
clang/include/clang/Serialization/ASTWriter.h
clang/lib/AST/APValue.cpp
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/utils/TableGen/ClangASTPropertiesEmitter.cpp

index eded348..f9b1899 100644 (file)
 #include "llvm/Support/AlignOf.h"
 
 namespace clang {
+namespace serialization {
+template <typename T> 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<LValuePathEntry> Path;
+
+    LValuePathSerializationHelper(ArrayRef<LValuePathEntry>, QualType);
+    QualType getType();
+  };
   struct NoLValuePath {};
   struct UninitArray {};
   struct UninitStruct {};
 
-  friend class ASTRecordReader;
-  friend class ASTWriter;
+  template <typename Impl> friend class clang::serialization::BasicReaderBase;
   friend class ASTImporter;
   friend class ASTNodeImporter;
 
index d7b3a9d..5505d66 100644 (file)
@@ -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<APValue::LValuePathEntry> &path) {
+    auto elemTy = asImpl().readQualType();
+    unsigned pathLength = asImpl().readUInt32();
+    for (unsigned i = 0; i < pathLength; ++i) {
+      if (elemTy->template getAs<RecordType>()) {
+        unsigned int_ = asImpl().readUInt32();
+        Decl *decl = asImpl().template readDeclAs<Decl>();
+        if (auto *recordDecl = dyn_cast<CXXRecordDecl>(decl))
+          elemTy = getASTContext().getRecordType(recordDecl);
+        else
+          elemTy = cast<ValueDecl>(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");
index 0a6730c..75aef73 100644 (file)
@@ -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 Impl>
 class DataStreamBasicWriter : public BasicWriterBase<Impl> {
 protected:
   using BasicWriterBase<Impl>::asImpl;
+  DataStreamBasicWriter(ASTContext &ctx) : BasicWriterBase<Impl>(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<APValue::LValuePathEntry> path = lvaluePath.Path;
+    QualType elemTy = lvaluePath.getType();
+    asImpl().writeQualType(elemTy);
+    asImpl().writeUInt32(path.size());
+    auto &ctx = ((BasicWriterBase<Impl> *)this)->getASTContext();
+    for (auto elem : path) {
+      if (elemTy->getAs<RecordType>()) {
+        asImpl().writeUInt32(elem.getAsBaseOrMember().getInt());
+        const Decl *baseOrMember = elem.getAsBaseOrMember().getPointer();
+        if (const auto *recordDecl = dyn_cast<CXXRecordDecl>(baseOrMember)) {
+          asImpl().writeDeclRef(recordDecl);
+          elemTy = ctx.getRecordType(recordDecl);
+        } else {
+          const auto *valueDecl = cast<ValueDecl>(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");
index ba0f237..a087cb4 100644 (file)
@@ -72,6 +72,8 @@ class CountPropertyType<string typeName = ""> : PropertyType<typeName> {
 
 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<PropertyType type, string name> : HasProperties {
   string Name = name;
 }
 
+// Type cases for APValue.
+def : PropertyTypeKind<APValue, APValueKind,
+                       "node.getKind()">;
+let Class = PropertyTypeCase<APValue, "None"> in {
+  def : Creator<[{ return APValue(); }]>;
+}
+let Class = PropertyTypeCase<APValue, "Indeterminate"> in {
+  def : Creator<[{ return APValue::IndeterminateValue(); }]>;
+}
+let Class = PropertyTypeCase<APValue, "Int"> in {
+  def : Property<"value", APSInt> {
+    let Read = [{ node.getInt() }];
+  }
+  def : Creator<[{ return APValue(value); }]>;
+}
+let Class = PropertyTypeCase<APValue, "Float"> in {
+  def : Property<"semantics", UInt32> {
+    let Read = [{
+      static_cast<uint32_t>(
+        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<llvm::APFloatBase::Semantics>(semantics));
+    return APValue(llvm::APFloat(floatSema, value));
+  }]>;
+}
+let Class = PropertyTypeCase<APValue, "FixedPoint"> 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<APValue, "ComplexInt"> 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<APValue, "ComplexFloat"> 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<uint32_t>(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<llvm::APFloatBase::Semantics>(semantics));
+    return APValue(llvm::APFloat(sema, real),
+                   llvm::APFloat(sema, imag));
+  }]>;
+}
+let Class = PropertyTypeCase<APValue, "Vector"> in {
+  def : ReadHelper<[{
+    SmallVector<APValue, 4> buffer;
+    unsigned len = node.getVectorLength();
+    for (unsigned i = 0; i < len; ++i)
+      buffer.push_back(node.getVectorElt(i));
+  }]>;
+  def : Property<"elements", Array<APValue>> {
+    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<APValue, "Array"> in {
+  def : ReadHelper<[{
+    SmallVector<APValue, 4> 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<APValue>> {
+    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<APValue, "Struct"> in {
+  def : ReadHelper<[{
+    SmallVector<APValue, 4> structBases;
+    unsigned numBases = node.getStructNumBases();
+    for (unsigned i = 0; i < numBases; ++i)
+      structBases.push_back(node.getStructBase(i));
+    SmallVector<APValue, 4> structFields;
+    unsigned numFields = node.getStructNumFields();
+    for (unsigned i = 0; i < numFields; ++i)
+      structFields.push_back(node.getStructField(i));
+  }]>;
+  def : Property<"bases", Array<APValue>> {
+    let Read = [{ structBases }];
+  }
+  def : Property<"fields", Array<APValue>> {
+    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<APValue, "Union"> in {
+  def : Property<"fieldDecl", DeclRef> {
+    let Read = [{ node.getUnionField() }];
+  }
+  def : Property<"value", APValue> {
+    let Read = [{ node.getUnionValue() }];
+  }
+  def : Creator<[{
+    return APValue(cast<clang::FieldDecl>(fieldDecl), std::move(value));
+  }]>;
+}
+let Class = PropertyTypeCase<APValue, "AddrLabelDiff"> in {
+  def : Property<"lhs", StmtRef> {
+    let Read = [{ const_cast<AddrLabelExpr *>(node.getAddrLabelDiffLHS()) }];
+  }
+  def : Property<"rhs", StmtRef> {
+    let Read = [{ const_cast<AddrLabelExpr *>(node.getAddrLabelDiffRHS()) }];
+  }
+  def : Creator<[{
+    return APValue(cast<AddrLabelExpr>(lhs), cast<AddrLabelExpr>(rhs));
+  }]>;
+}
+let Class = PropertyTypeCase<APValue, "MemberPointer"> in {
+  def : Property<"isDerived", Bool> {
+    let Read = [{ node.isMemberPointerToDerivedMember() }];
+  }
+  def : Property<"member", ValueDeclRef> {
+    let Read = [{ node.getMemberPointerDecl() }];
+  }
+  def : Property<"memberPath", Array<CXXRecordDeclRef>> {
+    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<APValue, "LValue"> in {
+  def : ReadHelper<[{
+    auto lvalueBase = node.getLValueBase();
+    const Expr *expr =
+        lvalueBase ? lvalueBase.dyn_cast<const Expr *>() : nullptr;
+    bool lvalueBaseIsExpr = (bool) expr;
+    bool lvalueBaseIsTypeInfo = lvalueBase.is<TypeInfoLValue>();
+    QualType elemTy;
+    if (lvalueBase) {
+      if (lvalueBaseIsTypeInfo) {
+        elemTy = lvalueBase.getTypeInfoType();
+      } else if (lvalueBaseIsExpr) {
+        elemTy = expr->getType();
+      } else {
+        elemTy = lvalueBase.get<const ValueDecl *>()->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<bool>(lvalueBase) }];
+  }
+  def : Property<"isNullPtr", Bool> {
+    let Read = [{ node.isNullPointer() }];
+  }
+  def : Property<"typeInfo", QualType> {
+    let Conditional = [{ hasBase && isTypeInfo }];
+    let Read = [{
+      QualType(node.getLValueBase().get<TypeInfoLValue>().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 *>(expr) }];
+  }
+  def : Property<"decl", DeclRef> {
+    let Conditional = [{ hasBase && !isTypeInfo && !isExpr }];
+    let Read = [{ lvalueBase.get<const ValueDecl *>() }];
+  }
+  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<Expr>(stmt.getValue()),
+                                   callIndex.getValue(), version.getValue());
+        elemTy = base.get<const Expr *>()->getType();
+      } else {
+        base = APValue::LValueBase(cast<ValueDecl>(decl.getValue()),
+                                   callIndex.getValue(), version.getValue());
+        elemTy = base.get<const ValueDecl *>()->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<DeclarationName, DeclarationNameKind,
                        "node.getNameKind()">;
index 3912ffe..b85609b 100644 (file)
@@ -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)
index e362463..0dc69bd 100644 (file)
@@ -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) {
index 7a6664a..02fd72f 100644 (file)
@@ -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
index c18f885..9a9233b 100644 (file)
@@ -154,6 +154,14 @@ void APValue::LValuePathEntry::Profile(llvm::FoldingSetNodeID &ID) const {
   ID.AddInteger(Value);
 }
 
+APValue::LValuePathSerializationHelper::LValuePathSerializationHelper(
+    ArrayRef<LValuePathEntry> Path, QualType ElemTy)
+    : ElemTy((const void *)ElemTy.getTypePtrOrNull()), Path(Path) {}
+
+QualType APValue::LValuePathSerializationHelper::getType() {
+  return QualType::getFromOpaquePtr(ElemTy);
+}
+
 namespace {
   struct LVBase {
     APValue::LValueBase Base;
index b48b23c..eda286c 100644 (file)
@@ -8941,165 +8941,6 @@ ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record,
   return SourceRange(beg, end);
 }
 
-static llvm::FixedPointSemantics
-ReadFixedPointSemantics(const SmallVectorImpl<uint64_t> &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<APValue::ValueKind>(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<llvm::APFloatBase::Semantics>(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<llvm::APFloatBase::Semantics>(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<FieldDecl>();
-    APValue Value = asImpl().readAPValue();
-    return APValue(FDecl, std::move(Value));
-  }
-  case APValue::AddrLabelDiff: {
-    auto *LHS = cast<AddrLabelExpr>(asImpl().readExpr());
-    auto *RHS = cast<AddrLabelExpr>(asImpl().readExpr());
-    return APValue(LHS, RHS);
-  }
-  case APValue::MemberPointer: {
-    APValue Result;
-    bool IsDerived = asImpl().readUInt32();
-    auto *Member = asImpl().readDeclAs<ValueDecl>();
-    unsigned PathSize = asImpl().readUInt32();
-    const CXXRecordDecl **PathArray =
-        Result.setMemberPointerUninit(Member, IsDerived, PathSize).data();
-    for (unsigned LoopIdx = 0; LoopIdx < PathSize; LoopIdx++)
-      PathArray[LoopIdx] =
-          asImpl().readDeclAs<const CXXRecordDecl>()->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<const Expr *>()->getType();
-        } else {
-          Base = APValue::LValueBase(asImpl().readDeclAs<const ValueDecl>(),
-                                     CallIndex, Version);
-          ElemTy = Base.get<const ValueDecl *>()->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<RecordType>()) {
-          unsigned Int = asImpl().readUInt32();
-          Decl *D = asImpl().readDeclAs<Decl>();
-          if (auto *RD = dyn_cast<CXXRecordDecl>(D))
-            ElemTy = getASTContext().getRecordType(RD);
-          else
-            ElemTy = cast<ValueDecl>(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());
index 3a281e4..27d41df 100644 (file)
@@ -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<uint64_t>(Kind));
-  switch (Kind) {
-  case APValue::None:
-  case APValue::Indeterminate:
-    return;
-  case APValue::Int:
-    AddAPSInt(Value.getInt());
-    return;
-  case APValue::Float:
-    push_back(static_cast<uint64_t>(
-        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<uint64_t>(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<AddrLabelExpr *>(Value.getAddrLabelDiffLHS()));
-    AddStmt(const_cast<AddrLabelExpr *>(Value.getAddrLabelDiffRHS()));
-    return;
-  case APValue::MemberPointer: {
-    push_back(Value.isMemberPointerToDerivedMember());
-    AddDeclRef(Value.getMemberPointerDecl());
-    ArrayRef<const CXXRecordDecl *> 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<const Expr *>() << 2 |
-              Value.getLValueBase().is<TypeInfoLValue>() << 3 |
-              Value.isNullPointer() << 4 |
-              static_cast<bool>(Value.getLValueBase()) << 5);
-    QualType ElemTy;
-    if (Value.getLValueBase()) {
-      assert(!Value.getLValueBase().is<DynamicAllocLValue>() &&
-             "in C++20 dynamic allocation are transient so they shouldn't "
-             "appear in the AST");
-      if (!Value.getLValueBase().is<TypeInfoLValue>()) {
-        push_back(Value.getLValueBase().getCallIndex());
-        push_back(Value.getLValueBase().getVersion());
-        if (const auto *E = Value.getLValueBase().dyn_cast<const Expr *>()) {
-          AddStmt(const_cast<Expr *>(E));
-          ElemTy = E->getType();
-        } else {
-          AddDeclRef(Value.getLValueBase().get<const ValueDecl *>());
-          ElemTy = Value.getLValueBase().get<const ValueDecl *>()->getType();
-        }
-      } else {
-        AddTypeRef(
-            QualType(Value.getLValueBase().get<TypeInfoLValue>().getType(), 0));
-        AddTypeRef(Value.getLValueBase().getTypeInfoType());
-        ElemTy = Value.getLValueBase().getTypeInfoType();
-      }
-    }
-    push_back(Value.getLValueOffset().getQuantity());
-    push_back(Value.getLValuePath().size());
-    if (Value.hasLValuePath()) {
-      ArrayRef<APValue::LValuePathEntry> Path = Value.getLValuePath();
-      for (auto Elem : Path) {
-        if (ElemTy->getAs<RecordType>()) {
-          push_back(Elem.getAsBaseOrMember().getInt());
-          const Decl *BaseOrMember = Elem.getAsBaseOrMember().getPointer();
-          if (const auto *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
-            AddDeclRef(RD);
-            ElemTy = Writer->Context->getRecordType(RD);
-          } else {
-            const auto *VD = cast<ValueDecl>(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));
 }
index 256ca42..caced02 100644 (file)
@@ -708,15 +708,13 @@ ASTPropsEmitter::emitBasicReaderWriterTemplate(const ReaderWriterInfo &info) {
   // Emit the Basic{Reader,Writer}Base template.
   Out << "template <class Impl>\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<Impl&>(*this); }\n";
 
   auto enterReaderWriterMethod = [&](StringRef cxxTypeName,