mirror of
https://github.com/fluencelabs/asmble
synced 2025-04-25 14:52:21 +00:00
Beginning of name support for issue #17
This commit is contained in:
parent
3c25b40c40
commit
96febbecd5
@ -15,6 +15,7 @@ sealed class Node {
|
||||
val elems: List<Elem> = emptyList(),
|
||||
val funcs: List<Func> = emptyList(),
|
||||
val data: List<Data> = emptyList(),
|
||||
val names: NameSection? = null,
|
||||
val customSections: List<CustomSection> = emptyList()
|
||||
) : Node()
|
||||
|
||||
@ -148,6 +149,12 @@ sealed class Node {
|
||||
}
|
||||
}
|
||||
|
||||
data class NameSection(
|
||||
val moduleName: String,
|
||||
val funcNames: Map<Int, String>,
|
||||
val localNames: Map<Int, Map<Int, String>>
|
||||
) : Node()
|
||||
|
||||
sealed class Instr : Node() {
|
||||
|
||||
fun op() = InstrOp.classToOpMap[this::class] ?: throw Exception("No op found for ${this::class}")
|
||||
|
@ -51,7 +51,7 @@ open class Compile : Command<Compile.Args>() {
|
||||
val inFormat =
|
||||
if (args.inFormat != "<use file extension>") args.inFormat
|
||||
else args.inFile.substringAfterLast('.', "<unknown>")
|
||||
val script = Translate.inToAst(args.inFile, inFormat)
|
||||
val script = Translate().also { it.logger = logger }.inToAst(args.inFile, inFormat)
|
||||
val mod = (script.commands.firstOrNull() as? Script.Cmd.Module) ?:
|
||||
error("Only a single sexpr for (module) allowed")
|
||||
val outStream = when (args.outFile) {
|
||||
|
@ -84,7 +84,7 @@ open class Translate : Command<Translate.Args>() {
|
||||
}
|
||||
}
|
||||
"wasm" ->
|
||||
Script(listOf(Script.Cmd.Module(BinaryToAst.toModule(
|
||||
Script(listOf(Script.Cmd.Module(BinaryToAst(logger = logger).toModule(
|
||||
ByteReader.InputStream(inBytes.inputStream())), null)))
|
||||
else -> error("Unknown in format '$inFormat'")
|
||||
}
|
||||
|
@ -2,11 +2,13 @@ package asmble.io
|
||||
|
||||
import asmble.ast.Node
|
||||
import asmble.util.*
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
open class BinaryToAst(
|
||||
val version: Long = 1L,
|
||||
val logger: Logger = Logger.Print(Logger.Level.OFF)
|
||||
val logger: Logger = Logger.Print(Logger.Level.OFF),
|
||||
val includeNameSection: Boolean = true
|
||||
) : Logger by logger {
|
||||
|
||||
fun toBlockType(b: ByteReader) = b.readVarInt7().toInt().let {
|
||||
@ -19,6 +21,23 @@ open class BinaryToAst(
|
||||
payload = b.readBytes()
|
||||
)
|
||||
|
||||
fun toNameSection(b: ByteReader) = generateSequence {
|
||||
if (b.isEof) null
|
||||
else b.readVarUInt7().toInt() to b.read(b.readVarUInt32AsInt())
|
||||
}.fold(Node.NameSection("", emptyMap(), emptyMap())) { sect, (type, b) ->
|
||||
fun <T> indexMap(b: ByteReader, fn: (ByteReader) -> T) =
|
||||
b.readList { it.readVarUInt32AsInt() to fn(it) }.let { pairs ->
|
||||
pairs.toMap().also { require(it.size == pairs.size) { "Malformed names: duplicate indices" } }
|
||||
}
|
||||
fun nameMap(b: ByteReader) = indexMap(b) { it.readString() }
|
||||
when (type) {
|
||||
0 -> sect.copy(moduleName = b.readString())
|
||||
1 -> sect.copy(funcNames = nameMap(b))
|
||||
2 -> sect.copy(localNames = indexMap(b, ::nameMap))
|
||||
else -> error("Malformed names: unrecognized type: $type")
|
||||
}.also { require(b.isEof) }
|
||||
}
|
||||
|
||||
fun toData(b: ByteReader) = Node.Data(
|
||||
index = b.readVarUInt32AsInt(),
|
||||
offset = toInitExpr(b),
|
||||
@ -173,6 +192,7 @@ open class BinaryToAst(
|
||||
sections.find { it.first == sectionId }?.second?.readList(fn) ?: emptyList()
|
||||
val types = readSectionList(1, this::toFuncType)
|
||||
val funcIndices = readSectionList(3) { it.readVarUInt32AsInt() }
|
||||
var nameSection: Node.NameSection? = null
|
||||
return Node.Module(
|
||||
types = types,
|
||||
imports = readSectionList(2, this::toImport),
|
||||
@ -193,10 +213,17 @@ open class BinaryToAst(
|
||||
val afterSectionId = if (index == 0) 0 else sections[index - 1].let { (prevSectionId, _) ->
|
||||
if (prevSectionId == 0) customSections.last().afterSectionId else prevSectionId
|
||||
}
|
||||
customSections + toCustomSection(b, afterSectionId)
|
||||
// Try to parse the name section
|
||||
val section = toCustomSection(b, afterSectionId).takeIf { section ->
|
||||
!includeNameSection && section.afterSectionId != 11 || section.name != "name" || try {
|
||||
nameSection = toNameSection(ByteReader.InputStream(section.payload.inputStream()))
|
||||
false
|
||||
} catch (e: Exception) { warn { "Failed parsing name section: $e" }; true }
|
||||
}
|
||||
if (section == null) customSections else customSections + section
|
||||
}
|
||||
}
|
||||
)
|
||||
).copy(names = nameSection)
|
||||
}
|
||||
|
||||
fun toResizableLimits(b: ByteReader) = b.readVarUInt1().let {
|
||||
|
Loading…
x
Reference in New Issue
Block a user