1// Copyright 2017 syzkaller project authors. All rights reserved. 2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4package prog 5 6func (p *Prog) Clone() *Prog { 7 p1 := &Prog{ 8 Target: p.Target, 9 Calls: make([]*Call, len(p.Calls)), 10 } 11 newargs := make(map[*ResultArg]*ResultArg) 12 for ci, c := range p.Calls { 13 c1 := new(Call) 14 c1.Meta = c.Meta 15 if c.Ret != nil { 16 c1.Ret = clone(c.Ret, newargs).(*ResultArg) 17 } 18 c1.Args = make([]Arg, len(c.Args)) 19 for ai, arg := range c.Args { 20 c1.Args[ai] = clone(arg, newargs) 21 } 22 p1.Calls[ci] = c1 23 } 24 p1.debugValidate() 25 return p1 26} 27 28func clone(arg Arg, newargs map[*ResultArg]*ResultArg) Arg { 29 var arg1 Arg 30 switch a := arg.(type) { 31 case *ConstArg: 32 a1 := new(ConstArg) 33 *a1 = *a 34 arg1 = a1 35 case *PointerArg: 36 a1 := new(PointerArg) 37 *a1 = *a 38 arg1 = a1 39 if a.Res != nil { 40 a1.Res = clone(a.Res, newargs) 41 } 42 case *DataArg: 43 a1 := new(DataArg) 44 *a1 = *a 45 a1.data = append([]byte{}, a.data...) 46 arg1 = a1 47 case *GroupArg: 48 a1 := new(GroupArg) 49 *a1 = *a 50 arg1 = a1 51 a1.Inner = make([]Arg, len(a.Inner)) 52 for i, arg2 := range a.Inner { 53 a1.Inner[i] = clone(arg2, newargs) 54 } 55 case *UnionArg: 56 a1 := new(UnionArg) 57 *a1 = *a 58 arg1 = a1 59 a1.Option = clone(a.Option, newargs) 60 case *ResultArg: 61 a1 := new(ResultArg) 62 *a1 = *a 63 arg1 = a1 64 if a1.Res != nil { 65 r := newargs[a1.Res] 66 a1.Res = r 67 if r.uses == nil { 68 r.uses = make(map[*ResultArg]bool) 69 } 70 r.uses[a1] = true 71 } 72 a1.uses = nil // filled when we clone the referent 73 newargs[a] = a1 74 default: 75 panic("bad arg kind") 76 } 77 return arg1 78} 79