Bug 1310949: Print the global section in the linear format; r=luke

MozReview-Commit-ID: J2ZuxfOtqd2

--HG--
extra : rebase_source : d63d0acea4db6f5a4377f15269f0445ce4096cd3
This commit is contained in:
Benjamin Bouvier 2016-10-19 18:08:29 +02:00
Родитель 28c2c9e157
Коммит 9f17700f0f
3 изменённых файлов: 266 добавлений и 80 удалений

Просмотреть файл

@ -97,6 +97,7 @@ class AstDecodeContext
AstDecodeStack exprs_;
DepthStack depths_;
const ValTypeVector* locals_;
GlobalDescVector globals_;
AstNameVector blockLabels_;
uint32_t currentLabelIndex_;
ExprType retType_;
@ -124,9 +125,28 @@ class AstDecodeContext
AstDecodeExprIter& iter() { return *iter_; }
AstDecodeStack& exprs() { return exprs_; }
DepthStack& depths() { return depths_; }
const ValTypeVector& locals() { return *locals_; }
AstNameVector& blockLabels() { return blockLabels_; }
ExprType retType() const { return retType_; }
const ValTypeVector& locals() const { return *locals_; }
bool addGlobalDesc(ValType type, bool isMutable, bool isImport) {
if (isImport)
return globals_.append(GlobalDesc(type, isMutable, globals_.length()));
// No need to have the precise init expr value; we just need the right
// type.
Val dummy;
switch (type) {
case ValType::I32: dummy = Val(uint32_t(0)); break;
case ValType::I64: dummy = Val(uint64_t(0)); break;
case ValType::F32: dummy = Val(RawF32(0.f)); break;
case ValType::F64: dummy = Val(RawF64(0.0)); break;
default: return false;
}
return globals_.append(GlobalDesc(InitExpr(dummy), isMutable));
}
const GlobalDescVector& globalDescs() const { return globals_; }
void popBack() { return exprs().popBack(); }
AstDecodeStackItem popCopy() { return exprs().popCopy(); }
@ -944,6 +964,54 @@ AstDecodeTeeLocal(AstDecodeContext& c)
return true;
}
static bool
AstDecodeGetGlobal(AstDecodeContext& c)
{
uint32_t globalId;
if (!c.iter().readGetGlobal(c.globalDescs(), &globalId))
return false;
AstRef globalRef;
if (!AstDecodeGenerateRef(c, AstName(u"global"), globalId, &globalRef))
return false;
auto* getGlobal = new(c.lifo) AstGetGlobal(globalRef);
if (!getGlobal)
return false;
if (!c.push(AstDecodeStackItem(getGlobal)))
return false;
return true;
}
static bool
AstDecodeSetGlobal(AstDecodeContext& c)
{
uint32_t globalId;
if (!c.iter().readSetGlobal(c.globalDescs(), &globalId, nullptr))
return false;
AstDecodeStackItem value = c.popCopy();
AstRef globalRef;
if (!AstDecodeGenerateRef(c, AstName(u"global"), globalId, &globalRef))
return false;
auto* setGlobal = new(c.lifo) AstSetGlobal(globalRef, *value.expr);
if (!setGlobal)
return false;
AstExpr* expr = c.handleVoidExpr(setGlobal);
if (!expr)
return false;
if (!c.push(AstDecodeStackItem(expr)))
return false;
return true;
}
static bool
AstDecodeReturn(AstDecodeContext& c)
{
@ -1337,6 +1405,14 @@ AstDecodeExpr(AstDecodeContext& c)
if (!AstDecodeStore(c, ValType::F64, 8, expr))
return false;
break;
case Expr::SetGlobal:
if (!AstDecodeSetGlobal(c))
return false;
break;
case Expr::GetGlobal:
if (!AstDecodeGetGlobal(c))
return false;
break;
case Expr::Br:
case Expr::BrIf:
if (!AstDecodeBranch(c, expr))
@ -1578,16 +1654,16 @@ AstDecodeImport(AstDecodeContext& c, uint32_t importIndex, AstImport** import)
if (!AstDecodeName(c, &fieldName))
return c.d.fail("expected import field name");
AstName importName;
if (!AstDecodeGenerateName(c, AstName(u"import"), importIndex, &importName))
return false;
uint32_t kind;
if (!c.d.readVarU32(&kind))
return c.d.fail("expected import kind");
switch (kind) {
case uint32_t(DefinitionKind::Function): {
AstName importName;
if (!AstDecodeGenerateName(c, AstName(u"import"), importIndex, &importName))
return false;
uint32_t sigIndex = AstNoIndex;
if (!AstDecodeSignatureIndex(c, &sigIndex))
return false;
@ -1600,16 +1676,27 @@ AstDecodeImport(AstDecodeContext& c, uint32_t importIndex, AstImport** import)
break;
}
case uint32_t(DefinitionKind::Global): {
AstName importName;
if (!AstDecodeGenerateName(c, AstName(u"global"), importIndex, &importName))
return false;
ValType type;
bool isMutable;
if (!DecodeGlobalType(c.d, &type, &isMutable))
return false;
if (!c.addGlobalDesc(type, isMutable, /* import */ true))
return false;
*import = new(c.lifo) AstImport(importName, moduleName, fieldName,
AstGlobal(importName, type, isMutable));
break;
}
case uint32_t(DefinitionKind::Table): {
AstName importName;
if (!AstDecodeGenerateName(c, AstName(u"table"), importIndex, &importName))
return false;
Limits table;
if (!AstDecodeLimitsTable(c, &table))
return false;
@ -1619,6 +1706,10 @@ AstDecodeImport(AstDecodeContext& c, uint32_t importIndex, AstImport** import)
break;
}
case uint32_t(DefinitionKind::Memory): {
AstName importName;
if (!AstDecodeGenerateName(c, AstName(u"memory"), importIndex, &importName))
return false;
Limits memory;
if (!DecodeLimits(c.d, &memory))
return false;
@ -1695,68 +1786,27 @@ AstDecodeMemorySection(AstDecodeContext& c)
}
static bool
AstDecodeInitializerExpression(AstDecodeContext& c, AstExpr** init, ValType type)
AstDecodeInitializerExpression(AstDecodeContext& c, ValType type, AstExpr** init)
{
Expr expr;
if (!c.d.readExpr(&expr))
return c.d.fail("missing initializer opcode");
InitExpr initExpr;
if (!DecodeInitializerExpression(c.d, c.globalDescs(), type, &initExpr))
return false;
switch (expr) {
case Expr::I32Const: {
int32_t i32;
if (!c.d.readVarS32(&i32))
return c.d.fail("missing initializer value");
*init = new(c.lifo) AstConst(Val((uint32_t)i32));
if (!*init)
return false;
if (type != ValType::I32)
return c.d.fail("initializer expression has incorrect type");
switch (initExpr.kind()) {
case InitExpr::Kind::Constant: {
*init = new(c.lifo) AstConst(Val(initExpr.val()));
break;
}
case Expr::I64Const: {
int64_t i64;
if (!c.d.readVarS64(&i64))
return c.d.fail("missing initializer value");
*init = new(c.lifo) AstConst(Val((uint64_t)i64));
if (!*init)
case InitExpr::Kind::GetGlobal: {
AstRef globalRef;
if (!AstDecodeGenerateRef(c, AstName(u"global"), initExpr.globalIndex(), &globalRef))
return false;
if (type != ValType::I64)
return c.d.fail("initializer expression has incorrect type");
*init = new(c.lifo) AstGetGlobal(globalRef);
break;
}
case Expr::F32Const: {
RawF32 f32;
if (!c.d.readFixedF32(&f32))
return c.d.fail("missing initializer value");
*init = new(c.lifo) AstConst(Val(f32));
if (!*init)
return false;
if (type != ValType::F32)
return c.d.fail("initializer expression has incorrect type");
break;
}
case Expr::F64Const: {
RawF64 f64;
if (!c.d.readFixedF64(&f64))
return c.d.fail("missing initializer value");
*init = new(c.lifo) AstConst(Val(f64));
if (!*init)
return false;
if (type != ValType::F64)
return c.d.fail("initializer expression has incorrect type");
break;
}
default:
return c.d.fail("unknown initializer opcode");
}
if (!c.d.readExpr(&expr))
return c.d.fail("missing initializer end");
if (expr != Expr::End)
return c.d.fail("initializer end isn't an end");
return true;
return !!*init;
}
static bool
@ -1772,8 +1822,11 @@ AstDecodeGlobal(AstDecodeContext& c, uint32_t i, AstGlobal* global)
return false;
AstExpr* init;
if (!AstDecodeInitializerExpression(c, &init, type))
return c.d.fail("missing initializer expression");
if (!AstDecodeInitializerExpression(c, type, &init))
return false;
if (!c.addGlobalDesc(type, isMutable, /* import */ false))
return false;
*global = AstGlobal(name, type, isMutable, Some(init));
return true;
@ -1792,9 +1845,11 @@ AstDecodeGlobalSection(AstDecodeContext& c)
if (!c.d.readVarU32(&numGlobals))
return c.d.fail("expected number of globals");
uint32_t numImported = c.globalDescs().length();
for (uint32_t i = 0; i < numGlobals; i++) {
auto* global = new(c.lifo) AstGlobal;
if (!AstDecodeGlobal(c, i, global))
if (!AstDecodeGlobal(c, i + numImported, global))
return false;
if (!c.module().append(global))
return false;
@ -2064,8 +2119,8 @@ AstDecodeElemSection(AstDecodeContext &c)
return c.d.fail("non-zero table index for element");
AstExpr* offset;
if (!AstDecodeInitializerExpression(c, &offset, ValType::I32))
return c.d.fail("missing initializer expression");
if (!AstDecodeInitializerExpression(c, ValType::I32, &offset))
return false;
uint32_t count;
if (!c.d.readVarU32(&count))

Просмотреть файл

@ -224,7 +224,7 @@ RenderBlockNameAndSignature(WasmRenderContext& c, const AstName& name, ExprType
}
static bool
RenderExpr(WasmRenderContext& c, AstExpr& expr);
RenderExpr(WasmRenderContext& c, AstExpr& expr, bool newLine = true);
#define MAP_AST_EXPR(c, expr) \
if (c.maybeSourceMap) { \
@ -386,12 +386,34 @@ RenderTeeLocal(WasmRenderContext& c, AstTeeLocal& tl)
MAP_AST_EXPR(c, tl);
if (!c.buffer.append("tee_local "))
return false;
if (!RenderRef(c, tl.local()))
return RenderRef(c, tl.local());
}
static bool
RenderGetGlobal(WasmRenderContext& c, AstGetGlobal& gg)
{
if (!RenderIndent(c))
return false;
if (!c.buffer.append('\n'))
MAP_AST_EXPR(c, gg);
if (!c.buffer.append("get_global "))
return false;
return true;
return RenderRef(c, gg.global());
}
static bool
RenderSetGlobal(WasmRenderContext& c, AstSetGlobal& sg)
{
if (!RenderExpr(c, sg.value()))
return false;
if (!RenderIndent(c))
return false;
MAP_AST_EXPR(c, sg);
if (!c.buffer.append("set_global "))
return false;
return RenderRef(c, sg.global());
}
static bool
@ -975,9 +997,8 @@ RenderReturn(WasmRenderContext& c, AstReturn& ret)
}
static bool
RenderExpr(WasmRenderContext& c, AstExpr& expr)
RenderExpr(WasmRenderContext& c, AstExpr& expr, bool newLine /* = true */)
{
bool newLine = true;
switch (expr.kind()) {
case AstExprKind::Drop:
if (!RenderDrop(c, expr.as<AstDrop>()))
@ -1011,6 +1032,14 @@ RenderExpr(WasmRenderContext& c, AstExpr& expr)
if (!RenderSetLocal(c, expr.as<AstSetLocal>()))
return false;
break;
case AstExprKind::GetGlobal:
if (!RenderGetGlobal(c, expr.as<AstGetGlobal>()))
return false;
break;
case AstExprKind::SetGlobal:
if (!RenderSetGlobal(c, expr.as<AstSetGlobal>()))
return false;
break;
case AstExprKind::TeeLocal:
if (!RenderTeeLocal(c, expr.as<AstTeeLocal>()))
return false;
@ -1193,9 +1222,69 @@ RenderTableSection(WasmRenderContext& c, const AstModule& module)
}
static bool
RenderImport(WasmRenderContext& c, AstImport& import, const AstModule::SigVector& sigs)
RenderGlobal(WasmRenderContext& c, const AstGlobal& glob, bool inImport = false)
{
if (!c.buffer.append("(global "))
return false;
if (!inImport) {
if (!RenderName(c, glob.name()))
return false;
if (!c.buffer.append(" "))
return false;
}
if (glob.isMutable()) {
if (!c.buffer.append("(mut "))
return false;
if (!RenderValType(c, glob.type()))
return false;
if (!c.buffer.append(")"))
return false;
} else {
if (!RenderValType(c, glob.type()))
return false;
}
if (glob.hasInit()) {
if (!c.buffer.append(" ("))
return false;
uint32_t prevIndent = c.indent;
c.indent = 0;
if (!RenderExpr(c, glob.init(), /* newLine */ false))
return false;
c.indent = prevIndent;
if (!c.buffer.append(")"))
return false;
}
if (!c.buffer.append(")"))
return false;
return inImport || c.buffer.append("\n");
}
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
RenderImport(WasmRenderContext& c, AstImport& import, const AstModule& module)
{
const AstSig* sig = sigs[import.funcSig().index()];
if (!RenderIndent(c))
return false;
if (!c.buffer.append("(import "))
@ -1216,22 +1305,40 @@ RenderImport(WasmRenderContext& c, AstImport& import, const AstModule::SigVector
if (!RenderEscapedString(c, fieldName))
return false;
if (!c.buffer.append("\""))
if (!c.buffer.append("\" "))
return false;
if (!RenderSignature(c, *sig))
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: {
// TODO next patch
break;
}
case DefinitionKind::Memory: {
// TODO next patch
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
RenderImportSection(WasmRenderContext& c, const AstModule::ImportVector& imports, const AstModule::SigVector& sigs)
RenderImportSection(WasmRenderContext& c, const AstModule& module)
{
uint32_t numImports = imports.length();
for (uint32_t i = 0; i < numImports; i++) {
if (!RenderImport(c, *imports[i], sigs))
for (AstImport* import : module.imports()) {
if (!RenderImport(c, *import, module))
return false;
}
return true;
@ -1442,12 +1549,15 @@ RenderModule(WasmRenderContext& c, AstModule& module)
if (!RenderTypeSection(c, module.sigs()))
return false;
if (!RenderImportSection(c, module.imports(), module.sigs()))
if (!RenderImportSection(c, module))
return false;
if (!RenderTableSection(c, module))
return false;
if (!RenderGlobalSection(c, module))
return false;
if (!RenderExportSection(c, module.exports(), module.funcImportNames(), module.funcs()))
return false;

Просмотреть файл

@ -21,3 +21,24 @@ wasmFullPass(`(module
)
(func) (func) (func)
(export "run" 0))`, 43);
// Global section.
wasmFullPass(`(module
(import $imported "globals" "x" (global i32))
(global $mut_local (mut i32) (i32.const 0))
(global $imm_local i32 (i32.const 37))
(global $imm_local_2 i32 (get_global 0))
(func $get (result i32)
i32.const 13
set_global $mut_local
get_global $imported
get_global $mut_local
i32.add
get_global $imm_local
i32.add
get_global $imm_local_2
i32.add
)
(export "run" $get)
)`, 13 + 42 + 37 + 42, { globals: {x: 42} });