/*
 * Copyright 2024 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//
// TranslateToExnref translates the old Phase 3 EH instructions, which include
// try, catch, catch_all, delegate, and rethrow, into the new EH instructions,
// which include try_table (with catch / catch_ref / catch_all / catch_all_ref)
// and throw_ref, passed at the Oct 2023 CG meeting. This translator can be used
// as a standalone tool by users of the previous EH toolchain to generate
// binaries for the new spec without recompiling, and also can be used at the
// end of the Binaryen pipeline to produce binaries for the new spec while the
// end-to-end toolchain implementation for the new spec is in progress.
//

#include <ir/drop.h>
#include <ir/find_all.h>
#include <ir/label-utils.h>
#include <ir/utils.h>
#include <pass.h>
#include <wasm.h>

namespace wasm {

namespace {

// Translates the old EH instructions (try / catch / catch_all / delegate /
// rethrow) into the new ones (try_table (+ catch / catch_ref / catch_all /
// catch_all_ref) / throw_ref).
struct TranslateToExnref : public WalkerPass<PostWalker<TranslateToExnref>> {
  bool isFunctionParallel() override { return true; }

  // Scans and records which try labels are targeted by delegates and rethrows.
  struct TargetTryLabelScanner : public PostWalker<TargetTryLabelScanner> {
    TargetTryLabelScanner(Function* func) { walkFunction(func); }

    std::set<Name> delegateTargets;
    std::set<Name> rethrowTargets;
    bool isTargetedByDelegates(Try* curr) const {
      return delegateTargets.find(curr->name) != delegateTargets.end();
    }
    bool isTargetedByRethrows(Try* curr) const {
      return rethrowTargets.find(curr->name) != rethrowTargets.end();
    }

    void visitTry(Try* curr) {
      if (curr->isDelegate()) {
        delegateTargets.insert(curr->delegateTarget);
      }
    }

    void visitRethrow(Rethrow* curr) { rethrowTargets.insert(curr->target); }
  };

  // For each try label targeted by rethrows, assign a local that will contain
  // its exnref in the new spec (via try + catch(_all)_ref instruction), so that
  // every 'rethrow $somelabel' can later be translated into
  // 'throw_ref $somelocal'.
  //
  // In the examples below, try's (do) bodies are omitted for the sake of
  // simplicity.
  //
  // For example,
  // (try $l0
  //   (catch
  //     (try $l1
  //       (catch
  //         (rethrow $l0) ;; will become (throw_ref $local0)
  //       )
  //       (catch
  //         (rethrow $l1) ;; will become (throw_ref $local1)
  //       )
  //     )
  //   )
  // )
  // In this case, we need two locals for exnrefs, each for $l0 and $l1.
  //
  // Note that the number of locals required is the maximum depth of try-catch
  // nests, when only counting 'try's that are targeted by rethrows, which means
  // the pattern below only needs one extra local:
  // (try $l0
  //   (catch
  //     (rethrow $l0)
  //   )
  // )
  // (try $l1
  //   (catch
  //     (rethrow $l1)
  //   )
  // )
  // Because the two trys are not nested within each other, one local can be
  // reused in both trys.
  //
  // Also even if there is a try-catch nest with depth N, if only some of them
  // are targeted by rethrows, we only need that many extra locals for the whole
  // nest:
  // (try $l0
  //   (catch
  //     (try $l1
  //       (catch
  //         ...
  //         ...
  //         (try $lN
  //           (catch
  //             ;; If this is the only rethrow in this nest, we only need one
  //             ;; extra exnref local for all N try-catches
  //             (rethrow $l1)
  //           )
  //         )
  //         ...
  //         ...
  //       )
  //     )
  //   )
  // )
  struct ExnrefLocalAssigner : public PostWalker<ExnrefLocalAssigner> {
    TargetTryLabelScanner* labelScanner = nullptr;

    std::vector<Index> exnrefLocals;
    std::unordered_map<Name, Index> rethrowTargetToExnrefLocal;

    // Depth of the current try nest, when only counting trys targeted with
    // rethrows.
    size_t rethrowTryDepth = 0;

    ExnrefLocalAssigner(Function* func, TargetTryLabelScanner* labelScanner)
      : labelScanner(labelScanner) {
      walkFunction(func);
    }

    std::optional<Index> getExnrefLocal(Name rethrowTarget) const {
      auto it = rethrowTargetToExnrefLocal.find(rethrowTarget);
      if (it == rethrowTargetToExnrefLocal.end()) {
        return {};
      } else {
        return it->second;
      }
    }

    static void incrementRethrowTryDepth(ExnrefLocalAssigner* self,
                                         Expression** currp) {
      self->rethrowTryDepth++;
    }
    static void decrementRethrowTryDepth(ExnrefLocalAssigner* self,
                                         Expression** currp) {
      self->rethrowTryDepth--;
    }

    static void scan(ExnrefLocalAssigner* self, Expression** currp) {
      auto* curr = *currp;
      if (auto* tryy = curr->dynCast<Try>()) {
        if (self->labelScanner->isTargetedByRethrows(tryy)) {
          self->pushTask(decrementRethrowTryDepth, currp);
        }
      }
      PostWalker<ExnrefLocalAssigner>::scan(self, currp);
      if (auto* tryy = curr->dynCast<Try>()) {
        if (self->labelScanner->isTargetedByRethrows(tryy)) {
          self->pushTask(incrementRethrowTryDepth, currp);
        }
      }
    }

    void visitTry(Try* curr) {
      if (labelScanner->isTargetedByRethrows(curr)) {
        while (exnrefLocals.size() < rethrowTryDepth) {
          exnrefLocals.push_back(
            Builder::addVar(getFunction(), Type(HeapType::exn, Nullable)));
        }
        rethrowTargetToExnrefLocal[curr->name] =
          exnrefLocals[rethrowTryDepth - 1];
      }
    }
  };

  std::optional<LabelUtils::LabelManager> labels;
  std::optional<TargetTryLabelScanner> labelScanner;
  std::optional<ExnrefLocalAssigner> localAssigner;

  std::unordered_map<Name, Name> delegateTargetToTrampoline;
  // Scratch locals used to contain extracted values and (extracted values,
  // exnref) tuples for a short time.
  std::unordered_map<Type, Index> typeToScratchLocal;

  std::unique_ptr<Pass> create() override {
    return std::make_unique<TranslateToExnref>();
  }

  // Get a scratch local for a given type. These locals are used to contain
  // extracted value(s) and (extracted value(s), exnref) tuples for a short
  // time. Because these locals are written and read right after that, we can
  // reuse these for all extracted values and (extracted values, exnref) tuples
  // as long as the type matches.
  Index getScratchLocal(Type type) {
    auto [it, inserted] = typeToScratchLocal.insert({type, 0});
    if (inserted) {
      it->second = Builder::addVar(getFunction(), type);
    }
    return it->second;
  }

  // Process try labels targeted by rethrows. This does NOT transform the
  // current 'try' into 'try_table' yet; it only adds block, br, and throw_ref
  // instructions to complete the conversions of inner try~delegates that target
  // the current try.
  void processDelegateTarget(Try* curr,
                             Block* outerBlock,
                             bool& outerBlockUsedSoFar) {
    Builder builder(*getModule());

    // Convert
    //
    // (try $delegate_target (result sometype)
    //   (do
    //     ...
    //     ;; This had originally been an inner try~delegate and has been
    //     ;; already translated to try_table at this point. See
    //     ;; processDelegate() for how it is done.
    //     (try_table (catch_all_ref $delegate_trampoline)
    //       ...
    //     )
    //     ...
    //   (catch
    //     ...
    //   )
    // )
    //
    // to =>
    //
    // If sometype (try's type) is none:
    // (block $outer (result sometype)
    //   (try (result sometype)
    //     (do
    //       (throw_ref
    //         (block $delegate_trampoline (result exnref)
    //           ...
    //           (try_table (catch_all_ref $delegate_trampoline)
    //             ...
    //           )
    //           ...
    //           (br $outer)
    //         )
    //       )
    //     )
    //     (catch
    //       ...
    //     )
    //   )
    // )
    //
    // If sometype (try's type) is concrete:
    // (block $outer (result sometype)
    //   (try (result sometype)
    //     (do
    //       (throw_ref
    //         (block $delegate_trampoline (result exnref)
    //           (br $outer ;; Now has the try_table as a child.
    //             ...
    //             (try_table (catch_all_ref $delegate_trampoline)
    //               ...
    //             )
    //             ...
    //           )
    //         )
    //       )
    //     )
    //     (catch
    //       ...
    //     )
    //   )
    // )
    //
    // Note that the current try-catch (or try-delegate) stays as is for now; it
    // will be converted to a try_table later in processDelegate() and
    // processCatches().
    //
    // Also note that even in case there are multiple inner try~delegates
    // targeting this try, we need to do this only once per try target. Those
    // multiple try~delegates that used to target the same delegate target now
    // jump to the same $delegate_trampoline using catch_all_ref.
    Name delegateTrampoline = delegateTargetToTrampoline[curr->name];
    Expression* innerBody = nullptr;
    if (curr->type.isConcrete()) {
      outerBlockUsedSoFar = true;
      auto* brToOuter = builder.makeBreak(outerBlock->name, curr->body);
      innerBody = builder.blockifyWithName(
        brToOuter, delegateTrampoline, nullptr, Type(HeapType::exn, Nullable));
    } else {
      outerBlockUsedSoFar = curr->body->type != Type::unreachable;
      auto* brToOuter = curr->body->type == Type::unreachable
                          ? nullptr
                          : builder.makeBreak(outerBlock->name);
      innerBody = builder.blockifyWithName(curr->body,
                                           delegateTrampoline,
                                           brToOuter,
                                           Type(HeapType::exn, Nullable));
    }
    curr->body = builder.makeThrowRef(innerBody);
  }

  void processDelegate(Try* curr, Block* outerBlock, bool outerBlockUsedSoFar) {
    Builder builder(*getModule());
    // Convert
    // (try
    //   (do
    //     ...
    //   )
    //   (delegate $delegate_target)
    // )
    //
    // to =>
    //
    // (try_table (catch_ref $delegate_trampoline)
    //   ...
    // )
    //
    // $delegate_trampoline is a block label that will be created in
    // processDelegateTarget(), when we process the 'try' that is the target of
    // this try~delegate. See processDelegateTarget() for how the rest of the
    // conversion is completed.
    auto* tryTable =
      builder.makeTryTable(curr->body,
                           {Name()},
                           {delegateTargetToTrampoline[curr->delegateTarget]},
                           {true});
    // If we need an outer block for other reasons (if this is a target of a
    // delegate), we insert the new try_table into it. If not we just replace
    // the current try with the new try_table.
    if (outerBlock && outerBlockUsedSoFar) {
      outerBlock->list.push_back(tryTable);
      replaceCurrent(outerBlock);
    } else {
      replaceCurrent(tryTable);
    }
  }

  void processCatches(Try* curr, Block* outerBlock, bool outerBlockUsedSoFar) {
    Module* wasm = getModule();
    Builder builder(*wasm);

    // Determine whether a given catch body should be translated to
    // catch/catch_all vs. catch_ref/catch_all_ref.
    auto shouldBeRef = [&](Expression* catchBody) -> bool {
      // If this try is targeted by rethrows and those rethrows exist in the
      // current catch body, we need to use catch_ref/catch_all_ref. By this
      // point, all rethrows in the catch bodies have been already converted to
      // throw_refs, so we check the local numbers to see if those (original)
      // rethrows used to target the current try label.
      std::optional<Index> local = localAssigner->getExnrefLocal(curr->name);
      if (local) {
        for (auto* throwRef : FindAll<ThrowRef>(catchBody).list) {
          // All rethrows within this catch body have already been converted to
          // throw_refs, which contains a local.get as its child.(See
          // visitRethrow() for details).
          if (auto* localGet = throwRef->exnref->dynCast<LocalGet>()) {
            if (localGet->index == *local) {
              return true;
            }
          }
        }
      }
      return false;
    };

    // Create try_table instruction with catch clauses.
    std::vector<Name> catchTags;
    std::vector<Name> catchDests;
    std::vector<bool> catchRefs;
    for (Index i = 0; i < curr->catchTags.size(); i++) {
      catchTags.push_back(curr->catchTags[i]);
      catchDests.push_back(labels->getUnique("catch"));
      catchRefs.push_back(shouldBeRef(curr->catchBodies[i]));
    }
    if (curr->hasCatchAll()) {
      catchTags.push_back(Name());
      catchDests.push_back(labels->getUnique("catch_all"));
      catchRefs.push_back(shouldBeRef(curr->catchBodies.back()));
    }
    auto* tryTable = builder.makeTryTable(
      curr->body, catchTags, catchDests, catchRefs, curr->type);

    // If we don't have any catches, we don't need to do more.
    if (curr->catchBodies.empty()) { // catch-less try
      // If we need an outer block for other reasons (if this is a target of a
      // delegate), we insert the new try_table into it. If not we just replace
      // the current try with the new try_table.
      if (outerBlock && outerBlockUsedSoFar) {
        outerBlock->list.push_back(tryTable);
        replaceCurrent(outerBlock);
      } else {
        replaceCurrent(tryTable);
      }
      return;
    }

    // Now we convert catch bodies.
    //
    // For simplicity, let's assume all tags have the none type and there are no
    // rethrows (which have converted to throw_refs at this point) and the try's
    // type is none as well. Then
    //
    // (try
    //   (catch $e
    //     (catch_body)
    //   )
    //   (catch_all
    //     (catch_all_body)
    //   )
    // )
    //
    // becomes
    //
    // (block $outer
    //   (block $catch_all
    //     (block $catch
    //       (try_table (catch $e $catch) (catch_all $catch_all)
    //         ...
    //       )
    //       (br $outer)
    //     )
    //     (catch_body)
    //     (br $outer)
    //   )
    //   (catch_all_body) ;; We don't need (br $outer) for the last catch
    // )
    //
    // Here (block $outer) has been already created and given as an argument to
    // this function. This is the outer block that will contain the whole
    // structure.
    //
    // If there are more catch clauses, there will be more layers of blocks,
    // catch bodies, and (br $outer)s.
    //
    // If try's type is concrete, (br $outer)s will contain try_table and catch
    // bodies as values:
    //
    // (block $outer
    //   (block $catch_all
    //     (block $catch
    //       (br $outer
    //         (try_table (result sometype)
    //                    (catch $e $catch) (catch_all $catch_all)
    //           ...
    //         )
    //       )
    //     )
    //     (br $outer
    //       (catch_body)
    //     )
    //   )
    //   (catch_all_body) ;; We don't need (br $outer) for the last catch
    // )
    //
    // ---
    //
    // When a tag has a concrete type, we assign it to a scratch local of that
    // type, and (pop tagtype) would have been already converted to
    // (local.get $scratch) in visitPop(). These scratch locals have extremely
    // short lifetimes; basically they are read right after they are written, so
    // we can reuse them throughout the function.
    //
    // So, when there is no rethrows (throw_refs), and if we assume that try's
    // type is none for simplicity,
    // (try
    //   ...
    //   (catch $e-i32 ;; concrete type
    //     (use_inst
    //       (pop i32)
    //     )
    //   )
    // )
    //
    // becomes
    // (block $outer
    //   (local.set $scratch-i32
    //     (block $catch (result tagtype)
    //       (try_table (catch $e-i32 $catch)
    //         ...
    //       )
    //       (br $outer)
    //     )
    //   )
    //   (use_inst
    //     (local.get $scratch-i32)
    //   )
    // )
    //
    // When the tag type is none or it is a catch_all, but there are rethrows
    // (throws_refs at this point) within the catch body that targets this try's
    // label, we use catch_ref (or catch_all_ref in case of catch_all), and
    // assign the block return value to a exnref local. rethrows would have been
    // converted to (local.get $exn) in visitRethrow() already. Unlike scratch
    // locals used for pops, exnref locals can have longer lifetimes and are
    // assigned in ExnrefLocalAssigner. So for example,
    // (try $l0
    //   ...
    //   (catch_all
    //     (rethrow $l0)
    //   )
    // )
    //
    // becomes
    //
    // (block $outer
    //   (local.set $exn
    //     (block $catch_all (result exnref)
    //       (try_table (catch_all_ref $catch_all)
    //         ...
    //       )
    //       (br $outer)
    //     )
    //   )
    //   (throw_ref
    //     (local.get $exn)
    //   )
    // )
    //
    // When the tag type is concrete and also there are rethrows within the
    // catch body that target this try's label, (extracted values, exnref)
    // is saved in a tuple local matching its tuple type, and tuple.extract
    // instructions are added to extract each of them and set them to a scratch
    // local for a later pop and exnref local for later throw_ref.
    //
    // (try $l0
    //   ...
    //   (catch $e-i32 ;; concrete type
    //     (use_inst
    //       (pop i32)
    //     )
    //     (rethrow $l0)
    //   )
    // )
    //
    // becomes
    //
    // (block $outer
    //   (local.set $tuple
    //     (block $catch (result i32 exnref)
    //       (try_table (catch_ref $e-i32 $catch)
    //         ...
    //       )
    //       (br $outer)
    //     )
    //   )
    //   (local.set $scratch-i32
    //     (tuple.extract 2 0
    //       (local.get $tuple)
    //     )
    //   )
    //   (local.set $exn
    //     (tuple.extract 2 1
    //       (local.get $tuple)
    //     )
    //   )
    //   (block
    //     (use_inst
    //       (local.get $scratch-i32)
    //     )
    //     (throw_ref
    //       (local.get $exn)
    //     )
    //   )
    // )
    //
    // The transformation is similar when the tag type itself is a tuple and
    // there are rethrows. We store the whole (tag types, exnref) in a tuple
    // scratch local, and tuple.extract 1~(n-1)th elements and set them in
    // another scratch local and nth element in an exnref local.

    // Make the body for the innermost block
    std::vector<Expression*> items;
    if (tryTable->type.isConcrete()) {
      items.push_back(builder.makeBreak(outerBlock->name, tryTable));
    } else {
      items.push_back(tryTable);
      if (tryTable->type != Type::unreachable) {
        items.push_back(builder.makeBreak(outerBlock->name));
      }
    }

    // Convert each catch body to a wrapping block + catch body + br
    for (Index i = 0; i < tryTable->catchTags.size(); i++) {
      Type sentType = tryTable->sentTypes[i];
      auto* catchBody = curr->catchBodies[i];
      Type tagType = Type::none;
      if (tryTable->catchTags[i]) {
        tagType = wasm->getTag(tryTable->catchTags[i])->params();
      }

      // This is to be the body of the next(outer) level block
      std::vector<Expression*> nextItems;

      auto* block = builder.makeBlock(tryTable->catchDests[i], items, sentType);

      if (tryTable->catchRefs[i]) {
        // When we use the exnref (i.e., there are throw_refs in the catch body)
        Index exnrefLocal = *localAssigner->getExnrefLocal(curr->name);
        if (tagType.isConcrete()) {
          // If the tag type is single and we use the exnref, the block
          // returns (tagtype, exnref). Get a scratch local to contain this
          // tuple and reassign its elements to a pop scratch local and this
          // try's corresponding exnref local respectively.
          //
          // If the tag type is a tuple and we use the exnref, the block returns
          // (tagtype0, ..., tagtypeN, exnref). Assign (tagtype0, ..., tagtypeN)
          // to a scratch (tuple) local and the exnref to this try's
          // corresponding exnref local respectively.
          Index allLocal = getScratchLocal(sentType);
          Index popLocal = getScratchLocal(tagType);
          auto* allLocalSet = builder.makeLocalSet(allLocal, block);
          nextItems.push_back(allLocalSet);
          Expression* popLocalSet = nullptr;
          if (tagType.isTuple()) {
            std::vector<Expression*> popVals;
            for (Index j = 0; j < tagType.size(); j++) {
              popVals.push_back(builder.makeTupleExtract(
                builder.makeLocalGet(allLocal, sentType), j));
            }
            popLocalSet =
              builder.makeLocalSet(popLocal, builder.makeTupleMake(popVals));
          } else {
            popLocalSet = builder.makeLocalSet(
              popLocal,
              builder.makeTupleExtract(builder.makeLocalGet(allLocal, sentType),
                                       0));
          }
          nextItems.push_back(popLocalSet);
          auto* exnrefLocalSet = builder.makeLocalSet(
            exnrefLocal,
            builder.makeTupleExtract(builder.makeLocalGet(allLocal, sentType),
                                     sentType.size() - 1));
          nextItems.push_back(exnrefLocalSet);
        } else {
          // If the tag type is none and we use the exnref, the block only
          // returns exnref. Assign in to this try's corresponding exnref local.
          auto* exnrefLocalSet = builder.makeLocalSet(exnrefLocal, block);
          nextItems.push_back(exnrefLocalSet);
        }
      } else {
        // When we don't use exnref and the tag type is concrete, we get a
        // scratch local of the tag type and assign the block return value to
        // that local. This process is the same for single and tuple tag types.
        // If the tag type is none, we don't need to use any locals.
        if (tagType.isConcrete()) {
          Index popLocal = getScratchLocal(tagType);
          auto* popLocalSet = builder.makeLocalSet(popLocal, block);
          nextItems.push_back(popLocalSet);
        } else {
          nextItems.push_back(block);
        }
      }

      if (catchBody->type.isConcrete()) {
        // If this is the last catch body, we can omit the br and fall through
        if (i < tryTable->catchTags.size() - 1) {
          nextItems.push_back(builder.makeBreak(outerBlock->name, catchBody));
        } else {
          nextItems.push_back(catchBody);
        }
      } else {
        nextItems.push_back(catchBody);
        // If this is the last catch body, we can omit the br and fall through
        if (i < tryTable->catchTags.size() - 1 &&
            catchBody->type != Type::unreachable) {
          nextItems.push_back(builder.makeBreak(outerBlock->name));
        }
      }
      items.swap(nextItems);
    }

    for (auto* item : items) {
      outerBlock->list.push_back(item);
    }
    replaceCurrent(outerBlock);
  }

  void visitTry(Try* curr) {
    Builder builder(*getModule());
    Block* outerBlock = nullptr;
    auto it = delegateTargetToTrampoline.find(curr->name);
    if (it != delegateTargetToTrampoline.end() || curr->isCatch()) {
      outerBlock =
        builder.makeBlock(labels->getUnique("outer"), {}, curr->type);
    }

    bool outerBlockUsedSoFar = false;
    if (it != delegateTargetToTrampoline.end()) {
      processDelegateTarget(curr, outerBlock, outerBlockUsedSoFar);
    }
    if (curr->isDelegate()) {
      processDelegate(curr, outerBlock, outerBlockUsedSoFar);
    } else { // try-catch or catch-less try
      processCatches(curr, outerBlock, outerBlockUsedSoFar);
    }
  }

  void visitPop(Pop* curr) {
    // We can assume a 'pop' value is always in a scratch local that matches
    // its type, because these locals are read right after being written and can
    // be reused for all pops. This applies to tuple type pops as well.
    Builder builder(*getModule());
    Index popLocal = getScratchLocal(curr->type);
    replaceCurrent(builder.makeLocalGet(popLocal, curr->type));
  }

  void visitRethrow(Rethrow* curr) {
    // After we assigned an exnref local for each try label targeted by
    // rethrows, we can assume the exnref we want to rethrow is located in that
    // exnref local at this point. We ensure this to happen when converting the
    // corresponding 'try' to 'try_table' by using catch_ref/catch_all_ref and
    // assining the exnref to that local.
    Builder builder(*getModule());
    Index exnrefLocal = *localAssigner->getExnrefLocal(curr->target);
    replaceCurrent(builder.makeThrowRef(
      builder.makeLocalGet(exnrefLocal, Type(HeapType::exn, Nullable))));
  }

  // Similar to processDelegateTarget(), but does it for the caller delegate
  // target, which means we should rethrow to the caller.
  void processCallerDelegateTarget() {
    Name callerDelegateTrampoline =
      delegateTargetToTrampoline[DELEGATE_CALLER_TARGET];
    Builder builder(*getModule());
    Function* func = getFunction();

    // The transformation is similar to that of normal delegate targets, but
    // instead of branching to an outer label in case no exception is thrown, we
    // just return.
    //
    // Convert
    //
    // (func $test (result sometype)
    //   ...
    //   (try_table (catch_all_ref $caller_delegate_trampoline)
    //     ...
    //   )
    //   ...
    // )
    //
    // to =>
    //
    // If sometype (func's type) is none:
    // (func $test (result sometype)
    //   (throw_ref
    //     (block $caller_delegate_trampoline (result exnref)
    //       ...
    //       (try_table (catch_all_ref $caller_delegate_trampoline)
    //         ...
    //       )
    //       ...
    //       (return)
    //     )
    //   )
    // )
    //
    // If sometype (func's type) is concrete:
    //   (throw_ref
    //     (block $caller_delegate_trampoline (result exnref)
    //       (return
    //         ...
    //         (try_table (catch_all_ref $caller_delegate_trampoline)
    //           ...
    //         )
    //         ...
    //       )
    //     )
    //   )
    // )
    Expression* innerBody = nullptr;
    if (func->getResults().isConcrete()) {
      auto* ret = builder.makeReturn(func->body);
      innerBody = builder.blockifyWithName(
        ret, callerDelegateTrampoline, nullptr, Type(HeapType::exn, Nullable));
    } else {
      auto* ret = builder.makeReturn();
      innerBody = builder.blockifyWithName(func->body,
                                           callerDelegateTrampoline,
                                           ret,
                                           Type(HeapType::exn, Nullable));
    }
    func->body = builder.makeThrowRef(innerBody);
  }

  void doWalkFunction(Function* func) {
    labels = std::make_optional<LabelUtils::LabelManager>(func);
    labelScanner = std::make_optional<TargetTryLabelScanner>(func);
    localAssigner =
      std::make_optional<ExnrefLocalAssigner>(func, &labelScanner.value());

    // Create a unique br target label for each existing delegate target label,
    // because we are going to achieve 'delegate's effects with 'br's. See
    // processDelegateTarget() for details.
    for (auto& target : labelScanner->delegateTargets) {
      delegateTargetToTrampoline[target] = labels->getUnique(target.toString());
    }

    Super::doWalkFunction(func);

    // Similar to processDelegateTarget(), but for the caller target.
    if (delegateTargetToTrampoline.find(DELEGATE_CALLER_TARGET) !=
        delegateTargetToTrampoline.end()) {
      processCallerDelegateTarget();
    }
  }
};

} // namespace

Pass* createTranslateToExnrefPass() { return new TranslateToExnref(); }

} // namespace wasm
