mirror of
https://github.com/fluencelabs/asmble
synced 2025-04-24 22:32:19 +00:00
Minor improvements to tee and select
This commit is contained in:
parent
fa099d4ab0
commit
ab635737b7
@ -46,8 +46,11 @@ data class ClsContext(
|
||||
|
||||
fun globalAtIndex(index: Int) = importGlobals.getOrNull(index).let {
|
||||
when (it) {
|
||||
null -> Either.Right(mod.globals.getOrNull(importGlobals.size - index) ?: error("No global at $index"))
|
||||
else -> Either.Left(it)
|
||||
null ->
|
||||
Either.Right(mod.globals.getOrNull(importGlobals.size - index) ?:
|
||||
throw CompileErr.UnknownGlobal(index))
|
||||
else ->
|
||||
Either.Left(it)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,13 @@ sealed class CompileErr(message: String, cause: Throwable? = null) : RuntimeExce
|
||||
}
|
||||
}
|
||||
|
||||
class SelectMismatch(
|
||||
val value1: TypeRef,
|
||||
val value2: TypeRef
|
||||
) : CompileErr("Select values $value1 and $value2 are not the same type") {
|
||||
override val asmErrString get() = "type mismatch"
|
||||
}
|
||||
|
||||
class IfThenValueWithoutElse() : CompileErr("If has value but no else clause") {
|
||||
override val asmErrString get() = "type mismatch"
|
||||
}
|
||||
@ -60,4 +67,10 @@ sealed class CompileErr(message: String, cause: Throwable? = null) : RuntimeExce
|
||||
) : CompileErr("Unknown local at index $index") {
|
||||
override val asmErrString get() = "unknown local"
|
||||
}
|
||||
|
||||
class UnknownGlobal(
|
||||
val index: Int
|
||||
) : CompileErr("Unknown global at index $index") {
|
||||
override val asmErrString get() = "unknown global"
|
||||
}
|
||||
}
|
@ -1128,8 +1128,9 @@ open class FuncBuilder {
|
||||
).push(import.type.contentType.typeRef)
|
||||
|
||||
fun applyTeeLocal(ctx: FuncContext, fn: Func, index: Int) = ctx.node.localByIndex(index).typeRef.let { typeRef ->
|
||||
fn.addInsns(InsnNode(if (typeRef.stackSize == 2) Opcodes.DUP2 else Opcodes.DUP)).
|
||||
push(typeRef).let { applySetLocal(ctx, it, index) }
|
||||
fn.popExpecting(typeRef).
|
||||
addInsns(InsnNode(if (typeRef.stackSize == 2) Opcodes.DUP2 else Opcodes.DUP)).
|
||||
push(typeRef).push(typeRef).let { fn -> applySetLocal(ctx, fn, index) }
|
||||
}
|
||||
|
||||
fun applySetLocal(ctx: FuncContext, fn: Func, index: Int) =
|
||||
@ -1150,8 +1151,6 @@ open class FuncBuilder {
|
||||
}.push(ctx.node.localByIndex(index).typeRef)
|
||||
|
||||
fun applySelectInsn(ctx: FuncContext, fn: Func): Func {
|
||||
// If this is dead code, just give up early
|
||||
if (fn.isCurrentBlockDead) return fn
|
||||
// 3 things, first two must have same type, third is 0 check (0 means use second, otherwise use first)
|
||||
// What we'll do is:
|
||||
// IFNE third L1 (which means if it's non-zero, goto L1)
|
||||
@ -1169,7 +1168,8 @@ open class FuncBuilder {
|
||||
// Pop next two and confirm they are the same type
|
||||
pop().let { (fn, type1) ->
|
||||
fn.pop().let { (fn, type2) ->
|
||||
require(type1 == type2) { "Select types do not match: $type1 and $type2" }
|
||||
// Don't check if unreachable
|
||||
if (!fn.isCurrentBlockDead && type1 != type2) throw CompileErr.SelectMismatch(type1, type2)
|
||||
// Label and pop
|
||||
fn.addInsns(
|
||||
nonZero,
|
||||
|
@ -328,14 +328,14 @@ open class SExprToAst {
|
||||
}
|
||||
"loop" -> {
|
||||
ret += Node.Instr.Loop(sigs.firstOrNull())
|
||||
toInstrs(exp, offset + opOffset, innerCtx).also {
|
||||
toInstrs(exp, offset + opOffset, innerCtx, false).also {
|
||||
ret += it.first
|
||||
opOffset += it.second
|
||||
}
|
||||
}
|
||||
"if" -> {
|
||||
ret += Node.Instr.Loop(sigs.firstOrNull())
|
||||
toInstrs(exp, offset + opOffset, innerCtx).also {
|
||||
ret += Node.Instr.If(sigs.firstOrNull())
|
||||
toInstrs(exp, offset + opOffset, innerCtx, false).also {
|
||||
ret += it.first
|
||||
opOffset += it.second
|
||||
}
|
||||
@ -348,7 +348,7 @@ open class SExprToAst {
|
||||
opOffset++
|
||||
innerCtx = innerCtx.copy(nameMap = innerCtx.nameMap + (it to ctx.blockDepth))
|
||||
}
|
||||
toInstrs(exp, offset + opOffset, innerCtx).also {
|
||||
toInstrs(exp, offset + opOffset, innerCtx, false).also {
|
||||
ret += it.first
|
||||
opOffset += it.second
|
||||
}
|
||||
@ -358,6 +358,7 @@ open class SExprToAst {
|
||||
else -> return Pair(emptyList(), 0)
|
||||
}
|
||||
require(exp.vals[offset + opOffset].symbolStr() == "end")
|
||||
ret += Node.Instr.End
|
||||
opOffset++
|
||||
exp.maybeName(offset + opOffset)?.also {
|
||||
opOffset++
|
||||
@ -570,7 +571,7 @@ open class SExprToAst {
|
||||
var instrAlign = 0
|
||||
if (exp.vals.size > offset + count) exp.vals[offset + count].symbolStr().also {
|
||||
if (it != null && it.startsWith("offset=")) {
|
||||
instrOffset = UnsignedInteger.valueOf(it.substring(7)).toLong()
|
||||
instrOffset = it.substring(7).toUnsignedIntConst().toLong()
|
||||
count++
|
||||
}
|
||||
}
|
||||
@ -691,6 +692,9 @@ open class SExprToAst {
|
||||
else BigInteger(this)
|
||||
private fun String.toIntConst() = toBigIntegerConst().toInt()
|
||||
private fun String.toLongConst() = toBigIntegerConst().toLong()
|
||||
private fun String.toUnsignedIntConst() =
|
||||
if (this.contains("0x")) UnsignedInteger.valueOf(this.replace("0x", ""), 16)
|
||||
else UnsignedInteger.valueOf(this)
|
||||
|
||||
private fun String.toFloatConst() =
|
||||
if (this == "infinity" || this == "+infinity") Float.POSITIVE_INFINITY
|
||||
|
Loading…
x
Reference in New Issue
Block a user