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

More tests and fixes on native calls.

parent 210ee90e
......@@ -8,3 +8,4 @@ target
*.swp
.tmpBin
.d8_history
hs_err_pid*.log
......@@ -275,7 +275,10 @@ class UIRTextReader(val idFactory: IDFactory) {
def mkConst(t: Type, c: ConstConstructorContext): Constant = {
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: ConstDoubleContext => ConstDouble(t, cc.doubleLiteral)
case cc: ConstStructContext => ConstStruct(t, null).later(phase2) {
......
......@@ -32,6 +32,7 @@ class ConstantPool(implicit microVM: MicroVM) {
case _:TypeStack => BoxStack(None)
}
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 f:Function => BoxFunc(Some(f))
}
......
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.typesafe.scalalogging.Logger
import uvm.FuncSig
import uvm.refimpl.UvmRefImplException
import uvm.refimpl.itpr._
import uvm.refimpl.itpr.ValueBox
import uvm.refimpl.mem.TypeSizes
import uvm.refimpl.mem.TypeSizes.Word
import uvm.types._
import uvm.types.{ Type => MType }
import uvm.utils.LazyPool
import javax.vecmath.Tuple2d
import uvm.refimpl.itpr._
import java.nio.ByteBuffer
import uvm.refimpl.mem.TypeSizes
import uvm.utils.HexDump
object NativeHelper {
val logger = Logger(LoggerFactory.getLogger(getClass.getName))
}
/**
* Helps calling native functions. Based on JFFI.
*/
class NativeHelper {
import NativeHelper._
val jffiTypePool: LazyPool[MType, JType] = LazyPool {
case TypeVoid() => JType.VOID
case TypeInt(8) => JType.SINT8
......@@ -55,13 +64,15 @@ class NativeHelper {
val fldvbs = vb.asInstanceOf[BoxStruct].values
for (((fty, fvb), i) <- (flds zip fldvbs).zipWithIndex) {
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)
}
}
private val FORCE_ALIGN_UP = 16L
private def putArg(hib: HeapInvocationBuffer, mty: MType, vb: ValueBox): Unit = {
mty match {
case TypeInt(8) => hib.putByte(vb.asInstanceOf[BoxInt].value.toByte)
......@@ -71,8 +82,10 @@ class NativeHelper {
case TypeFloat() => hib.putFloat(vb.asInstanceOf[BoxFloat].value)
case TypeDouble() => hib.putDouble(vb.asInstanceOf[BoxDouble].value)
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)
logger.debug("Hexdump:\n" + HexDump.dumpByteBuffer(buf))
hib.putStruct(buf.array(), buf.arrayOffset())
}
case _: AbstractPointerType => hib.putAddress(vb.asInstanceOf[BoxPointer].addr)
......@@ -91,6 +104,9 @@ class NativeHelper {
val inv = Invoker.getInstance
sig.retTy match {
case TypeVoid() => {
inv.invokeLong(jFunc, hib)
}
case TypeInt(8) => {
val rv = inv.invokeInt(jFunc, hib).toByte
retBox.asInstanceOf[BoxInt].value = OpHelper.trunc(BigInt(rv), 8)
......@@ -117,7 +133,8 @@ class NativeHelper {
}
case TypeStruct(flds) => {
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)
}
case _: AbstractPointerType => {
......@@ -139,7 +156,7 @@ class NativeHelper {
val fldvbs = vb.asInstanceOf[BoxStruct].values
for (((fty, fvb), i) <- (flds zip fldvbs).zipWithIndex) {
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)
......
......@@ -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 ConstPointer(var constTy: Type, var addr: Long) extends Constant
case class GlobalCell(var cellTy: Type) 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 {
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
val ci8 = our const "@ci8"
our globalValue "@ci8" shouldBe ci8
......
......@@ -57,7 +57,7 @@ class UvmInterpreterNativeTests extends UvmBundleTesterBase {
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) =>
val Seq(fp, rv, buf, bufV0P) = ca.dumpKeepalives(st, 0)
......@@ -77,11 +77,13 @@ class UvmInterpreterNativeTests extends UvmBundleTesterBase {
val lib = Library.getDefault()
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)
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 {
val a3 = ca.putDouble("@double", 6.25d)
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,
bitcast1, bitcast2, bitcast3, bitcast4, ptrcast1, ptrcast2, ptrcast3) = ca.dumpKeepalives(st, 0)
val kas = 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
zext.vb.asUInt(64) shouldBe 0xfedcba98L
sext.vb.asUInt(64) shouldBe BigInt("fffffffffedcba98", 16)
......@@ -679,13 +681,19 @@ class UvmInterpreterSpec extends UvmBundleTesterBase {
ptrcast2.vb.asPointer 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)
}
val a5 = ca.putInt("@i64", -0x123456789abcdef0L)
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,
bitcast1, bitcast2, bitcast3, bitcast4, ptrcast1, ptrcast2, ptrcast3) = ca.dumpKeepalives(st, 0)
val kas = 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()
......@@ -1409,7 +1417,7 @@ class UvmInterpreterSpec extends UvmBundleTesterBase {
e.vb.asSInt(64) shouldEqual 42
f.vb.asSInt(64) shouldEqual 42
val thr = th.vb.asThread.get
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 @@
.const @F_2 <@float> = 2.0f
.const @F_3 <@float> = 3.0f
.const @F_4 <@float> = 4.0f
.const @I32_1 <@float> = 1
.const @I32_2 <@float> = 2
.const @I32_3 <@float> = 3
.const @I32_4 <@float> = 4
.const @I32_1 <@i32> = 1
.const @I32_2 <@i32> = 2
.const @I32_3 <@i32> = 3
.const @I32_4 <@i32> = 4
.const @D_1 <@float> = 1.0d
.const @D_2 <@float> = 2.0d
......@@ -82,3 +82,9 @@
.typedef @sgf_t = struct<@ii64 @func0>
.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 @@
COMMINST @uvm.thread_exit
}
.const @PTRVOID_DUMMY1 <@ptrvoid> = 0xdeadbeef13572468
.const @FPI_I_DUMMY2 <@fpi_i> = 0x55aa55aa5a5a5a5a
.funcsig @conv_sig = @void (@i32 @i64 @float @double)
.funcdef @conv VERSION @conv_v1 <@conv_sig> (%p0 %p1 %p2 %p3) {
%entry:
......@@ -358,11 +361,16 @@
%ptrcast2 = PTRCAST <@ptrvoid @fpi_i> %ptrcast1
%ptrcast3 = PTRCAST <@fpi_i @i64> %ptrcast2
// Testing constants.
%ptrcast4 = PTRCAST <@ptrvoid @i64> @PTRVOID_DUMMY1
%ptrcast5 = PTRCAST <@fpi_i @ptrvoid> @FPI_I_DUMMY2
%ptrcast6 = PTRCAST <@ptrvoid @i32> @PTRVOID_DUMMY1
%trap = TRAP <@void> KEEPALIVE (
%trunc %zext %sext %fptrunc %fpext
%fptoui1 %fptosi1 %fptoui2 %fptosi2 %uitofp %sitofp
%bitcast1 %bitcast2 %bitcast3 %bitcast4
%ptrcast1 %ptrcast2 %ptrcast3
%ptrcast1 %ptrcast2 %ptrcast3 %ptrcast4 %ptrcast5 %ptrcast6
)
COMMINST @uvm.thread_exit
}
......
......@@ -82,9 +82,17 @@
.const @NULLSTACK <@stack> = NULL
.typedef @refi8 = ref<@i8>
.typedef @irefi8 = iref<@i8>
.typedef @refi16 = ref<@i16>
.typedef @refi32 = ref<@i32>
.typedef @refi64 = ref<@i64>
.typedef @reffloat = ref<@float>
.typedef @refdouble = ref<@double>
.typedef @irefi8 = iref<@i8>
.typedef @irefi16 = iref<@i16>
.typedef @irefi32 = iref<@i32>
.typedef @irefi64 = iref<@i64>
.typedef @ireffloat = iref<@float>
.typedef @irefdouble= iref<@double>
.const @NULLREF_I64 <@refi64> = NULL
.const @NULLIREF_I64 <@irefi64> = NULL
......@@ -96,6 +104,7 @@
.typedef @ptrfloat = ptr<@float>
.typedef @ptrdouble = ptr<@double>
.typedef @ptrptrvoid = ptr<@ptrvoid>
.typedef @ptrfpnoparamsnoret = ptr<@fpnoparamsnoret>
.typedef @ptrfpi_i = ptr<@fpi_i>
.typedef @fpnoparamsnoret = funcptr<@noparamsnoret>
......@@ -127,10 +136,9 @@
.const @I8_o <@i8> = 0x6f
.const @I8_NL <@i8> = 0x0a
.funcdef @writetest VERSION @writetest_v1 <@v_a> (%p0) {
.funcsig @writetest_sig = @void (@write_fp)
.funcdef @writetest VERSION @writetest_v1 <@writetest_sig> (%fp) {
%entry:
%fp = PTRCAST <@i64 @write_fp> %p0
%buf = NEWHYBRID <@CharBuf @i64> @I64_6
%buf_i = GETIREF <@CharBuf> %buf
%buf_v0 = GETVARPARTIREF <@CharBuf> %buf_i
......@@ -160,9 +168,11 @@
.funcsig @memcpy_sig = @ptrvoid (@ptrvoid @ptrvoid @size_t)
.typedef @memcpy_fp = funcptr<@write_sig>
.funcdef @memcpytest VERSION @memcpytest_v1 <@v_a> (%p0) {
.global @FP_MEMCPY <@memcpy_fp>
.funcdef @memcpytest VERSION @memcpytest_v1 <@noparamsnoret> () {
%entry:
%fp = PTRCAST <@i64 @write_fp> %p0
%fp = LOAD <@memcpy_fp> @FP_MEMCPY
%buf = NEWHYBRID <@CharBuf @i64> @I64_6
%buf_i = GETIREF <@CharBuf> %buf
......@@ -208,3 +218,114 @@
%trap = TRAP <@void> KEEPALIVE (%fp %rv %buf2_v0_p %buf2_0 %buf2_1 %buf2_2 %buf2_3 %buf2_4 %buf2_5)
COMMINST @uvm.thread_exit
}
.typedef @struct_foo = struct<@i64 @i32 @i16 @i8>
.typedef @struct_bar = struct<@ptrvoid @fpnoparamsnoret>
.typedef @struct_baz1 = struct<@float @i32>
.typedef @struct_baz = struct<@struct_baz1 @double>
.typedef @irefstruct_baz = iref<@struct_baz>
.typedef @ptrstruct_baz = ptr<@struct_baz>
.funcsig @foo_func_sig = @void (@struct_foo @ptri64 @ptri32 @ptri16 @ptri8)
.funcsig @bar_func_sig = @void (@struct_bar @ptrptrvoid @ptrfpnoparamsnoret)
.funcsig @baz_func_sig = @struct_baz (@struct_baz @ptrfloat @ptri32 @ptrdouble @ptrstruct_baz)
.typedef @foo_func_fp = funcptr<@foo_func_sig>
.typedef @bar_func_fp = funcptr<@bar_func_sig>
.typedef @baz_func_fp = funcptr<@baz_func_sig>
.const @I64BIG <@i64> = 0x55aa55aa55aa55aa
.const @I32BIG <@i32> = 0x5a5a5a5a
.const @I16BIG <@i16> = 0xa5a5
.const @I8BIG <@i8 > = 0x61
.const @o_foo <@struct_foo> = {@I64BIG @I32BIG @I16BIG @I8BIG}
.funcdef @foo_func_test VERSION @foo_func_test_v1 <@v_a> (%p0) {
%entry:
%fp = PTRCAST <@i64 @foo_func_fp> %p0
%aa = ALLOCA <@i64>