Commit 2cd61152 authored by Kunshan Wang's avatar Kunshan Wang

support external constants

parent 778b9b2f
......@@ -14,6 +14,7 @@ import uvm.staticanalysis.StaticAnalyzer
import uvm.utils.IDFactory
import uvm.ir.irbuilder.IRBuilder
import uvm.ir.irbuilder.IRNode
import uvm.refimpl.nat.NativeLibraryHolder
object MicroVM {
val DEFAULT_SOS_SIZE: Word = 2L * 1024L * 1024L; // 2MiB
......@@ -44,6 +45,8 @@ class MicroVM(vmConf: VMConf) {
private implicit val memorySupport = memoryManager.memorySupport
val nativeLibraryHolder = NativeLibraryHolder(vmConf.extraLibs: _*)
implicit val nativeCallHelper = new NativeCallHelper()
val threadStackManager = new ThreadStackManager()
......
......@@ -21,6 +21,7 @@ object VMConf {
var stackSize = DEFAULT_CONF.stackSize
var staticCheck = DEFAULT_CONF.staticCheck
var sourceInfo = DEFAULT_CONF.sourceInfo
var extraLibs = DEFAULT_CONF.extraLibs
confStr.lines foreach {
case ReComment() =>
case ReBlank() =>
......@@ -34,6 +35,7 @@ object VMConf {
case "sourceInfo" => sourceInfo = value.toLowerCase().toBoolean
case "vmLog" => setLog("uvm", value)
case "gcLog" => setLog("uvm.refimpl.mem", value)
case "extraLibs" => extraLibs = value.split(":")
case _ => throw new UvmRefImplException("Unrecognized option %s".format(key))
}
}
......@@ -59,5 +61,6 @@ class VMConf(
val globalSize: Word = MicroVM.DEFAULT_GLOBAL_SIZE,
val stackSize: Word = MicroVM.DEFAULT_STACK_SIZE,
val staticCheck: Boolean = true,
val sourceInfo: Boolean = true)
val sourceInfo: Boolean = true,
val extraLibs: Seq[String] = Seq())
......@@ -34,6 +34,10 @@ class ConstantPool(implicit microVM: MicroVM) {
case _: TypeThreadRef => BoxThread(None)
case _: TypeStackRef => BoxStack(None)
}
case ConstExtern(ty, sym) => {
val addr = microVM.nativeLibraryHolder.getSymbolAddress(sym)
BoxPointer(addr)
}
case gc: GlobalCell => BoxIRef(0L, microVM.memoryManager.globalMemory.addrForGlobalCell(gc))
case f: Function => BoxFunc(Some(f))
case ef: ExposedFunc => BoxPointer(microVM.nativeCallHelper.getStaticExpFuncAddr(ef))
......
package uvm.refimpl.nat
import scala.collection.mutable.ArrayBuffer
import com.kenai.jffi.Library
import uvm.refimpl.UvmRuntimeException
object NativeLibraryHolder {
/**
* Create a NativeLibraryHolder, load the default library, and additional libraries.
*/
def apply(libs: String*): NativeLibraryHolder = {
val nlh = new NativeLibraryHolder()
nlh.loadDefaultLibrary()
for (lib <- libs) {
nlh.loadLibrary(lib)
}
nlh
}
}
/**
* A holder of jffi Library instances. It can find symbols from all loaded libraries.
*/
class NativeLibraryHolder() {
val libs = new ArrayBuffer[Library]()
/**
* Load the default library: the current process.
*/
def loadDefaultLibrary(): Library = {
val lib = Library.getDefault()
libs += lib
lib
}
/**
* Load a specified library.
*
* @param path the path. eSee the man page of dlopen for the path format.
*/
def loadLibrary(path: String): Library = {
val lib = Option(Library.openLibrary(path, Library.NOW))
lib match {
case None => throw new UvmRuntimeException("Cannot load library: %s".format(path))
case Some(l) =>
libs += l
l
}
}
/**
* Get the address of a symbol.
*
* @param symbol the symbol.
*/
def getSymbolAddress(symbol: String): Long = {
for (lib <- libs) {
val addr = lib.getSymbolAddress(symbol)
if (addr != 0L) {
return addr
}
}
throw new UvmRuntimeException("Symbol cannot be resolved: %s".format(symbol))
}
}
......@@ -174,6 +174,14 @@ class StaticAnalyzer {
}
}
case cc @ ConstSeq(ty, elems) => // Ignore for now
case cc @ ConstExtern(ty, _) => ty match {
case TypeUPtr(_) =>
case TypeUFuncPtr(_) =>
case _ => {
throw error("Constant %s: external constant is not suitable for type %s".format(c.repr, ty.repr),
pretty = Seq(c, ty))
}
}
}
}
......
package uvm.refimpl.nat
import uvm.UvmTestBase
import uvm.ir.textinput.ExtraMatchers
import uvm.refimpl.UvmBundleTesterBase
import uvm.ssavariables.MemoryOrder
import uvm.comminsts.CommInsts
import uvm.ssavariables.ConvOptr
import uvm.ssavariables.Flag
import jnr.posix.POSIX
import jnr.posix.POSIXFactory
import uvm.refimpl.itpr.MemoryOperations
import java.nio.charset.StandardCharsets
import uvm.refimpl.HowToResume
class NativeLibraryHolderTest extends UvmBundleTesterBase {
behavior of "NativeLibraryHolder"
it should "link EXTERN consts with C symbols" in {
val message = "Hello world!\n\0".getBytes(StandardCharsets.US_ASCII)
val ctx = microVM.newContext()
val b = ctx.newBundle()
val int_t = ctx.newTypeInt(b, 32)
val void_t = ctx.newTypeVoid(b)
val voidp_t = ctx.newTypeUPtr(b)
ctx.setTypeUPtr(voidp_t, void_t)
val size_t = ctx.newTypeInt(b, 64)
val ssize_t = ctx.newTypeInt(b, 64)
val write_sig = ctx.newFuncSig(b, Seq(int_t, voidp_t, size_t), Seq(ssize_t))
val write_fp = ctx.newTypeUFuncPtr(b)
ctx.setTypeUFuncPtr(write_fp, write_sig)
val write = ctx.newConstExtern(b, write_fp, "write")
val stdout = ctx.newConstInt(b, int_t, 1)
val hw_sz = ctx.newConstInt(b, size_t, message.size)
val ch_t = ctx.newTypeInt(b, 8)
val str_t = ctx.newTypeHybrid(b, Seq(), ch_t)
val str_t_id = ctx.getID(b, str_t)
val refstr_t = ctx.newTypeRef(b)
ctx.setTypeRef(refstr_t, str_t)
val ptrstr_t = ctx.newTypeUPtr(b)
ctx.setTypeUPtr(ptrstr_t, str_t)
val hw_g = ctx.newGlobalCell(b, refstr_t)
val hw_g_id = ctx.getID(b, hw_g)
val write_test_sig = ctx.newFuncSig(b, Seq(), Seq())
val write_test = ctx.newFunc(b, write_test_sig)
val write_test_id = ctx.getID(b, write_test)
val write_test_v1 = ctx.newFuncVer(b, write_test)
{
val fv = write_test_v1
val entry = ctx.newBB(fv)
val load_i = ctx.newLoad(entry, false, MemoryOrder.NOT_ATOMIC, refstr_t, hw_g)
val hw_r = ctx.newInstRes(load_i)
val pin_i = ctx.newCommInst(entry, CommInsts("@uvm.native.pin").id, Seq(), Seq(refstr_t), Seq(), Seq(hw_r))
val hw_p = ctx.newInstRes(pin_i)
val ptrcast_i = ctx.newConv(entry, ConvOptr.PTRCAST, ptrstr_t, voidp_t, hw_p)
val hw_vp = ctx.newInstRes(ptrcast_i)
val ccall_i = ctx.newCCall(entry, Flag("#DEFAULT"), write_fp, write_sig, write, Seq(stdout, hw_vp, hw_sz))
val rv = ctx.newInstRes(ccall_i)
val thread_exit_i = ctx.newCommInst(entry, CommInsts("@uvm.thread_exit").id, Seq(), Seq(), Seq(), Seq())
}
ctx.loadBundleFromNode(b)
val h_hw_g_ir = ctx.handleFromGlobal(hw_g_id)
val h_sz = ctx.handleFromInt(message.size, 64)
val h_new_str_r = ctx.newHybrid(str_t_id, h_sz)
ctx.store(MemoryOrder.NOT_ATOMIC, h_hw_g_ir, h_new_str_r)
val h_new_str_p = ctx.pin(h_new_str_r)
val p_new_str_p = ctx.handleToPtr(h_new_str_p)
for ((ch, i) <- message.zipWithIndex) {
val ord = ch.toByte
val loc = p_new_str_p + i
NativeSupport.theMemory.putByte(loc, ord)
}
ctx.unpin(h_new_str_r)
val func = ctx.handleFromFunc(write_test_id)
testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
fail("There is no trap!")
}
ctx.closeContext()
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment