static bool RenderElemSection(WasmRenderContext& c, const AstModule& module) { for (const AstElemSegment* segment : module.elemSegments()) { if (!RenderIndent(c)) return false; if (!c.buffer.append("(elem ")) return false; if (!RenderInlineExpr(c, *segment->offset())) return false; for (const AstRef& elem : segment->elems()) { if (!c.buffer.append(" ")) return false; uint32_t index = elem.index(); AstName name = index < module.funcImportNames().length() ? module.funcImportNames()[index] : module.funcs()[index - module.funcImportNames().length()]->name(); if (name.empty()) { if (!RenderInt32(c, index)) return false; } else { if (!RenderName(c, name)) return false; } } if (!c.buffer.append(")\n")) return false; } return true; }
static bool RenderTableSection(WasmRenderContext& c, const AstModule& module) { if (module.elemSegments().empty()) return true; const AstElemSegment& segment = *module.elemSegments()[0]; if (!RenderIndent(c)) return false; if (!c.buffer.append("(table")) return false; for (const AstRef& elem : segment.elems()) { if (!c.buffer.append(" ")) return false; AstFunc* func = module.funcs()[elem.index()]; if (func->name().empty()) { if (!RenderInt32(c, elem.index())) return false; } else { if (!RenderName(c, func->name())) return false; } } if (!c.buffer.append(")\n")) return false; return true; }
static bool RenderModule(WasmRenderContext& c, AstModule& module) { if (!c.buffer.append("(module\n")) return false; c.indent++; if (!RenderTypeSection(c, module.sigs())) return false; if (!RenderImportSection(c, module.imports(), module.sigs())) return false; if (!RenderTableSection(c, module.maybeTable(), module.funcs())) return false; if (!RenderExportSection(c, module.exports(), module.funcs())) return false; if (!RenderCodeSection(c, module.funcs(), module.sigs())) return false; if (!RenderDataSection(c, module.maybeMemory())) return false; c.indent--; if (!c.buffer.append(")")) return false; return true; }
static bool RenderDataSection(WasmRenderContext& c, const AstModule& module) { if (!module.hasMemory()) return true; if (!RenderIndent(c)) return false; if (!c.buffer.append("(memory ")) return false; if (!RenderInt32(c, module.memory().initial())) return false; Maybe<uint32_t> memMax = module.memory().maximum(); if (memMax) { if (!c.buffer.append(" ")) return false; if (!RenderInt32(c, *memMax)) return false; } c.indent++; uint32_t numSegments = module.dataSegments().length(); if (!numSegments) { if (!c.buffer.append(")\n")) return false; return true; } if (!c.buffer.append("\n")) return false; for (uint32_t i = 0; i < numSegments; i++) { const AstDataSegment* segment = module.dataSegments()[i]; if (!RenderIndent(c)) return false; if (!c.buffer.append("(segment ")) return false; if (!RenderInt32(c, segment->offset())) return false; if (!c.buffer.append(" \"")) return false; RenderEscapedString(c, segment->text()); if (!c.buffer.append("\")\n")) return false; } c.indent--; if (!c.buffer.append(")\n")) return false; return true; }
bool wasm::BinaryToAst(JSContext* cx, const uint8_t* bytes, uint32_t length, LifoAlloc& lifo, AstModule** module) { AstModule* result = new(lifo) AstModule(lifo); if (!result->init()) return false; Decoder d(bytes, bytes + length); AstDecodeContext c(cx, lifo, d, *result, true); uint32_t u32; if (!d.readFixedU32(&u32) || u32 != MagicNumber) return AstDecodeFail(c, "failed to match magic number"); if (!d.readFixedU32(&u32) || u32 != EncodingVersion) return AstDecodeFail(c, "failed to match binary version"); if (!AstDecodeTypeSection(c)) return false; if (!AstDecodeImportSection(c)) return false; if (!AstDecodeFunctionSection(c)) return false; if (!AstDecodeTableSection(c)) return false; if (!AstDecodeMemorySection(c)) return false; if (!AstDecodeExportSection(c)) return false; if (!AstDecodeCodeSection(c)) return false; if (!AstDecodeDataSection(c)) return false; while (!d.done()) { if (!d.skipSection()) return AstDecodeFail(c, "failed to skip unknown section at end"); } *module = result; return true; }
static bool RenderGlobalSection(WasmRenderContext& c, const AstModule& module) { if (module.globals().empty()) return true; for (const AstGlobal* global : module.globals()) { if (!RenderIndent(c)) return false; if (!RenderGlobal(c, *global)) return false; } return true; }
static bool RenderStartSection(WasmRenderContext& c, AstModule& module) { if (!module.hasStartFunc()) return true; if (!RenderIndent(c)) return false; if (!c.buffer.append("(start ")) return false; if (!RenderRef(c, module.startFunc().func())) return false; if (!c.buffer.append(")\n")) return false; return true; }
static bool RenderTableSection(WasmRenderContext& c, const AstModule& module) { if (!module.hasTable()) return true; for (const AstResizable& table : module.tables()) { if (table.imported) continue; if (!RenderIndent(c)) return false; if (!RenderResizableTable(c, table.limits)) return false; if (!c.buffer.append("\n")) return false; } return true; }
static bool RenderImportSection(WasmRenderContext& c, const AstModule& module) { for (AstImport* import : module.imports()) { if (!RenderImport(c, *import, module)) return false; } return true; }
static bool RenderMemorySection(WasmRenderContext& c, const AstModule& module) { if (!module.hasMemory()) return true; for (const AstResizable& memory : module.memories()) { if (memory.imported) continue; if (!RenderIndent(c)) return false; if (!RenderResizableMemory(c, memory.limits)) return false; if (!c.buffer.append("\n")) return false; } return true; }
static bool RenderImport(WasmRenderContext& c, AstImport& import, const AstModule& module) { if (!RenderIndent(c)) return false; if (!c.buffer.append("(import ")) return false; if (!RenderName(c, import.name())) return false; if (!c.buffer.append(" \"")) return false; const AstName& moduleName = import.module(); if (!RenderEscapedString(c, moduleName)) return false; if (!c.buffer.append("\" \"")) return false; const AstName& fieldName = import.field(); if (!RenderEscapedString(c, fieldName)) return false; if (!c.buffer.append("\" ")) return false; switch (import.kind()) { case DefinitionKind::Function: { const AstSig* sig = module.sigs()[import.funcSig().index()]; if (!RenderSignature(c, *sig)) return false; break; } case DefinitionKind::Table: { if (!RenderResizableTable(c, import.limits())) return false; break; } case DefinitionKind::Memory: { if (!RenderResizableMemory(c, import.limits())) return false; break; } case DefinitionKind::Global: { const AstGlobal& glob = import.global(); if (!RenderGlobal(c, glob, /* inImport */ true)) return false; break; } } return c.buffer.append(")\n"); }
static bool RenderDataSection(WasmRenderContext& c, const AstModule& module) { uint32_t numSegments = module.dataSegments().length(); if (!numSegments) return true; for (const AstDataSegment* seg : module.dataSegments()) { if (!RenderIndent(c)) return false; if (!c.buffer.append("(data ")) return false; if (!RenderInlineExpr(c, *seg->offset())) return false; if (!c.buffer.append("\n")) return false; c.indent++; for (const AstName& fragment : seg->fragments()) { if (!RenderIndent(c)) return false; if (!c.buffer.append("\"")) return false; if (!RenderEscapedString(c, fragment)) return false; if (!c.buffer.append("\"\n")) return false; } c.indent--; if (!RenderIndent(c)) return false; if (!c.buffer.append(")\n")) return false; } return true; }