BundleConstructor.scala 6.66 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
package uvm.ir.irbuilder

import uvm._
import uvm.ssavariables._
import uvm.types._
import uvm.utils.Later
import uvm.utils.Later._
import uvm.ir.irbuilder.IRBuilderNode._
import scala.collection.mutable.ArrayBuffer

/** This class converts the soup of ID-referenced nodes into the refimpl's internal AST. */
class BundleConstructor(idNameMap: Map[MuID, MuName], nodeList: Seq[IRBuilderNode], globalBundle: GlobalBundle) {
  val idNodeMap = nodeList.map(n => (n.id, n)).toMap

  val bundle = new TrantientBundle()

  def setIDAndMaybeName[T <: IdentifiedSettable](obj: T, id: MuID): T = {
    obj.id = id
    obj.name = idNameMap.get(id)
    obj
  }

  def cascadeLookup[T <: Identified](id: MuID, ns1: Namespace[T], ns2: Namespace[T]): T = {
    ns1.get(id).getOrElse {
      ns2.get(id).getOrElse {
        throw new UnknownIDException(id)
      }
    }
  }

  implicit def resTy(id: MuID): Type = cascadeLookup(id, bundle.typeNs, globalBundle.typeNs)

  implicit def resSig(id: MuID): FuncSig = cascadeLookup(id, bundle.funcSigNs, globalBundle.funcSigNs)

  implicit def resConst(id: MuID): Constant = cascadeLookup(id, bundle.constantNs, globalBundle.constantNs)

  implicit def resGlobalVar(id: MuID): GlobalVariable = cascadeLookup(id, bundle.globalVarNs, globalBundle.globalVarNs)

  implicit def resFunc(id: MuID): Function = cascadeLookup(id, bundle.funcNs, globalBundle.funcNs)

  implicit def resConstInt(id: MuID): ConstInt = resConst(id) match {
    case ci: ConstInt => ci
    case other        => throw new AssertionError("Constant int expected, but %d found. ID: %d".format(other.getClass.getName, id))
  }

