text: //===--- SILFormat.h - The internals of serialized SILs ---------*- C++ -*-===//
  //
  // This source file is part of the Swift.org open source project
  //
  // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
  // Licensed under Apache License v2.0 with Runtime Library Exception
  //
  // See https://swift.org/LICENSE.txt for license information
  // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
  //
  //===----------------------------------------------------------------------===//
  ///
  /// \file Contains various constants and helper types to deal with serialized
  /// SILs.
  ///
  //===----------------------------------------------------------------------===//
  
  #ifndef SWIFT_SERIALIZATION_SILFORMAT_H
  #define SWIFT_SERIALIZATION_SILFORMAT_H
  
  #include "swift/Serialization/ModuleFormat.h"
  
  namespace swift {
  namespace serialization {
  
  using ValueID = DeclID;
  using ValueIDField = DeclIDField;
  
  using SILInstOpCodeField = BCFixed<8>;
  using SILTypeCategoryField = BCFixed<2>;
  
  enum SILStringEncoding : uint8_t {
    SIL_UTF8,
    SIL_UTF16,
    SIL_OBJC_SELECTOR,
  };
  
  enum SILLinkageEncoding : uint8_t {
    SIL_LINKAGE_PUBLIC,
    SIL_LINKAGE_PUBLIC_NON_ABI,
    SIL_LINKAGE_HIDDEN,
    SIL_LINKAGE_SHARED,
    SIL_LINKAGE_PRIVATE,
    SIL_LINKAGE_PUBLIC_EXTERNAL,
    SIL_LINKAGE_HIDDEN_EXTERNAL,
    SIL_LINKAGE_SHARED_EXTERNAL,
    SIL_LINKAGE_PRIVATE_EXTERNAL,
  };
  using SILLinkageField = BCFixed<4>;
  
  enum SILVTableEntryKindEncoding : uint8_t {
    SIL_VTABLE_ENTRY_NORMAL,
    SIL_VTABLE_ENTRY_INHERITED,
    SIL_VTABLE_ENTRY_OVERRIDE,
  };
  using SILVTableEntryKindField = BCFixed<2>;
  
  enum CheckedCastKindEncoding : uint8_t {
    SIL_CHECKED_CAST_ARCHETYPE_TO_ARCHETYPE,
    SIL_CHECKED_CAST_ARCHETYPE_TO_CONCRETE,
    SIL_CHECKED_CAST_ARRAY_DOWNCAST,
    SIL_CHECKED_CAST_ARRAY_DOWNCAST_BRIDGED,
    SIL_CHECKED_CAST_DICTIONARY_DOWNCAST,
    SIL_CHECKED_CAST_DICTIONARY_DOWNCAST_BRIDGED,
    SIL_CHECKED_CAST_DOWNCAST,
    SIL_CHECKED_CAST_IDENTICAL,
    SIL_CHECKED_CAST_EXISTENTIAL_TO_ARCHETYPE,
    SIL_CHECKED_CAST_EXISTENTIAL_TO_CONCRETE,
    SIL_CHECKED_CAST_SUPER_TO_ARCHETYPE,
    SIL_CHECKED_CAST_CONCRETE_TO_ARCHETYPE,
    SIL_CHECKED_CAST_CONCRETE_TO_UNRELATED_EXISTENTIAL,
  };
  
  enum CastConsumptionKindEncoding : uint8_t {
    SIL_CAST_CONSUMPTION_TAKE_ALWAYS,
    SIL_CAST_CONSUMPTION_TAKE_ON_SUCCESS,
    SIL_CAST_CONSUMPTION_COPY_ON_SUCCESS,
  };
  
  enum class KeyPathComponentKindEncoding : uint8_t {
    StoredProperty,
    GettableProperty,
    SettableProperty,
    OptionalChain,
    OptionalForce,
    OptionalWrap,
    External,
  };
  enum class KeyPathComputedComponentIdKindEncoding : uint8_t {
    Property,
    Function,
    DeclRef,
  };
  
  // Constants for packing an encoded CheckedCastKind and
  // CastConsumptionKind together.
  enum {
    // Must be large enough to store all the CheckedCastKindEncodings
    SIL_CAST_CONSUMPTION_BIT_OFFSET = 4,
    SIL_CHECKED_CAST_MASK =
      (1 << SIL_CAST_CONSUMPTION_BIT_OFFSET) - 1
  };
  
  /// The record types within the "sil-index" block.
  ///
  /// \sa SIL_INDEX_BLOCK_ID
  namespace sil_index_block {
    // These IDs must \em not be renumbered or reordered without incrementing
    // VERSION_MAJOR.
    enum RecordKind {
      SIL_FUNC_NAMES = 1,
      SIL_FUNC_OFFSETS,
      SIL_VTABLE_NAMES,
      SIL_VTABLE_OFFSETS,
      SIL_GLOBALVAR_NAMES,
      SIL_GLOBALVAR_OFFSETS,
      SIL_WITNESS_TABLE_NAMES,
      SIL_WITNESS_TABLE_OFFSETS,
      SIL_DEFAULT_WITNESS_TABLE_NAMES,
      SIL_DEFAULT_WITNESS_TABLE_OFFSETS,
      SIL_PROPERTY_OFFSETS,
    };
  
    using ListLayout = BCGenericRecordLayout<
      BCFixed<4>,  // record ID
      BCVBR<16>,  // table offset within the blob
      BCBlob      // map from identifier strings to IDs.
    >;
  
    using OffsetLayout = BCGenericRecordLayout<
      BCFixed<4>,  // record ID
      BCArray<BitOffsetField>
    >;
  }
  
  /// The record types within the "sil" block.
  ///
  /// \sa SIL_BLOCK_ID
  namespace sil_block {
    // These IDs must \em not be renumbered or reordered without incrementing
    // VERSION_MAJOR.
    enum RecordKind : uint8_t {
      // To avoid overlapping with BOUND_GENERIC_SUBSTITUTION, we start from +1.
      SIL_FUNCTION = decls_block::BOUND_GENERIC_SUBSTITUTION + 1,
      SIL_BASIC_BLOCK,
      SIL_ONE_VALUE_ONE_OPERAND,
      SIL_ONE_TYPE,
      SIL_ONE_OPERAND,
      SIL_ONE_TYPE_ONE_OPERAND,
      SIL_ONE_TYPE_VALUES,
      SIL_TWO_OPERANDS,
      SIL_TAIL_ADDR,
      SIL_INST_APPLY,
      SIL_INST_NO_OPERAND,
      SIL_VTABLE,
      SIL_VTABLE_ENTRY,
      SIL_GLOBALVAR,
      SIL_INST_CAST, // It has a cast kind instead of an attribute.
      SIL_INIT_EXISTENTIAL,
      SIL_WITNESS_TABLE,
      SIL_WITNESS_METHOD_ENTRY,
      SIL_WITNESS_BASE_ENTRY,
      SIL_WITNESS_ASSOC_PROTOCOL,
      SIL_WITNESS_ASSOC_ENTRY,
      SIL_WITNESS_CONDITIONAL_CONFORMANCE,
      SIL_DEFAULT_WITNESS_TABLE,
      SIL_DEFAULT_WITNESS_TABLE_ENTRY,
      SIL_DEFAULT_WITNESS_TABLE_NO_ENTRY,
      SIL_INST_WITNESS_METHOD,
      SIL_SPECIALIZE_ATTR,
      SIL_PROPERTY,
      SIL_ONE_OPERAND_EXTRA_ATTR,
      SIL_TWO_OPERANDS_EXTRA_ATTR,
  
      // We also share these layouts from the decls block. Their enumerators must
      // not overlap with ours.
      BOUND_GENERIC_SUBSTITUTION = decls_block::BOUND_GENERIC_SUBSTITUTION,
      ABSTRACT_PROTOCOL_CONFORMANCE = decls_block::ABSTRACT_PROTOCOL_CONFORMANCE,
      NORMAL_PROTOCOL_CONFORMANCE = decls_block::NORMAL_PROTOCOL_CONFORMANCE,
      SPECIALIZED_PROTOCOL_CONFORMANCE
        = decls_block::SPECIALIZED_PROTOCOL_CONFORMANCE,
      INHERITED_PROTOCOL_CONFORMANCE
        = decls_block::INHERITED_PROTOCOL_CONFORMANCE,
      GENERIC_PARAM = decls_block::GENERIC_PARAM,
      GENERIC_REQUIREMENT = decls_block::GENERIC_REQUIREMENT,
      LAYOUT_REQUIREMENT = decls_block::LAYOUT_REQUIREMENT,
    };
  
    using SILInstNoOperandLayout = BCRecordLayout<
      SIL_INST_NO_OPERAND,
      SILInstOpCodeField
    >;
  
    using VTableLayout = BCRecordLayout<
      SIL_VTABLE,
      DeclIDField,   // Class Decl
      BCFixed<1>     // IsSerialized.
    >;
  
    using VTableEntryLayout = BCRecordLayout<
      SIL_VTABLE_ENTRY,
      DeclIDField,  // SILFunction name
      SILVTableEntryKindField,  // Kind
      SILLinkageField,      // Linkage
      BCArray<ValueIDField> // SILDeclRef
    >;
    
    using PropertyLayout = BCRecordLayout<
      SIL_PROPERTY,
      DeclIDField,          // Property decl
      BCFixed<1>,           // Is serialized
      BCArray<ValueIDField> // Encoded key path component
      // Any substitutions or conformances required for the key path component
      // follow.
    >;
  
    using WitnessTableLayout = BCRecordLayout<
      SIL_WITNESS_TABLE,
      SILLinkageField,     // Linkage
      BCFixed<1>,          // Is this a declaration. We represent this separately
                           // from whether or not we have entries since we can
                           // have empty witness tables.
      BCFixed<1>           // IsSerialized.
      // Conformance follows
      // Witness table entries will be serialized after.
    >;
  
    using WitnessMethodEntryLayout = BCRecordLayout<
      SIL_WITNESS_METHOD_ENTRY,
      DeclIDField,  // SILFunction name
      BCArray<ValueIDField> // SILDeclRef
    >;
  
    using WitnessBaseEntryLayout = BCRecordLayout<
      SIL_WITNESS_BASE_ENTRY,
      DeclIDField  // ID of protocol decl
      // Trailed by the conformance itself.
    >;
  
    using WitnessAssocProtocolLayout = BCRecordLayout<
      SIL_WITNESS_ASSOC_PROTOCOL,
      TypeIDField, // ID of associated type
      DeclIDField  // ID of ProtocolDecl
      // Trailed by the conformance itself if appropriate.
    >;
  
    using WitnessAssocEntryLayout = BCRecordLayout<
      SIL_WITNESS_ASSOC_ENTRY,
      DeclIDField,  // ID of AssociatedTypeDecl
      TypeIDField
    >;
  
    using WitnessConditionalConformanceLayout = BCRecordLayout<
      SIL_WITNESS_CONDITIONAL_CONFORMANCE,
      TypeIDField // ID of associated type
      // Trailed by the conformance itself if appropriate.
    >;
  
    using DefaultWitnessTableLayout = BCRecordLayout<
      SIL_DEFAULT_WITNESS_TABLE,
      DeclIDField,  // ID of ProtocolDecl
      SILLinkageField  // Linkage
      // Default witness table entries will be serialized after.
    >;
  
    using DefaultWitnessTableEntryLayout = BCRecordLayout<
      SIL_DEFAULT_WITNESS_TABLE_ENTRY,
      DeclIDField,  // SILFunction name
      BCArray<ValueIDField> // SILDeclRef
    >;
  
    using DefaultWitnessTableNoEntryLayout = BCRecordLayout<
      SIL_DEFAULT_WITNESS_TABLE_NO_ENTRY
    >;
  
    using SILGlobalVarLayout = BCRecordLayout<
      SIL_GLOBALVAR,
      SILLinkageField,
      BCFixed<1>,          // serialized
      BCFixed<1>,          // Is this a declaration.
      BCFixed<1>,          // Is this a let variable.
      TypeIDField,
      DeclIDField
    >;
  
    using SILFunctionLayout =
        BCRecordLayout<SIL_FUNCTION, SILLinkageField,
                       BCFixed<1>,  // transparent
                       BCFixed<2>,  // serialized
                       BCFixed<2>,  // thunk/reabstraction_thunk
                       BCFixed<1>,  // global_init
                       BCFixed<2>,  // inlineStrategy
                       BCFixed<2>,  // optimizationMode
                       BCFixed<3>,  // side effect info.
                       BCVBR<8>,    // number of specialize attributes
                       BCFixed<1>,  // has qualified ownership
                       BCFixed<1>,  // must be weakly referenced
                       TypeIDField, // SILFunctionType
                       GenericEnvironmentIDField,
                       DeclIDField, // ClangNode owner
                       BCArray<IdentifierIDField> // Semantics Attribute
                       // followed by specialize attributes
                       // followed by generic param list, if any
                       >;
  
    using SILSpecializeAttrLayout =
        BCRecordLayout<SIL_SPECIALIZE_ATTR,
                       BCFixed<1>, // exported
                       BCFixed<1> // specialization kind
                       >;
  
    // Has an optional argument list where each argument is a typed valueref.
    using SILBasicBlockLayout = BCRecordLayout<
      SIL_BASIC_BLOCK,
      BCArray<DeclIDField> // The array contains type-value pairs.
    >;
  
    // SIL instructions with one valueref and one typed valueref.
    // (store)
    using SILOneValueOneOperandLayout = BCRecordLayout<
      SIL_ONE_VALUE_ONE_OPERAND,
      SILInstOpCodeField,
      BCFixed<2>,          // Optional attributes
      ValueIDField,
      TypeIDField,
      SILTypeCategoryField,
      ValueIDField
    >;
  
    // SIL instructions with one type and one typed valueref.
    using SILOneTypeOneOperandLayout = BCRecordLayout<
      SIL_ONE_TYPE_ONE_OPERAND,
      SILInstOpCodeField,
      BCFixed<2>,          // Optional attributes
      TypeIDField,
      SILTypeCategoryField,
      TypeIDField,
      SILTypeCategoryField,
      ValueIDField
    >;
  
    // SIL instructions that construct existential values.
    using SILInitExistentialLayout = BCRecordLayout<
      SIL_INIT_EXISTENTIAL,
      SILInstOpCodeField,   // opcode
      TypeIDField,          // result type
      SILTypeCategoryField, // result type category
      TypeIDField,          // operand type
      SILTypeCategoryField, // operand type category
      ValueIDField,         // operand id
      TypeIDField,          // formal concrete type
      BCVBR<5>              // # of protocol conformances
      // Trailed by protocol conformance info (if any)
    >;
  
    // SIL Cast instructions with a cast kind, one type and one typed valueref.
    using SILInstCastLayout = BCRecordLayout<
      SIL_INST_CAST,
      SILInstOpCodeField,
      BCFixed<4>,          // Cast kind
      TypeIDField,
      SILTypeCategoryField,
      TypeIDField,
      SILTypeCategoryField,
      ValueIDField
    >;
  
    // SIL instructions with one type and a list of values.
    using SILOneTypeValuesLayout = BCRecordLayout<
      SIL_ONE_TYPE_VALUES,
      SILInstOpCodeField,
      TypeIDField,
      SILTypeCategoryField,
      BCArray<ValueIDField>
    >;
  
    enum ApplyKind : unsigned {
      SIL_APPLY = 0,
      SIL_PARTIAL_APPLY,
      SIL_BUILTIN,
      SIL_TRY_APPLY,
      SIL_NON_THROWING_APPLY,
      SIL_BEGIN_APPLY,
      SIL_NON_THROWING_BEGIN_APPLY
    };
    
    using SILInstApplyLayout = BCRecordLayout<
      SIL_INST_APPLY,
      BCFixed<3>,           // ApplyKind
      BCFixed<32>,          // num substitutions
      TypeIDField,          // callee unsubstituted type
      TypeIDField,          // callee substituted type
      ValueIDField,         // callee value
      BCArray<ValueIDField> // a list of arguments
    >;
  
    // SIL instructions with one type. (alloc_stack)
    using SILOneTypeLayout = BCRecordLayout<
      SIL_ONE_TYPE,
      SILInstOpCodeField,
      TypeIDField,
      SILTypeCategoryField
    >;
  
    // SIL instructions with one typed valueref. (dealloc_stack, return)
    using SILOneOperandLayout = BCRecordLayout<
      SIL_ONE_OPERAND,
      SILInstOpCodeField,
      BCFixed<2>,          // Optional attributes
      TypeIDField,
      SILTypeCategoryField,
      ValueIDField
    >;
  
    using SILOneOperandExtraAttributeLayout = BCRecordLayout<
      SIL_ONE_OPERAND_EXTRA_ATTR,
      SILInstOpCodeField,
      BCFixed<6>, // Optional attributes
      TypeIDField, SILTypeCategoryField, ValueIDField
    >;
  
    // SIL instructions with two typed values.
    using SILTwoOperandsLayout = BCRecordLayout<
      SIL_TWO_OPERANDS,
      SILInstOpCodeField,
      BCFixed<2>,          // Optional attributes
      TypeIDField,
      SILTypeCategoryField,
      ValueIDField,
      TypeIDField,
      SILTypeCategoryField,
      ValueIDField
    >;
  
    using SILTwoOperandsExtraAttributeLayout = BCRecordLayout<
      SIL_TWO_OPERANDS_EXTRA_ATTR,
      SILInstOpCodeField,
      BCFixed<6>,          // Optional attributes
      TypeIDField,
      SILTypeCategoryField,
      ValueIDField,
      TypeIDField,
      SILTypeCategoryField,
      ValueIDField
    >;
  
    // The tail_addr instruction.
    using SILTailAddrLayout = BCRecordLayout<
      SIL_TAIL_ADDR,
      SILInstOpCodeField,
      TypeIDField,          // Base operand
      ValueIDField,
      TypeIDField,          // Count operand
      ValueIDField,
      TypeIDField           // Result type
    >;
  
    using SILInstWitnessMethodLayout = BCRecordLayout<
      SIL_INST_WITNESS_METHOD,
      TypeIDField,           // result type
      SILTypeCategoryField,
      BCFixed<1>,            // volatile?
      TypeIDField,           // lookup type
      SILTypeCategoryField,
      TypeIDField,           // Optional
      SILTypeCategoryField,  // opened
      ValueIDField,          // existential
      BCArray<ValueIDField>  // SILDeclRef
      // may be trailed by an inline protocol conformance
    >;
  }
  
  } // end namespace serialization
  } // end namespace swift
  
  #endif
  