// parseBasicBlock converts the provided LLVM IR basic block into a basic block // in which the instructions have been translated to Go AST statement nodes but // the terminator instruction is an unmodified LLVM IR value. func parseBasicBlock(llBB llvm.BasicBlock) (bb *basicBlock, err error) { name, err := getBBName(llBB.AsValue()) if err != nil { return nil, err } bb = &basicBlock{name: name, phis: make(map[string][]*definition)} for inst := llBB.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) { // Handle terminator instruction. if inst == llBB.LastInstruction() { err = bb.addTerm(inst) if err != nil { return nil, errutil.Err(err) } return bb, nil } // Handle PHI instructions. if inst.InstructionOpcode() == llvm.PHI { ident, def, err := parsePHIInst(inst) if err != nil { return nil, errutil.Err(err) } bb.phis[ident] = def continue } // Handle non-terminator instructions. stmt, err := parseInst(inst) if err != nil { return nil, err } bb.stmts = append(bb.stmts, stmt) } return nil, errutil.Newf("invalid basic block %q; contains no instructions", name) }
func (c *Codegen) generateControl(node *parser.IfStmtNode) (ret bool) { currFunc := c.module.NamedFunction(c.currFunc) tru := llvm.AddBasicBlock(currFunc, "") var els llvm.BasicBlock if node.Else != nil { els = llvm.AddBasicBlock(currFunc, "") } exit := llvm.AddBasicBlock(currFunc, "") cond := c.generateExpression(node.Condition) if node.Else != nil { c.builder.CreateCondBr(cond, tru, els) } else { c.builder.CreateCondBr(cond, tru, exit) } c.builder.SetInsertPoint(tru, tru.LastInstruction()) if c.generateBlock(node.Body) { ret = true } else { c.builder.CreateBr(exit) } if node.Else != nil { c.builder.SetInsertPoint(els, els.LastInstruction()) var ok bool switch t := node.Else.(type) { case *parser.BlockNode: ok = c.generateBlock(t) ret = ok && ret case *parser.IfStmtNode: ok = c.generateControl(t) ret = ok && ret } if !ok { c.builder.CreateBr(exit) } } c.builder.SetInsertPoint(exit, exit.LastInstruction()) return }