<commit_before>#if SWIFT_PACKAGE
import cllvm
#endif

/// A `TargetData` encapsulates information about the data requirements of a
/// particular target architecture and can be used to retrieve information about
/// sizes and offsets of types with respect to this target.
public class TargetData {
  internal let llvm: LLVMTargetDataRef
  private var structLayoutCache = [LLVMTypeRef: StructLayout]()

  /// Creates a Target Data object from an `LLVMTargetDataRef` object.
  public init(llvm: LLVMTargetDataRef) {
    self.llvm = llvm
  }

  /// Computes the byte offset of the indexed struct element for a target.
  ///
  /// - parameter element: The index of the element in the given structure to
  //    compute.
  /// - parameter type: The type of the structure to compute the offset with.
  ///
  /// - returns: The offset of the given element within the structure.
  public func offsetOfElement(at index: Int, type: StructType) -> Int {
    return Int(LLVMOffsetOfElement(llvm, type.asLLVM(), UInt32(index)))
  }

  /// Computes the index of the struct element at the provided offset in a
  /// struct type for a target.
  ///
  /// - parameter element: The index of the element in the given structure to
  //    compute.
  /// - parameter type: The type of the structure to compute the offset with.
  ///
  /// - returns: The offset of the given element within the structure.
  public func elementAtOffset(_ offset: Int, type: StructType) -> Int {
    return Int(LLVMElementAtOffset(llvm, type.asLLVM(), UInt64(offset)))
  }

  /// Computes the number of bits necessary to hold a value of the given type
  /// for this target environment.
  ///
  /// - parameter type: The type to compute the size of.
  ///
  /// - returns: The size of the type in bits.
  public func sizeOfTypeInBits(_ type: IRType) -> Int {
    return Int(LLVMSizeOfTypeInBits(llvm, type.asLLVM()))
  }

  /// The current platform byte order, either big or little endian.
  public var byteOrder: ByteOrder {
    return ByteOrder(llvm: LLVMByteOrder(llvm))
  }

  /// Creates a string representation of the target data.
  public var layoutString: String {
    let str = LLVMCopyStringRepOfTargetData(llvm)!
    defer { free(str) }
    return String(cString: str)
  }

  /// The integer type that is the same size as a pointer on this target.
  /// This is analoguous to the `intptr_t` type in C++.
  /// - parameters:
  ///   - context: The context in which to derive the type (optional).
  ///   - addressSpace: The address space in which to derive the type.
  /// - returns: An IntegerType that is the same size as the pointer type
  ///            on this target.
  public func intPointerType(context: Context? = nil, addressSpace: Int? = nil) -> IntType {
    let type: LLVMTypeRef
    switch (context, addressSpace) {
    case let (context?, addressSpace?):
      type = LLVMIntPtrTypeForASInContext(context.llvm, llvm, UInt32(addressSpace))
    case let (nil, addressSpace?):
      type = LLVMIntPtrTypeForAS(llvm, UInt32(addressSpace))
    case let (context?, nil):
      type = LLVMIntPtrTypeInContext(context.llvm, llvm)
    case (nil, nil):
      type = LLVMIntPtrType(llvm)
    }
    return convertType(type) as! IntType // Guaranteed to succeed
  }

  /// Computes the preferred alignment of the given global for this target
  ///
  /// - parameter global: The global variable
  /// - returns: The variable's preferred alignment in this target
  public func preferredAlignment(of global: Global) -> Alignment {
    return Alignment(LLVMPreferredAlignmentOfGlobal(llvm, global.asLLVM()))
  }

  /// Computes the preferred alignment of the given type for this target
  ///
  /// - parameter type: The type for which you're computing the alignment
  /// - returns: The type's preferred alignment in this target
  public func preferredAlignment(of type: IRType) -> Alignment {
    return Alignment(LLVMPreferredAlignmentOfType(llvm, type.asLLVM()))
  }

  /// Computes the minimum ABI-required alignment for the specified type.
  ///
  /// - parameter type: The type to whose ABI alignment you wish to compute.
  /// - returns: The minimum ABI-required alignment for the specified type.
  public func abiAlignment(of type: IRType) -> Alignment {
    return Alignment(LLVMABIAlignmentOfType(llvm, type.asLLVM()))
  }

