llvm::Error DeclDeserializer::deserializeDeclCommon()

in lib/Serialization/Deserialization.cpp [4326:4819]


llvm::Error DeclDeserializer::deserializeDeclCommon() {
  using namespace decls_block;

  SmallVector<uint64_t, 64> scratch;
  StringRef blobData;
  while (true) {
    BCOffsetRAII restoreOffset(MF.DeclTypeCursor);
    llvm::BitstreamEntry entry =
        MF.fatalIfUnexpected(MF.DeclTypeCursor.advance());
    if (entry.Kind != llvm::BitstreamEntry::Record) {
      // We don't know how to serialize decls represented by sub-blocks.
      MF.fatal();
    }

    unsigned recordID = MF.fatalIfUnexpected(
        MF.DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));

    if (recordID == ERROR_FLAG) {
      assert(!IsInvalid && "Error flag written multiple times");
      IsInvalid = true;
    } else if (isDeclAttrRecord(recordID)) {
      DeclAttribute *Attr = nullptr;
      bool skipAttr = false;
      switch (recordID) {
      case decls_block::SILGenName_DECL_ATTR: {
        bool isImplicit;
        serialization::decls_block::SILGenNameDeclAttrLayout::readRecord(
            scratch, isImplicit);
        Attr = new (ctx) SILGenNameAttr(blobData, isImplicit);
        break;
      }

      case decls_block::CDecl_DECL_ATTR: {
        bool isImplicit;
        serialization::decls_block::CDeclDeclAttrLayout::readRecord(
            scratch, isImplicit);
        Attr = new (ctx) CDeclAttr(blobData, isImplicit);
        break;
      }

      case decls_block::Alignment_DECL_ATTR: {
        bool isImplicit;
        unsigned alignment;
        serialization::decls_block::AlignmentDeclAttrLayout::readRecord(
            scratch, isImplicit, alignment);
        Attr = new (ctx) AlignmentAttr(alignment, SourceLoc(), SourceRange(),
                                       isImplicit);
        break;
      }

      case decls_block::SwiftNativeObjCRuntimeBase_DECL_ATTR: {
        bool isImplicit;
        IdentifierID nameID;
        serialization::decls_block::SwiftNativeObjCRuntimeBaseDeclAttrLayout
          ::readRecord(scratch, isImplicit, nameID);

        auto name = MF.getIdentifier(nameID);
        Attr = new (ctx) SwiftNativeObjCRuntimeBaseAttr(name, SourceLoc(),
                                                        SourceRange(),
                                                        isImplicit);
        break;
      }

      case decls_block::Semantics_DECL_ATTR: {
        bool isImplicit;
        serialization::decls_block::SemanticsDeclAttrLayout::readRecord(
            scratch, isImplicit);
        Attr = new (ctx) SemanticsAttr(blobData, isImplicit);
        break;
      }

      case decls_block::Inline_DECL_ATTR: {
        unsigned kind;
        serialization::decls_block::InlineDeclAttrLayout::readRecord(
            scratch, kind);
        Attr = new (ctx) InlineAttr((InlineKind)kind);
        break;
      }

      case decls_block::NonSendable_DECL_ATTR: {
        unsigned kind;
        serialization::decls_block::NonSendableDeclAttrLayout::readRecord(
            scratch, kind);
        Attr = new (ctx) NonSendableAttr((NonSendableKind)kind);
        break;
      }

      case decls_block::Optimize_DECL_ATTR: {
        unsigned kind;
        serialization::decls_block::OptimizeDeclAttrLayout::readRecord(
            scratch, kind);
        Attr = new (ctx) OptimizeAttr((OptimizationMode)kind);
        break;
      }

      case decls_block::Exclusivity_DECL_ATTR: {
        unsigned kind;
        serialization::decls_block::ExclusivityDeclAttrLayout::readRecord(
            scratch, kind);
        Attr = new (ctx) ExclusivityAttr((ExclusivityAttr::Mode)kind);
        break;
      }

      case decls_block::Effects_DECL_ATTR: {
        unsigned kind;
        IdentifierID customStringID;
        serialization::decls_block::EffectsDeclAttrLayout::
          readRecord(scratch, kind, customStringID);
        if (customStringID) {
          assert((EffectsKind)kind == EffectsKind::Custom);
          Attr = new (ctx) EffectsAttr(MF.getIdentifier(customStringID).str());
        } else {
          Attr = new (ctx) EffectsAttr((EffectsKind)kind);
        }
        break;
      }
      case decls_block::OriginallyDefinedIn_DECL_ATTR: {
        bool isImplicit;
        unsigned Platform;
        DEF_VER_TUPLE_PIECES(MovedVer);
        // Decode the record, pulling the version tuple information.
        serialization::decls_block::OriginallyDefinedInDeclAttrLayout::readRecord(
           scratch,
           isImplicit,
           LIST_VER_TUPLE_PIECES(MovedVer),
           Platform);
        llvm::VersionTuple MovedVer;
        DECODE_VER_TUPLE(MovedVer)
        auto ModuleNameEnd = blobData.find('\0');
        assert(ModuleNameEnd != StringRef::npos);
        auto ModuleName = blobData.slice(0, ModuleNameEnd);
        Attr = new (ctx) OriginallyDefinedInAttr(SourceLoc(), SourceRange(),
                                                 ModuleName,
                                                 (PlatformKind)Platform,
                                                 MovedVer,
                                                 isImplicit);
        break;
      }

      case decls_block::Available_DECL_ATTR: {
        Attr = readAvailable_DECL_ATTR(scratch, blobData);
        break;
      }

      case decls_block::ObjC_DECL_ATTR: {
        bool isImplicit;
        bool isImplicitName;
        bool isSwift3Inferred;
        uint64_t numArgs;
        ArrayRef<uint64_t> rawPieceIDs;
        serialization::decls_block::ObjCDeclAttrLayout::readRecord(
          scratch, isImplicit, isSwift3Inferred, isImplicitName, numArgs,
          rawPieceIDs);

        SmallVector<Identifier, 4> pieces;
        for (auto pieceID : rawPieceIDs)
          pieces.push_back(MF.getIdentifier(pieceID));

        if (numArgs == 0)
          Attr = ObjCAttr::create(ctx, None, isImplicitName);
        else
          Attr = ObjCAttr::create(ctx, ObjCSelector(ctx, numArgs-1, pieces),
                                  isImplicitName);
        Attr->setImplicit(isImplicit);
        cast<ObjCAttr>(Attr)->setSwift3Inferred(isSwift3Inferred);
        break;
      }

      case decls_block::MainType_DECL_ATTR: {
        bool isImplicit;
        serialization::decls_block::MainTypeDeclAttrLayout::readRecord(
            scratch, isImplicit);
        Attr = new (ctx) MainTypeAttr(isImplicit);
        break;
      }

      case decls_block::Specialize_DECL_ATTR: {
        unsigned exported;
        SpecializeAttr::SpecializationKind specializationKind;
        unsigned specializationKindVal;
        GenericSignatureID specializedSigID;

        ArrayRef<uint64_t> rawPieceIDs;
        uint64_t numArgs;
        uint64_t numSPIGroups;
        uint64_t numAvailabilityAttrs;
        DeclID targetFunID;

        serialization::decls_block::SpecializeDeclAttrLayout::readRecord(
            scratch, exported, specializationKindVal, specializedSigID,
            targetFunID, numArgs, numSPIGroups, numAvailabilityAttrs,
            rawPieceIDs);

        assert(rawPieceIDs.size() == numArgs + numSPIGroups ||
               rawPieceIDs.size() == (numArgs - 1 + numSPIGroups));
        specializationKind = specializationKindVal
                                 ? SpecializeAttr::SpecializationKind::Partial
                                 : SpecializeAttr::SpecializationKind::Full;
        // The 'target' parameter.
        DeclNameRef replacedFunctionName;
        if (numArgs) {
          bool numArgumentLabels = (numArgs == 1) ? 0 : numArgs - 2;
          auto baseName = MF.getDeclBaseName(rawPieceIDs[0]);
          SmallVector<Identifier, 4> pieces;
          if (numArgumentLabels) {
            for (auto pieceID : rawPieceIDs.slice(1, numArgumentLabels))
              pieces.push_back(MF.getIdentifier(pieceID));
          }
          replacedFunctionName = (numArgs == 1)
                                     ? DeclNameRef({baseName}) // simple name
                                     : DeclNameRef({ctx, baseName, pieces});
        }

        SmallVector<Identifier, 4> spis;
        if (numSPIGroups) {
          auto numTargetFunctionPiecesToSkip =
              (rawPieceIDs.size() == numArgs + numSPIGroups) ? numArgs
                                                             : numArgs - 1;
          for (auto id : rawPieceIDs.slice(numTargetFunctionPiecesToSkip))
            spis.push_back(MF.getIdentifier(id));
        }
        SmallVector<AvailableAttr *, 4> availabilityAttrs;
        while (numAvailabilityAttrs) {
          // Prepare to read the next record.
          restoreOffset.cancel();
          scratch.clear();

          // TODO: deserialize them.
          BCOffsetRAII restoreOffset2(MF.DeclTypeCursor);
          llvm::BitstreamEntry entry =
              MF.fatalIfUnexpected(MF.DeclTypeCursor.advance());
          if (entry.Kind != llvm::BitstreamEntry::Record) {
            // We don't know how to serialize decls represented by sub-blocks.
            MF.fatal();
          }
          unsigned recordID = MF.fatalIfUnexpected(
              MF.DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
          if (recordID != decls_block::Available_DECL_ATTR) {
            MF.fatal();
          }

          auto attr = readAvailable_DECL_ATTR(scratch, blobData);
          availabilityAttrs.push_back(attr);
          restoreOffset2.cancel();
          --numAvailabilityAttrs;
        }

        auto specializedSig = MF.getGenericSignature(specializedSigID);
        Attr = SpecializeAttr::create(ctx, exported != 0, specializationKind,
                                      spis, availabilityAttrs, specializedSig,
                                      replacedFunctionName, &MF, targetFunID);
        break;
      }

      case decls_block::DynamicReplacement_DECL_ATTR: {
        bool isImplicit;
        uint64_t numArgs;
        ArrayRef<uint64_t> rawPieceIDs;
        DeclID replacedFunID;
        serialization::decls_block::DynamicReplacementDeclAttrLayout::
            readRecord(scratch, isImplicit, replacedFunID, numArgs, rawPieceIDs);

        auto baseName = MF.getDeclBaseName(rawPieceIDs[0]);
        SmallVector<Identifier, 4> pieces;
        for (auto pieceID : rawPieceIDs.slice(1))
          pieces.push_back(MF.getIdentifier(pieceID));

        assert(numArgs != 0);
        assert(!isImplicit && "Need to update for implicit");
        Attr = DynamicReplacementAttr::create(
            ctx, DeclNameRef({ ctx, baseName, pieces }), &MF, replacedFunID);
        break;
      }

      case decls_block::TypeEraser_DECL_ATTR: {
        bool isImplicit;
        TypeID typeEraserID;
        serialization::decls_block::TypeEraserDeclAttrLayout::readRecord(
            scratch, isImplicit, typeEraserID);

        assert(!isImplicit);
        Attr = TypeEraserAttr::create(ctx, &MF, typeEraserID);
        break;
      }

      case decls_block::Custom_DECL_ATTR: {
        bool isImplicit;
        bool isArgUnsafe;
        TypeID typeID;
        serialization::decls_block::CustomDeclAttrLayout::readRecord(
          scratch, isImplicit, typeID, isArgUnsafe);

        Expected<Type> deserialized = MF.getTypeChecked(typeID);
        if (!deserialized) {
          if (deserialized.errorIsA<XRefNonLoadedModuleError>() ||
              MF.allowCompilerErrors()) {
            // A custom attribute defined behind an implementation-only import
            // is safe to drop when it can't be deserialized.
            // rdar://problem/56599179. When allowing errors we're doing a best
            // effort to create a module, so ignore in that case as well.
            consumeError(deserialized.takeError());
            skipAttr = true;
          } else
            return deserialized.takeError();
        } else if (!deserialized.get() && MF.allowCompilerErrors()) {
          // Serialized an invalid attribute, just skip it when allowing errors
          skipAttr = true;
        } else {
          auto *TE = TypeExpr::createImplicit(deserialized.get(), ctx);
          auto custom = CustomAttr::create(ctx, SourceLoc(), TE, isImplicit);
          custom->setArgIsUnsafe(isArgUnsafe);
          Attr = custom;
        }
        break;
      }

      case decls_block::ProjectedValueProperty_DECL_ATTR: {
        bool isImplicit;
        IdentifierID nameID;
        serialization::decls_block::ProjectedValuePropertyDeclAttrLayout
            ::readRecord(scratch, isImplicit, nameID);

        auto name = MF.getIdentifier(nameID);
        Attr = new (ctx) ProjectedValuePropertyAttr(
            name, SourceLoc(), SourceRange(), isImplicit);
        break;
      }

      case decls_block::Differentiable_DECL_ATTR: {
        bool isImplicit;
        uint64_t rawDiffKind;
        GenericSignatureID derivativeGenSigId;
        ArrayRef<uint64_t> parameters;

        serialization::decls_block::DifferentiableDeclAttrLayout::readRecord(
            scratch, isImplicit, rawDiffKind, derivativeGenSigId,
            parameters);

        auto diffKind = getActualDifferentiabilityKind(rawDiffKind);
        if (!diffKind)
          MF.fatal();
        auto derivativeGenSig = MF.getGenericSignature(derivativeGenSigId);
        llvm::SmallBitVector parametersBitVector(parameters.size());
        for (unsigned i : indices(parameters))
          parametersBitVector[i] = parameters[i];
        auto *indices = IndexSubset::get(ctx, parametersBitVector);
        auto *diffAttr = DifferentiableAttr::create(
            ctx, isImplicit, SourceLoc(), SourceRange(), *diffKind,
            /*parsedParameters*/ {}, /*trailingWhereClause*/ nullptr);

        // Cache parameter indices so that they can set later.
        // `DifferentiableAttr::setParameterIndices` cannot be called here
        // because it requires `DifferentiableAttr::setOriginalDeclaration` to
        // be called first. `DifferentiableAttr::setOriginalDeclaration` cannot
        // be called here because the original declaration is not accessible in
        // this function (`DeclDeserializer::deserializeDeclCommon`).
        diffAttrParamIndicesMap[diffAttr] = indices;
        diffAttr->setDerivativeGenericSignature(derivativeGenSig);
        Attr = diffAttr;
        break;
      }

      case decls_block::Derivative_DECL_ATTR: {
        bool isImplicit;
        uint64_t origNameId;
        bool hasAccessorKind;
        uint64_t rawAccessorKind;
        DeclID origDeclId;
        uint64_t rawDerivativeKind;
        ArrayRef<uint64_t> parameters;

        serialization::decls_block::DerivativeDeclAttrLayout::readRecord(
            scratch, isImplicit, origNameId, hasAccessorKind, rawAccessorKind,
            origDeclId, rawDerivativeKind, parameters);

        Optional<AccessorKind> accessorKind = None;
        if (hasAccessorKind) {
          auto maybeAccessorKind = getActualAccessorKind(rawAccessorKind);
          if (!maybeAccessorKind)
            MF.fatal();
          accessorKind = *maybeAccessorKind;
        }

        DeclNameRefWithLoc origName{DeclNameRef(MF.getDeclBaseName(origNameId)),
                                    DeclNameLoc(), accessorKind};
        auto derivativeKind =
            getActualAutoDiffDerivativeFunctionKind(rawDerivativeKind);
        if (!derivativeKind)
          MF.fatal();
        llvm::SmallBitVector parametersBitVector(parameters.size());
        for (unsigned i : indices(parameters))
          parametersBitVector[i] = parameters[i];
        auto *indices = IndexSubset::get(ctx, parametersBitVector);

        auto *derivativeAttr =
            DerivativeAttr::create(ctx, isImplicit, SourceLoc(), SourceRange(),
                                   /*baseType*/ nullptr, origName, indices);
        derivativeAttr->setOriginalFunctionResolver(&MF, origDeclId);
        derivativeAttr->setDerivativeKind(*derivativeKind);
        Attr = derivativeAttr;
        break;
      }

      case decls_block::Transpose_DECL_ATTR: {
        bool isImplicit;
        uint64_t origNameId;
        DeclID origDeclId;
        ArrayRef<uint64_t> parameters;

        serialization::decls_block::TransposeDeclAttrLayout::readRecord(
            scratch, isImplicit, origNameId, origDeclId, parameters);

        DeclNameRefWithLoc origName{
            DeclNameRef(MF.getDeclBaseName(origNameId)), DeclNameLoc(), None};
        auto *origDecl = cast<AbstractFunctionDecl>(MF.getDecl(origDeclId));
        llvm::SmallBitVector parametersBitVector(parameters.size());
        for (unsigned i : indices(parameters))
          parametersBitVector[i] = parameters[i];
        auto *indices = IndexSubset::get(ctx, parametersBitVector);
        auto *transposeAttr =
            TransposeAttr::create(ctx, isImplicit, SourceLoc(), SourceRange(),
                                  /*baseTypeRepr*/ nullptr, origName, indices);
        transposeAttr->setOriginalFunction(origDecl);
        Attr = transposeAttr;
        break;
      }

      case decls_block::SPIAccessControl_DECL_ATTR: {
        ArrayRef<uint64_t> spiIds;
        serialization::decls_block::SPIAccessControlDeclAttrLayout::readRecord(
                                                               scratch, spiIds);

        SmallVector<Identifier, 4> spis;
        for (auto id : spiIds)
          spis.push_back(MF.getIdentifier(id));

        Attr = SPIAccessControlAttr::create(ctx, SourceLoc(),
                                            SourceRange(), spis);
        break;
      }

      case decls_block::UnavailableFromAsync_DECL_ATTR: {
        bool isImplicit;
        serialization::decls_block::UnavailableFromAsyncDeclAttrLayout::
            readRecord(scratch, isImplicit);
        Attr = new (ctx) UnavailableFromAsyncAttr(blobData, isImplicit);
        break;
      }

#define SIMPLE_DECL_ATTR(NAME, CLASS, ...) \
      case decls_block::CLASS##_DECL_ATTR: { \
        bool isImplicit; \
        serialization::decls_block::CLASS##DeclAttrLayout::readRecord( \
            scratch, isImplicit); \
        Attr = new (ctx) CLASS##Attr(isImplicit); \
        break; \
      }
#include "swift/AST/Attr.def"

      default:
        // We don't know how to deserialize this kind of attribute.
        MF.fatal();
      }

      if (!skipAttr) {
        if (!Attr)
          return llvm::Error::success();

        AddAttribute(Attr);
      }

    } else if (recordID == decls_block::PRIVATE_DISCRIMINATOR) {
      IdentifierID discriminatorID;
      decls_block::PrivateDiscriminatorLayout::readRecord(scratch,
                                                          discriminatorID);
      privateDiscriminator = MF.getIdentifier(discriminatorID);

    } else if (recordID == decls_block::LOCAL_DISCRIMINATOR) {
      unsigned discriminator;
      decls_block::LocalDiscriminatorLayout::readRecord(scratch, discriminator);
      localDiscriminator = discriminator;
    } else if (recordID == decls_block::FILENAME_FOR_PRIVATE) {
      IdentifierID filenameID;
      decls_block::FilenameForPrivateLayout::readRecord(scratch, filenameID);
      filenameForPrivate = MF.getIdentifierText(filenameID);
    } else {
      return llvm::Error::success();
    }

    // Prepare to read the next record.
    restoreOffset.cancel();
    scratch.clear();
  }
}