Commit 96c3d9db authored by Kunshan Wang's avatar Kunshan Wang

Consider multi-bundle loading.

parent ea6be94b
......@@ -7,7 +7,38 @@ class Bundle {
val typeNs = new SimpleNamespace[Type]()
val funcSigNs = new SimpleNamespace[FuncSig]()
val declConstNs = new SimpleNamespace[DeclaredConstant]()
val globalDataNS = new SimpleNamespace[GlobalData]()
val globalDataNs = new SimpleNamespace[GlobalData]()
val funcNs = new SimpleNamespace[Function]()
val globalValueNS = new SimpleNamespace[GlobalValue]()
val globalValueNs = new SimpleNamespace[GlobalValue]()
private def simpleMerge[T <: Identified](oldNs: Namespace[T], newNs: Namespace[T]) {
for (cand <- newNs.all) {
try {
oldNs.add(cand)
} catch {
case e: NameConflictException =>
throw new IllegalRedefinitionException(
"Redefinition of type, function signature, declared constant," +
" global data or global value is not allowed", e);
}
}
}
private def mergeFunc(oldNs: Namespace[Function], newNs: Namespace[Function]) {
for (cand <- newNs.all) {
val id = cand.id
oldNs.get(id) match {
case None => oldNs.add(cand)
case Some(oldObj) => oldObj.cfg = cand.cfg
}
}
}
def merge(newBundle: Bundle) {
simpleMerge(typeNs, newBundle.typeNs)
simpleMerge(funcSigNs, newBundle.funcSigNs)
simpleMerge(declConstNs, newBundle.declConstNs)
simpleMerge(globalDataNs, newBundle.globalDataNs)
simpleMerge(globalValueNs, newBundle.globalValueNs)
mergeFunc(funcNs, newBundle.funcNs)
}
}
......@@ -2,6 +2,10 @@ package uvm
class UvmException(message: String = null, cause: Throwable = null) extends RuntimeException(message, cause)
class TypeResolutionException(message: String = null, cause: Throwable = null) extends UvmException(message, cause)
class BundleLoadingException(message: String = null, cause: Throwable = null) extends UvmException(message, cause)
class NameConflictException(message: String = null, cause: Throwable = null) extends UvmException(message, cause)
\ No newline at end of file
class TypeResolutionException(message: String = null, cause: Throwable = null) extends BundleLoadingException(message, cause)
class IllegalRedefinitionException(message: String = null, cause: Throwable = null) extends BundleLoadingException(message, cause)
class NameConflictException(message: String = null, cause: Throwable = null) extends UvmException(message, cause)
......@@ -5,17 +5,17 @@ import uvm.types._
import uvm.ssavalues._
import uvm.ifuncs._
object UvmIRReader {
object UvmIRReader {
import UvmIRAST._
def read(ir: CharSequence): Bundle = {
def read(ir: CharSequence, globalBundle: Bundle): Bundle = {
val ast = UvmIRParser(ir)
read(ast)
read(ast, globalBundle)
}
def read(ir: java.io.Reader): Bundle = {
def read(ir: java.io.Reader, globalBundle: Bundle): Bundle = {
val ast = UvmIRParser(ir)
read(ast)
read(ast, globalBundle)
}
object IDFactory {
......@@ -57,13 +57,13 @@ object UvmIRReader {
}
}
def read(ir: IR): Bundle = {
def read(ir: IR, globalBundle: Bundle): Bundle = {
val bundle = new Bundle()
val phase1 = new Later()
def resTy(te: TypeExpr): Type = te match {
case ReferredType(g) => bundle.typeNs(g.name)
case ReferredType(g) => bundle.typeNs.get(g.name).getOrElse(globalBundle.typeNs(g.name))
case tc: TypeCons => mkType(tc)
}
......@@ -90,7 +90,7 @@ object UvmIRReader {
}
def resSig(se: FuncSigExpr): FuncSig = se match {
case ReferredFuncSig(g) => bundle.funcSigNs(g.name)
case ReferredFuncSig(g) => bundle.funcSigNs.get(g.name).getOrElse(globalBundle.funcSigNs(g.name))
case FuncSigCons(r, ps) => mkSig(r, ps)
}
......@@ -122,7 +122,7 @@ object UvmIRReader {
val phase2 = new Later()
def resGV(t: Type, ce: ConstExpr): GlobalValue = ce match {
case ReferredConst(g) => bundle.globalValueNS(g.name)
case ReferredConst(g) => bundle.globalValueNs.get(g.name).getOrElse(globalBundle.globalValueNs(g.name))
case c: ConstCons => mkConst(t, c)
}
......@@ -161,16 +161,23 @@ object UvmIRReader {
val fc = ConstFunc(func)
return fc
}
def tryReuseFuncID(name: String): Option[Int] = {
globalBundle.funcNs.get(name).map(_.id)
}
def declFunc(n: GID, s: FuncSigExpr): Function = {
val sig = resSig(s)
val func = mkFunc(sig)
func.id = IDFactory.getID()
val maybeOldID = tryReuseFuncID(n.name)
func.id = maybeOldID.getOrElse(IDFactory.getID())
func.name = Some(n.name)
bundle.funcNs.add(func)
val fc = mkFuncConst(func)
bundle.globalValueNS.add(fc)
if (maybeOldID == None) {
val fc = mkFuncConst(func)
bundle.globalValueNs.add(fc)
}
return func
}
......@@ -183,16 +190,16 @@ object UvmIRReader {
val con = mkConst(ty, c)
con.name = Some(n.name)
bundle.declConstNs.add(con)
bundle.globalValueNS.add(con)
bundle.globalValueNs.add(con)
}
case GlobalDataDef(n, t) => {
val ty = resTy(t)
val gd = mkGlobalData(ty)
gd.name = Some(n.name)
bundle.globalDataNS.add(gd)
bundle.globalDataNs.add(gd)
val gdc = mkGlobalDataConst(gd)
bundle.globalValueNS.add(gdc)
bundle.globalValueNs.add(gdc)
}
case FuncDecl(n, s) => {
declFunc(n, s)
......@@ -245,7 +252,7 @@ object UvmIRReader {
def resVal(ty: Option[Type], ve: ValueExpr): Value = ve match {
case RefValue(id) => id match {
case GID(n) => bundle.globalValueNS(n)
case GID(n) => bundle.globalValueNs(n)
case LID(n) => cfg.lvNs(n)
}
case InlineValue(cc) => ty match {
......
......@@ -5,27 +5,37 @@ import uvm._
trait AbstractReaderSpec extends FlatSpec with Matchers
with TestingBundlesValidators {
def parseFile(fileName: String): Bundle
val EMPTY_BUNDLE = new Bundle()
def parseFile(fileName: String, globalBundle: Bundle): Bundle
def theSubject: String
behavior of theSubject
it should "read simple type definitions" in {
val b = parseFile("tests/uvm-parsing-test/types.uir")
val b = parseFile("tests/uvm-parsing-test/types.uir", EMPTY_BUNDLE)
validateTypes(b)
}
it should "read simple constant definitions" in {
val b = parseFile("tests/uvm-parsing-test/constants.uir")
val b = parseFile("tests/uvm-parsing-test/constants.uir", EMPTY_BUNDLE)
validateConstants(b)
}
it should "read simple function definitions" in {
val b = parseFile("tests/uvm-parsing-test/functions.uir")
val b = parseFile("tests/uvm-parsing-test/functions.uir", EMPTY_BUNDLE)
validateFunctions(b)
}
it should "read simple instruction definitions" in {
val b = parseFile("tests/uvm-parsing-test/instructions.uir")
val b = parseFile("tests/uvm-parsing-test/instructions.uir", EMPTY_BUNDLE)
validateInstructions(b)
}
it should "handle loading of multiple bundles" in {
val gb = parseFile("tests/uvm-parsing-test/redef-base.uir", EMPTY_BUNDLE)
val b = parseFile("tests/uvm-parsing-test/redef-overlay.uir", gb)
validateRedef(gb, b)
gb.merge(b)
validateRedefAfterMerge(gb, b)
}
}
\ No newline at end of file
......@@ -11,9 +11,9 @@ trait TestingBundlesValidators extends Matchers with ExtraMatchers {
implicit class MagicalOur(b: Bundle) {
def ty = b.typeNs
def const = b.globalValueNS
def globalValue = b.globalValueNS
def globalData = b.globalDataNS
def const = b.globalValueNs
def globalValue = b.globalValueNs
def globalData = b.globalDataNs
def sig = b.funcSigNs
def func = b.funcNs
}
......@@ -1007,4 +1007,45 @@ trait TestingBundlesValidators extends Matchers with ExtraMatchers {
}
}
}
def validateRedef(globalBundle: Bundle, bundle: Bundle) {
val ourOld = globalBundle
val ourNew = bundle
in (ourOld func "@meaning_of_life") { (func, cfg) =>
val my = cfg
my inst "%ret" shouldBeA[InstRet] { _.retVal shouldBeAConstIntOf(64, 42) }
}
(ourOld func "@foxsay").cfg shouldBe None
(ourNew func "@meaning_of_life").id shouldEqual (ourOld func "@meaning_of_life").id
(ourNew func "@foxsay").id shouldEqual (ourOld func "@foxsay").id
in (ourNew func "@meaning_of_life") { (func, cfg) =>
val my = cfg
my inst "%ret" shouldBeA[InstRet] { its =>
its.retTy shouldBe (ourOld ty "@i64")
its.retVal shouldBeAConstIntOf(64, 43)
}
}
(ourNew func "@foxsay").cfg shouldNot be(None)
in (ourNew func "@foxsay") { (func, cfg) =>
val my = cfg
my inst "%ret" shouldBeA[InstRet] { _.retVal shouldBeAConstIntOf(64, 99) }
}
}
def validateRedefAfterMerge(globalBundle: Bundle, bundle: Bundle) {
val ourGlobal = globalBundle
val ourNew = bundle
(ourGlobal func "@foxsay").cfg shouldBe (ourNew func "@foxsay").cfg
(ourGlobal func "@meaning_of_life").cfg shouldBe (ourNew func "@meaning_of_life").cfg
}
}
\ No newline at end of file
......@@ -8,8 +8,8 @@ class UvmIRReaderSpec extends AbstractReaderSpec {
override def theSubject = "UvmIRReader"
override def parseFile(fileName: String): Bundle = {
UvmIRReader.read(new java.io.FileReader(fileName))
override def parseFile(fileName: String, globalBundle: Bundle): Bundle = {
UvmIRReader.read(new java.io.FileReader(fileName), globalBundle)
}
......
.typedef @i64 = int<64>
.funcsig @IntReturner = @i64 ()
.funcdef @meaning_of_life <@IntReturner> () {
%ret = RET <@i64> 42
}
.funcdecl @foxsay <@IntReturner>
.funcdef @foxsay <@IntReturner> () {
%ret = RET <@i64> 99
}
.funcdef @meaning_of_life <@IntReturner> () {
%ret = RET <@i64> 43
}
......@@ -9,12 +9,20 @@
.funcsig @noparamsnoret = @void ()
.typedef @funcdumb = func<@noparamsnoret>
.typedef @thread = thread
.typedef @stack = stack
.typedef @tagref64 = tagref64
.const @TRUE <@i64> = 1
.const @FALSE <@i64> = 0
.funcsig @i_ii = @i64 (@i64 @i64)
.typedef @refvoid = ref<@void>
.typedef @irefvoid = iref<@void>
.typedef @weakrefvoid = weakref<@void>
.const @NULLREF <@refvoid> = NULL
.funcdef @binops32 <@void (@i32 @i32)> (%p0 %p1) {
......@@ -351,6 +359,330 @@
THROW @NULLREF
}
.typedef @ArrayBaz = array <@i16 1024>
.const @THREE <@i64> = 3
.typedef @JavaLikeByteArray = hybrid <@i32 @i8>
.const @I64_1024 <@i64> = 1024
.funcdef @memAddressing <@noparamsnoret> () {
%bar_ref = NEW <@StructBar>
%bar_iref = GETIREF <@StructBar> %bar_ref
%bar_3 = GETFIELDIREF <@StructBar 3> %bar_iref
%baz_iref = ALLOCA <@ArrayBaz>
%baz_3 = GETELEMIREF <@ArrayBaz> %baz_iref @THREE
%baz_6 = SHIFTIREF <@i16> %baz_3 @THREE
%ja_ref = NEWHYBRID <@JavaLikeByteArray> @I64_1024
%ja_iref = GETIREF <@JavaLikeByteArray> %ja_ref
%ja_fix = GETFIXEDPARTIREF <@JavaLikeByteArray> %ja_iref
%ja_var = GETVARPARTIREF <@JavaLikeByteArray> %ja_iref
%trap = TRAP <@void> %exit %exit KEEPALIVE (%bar_ref %bar_iref %bar_3
%baz_iref %baz_3 %baz_6 %ja_ref %ja_iref %ja_fix %ja_var)
%exit:
ICALL @uvm.thread_exit ()
THROW @NULLREF
}
.global @g_i8 <@i8>
.global @g_i16 <@i16>
.global @g_i32 <@i32>
.global @g_i64 <@i64>
.global @g_f <@float>
.global @g_d <@double>
.global @g_r <@refvoid>
.global @g_ir <@irefvoid>
.global @g_wr <@weakrefvoid>
.global @g_func <@funcdumb>
.global @g_thr <@thread>
.global @g_sta <@stack>
.global @g_tr64 <@tagref64>
.funcdef @memAccessing <@noparamsnoret> () {
STORE <@i8> @g_i8 41
STORE <@i16> @g_i16 42
STORE <@i32> @g_i32 43
STORE <@i64> @g_i64 44
STORE <@float> @g_f 45.0f
STORE <@double> @g_d 46.0d
%void_r = NEW <@void>
%void_ir = ALLOCA <@void>
STORE <@refvoid> @g_r %void_r
STORE <@irefvoid> @g_ir %void_ir
STORE <@weakrefvoid> @g_wr %void_r
STORE <@funcdumb> @g_func @memAccessing
%li8 = LOAD <@i8> @g_i8
%li16 = LOAD <@i16> @g_i16
%li32 = LOAD <@i32> @g_i32
%li64 = LOAD <@i64> @g_i64
%lf = LOAD <@float> @g_f
%ld = LOAD <@double> @g_d
%lr = LOAD <@refvoid> @g_r
%lir = LOAD <@irefvoid> @g_ir
%lwr = LOAD <@weakrefvoid> @g_wr
%lfunc = LOAD <@funcdumb> @g_func
%trap = TRAP <@void> %exit %exit KEEPALIVE (%void_r %void_ir %li8 %li16
%li32 %li64 %lf %ld %lr %lir %lwr %lfunc)
%exit:
ICALL @uvm.thread_exit ()
THROW @NULLREF
}
.funcdef @memAccessingAtomic <@noparamsnoret> () {
STORE SEQ_CST <@i32> @g_i32 43
STORE SEQ_CST <@i64> @g_i64 44
%void_r = NEW <@void>
%void_r2 = NEW <@void>
%void_r3 = NEW <@void>
STORE <@refvoid> @g_r %void_r
%cx32_1 = CMPXCHG SEQ_CST UNORDERED <@i32> @g_i32 43 53
%cx32_2 = CMPXCHG SEQ_CST UNORDERED <@i32> @g_i32 43 63
%cx64_1 = CMPXCHG SEQ_CST UNORDERED <@i64> @g_i64 44 54
%cx64_2 = CMPXCHG SEQ_CST UNORDERED <@i64> @g_i64 44 64
%l32 = LOAD SEQ_CST <@i32> @g_i32
%l64 = LOAD SEQ_CST <@i64> @g_i64
%cxr_1 = CMPXCHG SEQ_CST UNORDERED <@refvoid> @g_r %void_r %void_r2
%cxr_2 = CMPXCHG SEQ_CST UNORDERED <@refvoid> @g_r %void_r %void_r3
%lr = LOAD <@refvoid> @g_r
STORE <@i64> @g_i64 1
%rmw0 = ATOMICRMW SEQ_CST XCHG <@i64> @g_i64 0x55ab // 1 -> 0x55ab
%rmw1 = ATOMICRMW SEQ_CST ADD <@i64> @g_i64 3 // 0x55ab -> 0x55ae
%rmw2 = ATOMICRMW SEQ_CST SUB <@i64> @g_i64 4 // 0x55ae -> 0x55aa
%rmw3 = ATOMICRMW SEQ_CST AND <@i64> @g_i64 0x5a5a // 0x55aa -> 0x500a
%rmw4 = ATOMICRMW SEQ_CST NAND <@i64> @g_i64 0x5a5a // 0x500a -> ~0x500a
%rmw5 = ATOMICRMW SEQ_CST OR <@i64> @g_i64 0x5000 // ~0x500a -> ~0x000a
%rmw6 = ATOMICRMW SEQ_CST XOR <@i64> @g_i64 0x55aa // ~0x000a -> ~0x55a0
%rmw7 = ATOMICRMW SEQ_CST MIN <@i64> @g_i64 -0x7fffffffffffffde // ~0x55a0 -> -0x7fffffffffffffde
%rmw8 = ATOMICRMW SEQ_CST MAX <@i64> @g_i64 42 // -0x7fffffffffffffde -> 42
%rmw9 = ATOMICRMW SEQ_CST UMIN <@i64> @g_i64 11 // 42 -> 11
%rmwA = ATOMICRMW SEQ_CST UMAX <@i64> @g_i64 0xffffffffffffffde // 11 -> 0xffffffffffffffde
%l64_2 = LOAD SEQ_CST <@i64> @g_i64
%trap = TRAP <@void> %exit %exit KEEPALIVE (%void_r %void_r2 %void_r3
%cx32_1 %cx32_2 %cx64_1 %cx64_2 %l32 %l64 %cxr_1 %cxr_2 %lr
%rmw0 %rmw1 %rmw2 %rmw3 %rmw4 %rmw5 %rmw6 %rmw7 %rmw8 %rmw9 %rmwA %l64_2)
%exit:
ICALL @uvm.thread_exit ()
THROW @NULLREF
}
.funcdef @watchpointtest <@noparamsnoret> () {
BRANCH %head
%head:
%wp = WATCHPOINT 42 <@i64> %dis %ena %enaexc KEEPALIVE ()
%dis:
%trapdis = TRAP <@void> %exit %exit KEEPALIVE ()
%ena:
%trapena = TRAP <@void> %exit %exit KEEPALIVE (%wp)
%enaexc:
%exc = LANDINGPAD
%trapena = TRAP <@void> %exit %exit KEEPALIVE (%exc)
%exit:
ICALL @uvm.thread_exit ()
THROW @NULLREF
}
.funcdef @testswapstack <@noparamsnoret> () {
%valueret = ALLOCA <@i64>
%shouldstop = ALLOCA <@i64> // initially zeroed
%thisstack = ICALL @uvm.current_stack ()
%iter = NEWSTACK <@itersig> @rangeiter (3 %thisstack %valueret %shouldstop)
ICALL @uvm.swap_stack (%iter)
BRANCH %head
%head:
%value = LOAD <@i64> %valueret
%stop = LOAD <@i64> %shouldstop
TRAP <@void> %head2 %head2 KEEPALIVE (%value %stop)
%head2:
%eq = EQ <@i64> %stop 0
BRANCH2 %eq %body %exit
%body:
ICALL @uvm.swap_stack (%iter)
BRANCH %head
%exit:
ICALL @uvm.thread_exit ()
THROW @NULLREF
}
.typedef @irefi64 = iref<@i64>
.typedef @irefstack = iref<@stack>
.funcsig @itersig = @void (@i64 @stack @irefi64 @irefi64)
.funcdef @rangeiter <@itersig> (%n %src %valueret %shouldstop) {
%entry:
BRANCH %head
%head:
%i = PHI <@i64> {
%entry: 0;
%body: %i2;
}
%lt = SLT <@i64> %i %n
BRANCH2 %lt %body %exit
%body:
STORE <@i64> %valueret %i
ICALL @uvm.swap_stack (%src)
%i2 = ADD <@i64> %i 1
BRANCH %head
%exit:
STORE <@i64> %shouldstop 1
ICALL @uvm.swap_and_kill (%src)
THROW @NULLREF // unreachable
}
.const @I64_100 <@i64> = 100
.const @I64_50 <@i64> = 50
.const @I64_0 <@i64> = 0
.typedef @LongAry = hybrid <@void @i64>
.funcdef @testmultithreading <@noparamsnoret> () {
%entry:
%ary_r = NEWHYBRID <@LongAry> @I64_100
%ary_ir = GETIREF <@LongAry> %ary_r
%ary0_ir = GETVARPARTIREF <@LongAry> %ary_ir
BRANCH %head
%head:
%i = PHI <@i64> { %entry: 0; %body: %i2; }
%cmp = SLT <@i64> %i @I64_100
BRANCH2 %cmp %body %next
%body:
%aryi_ir = SHIFTIREF <@i64> %ary0_ir %i
STORE <@i64> %aryi_ir %i
%i2 = ADD <@i64> %i 1
BRANCH %head
%next:
%result0 = ALLOCA <@i64>
%sta0 = NEWSTACK <@summingslavesig> @summingslave (%ary0_ir @I64_50 %result0)
%result1 = ALLOCA <@i64>
%ary50_ir = SHIFTIREF <@i64> %ary0_ir @I64_50
%sta1 = NEWSTACK <@summingslavesig> @summingslave (%ary50_ir @I64_50 %result1)
%thr0 = ICALL @uvm.new_thread (%sta0)
%thr1 = ICALL @uvm.new_thread (%sta1)
BRANCH %wait0
%wait0:
%res0val = LOAD SEQ_CST <@i64> %result0
%cz0 = EQ <@i64> %res0val @I64_0
BRANCH2 %cz0 %wait0 %wait1
%wait1:
%res1val = LOAD SEQ_CST <@i64> %result1
%cz1 = EQ <@i64> %res1val @I64_0
BRANCH2 %cz1 %wait1 %getresult
%getresult:
%sum = ADD <@i64> %res0val %res1val
TRAP <@void> %exit %exit KEEPALIVE (%sum)
%exit:
ICALL @uvm.thread_exit ()
THROW @NULLREF
}
.funcsig @summingslavesig = @void (@irefi64 @i64 @irefi64)
.funcdef @summingslave <@summingslavesig> (%ary %sz %result) {
%entry:
BRANCH %head
%head:
%sum = PHI <@i64> { %entry: 0; %body: %sum2; }
%i = PHI <@i64> { %entry: 0; %body: %i2; }
%cmp = SLT <@i64> %i %sz
BRANCH2 %cmp %body %exit
%body:
%curptr = SHIFTIREF <@i64> %ary %i
%curnum = LOAD <@i64> %curptr
%sum2 = ADD <@i64> %sum %curnum
%i2 = ADD <@i64> %i 1
BRANCH %head
%exit:
STORE SEQ_CST <@i64> %result %sum
ICALL @uvm.thread_exit ()
THROW @NULLREF
}
.typedef @i6 = int<6>
.typedef @i52 = int<52>
.const @I6_31 <@i6> = 31
.const @I52_SAMPLE <@i52> = 0xfedcba9876543
.const @D_42 <@double> = 42.0d
.funcdef @testtr64 <@noparamsnoret> () {
%someobj = NEW <@i64>
%rv = REFCAST <@refi64 @refvoid> %someobj
%f = ICALL @uvm.tr64.from_fp (@D_42)
%i = ICALL @uvm.tr64.from_int (@I52_SAMPLE)
%r = ICALL @uvm.tr64.from_ref (%rv @I6_31)
%f_is_f = ICALL @uvm.tr64.is_fp (%f)
%f_is_i = ICALL @uvm.tr64.is_int (%f)
%f_is_r = ICALL @uvm.tr64.is_ref (%f)
%i_is_f = ICALL @uvm.tr64.is_fp (%i)
%i_is_i = ICALL @uvm.tr64.is_int (%i)
%i_is_r = ICALL @uvm.tr64.is_ref (%i)
%r_is_f = ICALL @uvm.tr64.is_fp (%r)
%r_is_i = ICALL @uvm.tr64.is_int (%r)
%r_is_r = ICALL @uvm.tr64.is_ref (%r)
%fb = ICALL @uvm.tr64.to_fp (%f)
%ib = ICALL @uvm.tr64.to_int (%i)
%rb = ICALL @uvm.tr64.to_ref (%r)
%rt = ICALL @uvm.tr64.to_tag (%r)
TRAP <@void> %exit %exit KEEPALIVE (%rv %f %i %r %f_is_f %f_is_i %f_is_r
%i_is_f %i_is_i %i_is_r %r_is_f %r_is_i %r_is_r %fb %ib %rb %rt)
%exit:
ICALL @uvm.thread_exit ()
THROW @NULLREF
}
///////////////////////// Simple sum
.funcdef @simplesum <@void (@i64 @i64)> (%from %to) {
......
.typedef @i8 = int<8>
.typedef @i16 = int<16>
.typedef @i32 = int<32>
.typedef @i64 = int<64>
.typedef @float = float
.typedef @double = double
.typedef @void = void
.funcsig @noparamsnoret = @void ()
.typedef @funcdumb = func<@noparamsnoret>
.typedef @thread = thread
.typedef @stack = stack
.typedef @tagref64 = tagref64
.const @TRUE <@i64> = 1
.const @FALSE <@i64> = 0
.funcsig @i_ii = @i64 (@i64 @i64)
.typedef @refvoid = ref<@void>
.typedef @irefvoid = iref<@void>
.typedef @weakrefvoid = weakref<@void>
.const @NULLREF <@refvoid> = NULL
.typedef @StructFoo = struct <@i32 @i64 @float @double>
.const @STRUCT_FOO <@StructFoo> = {1 2 3.0f 4.0d}
.typedef @refi64 = ref<@i64>
.typedef @irefi64 = iref<@i64>
.typedef @weakrefi64 = weakref<@i64>
.typedef @StructBar = struct <
@i64 @i32 @i16 @i8 @float @double
@refi64 @irefi64 @weakrefi64
>
.typedef @refBar = ref<@StructBar>
.typedef @irefBar = iref<@StructBar>
.typedef @hCharArray = hybrid<@i64 @i8>
.typedef @ArrayBaz = array <@i16 1024>
.const @THREE <@i64> = 3
.typedef @JavaLikeByteArray = hybrid <@i32 @i8>
.const @I64_1024 <@i64> = 1024
.global @g_i8 <@i8>
.global @g_i16 <@i16>
.global @g_i32 <@i32>
.global @g_i64 <@i64>
.global @g_f <@float>
.global @g_d <@double>
.global @g_r <@refvoid>
.global @g_ir <@irefvoid>
.global @g_wr <@weakrefvoid>