  /// Computes the minimum ABI-required alignment for the specified type.
  ///
  /// This function is equivalent to `TargetData.abiAlignment(of:)`.
  ///
  /// - parameter type: The type to whose ABI alignment you wish to compute.
  /// - returns: The minimum ABI-required alignment for the specified type.
  public func callFrameAlignment(of type: IRType) -> Alignment {
    return Alignment(LLVMCallFrameAlignmentOfType(llvm, type.asLLVM()))
  }

  /// Computes the ABI size of a type in bytes for a target.
  ///
  /// - parameter type: The type to whose ABI size you wish to compute.
  /// - returns: The ABI size for the specified type.
  public func abiSize(of type: IRType) -> Size {
    return Size(LLVMABISizeOfType(llvm, type.asLLVM()))
  }
  /// Computes the maximum number of bytes that may be overwritten by
  /// storing the specified type.
  ///
  /// - parameter type: The type to whose store size you wish to compute.
  /// - returns: The store size of the type in the given target.
  public func storeSize(of type: IRType) -> Size {
    return Size(LLVMStoreSizeOfType(llvm, type.asLLVM()))
  }

  /// Computes the pointer size for the platform, optionally in a given
  /// address space.
  ///
  /// - parameter addressSpace: The address space in which to compute
  ///                           pointer size.
  /// - returns: The size of a pointer in the target address space.
  public func pointerSize(addressSpace: Int? = nil) -> Size {
    if let addressSpace = addressSpace {
      return Size(UInt64(LLVMPointerSizeForAS(llvm, UInt32(addressSpace))))
    } else {
      return Size(UInt64(LLVMPointerSize(llvm)))
    }
  }

  /// Returns the offset in bytes between successive objects of the
  /// specified type, including alignment padding.
  ///
  /// This is the amount that alloca reserves for this type. For example,
  /// returns 12 or 16 for x86_fp80, depending on alignment.
  ///
  /// - parameter type: The type whose allocation size you wish to compute.
  /// - returns: The size an alloca would reserve for the given type.
  public func allocationSize(of type: IRType) -> Size {
    // Round up to the next alignment boundary.
    return TargetData.align(self.storeSize(of: type), to: self.abiAlignment(of: type))
  }

  /// Returns a `StructLayout` object containing the alignment of the
  /// struct, its size, and the offsets of its fields with respect to this
  /// data layout.
  ///
  /// - parameter struct: The struct type whose layout you wish to retrieve.
  /// - returns: A `StructLayout` describing the layout of the given type.
  public func layout(of struct: StructType) -> StructLayout {
    guard let cachedLayout = self.structLayoutCache[`struct`.asLLVM()] else {
      let layout = StructLayout(`struct`, self)
      self.structLayoutCache[`struct`.asLLVM()] = layout
      return layout
    }
    return cachedLayout
  }

  /// Returns the next integer (mod 2**64) that is greater than or equal to
  /// \p Value and is a multiple of \p Align. \p Align must be non-zero.
  ///
  /// If non-zero \p Skew is specified, the return value will be a minimal
  /// integer that is greater than or equal to \p Value and equal to
  /// \p Align * N + \p Skew for some integer N. If \p Skew is larger than
  /// \p Align, its value is adjusted to '\p Skew mod \p Align'.
  ///
  /// Computes the next size value that is greater than or equal to the given
  /// value and is a multiple of the given alignment.
  ///
  /// If the skew value is non-zero, the return value will be the next size
  /// value that is greater than or equal to the given value multipled by the
  /// provided alignment with a skew value added
  public static func align(_ value: Size, to align: Alignment, skew: Size = Size.zero) -> Size {
    precondition(!align.isZero, "Align can't be 0.")

    let skewValue = skew.rawValue % UInt64(align.rawValue)
    let alignValue = UInt64(align.rawValue)
    let retVal = (value.rawValue + alignValue - 1 - skewValue) / alignValue * alignValue + skewValue
    return Size(retVal)
  }
}

/// A `StructLayout` encapsulates information about the layout of a `StructType`.
public struct StructLayout {
  /// Returns the total size of the struct in bytes.
  ///
  /// If the structure is packed, this returns a value that is effectively
  /// the sum of the sizes of its fields.  If the structure is not packed, this
  /// returns the value of the sum of the sizes of its fields plus any
  /// platform-dictated padding.
  public let size: Size
  /// Returns the alignment of the struct in bytes.
  ///<commit_msg>Fixup the documentation for TargetData.align<commit_after>#if SWIFT_PACKAGE
import cllvm
#endif

/// A `TargetData` encapsulates information about the data requirements of a
/// particular target architecture and can be used to retrieve information about
/// sizes and offsets of types with respect to this target.
public class TargetData {
  internal let llvm: LLVMTargetDataRef
  private var structLayoutCache = [LLVMTypeRef: StructLayout]()

