示例#1
0
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);
  }
}