  def makeBundle(): TrantientBundle = {

    // Classify nodes into categories for phasing.
    val typeNodes = new ArrayBuffer[IRTypeNode]
    val sigNodes = new ArrayBuffer[IRSigNode]
    val constNodes = new ArrayBuffer[IRConstNode]
    val otherTopLevelNodes = new ArrayBuffer[OtherTopLevelNode]
    val funcVers = new ArrayBuffer[NodeFuncVer]()
    val otherNodes = new ArrayBuffer[IRBuilderNode]

    nodeList foreach {
      case n: IRTypeNode        => typeNodes += n
      case n: IRSigNode         => sigNodes += n
      case n: IRConstNode       => constNodes += n
      case n: OtherTopLevelNode => otherTopLevelNodes += n
      case n: NodeFuncVer       => funcVers += n
      case n                    => otherNodes += n
    }

    // Phase 1: create types and sigs, and resolve their refs

    val phase1 = new Later()

    typeNodes foreach { irNode =>
      val muNode: Type = irNode match {
        case NodeTypeInt(id, len)      => new TypeInt(len)
        case NodeTypeFloat(id)         => new TypeFloat()
        case NodeTypeDouble(id)        => new TypeDouble()
        case NodeTypeUPtr(id, ty)      => new TypeUPtr(null).later(phase1) { t => t.ty = ty }
        case NodeTypeUFuncPtr(id, sig) => new TypeUFuncPtr(null).later(phase1) { t => t.sig = sig }

        case NodeTypeStruct(id, fieldTys) => new TypeStruct(null).later(phase1) { t =>
          t.fieldTys = fieldTys.map(resTy)
        }
        case NodeTypeHybrid(id, fixedTys, varTy) => new TypeHybrid(null, null).later(phase1) { t =>
          t.fieldTys = fixedTys.map(resTy)
          t.varTy = varTy
        }
        case NodeTypeArray(id, elemTy, len) => new TypeArray(null, len).later(phase1) { t =>
          t.elemTy = elemTy
        }
        case NodeTypeVector(id, elemTy, len) => new TypeVector(null, len).later(phase1) { t =>
          t.elemTy = elemTy
        }
        case NodeTypeVoid(id)           => new TypeVoid()

        case NodeTypeRef(id, ty)        => new TypeRef(null).later(phase1) { t => t.ty = ty }
        case NodeTypeIRef(id, ty)       => new TypeIRef(null).later(phase1) { t => t.ty = ty }
        case NodeTypeWeakRef(id, ty)    => new TypeWeakRef(null).later(phase1) { t => t.ty = ty }
        case NodeTypeFuncRef(id, sig)   => new TypeFuncRef(null).later(phase1) { t => t.sig = sig }

        case NodeTypeTagRef64(id)       => new TypeTagRef64()
        case NodeTypeThreadRef(id)      => new TypeThreadRef()
        case NodeTypeStackRef(id)       => new TypeStackRef()
        case NodeTypeFrameCursorRef(id) => new TypeFrameCursorRef()
        case NodeTypeIRBuilderRef(id)   => new TypeIRBuilderRef()
      }
      setIDAndMaybeName(muNode, irNode.id)
      bundle.typeNs.add(muNode)
    }

    sigNodes foreach { irNode =>
      val NodeFuncSig(id, paramTys, retTys) = irNode
      val muNode: FuncSig = new FuncSig(null, null).later(phase1) { sig =>
        sig.paramTys = paramTys.map(resTy)
        sig.retTys = retTys.map(resTy)
      }
      setIDAndMaybeName(muNode, irNode.id)
      bundle.funcSigNs.add(muNode)
    }

    phase1.doAll()

    // Now, all types and sigs are created and their references are resolved.

    // Phase 2: create and resolve consts, global cells, funcs, expfuncs and resolve their refs.

    val phase2 = new Later()

    constNodes foreach { irNode =>
      val muNode: Constant = irNode match {
        case NodeConstInt(id, ty, value)     => new ConstInt(ty, value)
        case NodeConstFloat(id, ty, value)   => new ConstFloat(ty, value)
        case NodeConstDouble(id, ty, value)  => new ConstDouble(ty, value)
        case NodeConstNull(id, ty)           => new ConstNull(ty)
        case NodeConstExtern(id, ty, symbol) => new ConstExtern(ty, symbol)
        case NodeConstSeq(id, ty, elems) => new ConstSeq(ty, null).later(phase2) { c =>
          c.elems = elems.map(resGlobalVar)
        }
      }
      setIDAndMaybeName(muNode, irNode.id)
      bundle.constantNs.add(muNode)
    }

    otherTopLevelNodes foreach {
      case NodeGlobalCell(id: MuID, ty: MuTypeNode) => {
        val muNode = new GlobalCell(ty)
        setIDAndMaybeName(muNode, id)
        bundle.globalCellNs.add(muNode)
      }
      case NodeFunc(id: MuID, sig: MuFuncSigNode) => {
        val muNode = new Function()
        muNode.sig = sig
        setIDAndMaybeName(muNode, id)
        bundle.funcNs.add(muNode)
      }
      case NodeExpFunc(id: MuID, func: MuFuncNode, callconv: Flag, cookie: MuConstIntNode) => {
        val muNode = new ExposedFunc(func, callconv, cookie)
        setIDAndMaybeName(muNode, id)
        bundle.expFuncNs.add(muNode)
      }
    }
    
    phase2.doAll()
    
    // Now all top-level definitions are created and their inter-references are resolved
    
    // Phase 3: Define all defined functions (.funcdef)
    val phase3 = new Later()
    
    funcVers foreach { irNode =>
      val muNode = new FuncVer(irNode.func)
      setIDAndMaybeName(muNode, irNode.id)
      bundle.funcVerNs.add(muNode)
      
      phase3 { () => 
        defineFunction(irNode, muNode)
      }
    }
    
    phase3.doAll()

    bundle
  }
  
  def defineFunction(irNode: NodeFuncVer, muFunc: FuncVer): Unit = {
    ???
  }
}