// NewFunc returns a new function based on the given result type, function name, // and function parameters. func NewFunc(result, gname, params interface{}) (*ir.Function, error) { if result, ok := result.(types.Type); ok { name, err := getGlobalName(gname) if err != nil { return nil, errutil.Err(err) } var sig *types.Func switch params := params.(type) { case *Params: sig, err = types.NewFunc(result, params.params, params.variadic) if err != nil { return nil, errutil.Err(err) } case nil: sig, err = types.NewFunc(result, nil, false) if err != nil { return nil, errutil.Err(err) } default: return nil, errutil.Newf("invalid function parameters specifier type; expected *Params, got %T", params) } return ir.NewFunction(name, sig), nil } return nil, errutil.Newf("invalid function result type; expected types.Type, got %T", result) }
// 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 }
// NewFunction returns a new function generator based on the given function name // and signature. // // The caller is responsible for initializing basic blocks. func NewFunction(name string, sig *irtypes.Func) *Function { f := ir.NewFunction(name, sig) return &Function{Function: f, idents: make(map[int]value.Value), exists: make(map[string]bool)} }