  /// Creates a Target Data object from an `LLVMTargetDataRef` object.
  public init(llvm: LLVMTargetDataRef) {
    self.llvm = llvm
  }

  /// Computes the byte offset of the indexed struct element for a target.
  ///
  /// - parameter element: The index of the element in the given structure to
  //    compute.
  /// - parameter type: The type of the structure to compute the offset with.
  ///
  /// - returns: The offset of the given element within the structure.
  public func offsetOfElement(at index: Int, type: StructType) -> Int {
    return Int(LLVMOffsetOfElement(llvm, type.asLLVM(), UInt32(index)))
  }

  /// Computes the index of the struct element at the provided offset in a
  /// struct type for a target.
  ///
  /// - parameter element: The index of the element in the given structure to
  //    compute.
  /// - parameter type: The type of the structure to compute the offset with.
  ///
  /// - returns: The offset of the given element within the structure.
  public func elementAtOffset(_ offset: Int, type: StructType) -> Int {
    return Int(LLVMElementAtOffset(llvm, type.asLLVM(), UInt64(offset)))
  }

  /// Computes the number of bits necessary to hold a value of the given type
  /// for this target environment.
  ///
  /// - parameter type: The type to compute the size of.
  ///
  /// - returns: The size of the type in bits.
  public func sizeOfTypeInBits(_ type: IRType) -> Int {
    return Int(LLVMSizeOfTypeInBits(llvm, type.asLLVM()))
  }

  /// The current platform byte order, either big or little endian.
  public var byteOrder: ByteOrder {
    return ByteOrder(llvm: LLVMByteOrder(llvm))
  }

  /// Creates a string representation of the target data.
  public var layoutString: String {
    let str = LLVMCopyStringRepOfTargetData(llvm)!
    defer { free(str) }
    return String(cString: str)
  }

  /// The integer type that is the same size as a pointer on this target.
  /// This is analoguous to the `intptr_t` type in C++.
  /// - parameters:
  ///   - context: The context in which to derive the type (optional).
  ///   - addressSpace: The address space in which to derive the type.
  /// - returns: An IntegerType that is the same size as the pointer type
  ///            on this target.
  public func intPointerType(context: Context? = nil, addressSpace: Int? = nil) -> IntType {
    let type: LLVMTypeRef
    switch (context, addressSpace) {
    case let (context?, addressSpace?):
      type = LLVMIntPtrTypeForASInContext(context.llvm, llvm, UInt32(addressSpace))
    case let (nil, addressSpace?):
      type = LLVMIntPtrTypeForAS(llvm, UInt32(addressSpace))
    case let (context?, nil):
      type = LLVMIntPtrTypeInContext(context.llvm, llvm)
    case (nil, nil):
      type = LLVMIntPtrType(llvm)
    }
    return convertType(type) as! IntType // Guaranteed to succeed
  }

  /// Computes the preferred alignment of the given global for this target
  ///
  /// - parameter global: The global variable
  /// - returns: The variable's preferred alignment in this target
  public func preferredAlignment(of global: Global) -> Alignment {
    return Alignment(LLVMPreferredAlignmentOfGlobal(llvm, global.asLLVM()))
  }

  /// Computes the preferred alignment of the given type for this target
  ///
  /// - parameter type: The type for which you're computing the alignment
  /// - returns: The type's preferred alignment in this target
  public func preferredAlignment(of type: IRType) -> Alignment {
    return Alignment(LLVMPreferredAlignmentOfType(llvm, type.asLLVM()))
  }

  /// Computes the minimum ABI-required alignment for the specified type.
  ///
  /// - parameter type: The type to whose ABI alignment you wish to compute.
  /// - returns: The minimum ABI-required alignment for the specified type.
  public func abiAlignment(of type: IRType) -> Alignment {
    return Alignment(LLVMABIAlignmentOfType(llvm, type.asLLVM()))
  }

  /// Computes the minimum ABI-required alignment for the specified type.
  ///
  /// This function is equivalent to `TargetData.abiAlignment(of:)`.
  ///
  /// - parameter type: The type to whose ABI alignment you wish to compute.
  /// - returns: The minimum ABI-required alignment for the specified type.
  public func callFrameAlignment(of type: IRType) -> Alignment {
    return Alignment(LLVMCallFrameAlignmentOfType(llvm, type.asLLVM()))
  }

