diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/asm2wasm.h | 104 | ||||
-rw-r--r-- | src/emscripten-optimizer/simple_ast.cpp | 18 | ||||
-rw-r--r-- | src/emscripten-optimizer/simple_ast.h | 39 |
3 files changed, 100 insertions, 61 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 1d063a8ee..eaf4f8c18 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -1192,8 +1192,8 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { for (unsigned i = 0; i < params->size(); i++) { Ref curr = body[i]; - auto* assign = curr->asAssign(); - IString name = assign->target()->getIString(); + auto* assign = curr->asAssignName(); + IString name = assign->target(); AsmType asmType = detectType(assign->value(), nullptr, false, Math_fround, wasmOnly); Builder::addParam(function, name, asmToWasmType(asmType)); functionVariables.insert(name); @@ -1273,60 +1273,60 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { ret->type = ret->value.type; return ret; } - if (ast->isAssign()) { - auto* assign = ast->asAssign(); - if (assign->target()->isString()) { - IString name = assign->target()->getIString(); - if (functionVariables.has(name)) { - auto ret = allocator.alloc<SetLocal>(); - ret->index = function->getLocalIndex(assign->target()->getIString()); - ret->value = process(assign->value()); - ret->setTee(false); - ret->finalize(); - return ret; - } - // global var - assert(mappedGlobals.find(name) != mappedGlobals.end()); - auto* ret = builder.makeSetGlobal(name, process(assign->value())); - // set_global does not return; if our value is trivially not used, don't emit a load (if nontrivially not used, opts get it later) - auto parent = astStackHelper.getParent(); - if (!parent || parent->isArray(BLOCK) || parent->isArray(IF)) return ret; - return builder.makeSequence(ret, builder.makeGetGlobal(name, ret->value->type)); - } else if (assign->target()->isArray(SUB)) { - Ref target = assign->target(); - assert(target[1]->isString()); - IString heap = target[1]->getIString(); - assert(views.find(heap) != views.end()); - View& view = views[heap]; - auto ret = allocator.alloc<Store>(); - ret->bytes = view.bytes; - ret->offset = 0; - ret->align = view.bytes; - ret->ptr = processUnshifted(target[2], view.bytes); + if (ast->isAssignName()) { + auto* assign = ast->asAssignName(); + IString name = assign->target(); + if (functionVariables.has(name)) { + auto ret = allocator.alloc<SetLocal>(); + ret->index = function->getLocalIndex(assign->target()); ret->value = process(assign->value()); - ret->valueType = asmToWasmType(view.type); + ret->setTee(false); ret->finalize(); - if (ret->valueType != ret->value->type) { - // in asm.js we have some implicit coercions that we must do explicitly here - if (ret->valueType == f32 && ret->value->type == f64) { - auto conv = allocator.alloc<Unary>(); - conv->op = DemoteFloat64; - conv->value = ret->value; - conv->type = WasmType::f32; - ret->value = conv; - } else if (ret->valueType == f64 && ret->value->type == f32) { - auto conv = allocator.alloc<Unary>(); - conv->op = PromoteFloat32; - conv->value = ret->value; - conv->type = WasmType::f64; - ret->value = conv; - } else { - abort_on("bad sub[] types", ast); - } - } return ret; } - abort_on("confusing assign", ast); + // global var + assert(mappedGlobals.find(name) != mappedGlobals.end()); + auto* ret = builder.makeSetGlobal(name, process(assign->value())); + // set_global does not return; if our value is trivially not used, don't emit a load (if nontrivially not used, opts get it later) + auto parent = astStackHelper.getParent(); + if (!parent || parent->isArray(BLOCK) || parent->isArray(IF)) return ret; + return builder.makeSequence(ret, builder.makeGetGlobal(name, ret->value->type)); + } + if (ast->isAssign()) { + auto* assign = ast->asAssign(); + assert(assign->target()->isArray(SUB)); + Ref target = assign->target(); + assert(target[1]->isString()); + IString heap = target[1]->getIString(); + assert(views.find(heap) != views.end()); + View& view = views[heap]; + auto ret = allocator.alloc<Store>(); + ret->bytes = view.bytes; + ret->offset = 0; + ret->align = view.bytes; + ret->ptr = processUnshifted(target[2], view.bytes); + ret->value = process(assign->value()); + ret->valueType = asmToWasmType(view.type); + ret->finalize(); + if (ret->valueType != ret->value->type) { + // in asm.js we have some implicit coercions that we must do explicitly here + if (ret->valueType == f32 && ret->value->type == f64) { + auto conv = allocator.alloc<Unary>(); + conv->op = DemoteFloat64; + conv->value = ret->value; + conv->type = WasmType::f32; + ret->value = conv; + } else if (ret->valueType == f64 && ret->value->type == f32) { + auto conv = allocator.alloc<Unary>(); + conv->op = PromoteFloat32; + conv->value = ret->value; + conv->type = WasmType::f64; + ret->value = conv; + } else { + abort_on("bad sub[] types", ast); + } + } + return ret; } IString what = ast[0]->getIString(); if (what == BINARY) { diff --git a/src/emscripten-optimizer/simple_ast.cpp b/src/emscripten-optimizer/simple_ast.cpp index 618b0d9dd..75685f80e 100644 --- a/src/emscripten-optimizer/simple_ast.cpp +++ b/src/emscripten-optimizer/simple_ast.cpp @@ -64,11 +64,22 @@ Value& Value::setAssign(Ref target, Ref value) { return *this; } +Value& Value::setAssignName(IString target, Ref value) { + asAssignName()->target() = target; + asAssignName()->value() = value; + return *this; +} + Assign* Value::asAssign() { assert(isAssign()); return static_cast<Assign*>(this); } +AssignName* Value::asAssignName() { + assert(isAssignName()); + return static_cast<AssignName*>(this); +} + void Value::stringify(std::ostream &os, bool pretty) { static int indent = 0; #define indentify() { for (int i_ = 0; i_ < indent; i_++) os << " "; } @@ -153,6 +164,13 @@ void Value::stringify(std::ostream &os, bool pretty) { os << "]"; break; } + case AssignName_: { + os << "[\"" << asAssignName()->target().str << "\""; + os << ", "; + asAssignName()->value()->stringify(os, pretty); + os << "]"; + break; + } } } diff --git a/src/emscripten-optimizer/simple_ast.h b/src/emscripten-optimizer/simple_ast.h index aa02dd8fc..efbd7b6f6 100644 --- a/src/emscripten-optimizer/simple_ast.h +++ b/src/emscripten-optimizer/simple_ast.h @@ -97,6 +97,7 @@ public: }; struct Assign; +struct AssignName; // Main value type struct Value { @@ -107,7 +108,8 @@ struct Value { Null = 3, Bool = 4, Object = 5, - Assign_ = 6 // ref = target + Assign_ = 6, // ref = target + AssignName_ = 7 }; Type type; @@ -203,6 +205,7 @@ struct Value { return *this; } Value& setAssign(Ref target, Ref value); + Value& setAssignName(IString target, Ref value); bool isString() { return type == String; } bool isNumber() { return type == Number; } @@ -211,6 +214,7 @@ struct Value { bool isBool() { return type == Bool; } bool isObject() { return type == Object; } bool isAssign() { return type == Assign_; } + bool isAssignName() { return type == AssignName_; } bool isBool(bool b) { return type == Bool && b == boo; } // avoid overloading == as it might overload over int @@ -244,6 +248,7 @@ struct Value { } Assign* asAssign(); + AssignName* asAssignName(); int32_t getInteger() { // convenience function to get a known integer assert(fmod(getNumber(), 1) == 0); @@ -496,6 +501,25 @@ struct Assign : public Value { } }; +struct AssignName : public Value { + IString target_; + + AssignName(IString targetInit, Ref valueInit) { + type = AssignName_; + target() = targetInit; + value() = valueInit; + } + + AssignName() : AssignName(IString(), nullptr) {} + + IString& target() { + return target_; + } + Ref& value() { + return ref; + } +}; + // AST traversals // Traverse, calling visit before the children @@ -791,7 +815,11 @@ public: static Ref makeBinary(Ref left, IString op, Ref right) { if (op == SET) { - return &arena.alloc<Assign>()->setAssign(left, right); + if (left->isString()) { + return &arena.alloc<AssignName>()->setAssignName(left->getIString(), right); + } else { + return &arena.alloc<Assign>()->setAssign(left, right); + } } else if (op == COMMA) { return &makeRawArray(3)->push_back(makeRawString(SEQ)) .push_back(left) @@ -968,13 +996,6 @@ public: .push_back(value)); } - static Ref makeAssign(Ref target, Ref value) { - return &arena.alloc<Assign>()->setAssign(target, value); - } - static Ref makeAssign(IString target, Ref value) { - return &arena.alloc<Assign>()->setAssign(makeName(target), value); - } - static Ref makeSub(Ref obj, Ref index) { return &makeRawArray(2)->push_back(makeRawString(SUB)) .push_back(obj) |