diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2020-04-26 14:14:14 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-05-01 13:31:17 +0200 |
| commit | e54e9781a4e043b3140b0c908ba4f4e469fd317e (patch) | |
| tree | 16e6387d78a8577c5f3d9fb8d05a51752da6338e /prog/prog.go | |
| parent | 3f4dbb2f6fff9479d6c250e224bc3cb7f5cd66ed (diff) | |
prog: remove Dir from Type
Having Dir is Type is handy, but forces us to duplicate lots of types.
E.g. if a struct is referenced as both in and out, then we need to
have 2 copies and 2 copies of structs/types it includes.
If also prevents us from having the struct type as struct identity
(because we can have up to 3 of them).
Revert to the old way we used to do it: propagate Dir as we walk
syscall arguments. This moves lots of dir passing from pkg/compiler
to prog package.
Now Arg contains the dir, so once we build the tree, we can use dirs
as before.
Reduces size of sys/linux/gen/amd64.go from 6058336 to 5661150 (-6.6%).
Update #1580
Diffstat (limited to 'prog/prog.go')
| -rw-r--r-- | prog/prog.go | 60 |
1 files changed, 33 insertions, 27 deletions
diff --git a/prog/prog.go b/prog/prog.go index 1600c0a28..017a0dbbb 100644 --- a/prog/prog.go +++ b/prog/prog.go @@ -22,6 +22,7 @@ type Call struct { type Arg interface { Type() Type + Dir() Dir Size() uint64 validate(ctx *validCtx) error @@ -30,20 +31,25 @@ type Arg interface { type ArgCommon struct { typ Type + dir Dir } func (arg *ArgCommon) Type() Type { return arg.typ } +func (arg *ArgCommon) Dir() Dir { + return arg.dir +} + // Used for ConstType, IntType, FlagsType, LenType, ProcType and CsumType. type ConstArg struct { ArgCommon Val uint64 } -func MakeConstArg(t Type, v uint64) *ConstArg { - return &ConstArg{ArgCommon: ArgCommon{typ: t}, Val: v} +func MakeConstArg(t Type, dir Dir, v uint64) *ConstArg { + return &ConstArg{ArgCommon: ArgCommon{typ: t, dir: dir}, Val: v} } func (arg *ConstArg) Size() uint64 { @@ -84,34 +90,37 @@ type PointerArg struct { Res Arg // pointee (nil for vma) } -func MakePointerArg(t Type, addr uint64, data Arg) *PointerArg { +func MakePointerArg(t Type, dir Dir, addr uint64, data Arg) *PointerArg { if data == nil { panic("nil pointer data arg") } return &PointerArg{ - ArgCommon: ArgCommon{typ: t}, + ArgCommon: ArgCommon{typ: t, dir: DirIn}, // pointers are always in Address: addr, Res: data, } } -func MakeVmaPointerArg(t Type, addr, size uint64) *PointerArg { +func MakeVmaPointerArg(t Type, dir Dir, addr, size uint64) *PointerArg { if addr%1024 != 0 { panic("unaligned vma address") } return &PointerArg{ - ArgCommon: ArgCommon{typ: t}, + ArgCommon: ArgCommon{typ: t, dir: dir}, Address: addr, VmaSize: size, } } -func MakeSpecialPointerArg(t Type, index uint64) *PointerArg { +func MakeSpecialPointerArg(t Type, dir Dir, index uint64) *PointerArg { if index >= maxSpecialPointers { panic("bad special pointer index") } + if _, ok := t.(*PtrType); ok { + dir = DirIn // pointers are always in + } return &PointerArg{ - ArgCommon: ArgCommon{typ: t}, + ArgCommon: ArgCommon{typ: t, dir: dir}, Address: -index, } } @@ -138,18 +147,18 @@ type DataArg struct { size uint64 // for out Args } -func MakeDataArg(t Type, data []byte) *DataArg { - if t.Dir() == DirOut { +func MakeDataArg(t Type, dir Dir, data []byte) *DataArg { + if dir == DirOut { panic("non-empty output data arg") } - return &DataArg{ArgCommon: ArgCommon{typ: t}, data: append([]byte{}, data...)} + return &DataArg{ArgCommon: ArgCommon{typ: t, dir: dir}, data: append([]byte{}, data...)} } -func MakeOutDataArg(t Type, size uint64) *DataArg { - if t.Dir() != DirOut { +func MakeOutDataArg(t Type, dir Dir, size uint64) *DataArg { + if dir != DirOut { panic("empty input data arg") } - return &DataArg{ArgCommon: ArgCommon{typ: t}, size: size} + return &DataArg{ArgCommon: ArgCommon{typ: t, dir: dir}, size: size} } func (arg *DataArg) Size() uint64 { @@ -160,14 +169,14 @@ func (arg *DataArg) Size() uint64 { } func (arg *DataArg) Data() []byte { - if arg.Type().Dir() == DirOut { + if arg.Dir() == DirOut { panic("getting data of output data arg") } return arg.data } func (arg *DataArg) SetData(data []byte) { - if arg.Type().Dir() == DirOut { + if arg.Dir() == DirOut { panic("setting data of output data arg") } arg.data = append([]byte{}, data...) @@ -180,8 +189,8 @@ type GroupArg struct { Inner []Arg } -func MakeGroupArg(t Type, inner []Arg) *GroupArg { - return &GroupArg{ArgCommon: ArgCommon{typ: t}, Inner: inner} +func MakeGroupArg(t Type, dir Dir, inner []Arg) *GroupArg { + return &GroupArg{ArgCommon: ArgCommon{typ: t, dir: dir}, Inner: inner} } func (arg *GroupArg) Size() uint64 { @@ -227,8 +236,8 @@ type UnionArg struct { Option Arg } -func MakeUnionArg(t Type, opt Arg) *UnionArg { - return &UnionArg{ArgCommon: ArgCommon{typ: t}, Option: opt} +func MakeUnionArg(t Type, dir Dir, opt Arg) *UnionArg { + return &UnionArg{ArgCommon: ArgCommon{typ: t, dir: dir}, Option: opt} } func (arg *UnionArg) Size() uint64 { @@ -250,8 +259,8 @@ type ResultArg struct { uses map[*ResultArg]bool // ArgResult args that use this arg } -func MakeResultArg(t Type, r *ResultArg, v uint64) *ResultArg { - arg := &ResultArg{ArgCommon: ArgCommon{typ: t}, Res: r, Val: v} +func MakeResultArg(t Type, dir Dir, r *ResultArg, v uint64) *ResultArg { + arg := &ResultArg{ArgCommon: ArgCommon{typ: t, dir: dir}, Res: r, Val: v} if r == nil { return arg } @@ -266,10 +275,7 @@ func MakeReturnArg(t Type) *ResultArg { if t == nil { return nil } - if t.Dir() != DirOut { - panic("return arg is not out") - } - return &ResultArg{ArgCommon: ArgCommon{typ: t}} + return &ResultArg{ArgCommon: ArgCommon{typ: t, dir: DirOut}} } func (arg *ResultArg) Size() uint64 { @@ -369,7 +375,7 @@ func removeArg(arg0 Arg) { delete(uses, a) } for arg1 := range a.uses { - arg2 := arg1.Type().DefaultArg().(*ResultArg) + arg2 := arg1.Type().DefaultArg(arg1.Dir()).(*ResultArg) replaceResultArg(arg1, arg2) } }) |
