void IrGen::visit(AstIf& if_) { // setup needed basic blocks Function* functionIr = m_builder.GetInsertBlock()->getParent(); BasicBlock* ThenFirstBB = BasicBlock::Create(llvmContext, "if_then", functionIr); BasicBlock* ElseFirstBB = BasicBlock::Create(llvmContext, "if_else"); BasicBlock* MergeBB = BasicBlock::Create(llvmContext, "if_merge"); // current BB: Value* condIr = callAcceptOn(if_.condition()); assert(condIr); m_builder.CreateCondBr(condIr, ThenFirstBB, ElseFirstBB); // thenFirstBB: m_builder.SetInsertPoint(ThenFirstBB); Value* thenValue = callAcceptOn(if_.action()); assert(thenValue); if (!if_.action().objType().isNoreturn()) { m_builder.CreateBr(MergeBB); } BasicBlock* ThenLastBB = m_builder.GetInsertBlock(); // elseFirstBB: functionIr->getBasicBlockList().push_back(ElseFirstBB); m_builder.SetInsertPoint(ElseFirstBB); Value* elseValue = nullptr; if (if_.elseAction()) { elseValue = callAcceptOn(*if_.elseAction()); assert(elseValue); if (!if_.elseAction()->objType().isNoreturn()) { m_builder.CreateBr(MergeBB); } } else { elseValue = m_abstractObject; m_builder.CreateBr(MergeBB); } BasicBlock* ElseLastBB = m_builder.GetInsertBlock(); // mergeBB: // also sets IrValue of this AstIf functionIr->getBasicBlockList().push_back(MergeBB); m_builder.SetInsertPoint(MergeBB); if (thenValue != m_abstractObject && elseValue != m_abstractObject) { PHINode* phi = m_builder.CreatePHI(thenValue->getType(), 2, "if_phi"); assert(phi); phi->addIncoming(thenValue, ThenLastBB); phi->addIncoming(elseValue, ElseLastBB); allocateAndInitLocalIrObjectFor(if_, phi); } else { allocateAndInitLocalIrObjectFor(if_, m_abstractObject); } }