summaryrefslogtreecommitdiff
path: root/src/wasm-ir-builder.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm-ir-builder.h')
-rw-r--r--src/wasm-ir-builder.h80
1 files changed, 76 insertions, 4 deletions
diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h
index e7613b373..ee6721738 100644
--- a/src/wasm-ir-builder.h
+++ b/src/wasm-ir-builder.h
@@ -64,13 +64,21 @@ public:
[[nodiscard]] Result<> visitIfStart(If* iff, Name label = {});
[[nodiscard]] Result<> visitElse();
[[nodiscard]] Result<> visitLoopStart(Loop* iff);
+ [[nodiscard]] Result<> visitTryStart(Try* tryy, Name label = {});
+ [[nodiscard]] Result<> visitCatch(Name tag);
+ [[nodiscard]] Result<> visitCatchAll();
+ [[nodiscard]] Result<> visitDelegate(Index label);
[[nodiscard]] Result<> visitEnd();
// Binaryen IR uses names to refer to branch targets, but in general there may
// be branches to constructs that do not yet have names, so in IRBuilder we
// use indices to refer to branch targets instead, just as the binary format
// does. This function converts a branch target name to the correct index.
- [[nodiscard]] Result<Index> getLabelIndex(Name label);
+ //
+ // Labels in delegates need special handling because the indexing needs to be
+ // relative to the try's enclosing scope rather than the try itself.
+ [[nodiscard]] Result<Index> getLabelIndex(Name label,
+ bool inDelegate = false);
// Instead of calling visit, call makeXYZ to have the IRBuilder allocate the
// nodes. This is generally safer than calling `visit` because the function
@@ -145,7 +153,7 @@ public:
// [[nodiscard]] Result<> makeTableGrow();
// [[nodiscard]] Result<> makeTableFill();
// [[nodiscard]] Result<> makeTableCopy();
- // [[nodiscard]] Result<> makeTry();
+ [[nodiscard]] Result<> makeTry(Name label, Type type);
[[nodiscard]] Result<> makeThrow(Name tag);
// [[nodiscard]] Result<> makeRethrow();
// [[nodiscard]] Result<> makeTupleMake();
@@ -232,8 +240,27 @@ private:
struct LoopScope {
Loop* loop;
};
- using Scope = std::
- variant<NoScope, FuncScope, BlockScope, IfScope, ElseScope, LoopScope>;
+ struct TryScope {
+ Try* tryy;
+ Name originalLabel;
+ };
+ struct CatchScope {
+ Try* tryy;
+ Name originalLabel;
+ };
+ struct CatchAllScope {
+ Try* tryy;
+ Name originalLabel;
+ };
+ using Scope = std::variant<NoScope,
+ FuncScope,
+ BlockScope,
+ IfScope,
+ ElseScope,
+ LoopScope,
+ TryScope,
+ CatchScope,
+ CatchAllScope>;
// The control flow structure we are building expressions for.
Scope scope;
@@ -264,6 +291,15 @@ private:
return ScopeCtx(ElseScope{iff, originalLabel}, label);
}
static ScopeCtx makeLoop(Loop* loop) { return ScopeCtx(LoopScope{loop}); }
+ static ScopeCtx makeTry(Try* tryy, Name originalLabel = {}) {
+ return ScopeCtx(TryScope{tryy, originalLabel});
+ }
+ static ScopeCtx makeCatch(Try* tryy, Name originalLabel, Name label) {
+ return ScopeCtx(CatchScope{tryy, originalLabel}, label);
+ }
+ static ScopeCtx makeCatchAll(Try* tryy, Name originalLabel, Name label) {
+ return ScopeCtx(CatchAllScope{tryy, originalLabel}, label);
+ }
bool isNone() { return std::get_if<NoScope>(&scope); }
Function* getFunction() {
@@ -296,6 +332,24 @@ private:
}
return nullptr;
}
+ Try* getTry() {
+ if (auto* tryScope = std::get_if<TryScope>(&scope)) {
+ return tryScope->tryy;
+ }
+ return nullptr;
+ }
+ Try* getCatch() {
+ if (auto* catchScope = std::get_if<CatchScope>(&scope)) {
+ return catchScope->tryy;
+ }
+ return nullptr;
+ }
+ Try* getCatchAll() {
+ if (auto* catchAllScope = std::get_if<CatchAllScope>(&scope)) {
+ return catchAllScope->tryy;
+ }
+ return nullptr;
+ }
Type getResultType() {
if (auto* func = getFunction()) {
return func->type.getSignature().results;
@@ -312,6 +366,15 @@ private:
if (auto* loop = getLoop()) {
return loop->type;
}
+ if (auto* tryy = getTry()) {
+ return tryy->type;
+ }
+ if (auto* tryy = getCatch()) {
+ return tryy->type;
+ }
+ if (auto* tryy = getCatchAll()) {
+ return tryy->type;
+ }
WASM_UNREACHABLE("unexpected scope kind");
}
Name getOriginalLabel() {
@@ -330,6 +393,15 @@ private:
if (auto* loop = getLoop()) {
return loop->name;
}
+ if (auto* tryScope = std::get_if<TryScope>(&scope)) {
+ return tryScope->originalLabel;
+ }
+ if (auto* catchScope = std::get_if<CatchScope>(&scope)) {
+ return catchScope->originalLabel;
+ }
+ if (auto* catchAllScope = std::get_if<CatchAllScope>(&scope)) {
+ return catchAllScope->originalLabel;
+ }
WASM_UNREACHABLE("unexpected scope kind");
}
};