[Wasm] Add comments to .wat files

This commit is contained in:
Svyatoslav Kuzmich
2022-12-16 13:57:59 +00:00
committed by Space Team
parent 41dbbd1fc8
commit 62ac77ca39
6 changed files with 78 additions and 1 deletions
@@ -181,6 +181,7 @@ class BodyGenerator(
}
} else {
body.buildGetGlobal(context.referenceGlobalField(field.symbol))
body.commentPreviousInstr { "type: ${field.type.render()}" }
}
}
@@ -202,6 +203,7 @@ class BodyGenerator(
WasmImmediate.GcType(context.referenceGcType(field.parentAsClass.symbol)),
WasmImmediate.StructFieldIdx(context.getStructFieldRef(field))
)
body.commentPreviousInstr { "name: ${field.name.asString()}, type: ${field.type.render()}" }
}
override fun visitSetField(expression: IrSetField) {
@@ -215,9 +217,11 @@ class BodyGenerator(
struct = context.referenceGcType(field.parentAsClass.symbol),
fieldId = context.getStructFieldRef(field),
)
body.commentPreviousInstr { "name: ${field.name}, type: ${field.type.render()}" }
} else {
generateExpression(expression.value)
body.buildSetGlobal(context.referenceGlobalField(expression.symbol))
body.commentPreviousInstr { "type: ${field.type.render()}" }
}
body.buildGetUnit()
@@ -234,11 +238,13 @@ class BodyGenerator(
else
functionContext.referenceLocal(valueSymbol)
)
body.commentPreviousInstr { "type: ${valueDeclaration.type.render()}" }
}
override fun visitSetValue(expression: IrSetValue) {
generateExpression(expression.value)
body.buildSetLocal(functionContext.referenceLocal(expression.symbol))
body.commentPreviousInstr { "type: ${expression.symbol.owner.type.render()}" }
body.buildGetUnit()
}
@@ -263,6 +269,7 @@ class BodyGenerator(
WasmOp.ARRAY_NEW_DEFAULT,
WasmImmediate.GcType(wasmGcType)
)
body.commentPreviousInstr { "@WasmArrayOf ctor call: ${klass.fqNameWhenAvailable}" }
return
}
@@ -272,6 +279,7 @@ class BodyGenerator(
generateExpression(expression.getValueArgument(i)!!)
}
body.buildStructNew(wasmGcType)
body.commentPreviousInstr { "@WasmPrimitiveConstructor ctor call: ${klass.fqNameWhenAvailable}" }
return
}
@@ -281,6 +289,7 @@ class BodyGenerator(
private fun generateAnyParameters(klassSymbol: IrClassSymbol) {
//ClassITable and VTable load
body.commentGroupStart { "Any parameters" }
body.buildGetGlobal(context.referenceGlobalVTable(klassSymbol))
if (klassSymbol.owner.hasInterfaceSuperClass()) {
body.buildGetGlobal(context.referenceGlobalClassITable(klassSymbol))
@@ -290,6 +299,7 @@ class BodyGenerator(
body.buildConstI32Symbol(context.referenceClassId(klassSymbol))
body.buildConstI32(0) // Any::_hashCode
body.commentGroupEnd()
}
fun generateObjectCreationPrefixIfNeeded(constructor: IrConstructor) {
@@ -297,6 +307,7 @@ class BodyGenerator(
if (constructor.origin == PrimaryConstructorLowering.SYNTHETIC_PRIMARY_CONSTRUCTOR) return
if (parentClass.isAbstractOrSealed) return
val thisParameter = functionContext.referenceLocal(parentClass.thisReceiver!!.symbol)
body.commentGroupStart { "Object creation prefix" }
body.buildGetLocal(thisParameter)
body.buildInstr(WasmOp.REF_IS_NULL)
body.buildIf("this_init")
@@ -310,6 +321,7 @@ class BodyGenerator(
body.buildStructNew(context.referenceGcType(parentClass.symbol))
body.buildSetLocal(thisParameter)
body.buildEnd()
body.commentGroupEnd()
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) {
@@ -330,6 +342,7 @@ class BodyGenerator(
generateAnyParameters(klassSymbol)
generateExpression(expression)
body.buildStructNew(context.referenceGcType(klassSymbol))
body.commentPreviousInstr { "box" }
}
private fun generateCall(call: IrFunctionAccessExpression) {
@@ -394,17 +407,21 @@ class BodyGenerator(
val receiver = call.dispatchReceiver!!
generateExpression(receiver)
body.commentGroupStart { "virtual call: ${function.fqNameWhenAvailable}" }
//TODO: check why it could be needed
generateRefNullCast(receiver.type, klass.defaultType)
body.buildStructGet(context.referenceGcType(klass.symbol), WasmSymbol(0))
body.buildStructGet(context.referenceVTableGcType(klass.symbol), WasmSymbol(vfSlot))
body.buildInstr(WasmOp.CALL_REF, WasmImmediate.TypeIdx(context.referenceFunctionType(function.symbol)))
body.commentGroupEnd()
} else {
val symbol = klass.symbol
if (symbol in hierarchyDisjointUnions) {
generateExpression(call.dispatchReceiver!!)
body.commentGroupStart { "interface call: ${function.fqNameWhenAvailable}" }
body.buildStructGet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(1))
val classITableReference = context.referenceClassITableGcType(symbol)
@@ -416,6 +433,7 @@ class BodyGenerator(
body.buildStructGet(context.referenceVTableGcType(symbol), WasmSymbol(vfSlot))
body.buildInstr(WasmOp.CALL_REF, WasmImmediate.TypeIdx(context.referenceFunctionType(function.symbol)))
body.commentGroupEnd()
} else {
body.buildUnreachable()
}
@@ -494,10 +494,12 @@ fun generateConstExpression(expression: IrConst<*>, body: WasmExpressionBuilder,
is IrConstKind.String -> {
val stringValue = kind.valueOf(expression)
val (literalAddress, literalPoolId) = context.referenceStringLiteralAddressAndId(stringValue)
body.commentGroupStart { "const string: \"$stringValue\"" }
body.buildConstI32Symbol(literalPoolId)
body.buildConstI32Symbol(literalAddress)
body.buildConstI32(stringValue.length)
body.buildCall(context.referenceFunction(context.backendContext.wasmSymbols.stringGetLiteral))
body.commentGroupEnd()
}
else -> error("Unknown constant kind")
}
@@ -95,6 +95,9 @@ sealed class WasmImmediate {
class HeapType(val value: WasmHeapType) : WasmImmediate() {
constructor(type: WasmType) : this(type.getHeapType())
}
// Pseudo-immediates
class ConstString(val value: String) : WasmImmediate()
}
@@ -403,11 +406,17 @@ enum class WasmOp(
// ============================================================
// Pseudo-instruction, just alias for a normal call. It's used to easily spot get_unit on the wasm level.
GET_UNIT("call", 0x10, FUNC_IDX)
GET_UNIT("call", 0x10, FUNC_IDX),
PSEUDO_COMMENT_PREVIOUS_INSTR("<comment-single>", WASM_OP_PSEUDO_OPCODE),
PSEUDO_COMMENT_GROUP_START("<comment-group-start>", WASM_OP_PSEUDO_OPCODE),
PSEUDO_COMMENT_GROUP_END("<comment-group-end>", WASM_OP_PSEUDO_OPCODE),
;
constructor(mnemonic: String, opcode: Int, vararg immediates: WasmImmediateKind) : this(mnemonic, opcode, immediates.toList())
}
const val WASM_OP_PSEUDO_OPCODE = 0xFFFF
val opcodesToOp: Map<Int, WasmOp> =
enumValues<WasmOp>().associateBy { it.opcode }
@@ -178,4 +178,16 @@ abstract class WasmExpressionBuilder {
fun buildDrop() {
buildInstr(WasmOp.DROP)
}
inline fun commentPreviousInstr(text: () -> String) {
buildInstr(WasmOp.PSEUDO_COMMENT_PREVIOUS_INSTR, WasmImmediate.ConstString(text()))
}
inline fun commentGroupStart(text: () -> String) {
buildInstr(WasmOp.PSEUDO_COMMENT_GROUP_START, WasmImmediate.ConstString(text()))
}
fun commentGroupEnd() {
buildInstr(WasmOp.PSEUDO_COMMENT_GROUP_END)
}
}
@@ -210,6 +210,10 @@ class WasmIrToBinary(
}
val opcode = instr.operator.opcode
if (opcode == WASM_OP_PSEUDO_OPCODE)
return
if (opcode > 0xFF) {
b.writeByte((opcode ushr 8).toByte())
b.writeByte((opcode and 0xFF).toByte())
@@ -259,6 +263,8 @@ class WasmIrToBinary(
is WasmImmediate.GcType -> appendModuleFieldReference(x.value.owner)
is WasmImmediate.StructFieldIdx -> b.writeVarUInt32(x.value.owner)
is WasmImmediate.HeapType -> appendHeapType(x.value)
is WasmImmediate.ConstString ->
error("Instructions with pseudo immediates should be skipped")
}
}
@@ -60,6 +60,34 @@ class WasmIrToText : SExpressionBuilder() {
private fun appendInstr(wasmInstr: WasmInstr) {
val op = wasmInstr.operator
if (op.opcode == WASM_OP_PSEUDO_OPCODE) {
fun commentText() =
(wasmInstr.immediates.single() as WasmImmediate.ConstString).value
when (op) {
WasmOp.PSEUDO_COMMENT_PREVIOUS_INSTR -> {
val text = commentText()
require(text.lineSequence().count() < 2) { "Comments for single instruction should be in one line" }
stringBuilder.append(" ;; ")
stringBuilder.append(text)
}
WasmOp.PSEUDO_COMMENT_GROUP_START -> {
newLine()
commentText().lines().forEach { line ->
newLine()
stringBuilder.append(";; ")
stringBuilder.append(line)
}
}
WasmOp.PSEUDO_COMMENT_GROUP_END -> {
newLine()
}
else -> error("Unknown pseudo op $op")
}
return
}
if (op == WasmOp.END || op == WasmOp.ELSE || op == WasmOp.CATCH)
indent--
@@ -113,6 +141,8 @@ class WasmIrToText : SExpressionBuilder() {
is WasmImmediate.HeapType -> {
appendHeapType(x.value)
}
is WasmImmediate.ConstString -> error("Pseudo immediate")
}
}