Commit f2aac08e authored by Kunshan Wang's avatar Kunshan Wang

Type inferer as class, and stricter static check.

Type inferer and predefined entities are no longer single objects.  They
can be instantiated like other classes.

An SSA variable now has an `inferred type` field which represents its
type.  The type is filled in when loading a bundle, and can be dependedn
on during execution.

Added stricter static checking related to variable types.
parent fb6c7513
...@@ -65,6 +65,8 @@ class MicroVM private (val vmConf: VMConf, val allArgs: Option[Seq[String]]) ext ...@@ -65,6 +65,8 @@ class MicroVM private (val vmConf: VMConf, val allArgs: Option[Seq[String]]) ext
val stats = new VMStats() val stats = new VMStats()
val staticAnalyzer = new StaticAnalyzer()
val globalBundle = new GlobalBundle() val globalBundle = new GlobalBundle()
val constantPool = new ConstantPool() val constantPool = new ConstantPool()
...@@ -76,7 +78,7 @@ class MicroVM private (val vmConf: VMConf, val allArgs: Option[Seq[String]]) ext ...@@ -76,7 +78,7 @@ class MicroVM private (val vmConf: VMConf, val allArgs: Option[Seq[String]]) ext
// BYTES, BYTES_R, REFS, REFS_R: Types for the @uvm.meta.* common instructions. // BYTES, BYTES_R, REFS, REFS_R: Types for the @uvm.meta.* common instructions.
import InternalTypes._ import staticAnalyzer.predefinedEntities._
for (ty <- Seq(VOID, BYTE, BYTE_ARRAY, BYTES, BYTES_R, REFS, REFS_R)) { for (ty <- Seq(VOID, BYTE, BYTE_ARRAY, BYTES, BYTES_R, REFS, REFS_R)) {
globalBundle.typeNs.add(ty) globalBundle.typeNs.add(ty)
} }
...@@ -93,6 +95,9 @@ class MicroVM private (val vmConf: VMConf, val allArgs: Option[Seq[String]]) ext ...@@ -93,6 +95,9 @@ class MicroVM private (val vmConf: VMConf, val allArgs: Option[Seq[String]]) ext
for (ty <- Seq(C_INT, C_CHAR, C_CHARP, C_CHARPP)) { for (ty <- Seq(C_INT, C_CHAR, C_CHARP, C_CHARPP)) {
globalBundle.typeNs.add(ty) globalBundle.typeNs.add(ty)
} }
// Perform type inference on all preloaded s
staticAnalyzer.typeInferer.inferBundle(globalBundle)
} }
/** /**
...@@ -126,7 +131,6 @@ class MicroVM private (val vmConf: VMConf, val allArgs: Option[Seq[String]]) ext ...@@ -126,7 +131,6 @@ class MicroVM private (val vmConf: VMConf, val allArgs: Option[Seq[String]]) ext
val irBuilderRegistry = new IDObjectKeeper[IRBuilder]("IR builder") val irBuilderRegistry = new IDObjectKeeper[IRBuilder]("IR builder")
val irReader = new UIRTextReader(idFactory, recordSourceInfo = vmConf.sourceInfo) val irReader = new UIRTextReader(idFactory, recordSourceInfo = vmConf.sourceInfo)
val hailScriptLoader = new HailScriptLoader(recordSourceInfo = vmConf.sourceInfo) val hailScriptLoader = new HailScriptLoader(recordSourceInfo = vmConf.sourceInfo)
val staticAnalyzer = new StaticAnalyzer()
val bootImageBuilder = new BootImageBuilder() val bootImageBuilder = new BootImageBuilder()
...@@ -151,13 +155,16 @@ class MicroVM private (val vmConf: VMConf, val allArgs: Option[Seq[String]]) ext ...@@ -151,13 +155,16 @@ class MicroVM private (val vmConf: VMConf, val allArgs: Option[Seq[String]]) ext
* Add things from a bundle to the Micro VM. * Add things from a bundle to the Micro VM.
*/ */
def addBundle(bundle: TrantientBundle) { def addBundle(bundle: TrantientBundle) {
// Make sure all SSA variables have undergone type inference
staticAnalyzer.typeInferer.inferBundle(bundle)
if (vmConf.dumpBundle) { if (vmConf.dumpBundle) {
val dbs = new DebugBundleSerializer(bundle) val dbs = new DebugBundleSerializer(bundle)
dbs.writeUIR(new OutputStreamWriter(System.err)) dbs.writeUIR(new OutputStreamWriter(System.err))
} }
if (vmConf.staticCheck) { if (vmConf.staticCheck) {
staticAnalyzer.checkBundle(bundle, Some(globalBundle)) staticAnalyzer.bundleChecker.checkBundle(bundle, Some(globalBundle))
} }
globalBundle.merge(bundle); globalBundle.merge(bundle);
......
This diff is collapsed.
...@@ -14,27 +14,26 @@ import java.util.zip.ZipFile ...@@ -14,27 +14,26 @@ import java.util.zip.ZipFile
import scala.collection.Map import scala.collection.Map
import scala.collection.mutable.HashMap import scala.collection.mutable.HashMap
import org.slf4j.LoggerFactory
import com.typesafe.scalalogging.Logger
import uvm.{ MuID, MuName } import uvm.{ MuID, MuName }
import uvm.refimpl.{ Word, WORD_SIZE_BYTES } import uvm.refimpl.{ WORD_SIZE_BYTES, Word }
import uvm.refimpl.MicroVM import uvm.refimpl.MicroVM
import uvm.refimpl.cmdline.NativeArgv
import uvm.refimpl.itpr.BoxInt
import uvm.refimpl.itpr.BoxPointer
import uvm.refimpl.itpr.HowToResume
import uvm.refimpl.itpr.OpHelper import uvm.refimpl.itpr.OpHelper
import uvm.refimpl.mem.HeaderUtils
import uvm.refimpl.mem.TypeSizes import uvm.refimpl.mem.TypeSizes
import uvm.refimpl.nat.NativeSupport import uvm.refimpl.nat.NativeSupport
import uvm.types.TypeHybrid import uvm.types.TypeHybrid
import uvm.utils.IOHelpers
import uvm.utils.IOHelpers.forEachLine import uvm.utils.IOHelpers.forEachLine
import uvm.utils.MappedIDFactory import uvm.utils.MappedIDFactory
import uvm.utils.WithUtils.tryWithResource import uvm.utils.WithUtils.tryWithResource
import scala.collection.mutable.ArrayBuffer
import uvm.refimpl.itpr.HowToResume
import uvm.refimpl.cmdline.NativeArgv
import uvm.refimpl.itpr.BoxInt
import uvm.refimpl.InternalTypePool
import uvm.refimpl.InternalTypes
import uvm.refimpl.itpr.BoxPointer
import uvm.utils.IOHelpers
import com.typesafe.scalalogging.Logger
import org.slf4j.LoggerFactory
import uvm.refimpl.mem.HeaderUtils
object BootImageLoader { object BootImageLoader {
val logger = Logger(LoggerFactory.getLogger(getClass.getName)) val logger = Logger(LoggerFactory.getLogger(getClass.getName))
...@@ -44,8 +43,8 @@ object BootImageLoader { ...@@ -44,8 +43,8 @@ object BootImageLoader {
} }
class BootImageLoader(file: String, maybeAllArgs: Option[Seq[String]])(implicit microVM: MicroVM) extends AutoCloseable { class BootImageLoader(file: String, maybeAllArgs: Option[Seq[String]])(implicit microVM: MicroVM) extends AutoCloseable {
import BootImageLoader._
import BootImageFile._ import BootImageFile._
import BootImageLoader._
private val globalBundle = microVM.globalBundle private val globalBundle = microVM.globalBundle
private val memoryManager = microVM.memoryManager private val memoryManager = microVM.memoryManager
......
package uvm.refimpl.cmdline package uvm.refimpl.cmdline
import java.io.BufferedReader
import java.io.InputStreamReader
import java.nio.charset.StandardCharsets
import java.util.zip.ZipFile
import scala.collection.mutable.HashMap import scala.collection.mutable.HashMap
import uvm.{MuID, MuName}
import uvm.refimpl.HowToResume.PassValues
import uvm.refimpl.InternalTypes
import uvm.refimpl.MicroVM import uvm.refimpl.MicroVM
import uvm.refimpl.UvmRuntimeException
import uvm.refimpl.VMConf import uvm.refimpl.VMConf
import uvm.refimpl.WORD_SIZE_BYTES
import uvm.refimpl.nat.NativeSupport
import uvm.utils.WithUtils.tryWithResource import uvm.utils.WithUtils.tryWithResource
/** Run Mu from the command line. */ /** Run Mu from the command line. */
......
...@@ -69,6 +69,8 @@ class HailScriptLoader(recordSourceInfo: Boolean = true)(implicit microVM: Micro ...@@ -69,6 +69,8 @@ class HailScriptLoader(recordSourceInfo: Boolean = true)(implicit microVM: Micro
class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, mc: MuCtx, source: String, class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, mc: MuCtx, source: String,
val recordSourceInfo: Boolean) extends AdvancedAntlrHelper { val recordSourceInfo: Boolean) extends AdvancedAntlrHelper {
import HailScriptLoader._ import HailScriptLoader._
private val predefinedEntities = microVM.staticAnalyzer.predefinedEntities
val sourceLines = source.lines.toIndexedSeq val sourceLines = source.lines.toIndexedSeq
...@@ -229,7 +231,7 @@ class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, m ...@@ -229,7 +231,7 @@ class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, m
def unexpectedGlobalTypeError(gv: GlobalVariable): Nothing = { def unexpectedGlobalTypeError(gv: GlobalVariable): Nothing = {
throw new UvmHailParsingException(inCtx(rv, "Unsuitable global variable type. Expected: %s, Found: %s".format( throw new UvmHailParsingException(inCtx(rv, "Unsuitable global variable type. Expected: %s, Found: %s".format(
lty, TypeInferer.inferType(gv)))) lty, gv.inferredType)))
} }
// Reused by their types as well as tagref64 // Reused by their types as well as tagref64
...@@ -254,7 +256,7 @@ class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, m ...@@ -254,7 +256,7 @@ class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, m
def resForRefType(rv: RValueContext): (MuRefValue, Boolean) = { def resForRefType(rv: RValueContext): (MuRefValue, Boolean) = {
rv match { rv match {
case nu: RVNullContext => (mc.handleFromConst(InternalTypes.NULL_REF_VOID.id).asInstanceOf[MuRefValue], true) case nu: RVNullContext => (mc.handleFromConst(predefinedEntities.NULL_REF_VOID.id).asInstanceOf[MuRefValue], true)
case hr: RVHailRefContext => (resRVHailRef(hr), false) case hr: RVHailRefContext => (resRVHailRef(hr), false)
case _ => unexpectedRValueError() case _ => unexpectedRValueError()
} }
...@@ -367,7 +369,7 @@ class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, m ...@@ -367,7 +369,7 @@ class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, m
} }
case t: TypeIRef => { case t: TypeIRef => {
val hr = rv match { val hr = rv match {
case nu: RVNullContext => mc.handleFromConst(InternalTypes.NULL_IREF_VOID.id) case nu: RVNullContext => mc.handleFromConst(predefinedEntities.NULL_IREF_VOID.id)
case io: RVIRefOfContext => evalLValue(io.lValue()).iref case io: RVIRefOfContext => evalLValue(io.lValue()).iref
case RVGlobalOf(gv: GlobalCell) => mc.handleFromGlobal(gv.id) case RVGlobalOf(gv: GlobalCell) => mc.handleFromGlobal(gv.id)
case RVGlobalOf(gv) => unexpectedGlobalTypeError(gv) case RVGlobalOf(gv) => unexpectedGlobalTypeError(gv)
...@@ -378,7 +380,7 @@ class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, m ...@@ -378,7 +380,7 @@ class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, m
} }
case t: TypeFuncRef => { case t: TypeFuncRef => {
val hr = rv match { val hr = rv match {
case nu: RVNullContext => mc.handleFromConst(InternalTypes.NULL_FUNCREF_VV.id) case nu: RVNullContext => mc.handleFromConst(predefinedEntities.NULL_FUNCREF_VV.id)
case RVGlobalOf(gv: Function) => mc.handleFromFunc(gv.id) case RVGlobalOf(gv: Function) => mc.handleFromFunc(gv.id)
case RVGlobalOf(gv) => unexpectedGlobalTypeError(gv) case RVGlobalOf(gv) => unexpectedGlobalTypeError(gv)
case _ => unexpectedRValueError() case _ => unexpectedRValueError()
...@@ -388,7 +390,7 @@ class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, m ...@@ -388,7 +390,7 @@ class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, m
} }
case t: TypeThreadRef => { case t: TypeThreadRef => {
val hr = rv match { val hr = rv match {
case nu: RVNullContext => mc.handleFromConst(InternalTypes.NULL_THREADREF.id) case nu: RVNullContext => mc.handleFromConst(predefinedEntities.NULL_THREADREF.id)
case _ => unexpectedRValueError() case _ => unexpectedRValueError()
} }
mc.store(NOT_ATOMIC, lir, hr) mc.store(NOT_ATOMIC, lir, hr)
...@@ -396,7 +398,7 @@ class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, m ...@@ -396,7 +398,7 @@ class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, m
} }
case t: TypeStackRef => { case t: TypeStackRef => {
val hr = rv match { val hr = rv match {
case nu: RVNullContext => mc.handleFromConst(InternalTypes.NULL_STACKREF.id) case nu: RVNullContext => mc.handleFromConst(predefinedEntities.NULL_STACKREF.id)
case _ => unexpectedRValueError() case _ => unexpectedRValueError()
} }
mc.store(NOT_ATOMIC, lir, hr) mc.store(NOT_ATOMIC, lir, hr)
......
...@@ -16,6 +16,8 @@ trait InstructionExecutor extends InterpreterActions with CommInstExecutor { ...@@ -16,6 +16,8 @@ trait InstructionExecutor extends InterpreterActions with CommInstExecutor {
protected def mutator: Mutator protected def mutator: Mutator
implicit protected def microVM: MicroVM implicit protected def microVM: MicroVM
implicit protected def memorySupport: MemorySupport implicit protected def memorySupport: MemorySupport
private def internalEntityPool = microVM.staticAnalyzer.internalEntityPool
/** Interpret the current instruction. */ /** Interpret the current instruction. */
protected def interpretCurrentInstruction(): Unit = try { protected def interpretCurrentInstruction(): Unit = try {
...@@ -459,7 +461,7 @@ trait InstructionExecutor extends InterpreterActions with CommInstExecutor { ...@@ -459,7 +461,7 @@ trait InstructionExecutor extends InterpreterActions with CommInstExecutor {
} }
case i @ InstLoad(ptr, ord, referentTy, loc, excClause) => { case i @ InstLoad(ptr, ord, referentTy, loc, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy) val uty = internalEntityPool.unmarkedOf(referentTy)
val ib = resultBox(0) val ib = resultBox(0)
val addr = addressOf(ptr, loc) val addr = addressOf(ptr, loc)
...@@ -472,7 +474,7 @@ trait InstructionExecutor extends InterpreterActions with CommInstExecutor { ...@@ -472,7 +474,7 @@ trait InstructionExecutor extends InterpreterActions with CommInstExecutor {
} }
case i @ InstStore(ptr, ord, referentTy, loc, newVal, excClause) => { case i @ InstStore(ptr, ord, referentTy, loc, newVal, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy) val uty = internalEntityPool.unmarkedOf(referentTy)
val nvb = boxOf(newVal) val nvb = boxOf(newVal)
val addr = addressOf(ptr, loc) val addr = addressOf(ptr, loc)
...@@ -485,7 +487,7 @@ trait InstructionExecutor extends InterpreterActions with CommInstExecutor { ...@@ -485,7 +487,7 @@ trait InstructionExecutor extends InterpreterActions with CommInstExecutor {
} }
case i @ InstCmpXchg(ptr, weak, ordSucc, ordFail, referentTy, loc, expected, desired, excClause) => { case i @ InstCmpXchg(ptr, weak, ordSucc, ordFail, referentTy, loc, expected, desired, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy) val uty = internalEntityPool.unmarkedOf(referentTy)
val eb = boxOf(expected) val eb = boxOf(expected)
val db = boxOf(desired) val db = boxOf(desired)
val br = resultBox(0) val br = resultBox(0)
...@@ -502,7 +504,7 @@ trait InstructionExecutor extends InterpreterActions with CommInstExecutor { ...@@ -502,7 +504,7 @@ trait InstructionExecutor extends InterpreterActions with CommInstExecutor {
} }
case i @ InstAtomicRMW(ptr, ord, op, referentTy, loc, opnd, excClause) => { case i @ InstAtomicRMW(ptr, ord, op, referentTy, loc, opnd, excClause) => {
val uty = InternalTypePool.unmarkedOf(referentTy) val uty = internalEntityPool.unmarkedOf(referentTy)
val ob = boxOf(opnd) val ob = boxOf(opnd)
val ib = resultBox(0) val ib = resultBox(0)
......
...@@ -715,10 +715,10 @@ object MemoryOperations { ...@@ -715,10 +715,10 @@ object MemoryOperations {
* *
* @return The address of the allocated object. * @return The address of the allocated object.
*/ */
def strToBytes(str: String)(implicit memorySupport: MemorySupport, mutator: Mutator): Word = { def strToBytes(str: String)(implicit microVM: MicroVM, memorySupport: MemorySupport, mutator: Mutator): Word = {
val bytes = str.getBytes(US_ASCII) val bytes = str.getBytes(US_ASCII)
val len = bytes.length val len = bytes.length
val loc = mutator.newHybrid(InternalTypes.BYTES, len) val loc = mutator.newHybrid(microVM.staticAnalyzer.predefinedEntities.BYTES, len)
memorySupport.storeLong(loc, bytes.length.toLong) memorySupport.storeLong(loc, bytes.length.toLong)
val begin = loc + WORD_SIZE_BYTES val begin = loc + WORD_SIZE_BYTES
memorySupport.storeBytes(begin, bytes, 0, len, true) memorySupport.storeBytes(begin, bytes, 0, len, true)
......
...@@ -515,7 +515,7 @@ class DefinedMuFrame( ...@@ -515,7 +515,7 @@ class DefinedMuFrame(
} }
private def putBox(lv: LocalVariable) { private def putBox(lv: LocalVariable) {
val ty = TypeInferer.inferType(lv) val ty = lv.inferredType
try { try {
boxes.put(lv, ValueBox.makeBoxForType(ty)) boxes.put(lv, ValueBox.makeBoxForType(ty))
} catch { } catch {
......
...@@ -52,7 +52,7 @@ class MemoryManager(val vmConf: VMConf)(implicit microVM: MicroVM) extends AutoC ...@@ -52,7 +52,7 @@ class MemoryManager(val vmConf: VMConf)(implicit microVM: MicroVM) extends AutoC
def makeMutator(name: String): Mutator = heap.makeMutator(name) def makeMutator(name: String): Mutator = heap.makeMutator(name)
def makeStackMemory(mutator: Mutator): StackMemory = { def makeStackMemory(mutator: Mutator): StackMemory = {
val objRef = mutator.newHybrid(InternalTypes.BYTE_ARRAY, vmConf.stackSize) val objRef = mutator.newHybrid(microVM.staticAnalyzer.predefinedEntities.BYTE_ARRAY, vmConf.stackSize)
val stackMemory = new StackMemory(objRef, vmConf.stackSize) val stackMemory = new StackMemory(objRef, vmConf.stackSize)
stackMemory stackMemory
} }
......
...@@ -6,7 +6,14 @@ import uvm._ ...@@ -6,7 +6,14 @@ import uvm._
import uvm.comminsts._ import uvm.comminsts._
import uvm.types._ import uvm.types._
abstract class SSAVariable extends ChildNode abstract class SSAVariable extends ChildNode {
/**
* The type is discovered by the static analyser at bundle loading time.
* During the execution of Mu IR programs, the MicroVM implementation can
* assume this field is already assigned.
*/
var inferredType: Type = null
}
// Global variables: Constants, Global Cells and Functions (Function is defined in controlFlow.scala) // Global variables: Constants, Global Cells and Functions (Function is defined in controlFlow.scala)
......
This diff is collapsed.
package uvm.staticanalysis
import uvm.types._
import uvm.utils.LazyPool
class InternalEntityPool {
val intOf = LazyPool(TypeInt)
val refOf = LazyPool(TypeRef)
val irefOf = LazyPool(TypeIRef)
val ptrOf = LazyPool(TypeUPtr)
val funcOf = LazyPool(TypeFuncRef)
val funcPtrOf = LazyPool(TypeUFuncPtr)
val vecOf = LazyPool[(Type, Long), TypeVector] { case (t, l) => TypeVector(t, l) }
def unmarkedOf(t: Type): Type = t match {
case TypeWeakRef(r) => refOf(r)
case _ => t
}
}
\ No newline at end of file
package uvm.staticanalysis
import uvm._
import uvm.ssavariables._
import uvm.types._
import uvm.utils.IDFactory
class PredefinedEntities(privateIDFactory: IDFactory) {
import uvm.RichIdentifiedSettable._
def internal(name: MuName): (MuID, MuName) = {
val id = privateIDFactory.getID()
val n = "@uvm.internal.types." + name
(id, n)
}
val C_INT = TypeInt(32) := internal("c_int")
val C_CHAR = TypeInt(8) := internal("c_char")
val C_CHARP = TypeUPtr(C_CHAR) := internal("c_charp")
val C_CHARPP = TypeUPtr(C_CHARP) := internal("c_charpp")
val I1 = TypeInt(1) := internal("i1")
val I6 = TypeInt(6) := internal("i6")
val I8 = TypeInt(6) := internal("i8")
val I16 = TypeInt(6) := internal("i16")
val I32 = TypeInt(32) := internal("i32")
val I52 = TypeInt(52) := internal("i52")
val I64 = TypeInt(52) := internal("i64")
val FLOAT = TypeFloat() := internal("float")
val DOUBLE = TypeDouble() := internal("double")
val VOID = TypeVoid() := internal("void")
val BYTE = TypeInt(8) := internal("byte")
val BYTE_ARRAY = TypeHybrid(Seq(), BYTE) := internal("byte_array")
val REF_VOID = TypeRef(VOID) := internal("ref_void")
val IREF_VOID = TypeIRef(VOID) := internal("iref_void")
val SIG_VV = FuncSig(Seq(), Seq()) := internal("sig_vv")
val FUNCREF_VV = TypeFuncRef(SIG_VV) := internal("funcref_vv")
val STACKREF = TypeStackRef() := internal("stackref")
val THREADREF = TypeThreadRef() := internal("threadref")
val FRAMECURSORREF = TypeFrameCursorRef() := internal("framecursorref")
val IRBUILDERREF = TypeIRBuilderRef() := internal("irbuilderref")
val TAGREF64 = TypeTagRef64() := internal("tagref64")
val BYTES = TypeHybrid(Seq(I64), I8) := (0x260, "@uvm.meta.bytes")
val BYTES_R = TypeRef(BYTES) := (0x261, "@uvm.meta.bytes_r")
val REFS = TypeHybrid(Seq(I64), REF_VOID) := (0x262, "@uvm.meta.refs")
val REFS_R = TypeRef(BYTES) := (0x263, "@uvm.meta.refs_r")
val NULL_REF_VOID = ConstNull(REF_VOID) := internal("null_ref_void")
val NULL_IREF_VOID = ConstNull(IREF_VOID) := internal("null_iref_void")
val NULL_FUNCREF_VV = ConstNull(FUNCREF_VV) := internal("null_funcref_vv")
val NULL_THREADREF = ConstNull(THREADREF) := internal("null_threadref")
val NULL_STACKREF = ConstNull(STACKREF) := internal("null_stackref")
}
\ No newline at end of file
package uvm.refimpl package uvm.staticanalysis
import uvm._ import uvm._
import uvm.FuncSig
import uvm.ssavariables._
import uvm.types._ import uvm.types._
import uvm.utils.IDFactory import uvm.ssavariables._
import uvm.utils.LazyPool
object InternalTypes {
import uvm.RichIdentifiedSettable._
val privateIDFactory = IDFactory.newPrivateIDFactory() // IDs from 32768-65535 are for implementation internal use. class TypeInferer(
predefinedEntities: PredefinedEntities,
internalEntityPool: InternalEntityPool) {
import predefinedEntities._
import internalEntityPool._
def internal(name: MuName): (MuID, MuName) = { def ptrOrIRefOf(ptr: Boolean, ty: Type): Type = {
val id = privateIDFactory.getID() if (ptr) ptrOf(ty) else irefOf(ty)
val n = "@uvm.internal.types." + name
(id, n)
} }
val C_INT = TypeInt(32) := internal("c_int") /**
val C_CHAR = TypeInt(8) := internal("c_char") * Perform type inference on all entities, global or local, in the bundle b.
val C_CHARP = TypeUPtr(C_CHAR) := internal("c_charp") */
val C_CHARPP = TypeUPtr(C_CHARP) := internal("c_charpp") def inferBundle(b: Bundle): Unit = {
for (v <- b.globalVarNs.all) {
val I1 = TypeInt(1) := internal("i1") inferAndSet(v)
val I6 = TypeInt(6) := internal("i6") }
val I8 = TypeInt(6) := internal("i8")
val I16 = TypeInt(6) := internal("i16") for (fv <- b.funcVerNs.all) {
val I32 = TypeInt(32) := internal("i32") for (bb <- fv.bbs) {
val I52 = TypeInt(52) := internal("i52") for (v <- bb.localVarNs.all) {
val I64 = TypeInt(52) := internal("i64") inferAndSet(v)
val FLOAT = TypeFloat() := internal("float") }
val DOUBLE = TypeDouble() := internal("double") }
val VOID = TypeVoid() := internal("void") }
val BYTE = TypeInt(8) := internal("byte")
val BYTE_ARRAY = TypeHybrid(Seq(), BYTE) := internal("byte_array")
val REF_VOID = TypeRef(VOID) := internal("ref_void")
val IREF_VOID = TypeIRef(VOID) := internal("iref_void")
val SIG_VV = FuncSig(Seq(), Seq()) := internal("sig_vv")
val FUNCREF_VV = TypeFuncRef(SIG_VV) := internal("funcref_vv")
val STACKREF = TypeStackRef() := internal("stackref")
val THREADREF = TypeThreadRef() := internal("threadref")
val FRAMECURSORREF = TypeFrameCursorRef() := internal("framecursorref")
val IRBUILDERREF = TypeIRBuilderRef() := internal("irbuilderref")
val TAGREF64 = TypeTagRef64() := internal("tagref64")
val BYTES = TypeHybrid(Seq(I64), I8) := (0x260, "@uvm.meta.bytes")
val BYTES_R = TypeRef(BYTES) := (0x261, "@uvm.meta.bytes_r")
val REFS = TypeHybrid(Seq(I64), REF_VOID) := (0x262, "@uvm.meta.refs")
val REFS_R = TypeRef(BYTES) := (0x263, "@uvm.meta.refs_r")
val NULL_REF_VOID = ConstNull(REF_VOID) := internal("null_ref_void")
val NULL_IREF_VOID = ConstNull(IREF_VOID) := internal("null_iref_void")
val NULL_FUNCREF_VV = ConstNull(FUNCREF_VV) := internal("null_funcref_vv")
val NULL_THREADREF = ConstNull(THREADREF) := internal("null_threadref")
val NULL_STACKREF = ConstNull(STACKREF) := internal("null_stackref")
}
object InternalTypePool {
val intOf = LazyPool(TypeInt)
val refOf = LazyPool(TypeRef)
val irefOf = LazyPool(TypeIRef)
val ptrOf = LazyPool(TypeUPtr)
val funcOf = LazyPool(TypeFuncRef)
val funcPtrOf = LazyPool(TypeUFuncPtr)
val vecOf = LazyPool[(Type, Long), TypeVector] { case (t, l) => TypeVector(t, l) }
def unmarkedOf(t: Type): Type = t match {
case TypeWeakRef(r) => refOf(r)
case _ => t
} }
}
private def inferAndSet(v: SSAVariable): Unit = {
object TypeInferer { val inferredType = inferType(v)
import InternalTypePool._ v.inferredType = inferredType
import InternalTypes._
def ptrOrIRefOf(ptr: Boolean, ty: Type): Type = {
if (ptr) ptrOf(ty) else irefOf(ty)
} }
def inferType(v: SSAVariable): Type = v match { def inferType(v: SSAVariable): Type = v match {
...@@ -95,7 +49,7 @@ object TypeInferer { ...@@ -95,7 +49,7 @@ object TypeInferer {
try { try {
resTys(r.index) resTys(r.index)
} catch { } catch {
case e: IndexOutOfBoundsException => throw new UvmRefImplException( case e: IndexOutOfBoundsException => throw new StaticAnalyserException(
s"Instruction ${r.inst} produces only ${resTys.size} results, but result index ${r.index} is requested") s"Instruction ${r.inst} produces only ${resTys.size} results, but result index ${r.index} is requested")
} }
} }
...@@ -288,4 +242,4 @@ object TypeInferer { ...@@ -288,4 +242,4 @@ object TypeInferer {
/// GEN:END:IRBUILDER_RETVALS /// GEN:END:IRBUILDER_RETVALS
} }
} }
} }
\ No newline at end of file
package uvm.staticanalysis
import uvm.UvmException
class StaticAnalyserException(message: String = null, cause: Throwable = null) extends UvmException(message, cause)
\ No newline at end of file
...@@ -6,6 +6,9 @@ abstract class Type extends TopLevel { ...@@ -6,6 +6,9 @@ abstract class Type extends TopLevel {
override final def toString: String = Type.prettyPrint(this) override final def toString: String = Type.prettyPrint(this)
} }
abstract trait AbstractEQComparableType extends Type
abstract trait AbstractULTComparableType extends Type
abstract class AbstractFPType extends Type abstract class AbstractFPType extends Type
abstract class AbstractGenRefType extends Type abstract class AbstractGenRefType extends Type
...@@ -16,7 +19,7 @@ abstract class AbstractRefType extends AbstractGenRefType { ...@@ -16,7 +19,7 @@ abstract class AbstractRefType extends AbstractGenRefType {
abstract class AbstractObjRefType extends AbstractRefType abstract class AbstractObjRefType extends AbstractRefType
abstract class AbstractOpaqueRefType extends AbstractGenRefType abstract class AbstractOpaqueRefType extends AbstractGenRefType with AbstractEQComparableType
abstract class AbstractCompositeType extends Type abstract class AbstractCompositeType extends Type
...@@ -29,9 +32,9 @@ abstract class AbstractSeqType extends AbstractCompositeType { ...@@ -29,9 +32,9 @@ abstract class AbstractSeqType extends AbstractCompositeType {
def len: Long def len: Long
} }
abstract class AbstractPointerType extends Type abstract class AbstractPointerType extends Type with AbstractEQComparableType with AbstractULTComparableType
case class TypeInt(var length: Int) extends Type case class TypeInt(var length: Int) extends Type with AbstractEQComparableType with AbstractULTComparableType
case class TypeFloat() extends AbstractFPType case class TypeFloat() extends AbstractFPType
case class TypeDouble() extends AbstractFPType case class TypeDouble() extends AbstractFPType
case class TypeUPtr(var ty: Type) extends AbstractPointerType