  /// Computes the ABI size of a type in bytes for a target.
  ///
  /// - parameter type: The type to whose ABI size you wish to compute.
  /// - returns: The ABI size for the specified type.
  public func abiSize(of type: IRType) -> Size {
    return Size(LLVMABISizeOfType(llvm, type.asLLVM()))
  }
  /// Computes the maximum number of bytes that may be overwritten by
  /// storing the specified type.
  ///
  /// - parameter type: The type to whose store size you wish to compute.
  /// - returns: The store size of the type in the given target.
  public func storeSize(of type: IRType) -> Size {
    return Size(LLVMStoreSizeOfType(llvm, type.asLLVM()))
  }

  /// Computes the pointer size for the platform, optionally in a given
  /// address space.
  ///
  /// - parameter addressSpace: The address space in which to compute
  ///                           pointer size.
  /// - returns: The size of a pointer in the target address space.
  public func pointerSize(addressSpace: Int? = nil) -> Size {
    if let addressSpace = addressSpace {
      return Size(UInt64(LLVMPointerSizeForAS(llvm, UInt32(addressSpace))))
    } else {
      return Size(UInt64(LLVMPointerSize(llvm)))
    }
  }

  /// Returns the offset in bytes between successive objects of the
  /// specified type, including alignment padding.
  ///
  /// This is the amount that alloca reserves for this type. For example,
  /// returns 12 or 16 for x86_fp80, depending on alignment.
  ///
  /// - parameter type: The type whose allocation size you wish to compute.
  /// - returns: The size an alloca would reserve for the given type.
  public func allocationSize(of type: IRType) -> Size {
    // Round up to the next alignment boundary.
    return TargetData.align(self.storeSize(of: type), to: self.abiAlignment(of: type))
  }

  /// Returns a `StructLayout` object containing the alignment of the
  /// struct, its size, and the offsets of its fields with respect to this
  /// data layout.
  ///
  /// - parameter struct: The struct type whose layout you wish to retrieve.
  /// - returns: A `StructLayout` describing the layout of the given type.
  public func layout(of struct: StructType) -> StructLayout {
    guard let cachedLayout = self.structLayoutCache[`struct`.asLLVM()] else {
      let layout = StructLayout(`struct`, self)
      self.structLayoutCache[`struct`.asLLVM()] = layout
      return layout
    }
    return cachedLayout
  }

  /// Returns the next integer (mod 2^64) that is greater than or equal to
  /// the given size value and is a multiple of the given alignment value.
  /// The alignment must be non-zero.
  ///
  /// If a non-zero skew value is specified, the return value will be a minimal
  /// integer that is greater than or equal to the given size value and equal to
  /// `align * n + skew` for some integer `n`. If the given skew value is
  /// larger than the given alignment value, its value is adjusted to
  /// `skew mod alignment`.
  ///
  /// Computes the next size value that is greater than or equal to the given
  /// value and is a multiple of the given alignment.
  ///
  /// If the skew value is non-zero, the return value will be the next size
  /// value that is greater than or equal to the given value multipled by the
  /// provided alignment with a skew value added
  public static func align(_ value: Size, to align: Alignment, skew: Size = Size.zero) -> Size {
    precondition(!align.isZero, "Align can't be 0.")

    let skewValue = skew.rawValue % UInt64(align.rawValue)
    let alignValue = UInt64(align.rawValue)
    let retVal = (value.rawValue + alignValue - 1 - skewValue) / alignValue * alignValue + skewValue
    return Size(retVal)
  }
}

/// A `StructLayout` encapsulates information about the layout of a `StructType`.
public struct StructLayout {
  /// Returns the total size of the struct in bytes.
  ///
  /// If the structure is packed, this returns a value that is effectively
  /// the sum of the sizes of its fields.  If the structure is not packed, this
  /// returns the value of the sum of the sizes of its fields plus any
  /// platform-dictated padding.
  public let size: Size
  /// Returns the alignment of the struct in bytes.
  ///
{'fraction_non_alphanumeric': 0.09787900833846326, 'fraction_numerical': 0.003469696121775141, 'mean_word_length': 2.9017467248908297, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1335739', 'n_tokens_mistral': 5012, 'n_tokens_neox': 4892, 'n_words': 2137}