summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm.h104
-rw-r--r--src/emscripten-optimizer/simple_ast.cpp18
-rw-r--r--src/emscripten-optimizer/simple_ast.h39
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)