static bool AstDecodeImport(AstDecodeContext& c, uint32_t importIndex, AstImport** import) { uint32_t sigIndex = AstNoIndex; if (!AstDecodeSignatureIndex(c, &sigIndex)) return false; AstRef sigRef; if (!AstDecodeGenerateRef(c, AstName(MOZ_UTF16("type")), sigIndex, &sigRef)) return false; AstName moduleName; if (!AstDecodeName(c, &moduleName)) return AstDecodeFail(c, "expected import module name"); if (moduleName.empty()) return AstDecodeFail(c, "module name cannot be empty"); AstName funcName; if (!AstDecodeName(c, &funcName)) return AstDecodeFail(c, "expected import func name"); AstName importName; if (!AstDecodeGenerateName(c, AstName(MOZ_UTF16("import")), importIndex, &importName)) return false; *import = new(c.lifo) AstImport(importName, moduleName, funcName, sigRef); if (!*import) return false; return true; }
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 RenderEscapedString(WasmRenderContext& c, const AstName& s) { size_t length = s.length(); const char16_t* p = s.begin(); for (size_t i = 0; i < length; i++) { char16_t byte = p[i]; switch (byte) { case '\n': if (!c.buffer.append("\\n")) return false; break; case '\r': if (!c.buffer.append("\\0d")) return false; break; case '\t': if (!c.buffer.append("\\t")) return false; break; case '\f': if (!c.buffer.append("\\0c")) return false; break; case '\b': if (!c.buffer.append("\\08")) return false; break; case '\\': if (!c.buffer.append("\\\\")) return false; break; case '"' : if (!c.buffer.append("\\\"")) return false; break; case '\'': if (!c.buffer.append("\\'")) return false; break; default: if (byte >= 32 && byte < 127) { if (!c.buffer.append((char)byte)) return false; } else { char digit1 = byte / 16, digit2 = byte % 16; if (!c.buffer.append("\\")) return false; if (!c.buffer.append((char)(digit1 < 10 ? digit1 + '0' : digit1 + 'a' - 10))) return false; if (!c.buffer.append((char)(digit2 < 10 ? digit2 + '0' : digit2 + 'a' - 10))) return false; } break; } } return true; }
static bool RenderExport(WasmRenderContext& c, AstExport& export_, const AstModule::NameVector& funcImportNames, const AstModule::FuncVector& funcs) { if (!RenderIndent(c)) return false; if (!c.buffer.append("(export \"")) return false; if (!RenderEscapedString(c, export_.name())) return false; if (!c.buffer.append("\" ")) return false; switch (export_.kind()) { case DefinitionKind::Function: { uint32_t index = export_.ref().index(); AstName name = index < funcImportNames.length() ? funcImportNames[index] : funcs[index - funcImportNames.length()]->name(); if (name.empty()) { if (!RenderInt32(c, index)) return false; } else { if (!RenderName(c, name)) return false; } break; } case DefinitionKind::Table: { if (!c.buffer.append("table")) return false; break; } case DefinitionKind::Memory: { if (!c.buffer.append("memory")) return false; break; } case DefinitionKind::Global: { if (!c.buffer.append("global")) return false; if (!RenderRef(c, export_.ref())) return false; break; } } return c.buffer.append(")\n"); }
static bool AstDecodeGenerateRef(AstDecodeContext& c, const AstName& prefix, uint32_t index, AstRef* ref) { MOZ_ASSERT(index != AstNoIndex); if (!c.generateNames) { *ref = AstRef(AstName(), index); return true; } AstName name; if (!AstDecodeGenerateName(c, prefix, index, &name)) return false; MOZ_ASSERT(!name.empty()); *ref = AstRef(name, AstNoIndex); ref->setIndex(index); return true; }
static bool RenderBlockNameAndSignature(WasmRenderContext& c, const AstName& name, ExprType type) { if (!name.empty()) { if (!c.buffer.append(' ')) return false; if (!RenderName(c, name)) return false; } if (!IsVoid(type)) { if (!c.buffer.append(' ')) return false; if (!RenderExprType(c, type)) return false; } return true; }
static bool RenderName(WasmRenderContext& c, const AstName& name) { return c.buffer.append(name.begin(), name.end()); }