summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/wasm-interpreter.h10
-rw-r--r--src/wasm-js.cpp6
-rw-r--r--src/wasm-s-parser.h13
-rw-r--r--src/wasm-validator.h22
-rw-r--r--src/wasm.h7
5 files changed, 42 insertions, 16 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 3f9427ed7..73a536903 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -233,17 +233,17 @@ private:
Flow visitBreak(Break *curr) {
NOTE_ENTER("Break");
bool condition = true;
- if (curr->condition) {
- Flow flow = visit(curr->condition);
- if (flow.breaking()) return flow;
- condition = flow.value.getInteger();
- }
Flow flow(curr->name);
if (curr->value) {
flow = visit(curr->value);
if (flow.breaking()) return flow;
flow.breakTo = curr->name;
}
+ if (curr->condition) {
+ Flow conditionFlow = visit(curr->condition);
+ if (conditionFlow.breaking()) return conditionFlow;
+ condition = conditionFlow.value.getInteger();
+ }
return condition ? flow : Flow();
}
Flow visitSwitch(Switch *curr) {
diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp
index 067e3fdea..82a74d2ab 100644
--- a/src/wasm-js.cpp
+++ b/src/wasm-js.cpp
@@ -311,8 +311,8 @@ extern "C" void EMSCRIPTEN_KEEPALIVE call_from_js(const char *target) {
if (wasmJSDebug) std::cout << "call_from_js returning " << ret << '\n';
if (ret.type == none) EM_ASM({ Module['tempReturn'] = undefined });
- else if (ret.type == i32) EM_ASM_({ Module['tempReturn'] = $0 }, ret.i32);
- else if (ret.type == f32) EM_ASM_({ Module['tempReturn'] = $0 }, ret.f32);
- else if (ret.type == f64) EM_ASM_({ Module['tempReturn'] = $0 }, ret.f64);
+ else if (ret.type == i32) EM_ASM_({ Module['tempReturn'] = $0 }, ret.geti32());
+ else if (ret.type == f32) EM_ASM_({ Module['tempReturn'] = $0 }, ret.getf32());
+ else if (ret.type == f64) EM_ASM_({ Module['tempReturn'] = $0 }, ret.getf64());
else abort();
}
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index dc946fc3b..ce216fd8e 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -868,10 +868,6 @@ private:
Expression* makeBreak(Element& s) {
auto ret = allocator.alloc<Break>();
size_t i = 1;
- if (s[0]->str() == BR_IF) {
- ret->condition = parseExpression(s[i]);
- i++;
- }
if (s[i]->dollared()) {
ret->name = s[i]->str();
} else {
@@ -881,7 +877,14 @@ private:
ret->name = labelStack[labelStack.size() - 1 - offset];
}
i++;
- if (i < s.size()) {
+ if (i == s.size()) return ret;
+ if (s[0]->str() == BR_IF) {
+ if (i + 1 < s.size()) {
+ ret->value = parseExpression(s[i]);
+ i++;
+ }
+ ret->condition = parseExpression(s[i]);
+ } else {
ret->value = parseExpression(s[i]);
}
return ret;
diff --git a/src/wasm-validator.h b/src/wasm-validator.h
index ba4e5fe08..fad33a081 100644
--- a/src/wasm-validator.h
+++ b/src/wasm-validator.h
@@ -28,6 +28,8 @@ namespace wasm {
struct WasmValidator : public WasmWalker<WasmValidator> {
bool valid;
+ std::map<Name, WasmType> breakTypes; // breaks to a label must all have the same type, and the right type
+
public:
bool validate(Module& module) {
valid = true;
@@ -37,6 +39,15 @@ public:
// visitors
+ void visitBlock(Block *curr) {
+ // if we are break'ed to, then the value must be right for us
+ if (curr->name.is()) {
+ if (breakTypes.count(curr->name) > 0) {
+ shouldBeTrue(curr->type == breakTypes[curr->name]);
+ breakTypes.erase(curr->name);
+ }
+ }
+ }
void visitLoop(Loop *curr) {
if (curr->in.is()) {
LoopChildChecker childChecker(curr->in);
@@ -44,6 +55,17 @@ public:
shouldBeTrue(childChecker.valid);
}
}
+ void visitBreak(Break *curr) {
+ WasmType valueType = none;
+ if (curr->value) {
+ valueType = curr->value->type;
+ }
+ if (breakTypes.count(curr->name) == 0) {
+ breakTypes[curr->name] = valueType;
+ } else {
+ shouldBeTrue(valueType == breakTypes[curr->name]);
+ }
+ }
void visitSetLocal(SetLocal *curr) {
shouldBeTrue(curr->type == curr->value->type);
}
diff --git a/src/wasm.h b/src/wasm.h
index 893c777c4..20a7b34ef 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -511,10 +511,8 @@ public:
std::ostream& doPrint(std::ostream &o, unsigned indent) {
if (condition) {
- printOpening(o, "br_if");
+ printOpening(o, "br_if ") << name;
incIndent(o, indent);
- printFullLine(o, indent, condition);
- doIndent(o, indent) << name << '\n';
} else {
printOpening(o, "br ") << name;
if (!value || value->is<Nop>()) {
@@ -525,6 +523,9 @@ public:
incIndent(o, indent);
}
if (value && !value->is<Nop>()) printFullLine(o, indent, value);
+ if (condition) {
+ printFullLine(o, indent, condition);
+ }
return decIndent(o, indent);
}
};