示例#1
0
void ScopeStack::jumpToStatement(std::vector<JumpTarget> &targets,
                                 Statement *loopOrSwitchStatement) {
  for (auto it = targets.rbegin(), end = targets.rend(); it != end; ++it) {
    if (it->targetStatement == loopOrSwitchStatement) {
      runCleanups(it->cleanupScope, it->targetBlock);
      return;
    }
  }
  assert(false && "Target for labeled break not found.");
}
示例#2
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);
}
示例#3
0
llvm::BasicBlock *ScopeStack::emitLandingPad() {
  // save and rewrite scope
  IRScope savedIRScope = irs->scope();

  llvm::BasicBlock *beginBB =
      llvm::BasicBlock::Create(irs->context(), "landingPad", irs->topfunc());
  irs->scope() = IRScope(beginBB);

  llvm::LandingPadInst *landingPad = createLandingPadInst(irs);

  // Stash away the exception object pointer and selector value into their
  // stack slots.
  llvm::Value *ehPtr = DtoExtractValue(landingPad, 0);
  irs->ir->CreateStore(ehPtr, irs->func()->getOrCreateEhPtrSlot());

  llvm::Value *ehSelector = DtoExtractValue(landingPad, 1);
  if (!irs->func()->ehSelectorSlot) {
    irs->func()->ehSelectorSlot =
        DtoRawAlloca(ehSelector->getType(), 0, "eh.selector");
  }
  irs->ir->CreateStore(ehSelector, irs->func()->ehSelectorSlot);

  // Add landingpad clauses, emit finallys and 'if' chain to catch the
  // exception.
  CleanupCursor lastCleanup = currentCleanupScope();
  for (auto it = catchScopes.rbegin(), end = catchScopes.rend(); it != end;
       ++it) {
    // Insert any cleanups in between the last catch we ran (i.e. tested for
    // and found that the type does not match) and this one.
    assert(lastCleanup >= it->cleanupScope);
    if (lastCleanup > it->cleanupScope) {
      landingPad->setCleanup(true);
      llvm::BasicBlock *afterCleanupBB = llvm::BasicBlock::Create(
          irs->context(), beginBB->getName() + llvm::Twine(".after.cleanup"),
          irs->topfunc());
      runCleanups(lastCleanup, it->cleanupScope, afterCleanupBB);
      irs->scope() = IRScope(afterCleanupBB);
      lastCleanup = it->cleanupScope;
    }

    // Add the ClassInfo reference to the landingpad instruction so it is
    // emitted to the EH tables.
    landingPad->addClause(it->classInfoPtr);

    llvm::BasicBlock *mismatchBB = llvm::BasicBlock::Create(
        irs->context(), beginBB->getName() + llvm::Twine(".mismatch"),
        irs->topfunc());

    // "Call" llvm.eh.typeid.for, which gives us the eh selector value to
    // compare the landing pad selector value with.
    llvm::Value *ehTypeId =
        irs->ir->CreateCall(GET_INTRINSIC_DECL(eh_typeid_for),
                            DtoBitCast(it->classInfoPtr, getVoidPtrType()));

    // Compare the selector value from the unwinder against the expected
    // one and branch accordingly.
    irs->ir->CreateCondBr(
        irs->ir->CreateICmpEQ(irs->ir->CreateLoad(irs->func()->ehSelectorSlot),
                              ehTypeId),
        it->bodyBlock, mismatchBB);
    irs->scope() = IRScope(mismatchBB);
  }

  // No catch matched. Execute all finallys and resume unwinding.
  if (lastCleanup > 0) {
    landingPad->setCleanup(true);
    runCleanups(lastCleanup, 0, irs->func()->getOrCreateResumeUnwindBlock());
  } else if (!catchScopes.empty()) {
    // Directly convert the last mismatch branch into a branch to the
    // unwind resume block.
    irs->scopebb()->replaceAllUsesWith(
        irs->func()->getOrCreateResumeUnwindBlock());
    irs->scopebb()->eraseFromParent();
  } else {
    irs->ir->CreateBr(irs->func()->getOrCreateResumeUnwindBlock());
  }

  irs->scope() = savedIRScope;
  return beginBB;
}
示例#4
0
void ScopeStack::jumpToClosest(std::vector<JumpTarget> &targets) {
  assert(!targets.empty() &&
         "Encountered break/continue but no loop in scope.");
  JumpTarget &t = targets.back();
  runCleanups(t.cleanupScope, t.targetBlock);
}
示例#5
0
void ScopeStack::runAllCleanups(llvm::BasicBlock *continueWith) {
  runCleanups(0, continueWith);
}
示例#6
0
llvm::BasicBlock *TryCatchFinallyScopes::emitLandingPad() {
#if LDC_LLVM_VER >= 308
  if (useMSVCEH()) {
    assert(currentCleanupScope() > 0);
    return emitLandingPadMSVC(currentCleanupScope() - 1);
  }
#endif

  // save and rewrite scope
  IRScope savedIRScope = irs.scope();

  // insert landing pads at the end of the function, in emission order,
  // to improve human-readability of the IR
  llvm::BasicBlock *beginBB = irs.insertBBBefore(nullptr, "landingPad");
  irs.scope() = IRScope(beginBB);

  llvm::LandingPadInst *landingPad = createLandingPadInst(irs);

  // Stash away the exception object pointer and selector value into their
  // stack slots.
  llvm::Value *ehPtr = DtoExtractValue(landingPad, 0);
  irs.ir->CreateStore(ehPtr, getOrCreateEhPtrSlot());

  llvm::Value *ehSelector = DtoExtractValue(landingPad, 1);
  if (!ehSelectorSlot)
    ehSelectorSlot = DtoRawAlloca(ehSelector->getType(), 0, "eh.selector");
  irs.ir->CreateStore(ehSelector, ehSelectorSlot);

  // Add landingpad clauses, emit finallys and 'if' chain to catch the
  // exception.
  CleanupCursor lastCleanup = currentCleanupScope();
  for (auto it = tryCatchScopes.rbegin(), end = tryCatchScopes.rend();
       it != end; ++it) {
    const auto &tryCatchScope = *it;

    // Insert any cleanups in between the previous (inner-more) try-catch scope
    // and this one.
    const auto newCleanup = tryCatchScope.getCleanupScope();
    assert(lastCleanup >= newCleanup);
    if (lastCleanup > newCleanup) {
      landingPad->setCleanup(true);
      llvm::BasicBlock *afterCleanupBB =
          irs.insertBB(beginBB->getName() + llvm::Twine(".after.cleanup"));
      runCleanups(lastCleanup, newCleanup, afterCleanupBB);
      irs.scope() = IRScope(afterCleanupBB);
      lastCleanup = newCleanup;
    }

    for (const auto &cb : tryCatchScope.getCatchBlocks()) {
      // Add the ClassInfo reference to the landingpad instruction so it is
      // emitted to the EH tables.
      landingPad->addClause(cb.classInfoPtr);

      llvm::BasicBlock *mismatchBB =
          irs.insertBB(beginBB->getName() + llvm::Twine(".mismatch"));

      // "Call" llvm.eh.typeid.for, which gives us the eh selector value to
      // compare the landing pad selector value with.
      llvm::Value *ehTypeId =
          irs.ir->CreateCall(GET_INTRINSIC_DECL(eh_typeid_for),
                             DtoBitCast(cb.classInfoPtr, getVoidPtrType()));

      // Compare the selector value from the unwinder against the expected
      // one and branch accordingly.
      irs.ir->CreateCondBr(
          irs.ir->CreateICmpEQ(irs.ir->CreateLoad(ehSelectorSlot), ehTypeId),
          cb.bodyBB, mismatchBB, cb.branchWeights);
      irs.scope() = IRScope(mismatchBB);
    }
  }

  // No catch matched. Execute all finallys and resume unwinding.
  auto resumeUnwindBlock = getOrCreateResumeUnwindBlock();
  if (lastCleanup > 0) {
    landingPad->setCleanup(true);
    runCleanups(lastCleanup, 0, resumeUnwindBlock);
  } else if (!tryCatchScopes.empty()) {
    // Directly convert the last mismatch branch into a branch to the
    // unwind resume block.
    irs.scopebb()->replaceAllUsesWith(resumeUnwindBlock);
    irs.scopebb()->eraseFromParent();
  } else {
    irs.ir->CreateBr(resumeUnwindBlock);
  }

  irs.scope() = savedIRScope;
  return beginBB;
}
示例#7
0
void TryCatchFinallyScopes::runCleanups(CleanupCursor targetScope,
                                        llvm::BasicBlock *continueWith) {
  runCleanups(currentCleanupScope(), targetScope, continueWith);
}