std::pair<Function *, Function *> ESTreeIRGen::doLazyFunction(
    hbc::LazyCompilationData *lazyData) {
  // Create a top level function that will never be executed, because:
  // 1. IRGen assumes the first function always has global scope
  // 2. It serves as the root for dummy functions for lexical data
  Function *topLevel = Builder.createTopLevelFunction(lazyData->strictMode, {});

  FunctionContext topLevelFunctionContext{this, topLevel, nullptr};

  // Save the top-level context, but ensure it doesn't outlive what it is
  // pointing to.
  llvh::SaveAndRestore<FunctionContext *> saveTopLevelContext(
      topLevelContext, &topLevelFunctionContext);

  auto *node = cast<ESTree::FunctionLikeNode>(Root);

  // We restore scoping information in two separate ways:
  // 1. By adding them to ExternalScopes for resolution here
  // 2. By adding dummy functions for lexical scoping debug info later
  //
  // Instruction selection determines the delta between the ExternalScope
  // and the dummy function chain, so we add the ExternalScopes with
  // positive depth.
  lexicalScopeChain = lazyData->parentScope;
  materializeScopesInChain(
      topLevel, lexicalScopeChain, getDepth(lexicalScopeChain) - 1);

  // If lazyData->closureAlias is specified, we must create an alias binding
  // between originalName (which must be valid) and the variable identified by
  // closureAlias.
  Variable *parentVar = nullptr;
  if (lazyData->closureAlias.isValid()) {
    assert(lazyData->originalName.isValid() && "Original name invalid");
    assert(
        lazyData->originalName != lazyData->closureAlias &&
        "Original name must be different from the alias");

    // NOTE: the closureAlias target must exist and must be a Variable.
    parentVar = cast<Variable>(nameTable_.lookup(lazyData->closureAlias));

    // Re-create the alias.
    nameTable_.insert(lazyData->originalName, parentVar);
  }

  assert(
      !llvh::isa<ESTree::ArrowFunctionExpressionNode>(node) &&
      "lazy compilation not supported for arrow functions");

  auto *func = genES5Function(
      lazyData->originalName,
      parentVar,
      node,
      lazyData->isGeneratorInnerFunction);
  addLexicalDebugInfo(func, topLevel, lexicalScopeChain);
  return {func, topLevel};
}
std::pair<Function *, Function *> ESTreeIRGen::doLazyFunction(
    hbc::LazyCompilationData *lazyData) {
   
   
   
  Function *topLevel = Builder.createTopLevelFunction(lazyData->strictMode, {});

  FunctionContext topLevelFunctionContext{this, topLevel, nullptr};

   
   
  llvh::SaveAndRestore<FunctionContext *> saveTopLevelContext(
      topLevelContext, &topLevelFunctionContext);

  auto *node = cast<ESTree::FunctionLikeNode>(Root);

   
   
   
   
   
   
   
  lexicalScopeChain = lazyData->parentScope;
  materializeScopesInChain(
      topLevel, lexicalScopeChain, getDepth(lexicalScopeChain) - 1);

   
   
   
  Variable *parentVar = nullptr;
  if (lazyData->closureAlias.isValid()) {
    assert(lazyData->originalName.isValid() && "Original name invalid");
    assert(
        lazyData->originalName != lazyData->closureAlias &&
        "Original name must be different from the alias");

     
    parentVar = cast<Variable>(nameTable_.lookup(lazyData->closureAlias));

     
    nameTable_.insert(lazyData->originalName, parentVar);
  }

  assert(
      !llvh::isa<ESTree::ArrowFunctionExpressionNode>(node) &&
      "lazy compilation not supported for arrow functions");

  auto *func = genES5Function(
      lazyData->originalName,
      parentVar,
      node,
      lazyData->isGeneratorInnerFunction);
  addLexicalDebugInfo(func, topLevel, lexicalScopeChain);
  return {func, topLevel};
}