Commit 710ea15b authored by Kunshan Wang's avatar Kunshan Wang

More tests and fixes on native calls.

parent 210ee90e
...@@ -8,3 +8,4 @@ target ...@@ -8,3 +8,4 @@ target
*.swp *.swp
.tmpBin .tmpBin
.d8_history .d8_history
hs_err_pid*.log
...@@ -275,7 +275,10 @@ class UIRTextReader(val idFactory: IDFactory) { ...@@ -275,7 +275,10 @@ class UIRTextReader(val idFactory: IDFactory) {
def mkConst(t: Type, c: ConstConstructorContext): Constant = { def mkConst(t: Type, c: ConstConstructorContext): Constant = {
val con = c match { val con = c match {
case cc: ConstIntContext => ConstInt(t, cc.intLiteral) case cc: ConstIntContext => t match {
case _: TypeInt => ConstInt(t, cc.intLiteral)
case _: AbstractPointerType => ConstPointer(t, cc.intLiteral().longValue())
}
case cc: ConstFloatContext => ConstFloat(t, cc.floatLiteral) case cc: ConstFloatContext => ConstFloat(t, cc.floatLiteral)
case cc: ConstDoubleContext => ConstDouble(t, cc.doubleLiteral) case cc: ConstDoubleContext => ConstDouble(t, cc.doubleLiteral)
case cc: ConstStructContext => ConstStruct(t, null).later(phase2) { case cc: ConstStructContext => ConstStruct(t, null).later(phase2) {
......
...@@ -32,6 +32,7 @@ class ConstantPool(implicit microVM: MicroVM) { ...@@ -32,6 +32,7 @@ class ConstantPool(implicit microVM: MicroVM) {
case _:TypeStack => BoxStack(None) case _:TypeStack => BoxStack(None)
} }
case ConstVector(ty, elems) => BoxVector(elems.map(maybeMakeBox)) case ConstVector(ty, elems) => BoxVector(elems.map(maybeMakeBox))
case ConstPointer(ty, addr) => BoxPointer(addr)
case gc:GlobalCell => BoxIRef(0L, microVM.memoryManager.globalMemory.addrForGlobalCell(gc)) case gc:GlobalCell => BoxIRef(0L, microVM.memoryManager.globalMemory.addrForGlobalCell(gc))
case f:Function => BoxFunc(Some(f)) case f:Function => BoxFunc(Some(f))
} }
......
package uvm.refimpl.nat package uvm.refimpl.nat
import java.nio.ByteBuffer
import java.nio.ByteOrder
import org.slf4j.LoggerFactory
import com.kenai.jffi.{ Type => JType, Struct => JStruct, Function => JFunction, HeapInvocationBuffer, Invoker } import com.kenai.jffi.{ Type => JType, Struct => JStruct, Function => JFunction, HeapInvocationBuffer, Invoker }
import com.typesafe.scalalogging.Logger
import uvm.FuncSig import uvm.FuncSig
import uvm.refimpl.UvmRefImplException import uvm.refimpl.UvmRefImplException
import uvm.refimpl.itpr._
import uvm.refimpl.itpr.ValueBox import uvm.refimpl.itpr.ValueBox
import uvm.refimpl.mem.TypeSizes
import uvm.refimpl.mem.TypeSizes.Word import uvm.refimpl.mem.TypeSizes.Word
import uvm.types._ import uvm.types._
import uvm.types.{ Type => MType } import uvm.types.{ Type => MType }
import uvm.utils.LazyPool import uvm.utils.LazyPool
import javax.vecmath.Tuple2d import uvm.utils.HexDump
import uvm.refimpl.itpr._
import java.nio.ByteBuffer object NativeHelper {
import uvm.refimpl.mem.TypeSizes val logger = Logger(LoggerFactory.getLogger(getClass.getName))
}
/** /**
* Helps calling native functions. Based on JFFI. * Helps calling native functions. Based on JFFI.
*/ */
class NativeHelper { class NativeHelper {
import NativeHelper._
val jffiTypePool: LazyPool[MType, JType] = LazyPool { val jffiTypePool: LazyPool[MType, JType] = LazyPool {
case TypeVoid() => JType.VOID case TypeVoid() => JType.VOID
case TypeInt(8) => JType.SINT8 case TypeInt(8) => JType.SINT8
...@@ -55,13 +64,15 @@ class NativeHelper { ...@@ -55,13 +64,15 @@ class NativeHelper {
val fldvbs = vb.asInstanceOf[BoxStruct].values val fldvbs = vb.asInstanceOf[BoxStruct].values
for (((fty, fvb), i) <- (flds zip fldvbs).zipWithIndex) { for (((fty, fvb), i) <- (flds zip fldvbs).zipWithIndex) {
val off2 = TypeSizes.fieldOffsetOf(s, i) val off2 = TypeSizes.fieldOffsetOf(s, i)
putArgToBuf(buf, off + off2.toInt, mty, vb) putArgToBuf(buf, off + off2.toInt, fty, fvb)
} }
} }
case _: AbstractPointerType => buf.putLong(off, vb.asInstanceOf[BoxPointer].addr) case _: AbstractPointerType => buf.putLong(off, vb.asInstanceOf[BoxPointer].addr)
} }
} }
private val FORCE_ALIGN_UP = 16L
private def putArg(hib: HeapInvocationBuffer, mty: MType, vb: ValueBox): Unit = { private def putArg(hib: HeapInvocationBuffer, mty: MType, vb: ValueBox): Unit = {
mty match { mty match {
case TypeInt(8) => hib.putByte(vb.asInstanceOf[BoxInt].value.toByte) case TypeInt(8) => hib.putByte(vb.asInstanceOf[BoxInt].value.toByte)
...@@ -71,8 +82,10 @@ class NativeHelper { ...@@ -71,8 +82,10 @@ class NativeHelper {
case TypeFloat() => hib.putFloat(vb.asInstanceOf[BoxFloat].value) case TypeFloat() => hib.putFloat(vb.asInstanceOf[BoxFloat].value)
case TypeDouble() => hib.putDouble(vb.asInstanceOf[BoxDouble].value) case TypeDouble() => hib.putDouble(vb.asInstanceOf[BoxDouble].value)
case TypeStruct(flds) => { case TypeStruct(flds) => {
val buf = ByteBuffer.allocate(TypeSizes.sizeOf(mty).toInt) val buf = ByteBuffer.allocate(TypeSizes.alignUp(TypeSizes.sizeOf(mty), FORCE_ALIGN_UP).intValue())
buf.order(ByteOrder.LITTLE_ENDIAN)
putArgToBuf(buf, 0, mty, vb) putArgToBuf(buf, 0, mty, vb)
logger.debug("Hexdump:\n" + HexDump.dumpByteBuffer(buf))
hib.putStruct(buf.array(), buf.arrayOffset()) hib.putStruct(buf.array(), buf.arrayOffset())
} }
case _: AbstractPointerType => hib.putAddress(vb.asInstanceOf[BoxPointer].addr) case _: AbstractPointerType => hib.putAddress(vb.asInstanceOf[BoxPointer].addr)
...@@ -91,6 +104,9 @@ class NativeHelper { ...@@ -91,6 +104,9 @@ class NativeHelper {
val inv = Invoker.getInstance val inv = Invoker.getInstance
sig.retTy match { sig.retTy match {
case TypeVoid() => {
inv.invokeLong(jFunc, hib)
}
case TypeInt(8) => { case TypeInt(8) => {
val rv = inv.invokeInt(jFunc, hib).toByte val rv = inv.invokeInt(jFunc, hib).toByte
retBox.asInstanceOf[BoxInt].value = OpHelper.trunc(BigInt(rv), 8) retBox.asInstanceOf[BoxInt].value = OpHelper.trunc(BigInt(rv), 8)
...@@ -117,7 +133,8 @@ class NativeHelper { ...@@ -117,7 +133,8 @@ class NativeHelper {
} }
case TypeStruct(flds) => { case TypeStruct(flds) => {
val rv = inv.invokeStruct(jFunc, hib) val rv = inv.invokeStruct(jFunc, hib)
val buf = ByteBuffer.wrap(rv) val buf = ByteBuffer.wrap(rv).order(ByteOrder.LITTLE_ENDIAN)
logger.debug("Hexdump:\n" + HexDump.dumpByteBuffer(buf))
getArgFromBuf(buf, 0, sig.retTy, retBox) getArgFromBuf(buf, 0, sig.retTy, retBox)
} }
case _: AbstractPointerType => { case _: AbstractPointerType => {
...@@ -139,7 +156,7 @@ class NativeHelper { ...@@ -139,7 +156,7 @@ class NativeHelper {
val fldvbs = vb.asInstanceOf[BoxStruct].values val fldvbs = vb.asInstanceOf[BoxStruct].values
for (((fty, fvb), i) <- (flds zip fldvbs).zipWithIndex) { for (((fty, fvb), i) <- (flds zip fldvbs).zipWithIndex) {
val off2 = TypeSizes.fieldOffsetOf(s, i) val off2 = TypeSizes.fieldOffsetOf(s, i)
getArgFromBuf(buf, off + off2.toInt, mty, vb) getArgFromBuf(buf, off + off2.toInt, fty, fvb)
} }
} }
case _: AbstractPointerType => vb.asInstanceOf[BoxPointer].addr = buf.getLong(off) case _: AbstractPointerType => vb.asInstanceOf[BoxPointer].addr = buf.getLong(off)
......
...@@ -32,6 +32,8 @@ case class ConstNull(var constTy: Type) extends Constant ...@@ -32,6 +32,8 @@ case class ConstNull(var constTy: Type) extends Constant
case class ConstVector(var constTy: Type, var elems: Seq[Constant]) extends Constant case class ConstVector(var constTy: Type, var elems: Seq[Constant]) extends Constant
case class ConstPointer(var constTy: Type, var addr: Long) extends Constant
case class GlobalCell(var cellTy: Type) extends GlobalVariable case class GlobalCell(var cellTy: Type) extends GlobalVariable
case class ExposedFunc(var func: Function, var callConv: Flag, var cookie: ConstInt) extends GlobalVariable case class ExposedFunc(var func: Function, var callConv: Flag, var cookie: ConstInt) extends GlobalVariable
......
package uvm.utils
import jnr.ffi.Pointer
import jnr.ffi.Runtime
import uvm.refimpl.mem.TypeSizes._
import scala.annotation.elidable
import scala.annotation.elidable.ASSERTION
import java.nio.ByteBuffer
/**
* Show binary data in hexadecimal bytes notations.
*/
object HexDump {
val mem = Pointer.wrap(Runtime.getSystemRuntime, 0L)
val LINE_SIZE = 16
def dumpByteBuffer(buf: ByteBuffer): String = dumpByteBuffer(buf, 0, buf.limit())
def dumpByteBuffer(buf: ByteBuffer, begin: Int, size: Int): String = {
val hd = new HexDump(begin)
for (addr <- begin until (begin + size)) {
val b = buf.get(addr)
hd.addByte(b)
}
hd.finish()
}
def dumpMemory(begin: Long, size: Long): String = {
val hd = new HexDump(begin)
for (addr <- begin until (begin + size)) {
val b = mem.getByte(addr)
hd.addByte(b)
}
hd.finish()
}
}
class HexDump(beginAddr: Long) {
import HexDump._
val buf = new Array[Byte](16)
var curLineAddr: Long = alignDown(beginAddr, 16)
var curLineSize: Int = (beginAddr - curLineAddr).toInt
var linePreSkip: Int = curLineSize
var linePostSkip: Int = 0
val sb = new StringBuilder()
def addByte(b: Byte) {
buf(curLineSize) = b
curLineSize += 1
if (curLineSize == LINE_SIZE) {
processLine()
}
}
def processLine() {
assert(curLineSize == LINE_SIZE, "Line not full: current: %d, expected: %d".format(curLineSize, LINE_SIZE))
sb ++= "%16x".format(curLineAddr)
sb ++= ": "
for ((b, i) <- buf.zipWithIndex) {
val padding = i match {
case 0 => ""
case 8 => " "
case _ => " "
}
sb ++= padding
val num = if (i < linePreSkip || i + linePostSkip >= LINE_SIZE) " "
else "%02x".format(b)
sb ++= num
}
sb ++= " "
sb ++= "|"
for ((b, i) <- buf.zipWithIndex) {
val chr = if (i < linePreSkip || i + linePostSkip >= LINE_SIZE) " "
else if (32 <= b && b <= 126) b.toChar.toString() else "."
sb ++= chr
}
sb ++= "|"
sb ++= "\n"
curLineSize = 0
linePreSkip = 0
linePostSkip = 0
curLineAddr += LINE_SIZE
}
def finish(): String = {
if (curLineSize > 0) {
if (curLineSize < 16) {
linePostSkip = (alignUp(curLineSize, 16) - curLineSize).toInt
curLineSize = 16
}
processLine()
}
sb.toString()
}
}
\ No newline at end of file
...@@ -230,6 +230,17 @@ trait TestingBundlesValidators extends Matchers with ExtraMatchers { ...@@ -230,6 +230,17 @@ trait TestingBundlesValidators extends Matchers with ExtraMatchers {
its fields 1 shouldBe (our globalValue "@fdummy") its fields 1 shouldBe (our globalValue "@fdummy")
} }
our const "@I32P_PTR1" shouldBeA[ConstPointer] { its =>
its.constTy shouldBe (our ty "@i32_p")
its.addr shouldBe 0x123456789abcdef0L
}
our const "@SIG0FP_PTR1" shouldBeA[ConstPointer] { its =>
its.constTy shouldBe (our ty "@sig0_fp")
its.addr shouldBe 0xfedcba9876543210L
}
// Testing namespaces // Testing namespaces
val ci8 = our const "@ci8" val ci8 = our const "@ci8"
our globalValue "@ci8" shouldBe ci8 our globalValue "@ci8" shouldBe ci8
......
...@@ -57,7 +57,7 @@ class UvmInterpreterNativeTests extends UvmBundleTesterBase { ...@@ -57,7 +57,7 @@ class UvmInterpreterNativeTests extends UvmBundleTesterBase {
val func = ca.putFunction("@writetest") val func = ca.putFunction("@writetest")
val a0 = ca.putInt("@i64", funcAddr) val a0 = ca.putPointer("@write_fp", funcAddr)
testFunc(ca, func, Seq(a0)) { (ca, th, st, wp) => testFunc(ca, func, Seq(a0)) { (ca, th, st, wp) =>
val Seq(fp, rv, buf, bufV0P) = ca.dumpKeepalives(st, 0) val Seq(fp, rv, buf, bufV0P) = ca.dumpKeepalives(st, 0)
...@@ -77,11 +77,13 @@ class UvmInterpreterNativeTests extends UvmBundleTesterBase { ...@@ -77,11 +77,13 @@ class UvmInterpreterNativeTests extends UvmBundleTesterBase {
val lib = Library.getDefault() val lib = Library.getDefault()
val funcAddr = lib.getSymbolAddress("memcpy") val funcAddr = lib.getSymbolAddress("memcpy")
val func = ca.putFunction("@memcpytest") val hgfp = ca.putGlobal("@FP_MEMCPY")
val hfp = ca.putPointer("@memcpy_fp", funcAddr)
ca.store(MemoryOrder.NOT_ATOMIC, hgfp, hfp)
val a0 = ca.putInt("@i64", funcAddr) val func = ca.putFunction("@memcpytest")
testFunc(ca, func, Seq(a0)) { (ca, th, st, wp) => testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
val Seq(fp, rv, ob, b0, b1, b2, b3, b4, b5) = ca.dumpKeepalives(st, 0) val Seq(fp, rv, ob, b0, b1, b2, b3, b4, b5) = ca.dumpKeepalives(st, 0)
fp.vb.asPointer shouldEqual funcAddr fp.vb.asPointer shouldEqual funcAddr
......
package uvm.refimpl.itpr
import org.scalatest._
import java.io.FileReader
import uvm._
import uvm.types._
import uvm.ssavariables._
import uvm.refimpl._
import uvm.refimpl.itpr._
import MemoryOrder._
import AtomicRMWOptr._
import uvm.refimpl.mem.TypeSizes.Word
import ch.qos.logback.classic.Level._
import uvm.refimpl.UvmBundleTesterBase
import com.kenai.jffi.Library
import jnr.posix.POSIXFactory
import jnr.ffi.LibraryLoader
import uvm.utils.HexDump
class UvmInterpreterNativeTestsExtra extends UvmBundleTesterBase {
setLogLevels(
ROOT_LOGGER_NAME -> INFO,
"uvm.refimpl.nat" -> DEBUG,
"uvm.refimpl.itpr" -> DEBUG)
val fileName = "tests/c-snippets/structtest.so"
if (!new java.io.File(fileName).isFile()) {
throw new RuntimeException("Need to compile the structtest.so library. cd into tests/c-snippets and invoke 'make'.")
}
preloadBundles("tests/uvm-refimpl-test/native-tests.uir")
"The CCALL instruction" should "handle struct parameters in foo" in {
val ca = microVM.newClientAgent()
val lib = Library.openLibrary(fileName, Library.NOW)
val funcAddr = lib.getSymbolAddress("foo_func")
val func = ca.putFunction("@foo_func_test")
val a0 = ca.putInt("@i64", funcAddr)
testFunc(ca, func, Seq(a0)) { (ca, th, st, wp) =>
val Seq(fp, rv, a, b, c, d) = ca.dumpKeepalives(st, 0)
fp.vb.asPointer shouldEqual funcAddr
// println("%x".format(a.vb.asUInt(64).toLong))
a.vb.asUInt(64) shouldEqual 0x55aa55aa55aa55aaL
b.vb.asUInt(32) shouldEqual 0x5a5a5a5a
c.vb.asUInt(16) shouldEqual 0xa5a5
d.vb.asUInt(8) shouldEqual 0x61
TrapRebindPassVoid(st)
}
ca.close()
}
"The CCALL instruction" should "handle struct parameters in bar involving pointers" in {
val ca = microVM.newClientAgent()
val lib = Library.openLibrary(fileName, Library.NOW)
val funcAddr = lib.getSymbolAddress("bar_func")
val func = ca.putFunction("@bar_func_test")
val a0 = ca.putInt("@i64", funcAddr)
testFunc(ca, func, Seq(a0)) { (ca, th, st, wp) =>
val Seq(fp, rv, a, b) = ca.dumpKeepalives(st, 0)
fp.vb.asPointer shouldEqual funcAddr
// println("%x".format(a.vb.asUInt(64).toLong))
a.vb.asPointer shouldEqual 0x123456789abcdef0L
b.vb.asPointer shouldEqual 0xfedcba9876543210L
TrapRebindPassVoid(st)
}
ca.close()
}
"The CCALL instruction" should "handle struct parameters and return value in baz" in {
val ca = microVM.newClientAgent()
val lib = Library.openLibrary(fileName, Library.NOW)
val funcAddr = lib.getSymbolAddress("baz_func")
val func = ca.putFunction("@baz_func_test")
val a0 = ca.putInt("@i64", funcAddr)
testFunc(ca, func, Seq(a0)) { (ca, th, st, wp) =>
val Seq(fp, rv, a, b, c, pextra, aextra) = ca.dumpKeepalives(st, 0)
fp.vb.asPointer shouldEqual funcAddr
val Seq(rab, rbb) = rv.vb.asStruct
val Seq(raxb, rayb) = rab.asStruct
raxb.asFloat shouldEqual 4.0f
rayb.asSInt(32) shouldEqual 5
rbb.asDouble shouldEqual 6.0
// println("%x".format(a.vb.asUInt(64).toLong))
a.vb.asFloat shouldEqual 1.0f
b.vb.asSInt(32) shouldEqual 2
c.vb.asDouble shouldEqual 3.0
val ptr = pextra.vb.asPointer
println("ptr is 0x%x".format(ptr))
val (oref, off) = aextra.vb.asIRef
println("oref, off is 0x%x 0x%x".format(oref, off))
print(HexDump.dumpMemory(ptr-32, 16+64))
val m = microVM.memoryManager.memorySupport.theMemory
m.getFloat(ptr) shouldEqual 4.0f
m.getInt(ptr+4) shouldEqual 5
m.getDouble(ptr+8) shouldEqual 6.0
TrapRebindPassVoid(st)
}
ca.close()
}
}
\ No newline at end of file
...@@ -653,9 +653,11 @@ class UvmInterpreterSpec extends UvmBundleTesterBase { ...@@ -653,9 +653,11 @@ class UvmInterpreterSpec extends UvmBundleTesterBase {
val a3 = ca.putDouble("@double", 6.25d) val a3 = ca.putDouble("@double", 6.25d)
testFunc(ca, func, Seq(a0, a1, a2, a3)) { (ca, th, st, wp) => testFunc(ca, func, Seq(a0, a1, a2, a3)) { (ca, th, st, wp) =>
val Seq(trunc, zext, sext, fptrunc, fpext, fptoui1, fptosi1, fptoui2, fptosi2, uitofp, sitofp, val kas = ca.dumpKeepalives(st, 0)
bitcast1, bitcast2, bitcast3, bitcast4, ptrcast1, ptrcast2, ptrcast3) = ca.dumpKeepalives(st, 0)
val Seq(trunc, zext, sext, fptrunc, fpext, fptoui1, fptosi1, fptoui2, fptosi2, uitofp, sitofp) = kas.take(11)
val Seq(bitcast1, bitcast2, bitcast3, bitcast4, ptrcast1, ptrcast2, ptrcast3, ptrcast4, ptrcast5, ptrcast6) = kas.drop(11)
trunc.vb.asUInt(32) shouldBe 0x9abcdef0L trunc.vb.asUInt(32) shouldBe 0x9abcdef0L
zext.vb.asUInt(64) shouldBe 0xfedcba98L zext.vb.asUInt(64) shouldBe 0xfedcba98L
sext.vb.asUInt(64) shouldBe BigInt("fffffffffedcba98", 16) sext.vb.asUInt(64) shouldBe BigInt("fffffffffedcba98", 16)
...@@ -679,13 +681,19 @@ class UvmInterpreterSpec extends UvmBundleTesterBase { ...@@ -679,13 +681,19 @@ class UvmInterpreterSpec extends UvmBundleTesterBase {
ptrcast2.vb.asPointer shouldBe 0x123456789abcdef0L ptrcast2.vb.asPointer shouldBe 0x123456789abcdef0L
ptrcast3.vb.asSInt(64) shouldBe 0x123456789abcdef0L ptrcast3.vb.asSInt(64) shouldBe 0x123456789abcdef0L
ptrcast4.vb.asSInt(64) shouldBe 0xdeadbeef13572468L
ptrcast5.vb.asPointer shouldBe 0x55aa55aa5a5a5a5aL
ptrcast6.vb.asInt shouldBe 0x13572468L
TrapRebindPassVoid(st) TrapRebindPassVoid(st)
} }
val a5 = ca.putInt("@i64", -0x123456789abcdef0L) val a5 = ca.putInt("@i64", -0x123456789abcdef0L)
testFunc(ca, func, Seq(a0, a5, a2, a3)) { (ca, th, st, wp) => testFunc(ca, func, Seq(a0, a5, a2, a3)) { (ca, th, st, wp) =>
val Seq(trunc, zext, sext, fptrunc, fpext, fptoui1, fptosi1, fptoui2, fptosi2, uitofp, sitofp, val kas = ca.dumpKeepalives(st, 0)
bitcast1, bitcast2, bitcast3, bitcast4, ptrcast1, ptrcast2, ptrcast3) = ca.dumpKeepalives(st, 0)
val Seq(trunc, zext, sext, fptrunc, fpext, fptoui1, fptosi1, fptoui2, fptosi2, uitofp, sitofp) = kas.take(11)
val Seq(bitcast1, bitcast2, bitcast3, bitcast4, ptrcast1, ptrcast2, ptrcast3, ptrcast4, ptrcast5, ptrcast6) = kas.drop(11)
sitofp.vb.asDouble shouldBe (-0x123456789abcdef0L).doubleValue() sitofp.vb.asDouble shouldBe (-0x123456789abcdef0L).doubleValue()
...@@ -1409,7 +1417,7 @@ class UvmInterpreterSpec extends UvmBundleTesterBase { ...@@ -1409,7 +1417,7 @@ class UvmInterpreterSpec extends UvmBundleTesterBase {
e.vb.asSInt(64) shouldEqual 42 e.vb.asSInt(64) shouldEqual 42
f.vb.asSInt(64) shouldEqual 42 f.vb.asSInt(64) shouldEqual 42
val thr = th.vb.asThread.get val thr = th.vb.asThread.get
thr.pinSet should contain(cAddr) thr.pinSet should contain(cAddr)
......
package uvm.testutil
import org.scalatest.Matchers
import org.scalatest.FlatSpec
import uvm.utils.HexDump
class HexDumpTest extends FlatSpec with Matchers {
"HexDump" should "dump render 256 byte values" in {
val hd = new HexDump(0x420)
for (i <- 0 until 256) {
hd.addByte(i.toByte)
}
val result = hd.finish()
print(result)
}
"HexDump" should "dump render 256 byte values from non 16-byte-aligned starting point" in {
val hd = new HexDump(0x424)
for (i <- 0 until 256) {
hd.addByte(i.toByte)
}
val result = hd.finish()
print(result)
}
}
\ No newline at end of file
all: structtest.so
structtest.so: structtest.c
cc -fPIC -shared -o structtest.so structtest.c
#include <stdio.h>
struct foo {
long a;
int b;
short c;
char d;
};
struct bar {
void *a;
void (*b)();
};
struct baz {
struct baz1 {
float x;
int y;
} a;
double b;
};
void foo_func(struct foo o, long *a, int *b, short *c, char *d) {
*a = o.a;
*b = o.b;
*c = o.c;
*d = o.d;
}
void bar_func(struct bar o, void **a, void (**b)()) {
*a = o.a;
*b = o.b;
}
struct baz baz_func(struct baz o, float *x, int *y, double *b, struct baz *extra) {
*x = o.a.x;
*y = o.a.y;
*b = o.b;
struct baz p;
p.a.x = 4.0;
p.a.y = 5;
p.b = 6.0;
printf("[C:baz_func] *extra = %p\n", extra);
printf("[C:baz_func] extra->a.x = %f\n", extra->a.x);
printf("[C:baz_func] extra->a.y = %d\n", extra->a.y);
printf("[C:baz_func] extra->b = %lf\n", extra->b);
*extra = p;
printf("[C:baz_func] *extra = %p\n", extra);
printf("[C:baz_func] extra->a.x = %f\n", extra->a.x);
printf("[C:baz_func] extra->a.y = %d\n", extra->a.y);
printf("[C:baz_func] extra->b = %lf\n", extra->b);
return p;
}
...@@ -64,10 +64,10 @@ ...@@ -64,10 +64,10 @@
.const @F_2 <@float> = 2.0f .const @F_2 <@float> = 2.0f
.const @F_3 <@float> = 3.0f .const @F_3 <@float> = 3.0f
.const @F_4 <@float> = 4.0f .const @F_4 <@float> = 4.0f
.const @I32_1 <@float> = 1 .const @I32_1 <@i32> = 1
.const @I32_2 <@float> = 2 .const @I32_2 <@i32> = 2
.const @I32_3 <@float> = 3 .const @I32_3 <@i32> = 3
.const @I32_4 <@float> = 4 .const @I32_4 <@i32> = 4
.const @D_1 <@float> = 1.0d .const @D_1 <@float> = 1.0d
.const @D_2 <@float> = 2.0d .const @D_2 <@float> = 2.0d
...@@ -82,3 +82,9 @@ ...@@ -82,3 +82,9 @@
.typedef @sgf_t = struct<@ii64 @func0> .typedef @sgf_t = struct<@ii64 @func0>
.const @sgf <@sgf_t> = {@gi64 @fdummy} .const @sgf <@sgf_t> = {@gi64 @fdummy}
.typedef @i32_p = ptr<@i32>
.typedef @sig0_fp = funcptr<@sig0>
.const @I32P_PTR1 <@i32_p> = 0x123456789abcdef0
.const @SIG0FP_PTR1 <@sig0_fp> = 0xfedcba9876543210
...@@ -332,6 +332,9 @@ ...@@ -332,6 +332,9 @@
COMMINST @uvm.thread_exit COMMINST @uvm.thread_exit
} }