func (c *compiler) VisitIfStmt(stmt *ast.IfStmt) { curr_block := c.builder.GetInsertBlock() resume_block := llvm.AddBasicBlock(curr_block.Parent(), "endif") resume_block.MoveAfter(curr_block) var if_block, else_block llvm.BasicBlock if stmt.Else != nil { else_block = llvm.InsertBasicBlock(resume_block, "else") if_block = llvm.InsertBasicBlock(else_block, "if") } else { if_block = llvm.InsertBasicBlock(resume_block, "if") } if stmt.Else == nil { else_block = resume_block } if stmt.Init != nil { c.PushScope() c.VisitStmt(stmt.Init) defer c.PopScope() } cond_val := c.VisitExpr(stmt.Cond) c.builder.CreateCondBr(cond_val.LLVMValue(), if_block, else_block) c.builder.SetInsertPointAtEnd(if_block) c.VisitBlockStmt(stmt.Body) if in := if_block.LastInstruction(); in.IsNil() || in.IsATerminatorInst().IsNil() { c.builder.CreateBr(resume_block) } if stmt.Else != nil { c.builder.SetInsertPointAtEnd(else_block) c.VisitStmt(stmt.Else) if in := else_block.LastInstruction(); in.IsNil() || in.IsATerminatorInst().IsNil() { c.builder.CreateBr(resume_block) } } // If there's a block after the "resume" block (i.e. a nested control // statement), then create a branch to it as the last instruction. c.builder.SetInsertPointAtEnd(resume_block) if last := resume_block.Parent().LastBasicBlock(); last != resume_block { c.builder.CreateBr(last) c.builder.SetInsertPointBefore(resume_block.FirstInstruction()) } }