Minor improvements to tee and select

This commit is contained in:
Chad Retz 2017-04-03 14:55:26 -05:00
parent fa099d4ab0
commit ab635737b7
4 changed files with 32 additions and 12 deletions

View File

@ -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)
}
}

View File

@ -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"
}
}

View File

@ -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,

View File

@ -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