mirror of
https://github.com/fluencelabs/asmble
synced 2025-04-25 06:42:22 +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 elems: List<Elem> = emptyList(),
|
||||||
val funcs: List<Func> = emptyList(),
|
val funcs: List<Func> = emptyList(),
|
||||||
val data: List<Data> = emptyList(),
|
val data: List<Data> = emptyList(),
|
||||||
|
val names: NameSection? = null,
|
||||||
val customSections: List<CustomSection> = emptyList()
|
val customSections: List<CustomSection> = emptyList()
|
||||||
) : Node()
|
) : 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() {
|
sealed class Instr : Node() {
|
||||||
|
|
||||||
fun op() = InstrOp.classToOpMap[this::class] ?: throw Exception("No op found for ${this::class}")
|
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 =
|
val inFormat =
|
||||||
if (args.inFormat != "<use file extension>") args.inFormat
|
if (args.inFormat != "<use file extension>") args.inFormat
|
||||||
else args.inFile.substringAfterLast('.', "<unknown>")
|
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) ?:
|
val mod = (script.commands.firstOrNull() as? Script.Cmd.Module) ?:
|
||||||
error("Only a single sexpr for (module) allowed")
|
error("Only a single sexpr for (module) allowed")
|
||||||
val outStream = when (args.outFile) {
|
val outStream = when (args.outFile) {
|
||||||
|
@ -84,7 +84,7 @@ open class Translate : Command<Translate.Args>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"wasm" ->
|
"wasm" ->
|
||||||
Script(listOf(Script.Cmd.Module(BinaryToAst.toModule(
|
Script(listOf(Script.Cmd.Module(BinaryToAst(logger = logger).toModule(
|
||||||
ByteReader.InputStream(inBytes.inputStream())), null)))
|
ByteReader.InputStream(inBytes.inputStream())), null)))
|
||||||
else -> error("Unknown in format '$inFormat'")
|
else -> error("Unknown in format '$inFormat'")
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,13 @@ package asmble.io
|
|||||||
|
|
||||||
import asmble.ast.Node
|
import asmble.ast.Node
|
||||||
import asmble.util.*
|
import asmble.util.*
|
||||||
|
import java.io.ByteArrayInputStream
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
open class BinaryToAst(
|
open class BinaryToAst(
|
||||||
val version: Long = 1L,
|
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 {
|
) : Logger by logger {
|
||||||
|
|
||||||
fun toBlockType(b: ByteReader) = b.readVarInt7().toInt().let {
|
fun toBlockType(b: ByteReader) = b.readVarInt7().toInt().let {
|
||||||
@ -19,6 +21,23 @@ open class BinaryToAst(
|
|||||||
payload = b.readBytes()
|
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(
|
fun toData(b: ByteReader) = Node.Data(
|
||||||
index = b.readVarUInt32AsInt(),
|
index = b.readVarUInt32AsInt(),
|
||||||
offset = toInitExpr(b),
|
offset = toInitExpr(b),
|
||||||
@ -173,6 +192,7 @@ open class BinaryToAst(
|
|||||||
sections.find { it.first == sectionId }?.second?.readList(fn) ?: emptyList()
|
sections.find { it.first == sectionId }?.second?.readList(fn) ?: emptyList()
|
||||||
val types = readSectionList(1, this::toFuncType)
|
val types = readSectionList(1, this::toFuncType)
|
||||||
val funcIndices = readSectionList(3) { it.readVarUInt32AsInt() }
|
val funcIndices = readSectionList(3) { it.readVarUInt32AsInt() }
|
||||||
|
var nameSection: Node.NameSection? = null
|
||||||
return Node.Module(
|
return Node.Module(
|
||||||
types = types,
|
types = types,
|
||||||
imports = readSectionList(2, this::toImport),
|
imports = readSectionList(2, this::toImport),
|
||||||
@ -193,10 +213,17 @@ open class BinaryToAst(
|
|||||||
val afterSectionId = if (index == 0) 0 else sections[index - 1].let { (prevSectionId, _) ->
|
val afterSectionId = if (index == 0) 0 else sections[index - 1].let { (prevSectionId, _) ->
|
||||||
if (prevSectionId == 0) customSections.last().afterSectionId else 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 {
|
fun toResizableLimits(b: ByteReader) = b.readVarUInt1().let {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user