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