diff options
Diffstat (limited to 'src/wasm-interpreter.h')
-rw-r--r-- | src/wasm-interpreter.h | 78 |
1 files changed, 55 insertions, 23 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 86d868ac8..94230b747 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1500,17 +1500,25 @@ public: } Flow visitBrOn(BrOn* curr) { NOTE_ENTER("BrOn"); - // BrOnCast uses the casting infrastructure, so handle it first. - if (curr->op == BrOnCast) { + // BrOnCast* uses the casting infrastructure, so handle it first. + if (curr->op == BrOnCast || curr->op == BrOnCastFail) { auto cast = doCast(curr); if (cast.outcome == cast.Break) { return cast.breaking; } if (cast.outcome == cast.Null || cast.outcome == cast.Failure) { - return cast.originalRef; + if (curr->op == BrOnCast) { + return cast.originalRef; + } else { + return Flow(curr->name, cast.originalRef); + } } assert(cast.outcome == cast.Success); - return Flow(curr->name, cast.castRef); + if (curr->op == BrOnCast) { + return Flow(curr->name, cast.castRef); + } else { + return cast.castRef; + } } // The others do a simpler check for the type. Flow flow = visit(curr->ref); @@ -1528,30 +1536,54 @@ public: // If the branch is not taken, we return the non-null value. return {value}; } + if (curr->op == BrOnNonNull) { + // Unlike the others, BrOnNonNull does not return a value if it does not + // take the branch. + if (value.isNull()) { + return Flow(); + } + // If the branch is taken, we send the non-null value. + return Flow(curr->name, value); + } + // See if the input is the right kind (ignoring the flipping behavior of + // BrOn*). + bool isRightKind; if (value.isNull()) { - return {value}; + // A null is never the right kind. + isRightKind = false; + } else { + switch (curr->op) { + case BrOnNonFunc: + case BrOnFunc: + isRightKind = value.type.isFunction(); + break; + case BrOnNonData: + case BrOnData: + isRightKind = value.isData(); + break; + case BrOnNonI31: + case BrOnI31: + isRightKind = value.type.getHeapType() == HeapType::i31; + break; + default: + WASM_UNREACHABLE("invalid br_on_*"); + } } + // The Non* operations require us to flip the normal behavior. switch (curr->op) { - case BrOnFunc: - if (!value.type.isFunction()) { - return {value}; - } - break; - case BrOnData: - if (!value.isData()) { - return {value}; - } + case BrOnNonFunc: + case BrOnNonData: + case BrOnNonI31: + isRightKind = !isRightKind; break; - case BrOnI31: - if (value.type.getHeapType() != HeapType::i31) { - return {value}; - } - break; - default: - WASM_UNREACHABLE("invalid br_on_*"); + default: { + } + } + if (isRightKind) { + // Take the branch. + return Flow(curr->name, value); } - // No problems: take the branch. - return Flow(curr->name, value); + return {value}; } Flow visitRttCanon(RttCanon* curr) { return Literal(curr->type); } Flow visitRttSub(RttSub* curr) { |