All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.scalanative.codegen.Metadata.scala Maven / Gradle / Ivy

There is a newer version: 0.5.5
Show newest version
package scala.scalanative
package codegen

import scala.collection.mutable
import scalanative.linker.{Trait, Class, ReachabilityAnalysis}

private[scalanative] class Metadata(
    val analysis: ReachabilityAnalysis.Result,
    val buildConfig: build.Config,
    proxies: Seq[nir.Defn]
)(implicit val platform: PlatformInfo) {
  def config: build.NativeConfig = buildConfig.compilerConfig
  implicit private def self: Metadata = this

  final val usesLockWords = platform.isMultithreadingEnabled
  val lockWordType = if (usesLockWords) Some(nir.Type.Ptr) else None
  private[codegen] val lockWordVals = lockWordType.map(_ => nir.Val.Null).toList

  val layouts = new CommonMemoryLayouts()
  val rtti = mutable.Map.empty[linker.Info, RuntimeTypeInformation]
  val vtable = mutable.Map.empty[linker.Class, VirtualTable]
  val layout = mutable.Map.empty[linker.Class, FieldLayout]
  val dynmap = mutable.Map.empty[linker.Class, DynamicHashMap]
  val ids = mutable.Map.empty[linker.ScopeInfo, Int]
  val ranges = mutable.Map.empty[linker.Class, Range]

  val classes = initClassIdsAndRanges()
  val traits = initTraitIds()
  val moduleArray = new ModuleArray(this)
  val dispatchTable = new TraitDispatchTable(this)
  val hasTraitTables = new HasTraitTables(this)

  initClassMetadata()
  initTraitMetadata()

  def initTraitIds(): Seq[Trait] = {
    val traits =
      analysis.infos.valuesIterator
        .collect { case info: Trait => info }
        .toIndexedSeq
        .sortBy(_.name.show)
    traits.zipWithIndex.foreach {
      case (node, id) =>
        ids(node) = id
    }
    traits
  }

  def initClassIdsAndRanges(): Seq[Class] = {
    val out = mutable.UnrolledBuffer.empty[Class]
    var id = 0

    def loop(
        node: Class,
        topLevelSubclassOrdering: Array[Class] => Array[Class]
    ): Unit = {
      out += node
      val start = id
      id += 1
      topLevelSubclassOrdering(
        node.subclasses
          .filter(_.parent.contains(node))
          .toArray
      ).foreach(loop(_, identity))
      val end = id - 1
      ids(node) = start
      ranges(node) = start to end
    }

    def fromRootClass(
        symbol: nir.Global.Top,
        ordering: Array[Class] => Array[Class] = identity
    ) =
      loop(
        node = analysis.infos(symbol).asInstanceOf[Class],
        topLevelSubclassOrdering = ordering
      )

    nir.Rt.PrimitiveTypes.foreach(fromRootClass(_))
    fromRootClass(
      nir.Rt.Object.name,
      ordering = subclasses => {
        val (arrays, other) =
          subclasses.partition(_.name == nir.Rt.GenericArray.name)
        arrays ++ other
      }
    )

    out.toSeq
  }

  def initClassMetadata(): Unit = {
    classes.foreach { node =>
      vtable(node) = new VirtualTable(node)
      layout(node) = new FieldLayout(node)
      if (layouts.ClassRtti.usesDynMap) {
        dynmap(node) = new DynamicHashMap(node, proxies)
      }
      rtti(node) = new RuntimeTypeInformation(node)
    }
  }

  def initTraitMetadata(): Unit = {
    traits.foreach { node =>
      rtti(node) = new RuntimeTypeInformation(node)
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy