Ejemplo n.º 1
0
void ScopeStack::popCleanups(CleanupCursor targetScope) {
  assert(targetScope <= currentCleanupScope());
  if (targetScope == currentCleanupScope()) {
    return;
  }

  for (CleanupCursor i = currentCleanupScope(); i-- > targetScope;) {
    // Any gotos that are still unresolved necessarily leave this scope.
    // Thus, the cleanup needs to be executed.
    for (const auto &gotoJump : currentUnresolvedGotos()) {
      // Make the source resp. last cleanup branch to this one.
      llvm::BasicBlock *tentative = gotoJump.tentativeTarget;
      tentative->replaceAllUsesWith(cleanupScopes[i].beginBlock);

      // And continue execution with the tentative target (we simply reuse
      // it because there is no reason not to).
      executeCleanup(irs, cleanupScopes[i], gotoJump.sourceBlock, tentative);
    }

    std::vector<GotoJump> &nextUnresolved =
        (i == 0) ? topLevelUnresolvedGotos
                 : cleanupScopes[i - 1].unresolvedGotos;
    nextUnresolved.insert(nextUnresolved.end(),
                          currentUnresolvedGotos().begin(),
                          currentUnresolvedGotos().end());

    cleanupScopes.pop_back();
  }
}
Ejemplo n.º 2
0
TryCatchFinallyScopes::~TryCatchFinallyScopes() {
  assert(currentCleanupScope() == 0);
  // If there are still unresolved gotos left, it means that they were either
  // down or "sideways" (i.e. down another branch) of the tree of all
  // cleanup scopes, both of which are not allowed in D.
  if (!currentUnresolvedGotos().empty()) {
    for (const auto &i : currentUnresolvedGotos()) {
      error(i.sourceLoc, "`goto` into `try`/`finally` scope is not allowed");
    }
    fatal();
  }
}
Ejemplo n.º 3
0
void ScopeStack::jumpToLabel(Loc loc, Identifier *labelName) {
  // If we have already seen that label, branch to it, executing any cleanups
  // as necessary.
  auto it = labelTargets.find(labelName);
  if (it != labelTargets.end()) {
    runCleanups(it->second.cleanupScope, it->second.targetBlock);
    return;
  }

  llvm::BasicBlock *target = llvm::BasicBlock::Create(
      irs->context(), "goto.unresolved", irs->topfunc());
  irs->ir->CreateBr(target);
  currentUnresolvedGotos().emplace_back(loc, irs->scopebb(), target, labelName);
}
Ejemplo n.º 4
0
void TryCatchFinallyScopes::popCleanups(CleanupCursor targetScope) {
  assert(targetScope <= currentCleanupScope());
  if (targetScope == currentCleanupScope())
    return;

  for (CleanupCursor i = currentCleanupScope(); i-- > targetScope;) {
    // Any gotos that are still unresolved necessarily leave this scope.
    // Thus, the cleanup needs to be executed.
    for (const auto &gotoJump : currentUnresolvedGotos()) {
      // Replace all branches to the tentative target by branches to the cleanup
      // and continue with the tentative target (we simply reuse it because
      // there is no reason not to).
      llvm::BasicBlock *tentative = gotoJump.tentativeTarget;
      // 1) Replace all branches to the tentative target by branches to a
      //    temporary placeholder BB.
      llvm::BasicBlock *dummy = irs.insertBB("");
      tentative->replaceAllUsesWith(dummy);
      // 2) We need a cleanup instance which continues execution with the
      //    tentative target.
      auto startCleanup =
          cleanupScopes[i].run(irs, gotoJump.sourceBlock, tentative);
      // 3) Replace all branches to the placeholder BB by branches to the
      //    cleanup.
      dummy->replaceAllUsesWith(startCleanup);
      dummy->eraseFromParent();
    }

    Gotos &nextUnresolved = unresolvedGotosPerCleanupScope[i];
    nextUnresolved.insert(nextUnresolved.end(),
                          currentUnresolvedGotos().begin(),
                          currentUnresolvedGotos().end());

    cleanupScopes.pop_back();
    unresolvedGotosPerCleanupScope.pop_back();
    landingPadsPerCleanupScope.pop_back();
  }
}
Ejemplo n.º 5
0
void TryCatchFinallyScopes::tryResolveGotos(Identifier *labelName,
                                            llvm::BasicBlock *targetBlock) {
  auto &unresolved = currentUnresolvedGotos();
  size_t i = 0;
  while (i < unresolved.size()) {
    if (unresolved[i].targetLabel != labelName) {
      ++i;
      continue;
    }

    unresolved[i].tentativeTarget->replaceAllUsesWith(targetBlock);
    unresolved[i].tentativeTarget->eraseFromParent();
    unresolved.erase(unresolved.begin() + i);
  }
}
Ejemplo n.º 6
0
void ScopeStack::addLabelTarget(Identifier *labelName,
                                llvm::BasicBlock *targetBlock) {
  labelTargets[labelName] = {targetBlock, currentCleanupScope(), nullptr};

  // See whether any of the unresolved gotos target this label, and resolve
  // those that do.
  std::vector<GotoJump> &unresolved = currentUnresolvedGotos();
  size_t i = 0;
  while (i < unresolved.size()) {
    if (unresolved[i].targetLabel != labelName) {
      ++i;
      continue;
    }

    unresolved[i].tentativeTarget->replaceAllUsesWith(targetBlock);
    unresolved[i].tentativeTarget->eraseFromParent();
    unresolved.erase(unresolved.begin() + i);
  }
}
Ejemplo n.º 7
0
void TryCatchFinallyScopes::registerUnresolvedGoto(Loc loc,
                                                   Identifier *labelName) {
  llvm::BasicBlock *target = irs.insertBB("goto.unresolved");
  irs.ir->CreateBr(target);
  currentUnresolvedGotos().push_back({loc, irs.scopebb(), target, labelName});
}