//===-- funcgenstate.cpp --------------------------------------------------===// // // LDC – the LLVM D compiler // // This file is distributed under the BSD-style LDC license. See the LICENSE // file for details. // //===----------------------------------------------------------------------===// #include "gen/funcgenstate.h" #include "identifier.h" #include "gen/llvm.h" #include "gen/llvmhelpers.h" #include "gen/ms-cxx-helper.h" #include "gen/runtime.h" #include "ir/irfunction.h" JumpTarget::JumpTarget(llvm::BasicBlock *targetBlock, CleanupCursor cleanupScope, Statement *targetStatement) : targetBlock(targetBlock), cleanupScope(cleanupScope), targetStatement(targetStatement) {} JumpTargets::JumpTargets(TryCatchFinallyScopes &scopes) : scopes(scopes) {} void JumpTargets::pushLoopTarget(Statement *loopStatement, llvm::BasicBlock *continueTarget, llvm::BasicBlock *breakTarget) { continueTargets.emplace_back(continueTarget, scopes.currentCleanupScope(), loopStatement); breakTargets.emplace_back(breakTarget, scopes.currentCleanupScope(), loopStatement); } void JumpTargets::popLoopTarget() { continueTargets.pop_back(); breakTargets.pop_back(); } void JumpTargets::pushBreakTarget(Statement *switchStatement, llvm::BasicBlock *targetBlock) { breakTargets.push_back( {targetBlock, scopes.currentCleanupScope(), switchStatement}); } void JumpTargets::popBreakTarget() { breakTargets.pop_back(); } void JumpTargets::addLabelTarget(Identifier *labelName, llvm::BasicBlock *targetBlock) { labelTargets[labelName] = {targetBlock, scopes.currentCleanupScope(), nullptr}; // See whether any of the unresolved gotos target this label, and resolve // those that do. scopes.tryResolveGotos(labelName, targetBlock); } void JumpTargets::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()) { scopes.runCleanups(it->second.cleanupScope, it->second.targetBlock); } else { scopes.registerUnresolvedGoto(loc, labelName); } } void JumpTargets::jumpToStatement(std::vector &targets, Statement *loopOrSwitchStatement) { for (auto it = targets.rbegin(), end = targets.rend(); it != end; ++it) { if (it->targetStatement == loopOrSwitchStatement) { scopes.runCleanups(it->cleanupScope, it->targetBlock); return; } } assert(false && "Target for labeled break not found."); } void JumpTargets::jumpToClosest(std::vector &targets) { assert(!targets.empty() && "Encountered break/continue but no loop in scope."); JumpTarget &t = targets.back(); scopes.runCleanups(t.cleanupScope, t.targetBlock); } llvm::BasicBlock *SwitchCaseTargets::get(Statement *stmt) { auto it = targetBBs.find(stmt); assert(it != targetBBs.end()); return it->second; } llvm::BasicBlock *SwitchCaseTargets::getOrCreate(Statement *stmt, const llvm::Twine &name, IRState &irs) { auto &bb = targetBBs[stmt]; if (!bb) bb = irs.insertBB(name); return bb; } FuncGenState::FuncGenState(IrFunction &irFunc, IRState &irs) : irFunc(irFunc), scopes(irs), jumpTargets(scopes), switchTargets(), irs(irs) {}