// NewBasicBlock returns a new basic block based on the given name, non- // terminating instructions and terminator. func NewBasicBlock(nameToken, insts, term interface{}) (*ir.BasicBlock, error) { // Get label name. var name string switch nameToken := nameToken.(type) { case *token.Token: // Strip ":" suffix. s, err := stripLabelSuffix(nameToken.Lit) if err != nil { return nil, errutil.Err(err) } name = s case nil: // Unnamed basic block. default: return nil, errutil.Newf("invalid basic block name type; expected *token.Token, got %T", nameToken) } if term, ok := term.(instruction.Terminator); ok { switch insts := insts.(type) { case []instruction.Instruction: block := ir.NewBasicBlock(name) block.SetInsts(insts) block.SetTerm(term) return block, nil case nil: block := ir.NewBasicBlock(name) block.SetTerm(term) return block, nil default: return nil, errutil.Newf("invalid non-terminating instructions type; expected []instruction.Instruction, got %T", insts) } } return nil, errutil.Newf("invalid terminator type; expected instruction.Terminator, got %T", term) }
// fixFunc replaces dummy values within the given function with their // corresponding local variables. func (m dummyMap) fixFunc(oldFunc *ir.Function) *ir.Function { f := ir.NewFunction(oldFunc.Name(), oldFunc.Sig()) // Add mapping for basic blocks so they may be forward-referenced from // instructions. for _, oldBlock := range oldFunc.Blocks() { name := oldBlock.Name() block := ir.NewBasicBlock(name) m.set(name, block) } for _, oldBlock := range oldFunc.Blocks() { block := m.fixBlock(oldBlock) f.AppendBlock(block) } if err := f.AssignIDs(); err != nil { panic(errutil.Err(err)) } return f }
// NewBasicBlock returns a new basic block generator based on the given name and // parent function. func (f *Function) NewBasicBlock(name string) *BasicBlock { block := ir.NewBasicBlock(name) return &BasicBlock{BasicBlock: block, parent: f} }