From 5ca897bd501e4b9a3a1b130bc9ec95243a4804a0 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sat, 5 May 2018 09:08:48 +0200 Subject: prog: remove ReturnArg It's not all that needed. --- prog/clone.go | 4 ---- prog/encodingexec.go | 11 ++++++++--- prog/prog.go | 30 ++++++++++-------------------- prog/validation.go | 18 +++++------------- 4 files changed, 23 insertions(+), 40 deletions(-) diff --git a/prog/clone.go b/prog/clone.go index bdb9b5074..e7d937318 100644 --- a/prog/clone.go +++ b/prog/clone.go @@ -63,10 +63,6 @@ func clone(arg Arg, newargs map[Arg]Arg) Arg { a1 := new(ResultArg) *a1 = *a arg1 = a1 - case *ReturnArg: - a1 := new(ReturnArg) - *a1 = *a - arg1 = a1 default: panic("bad arg kind") } diff --git a/prog/encodingexec.go b/prog/encodingexec.go index ea01560d9..4085262a9 100644 --- a/prog/encodingexec.go +++ b/prog/encodingexec.go @@ -153,7 +153,10 @@ func (p *Prog) SerializeForExec(buffer []byte) (int, error) { // Generate the call itself. w.write(uint64(c.Meta.ID)) if isUsed(c.Ret) { - w.args[c.Ret] = argInfo{Idx: copyoutSeq} + if _, ok := w.args[c.Ret]; ok { + panic("argInfo is already created for return value") + } + w.args[c.Ret] = argInfo{Idx: copyoutSeq, Ret: true} w.write(copyoutSeq) copyoutSeq++ } else { @@ -169,11 +172,12 @@ func (p *Prog) SerializeForExec(buffer []byte) (int, error) { return } switch arg.(type) { - case *ReturnArg: - // Idx is already assigned above. case *ConstArg, *ResultArg: // Create a separate copyout instruction that has own Idx. info := w.args[arg] + if info.Ret { + break // Idx is already assigned above. + } info.Idx = copyoutSeq copyoutSeq++ w.args[arg] = info @@ -210,6 +214,7 @@ type execContext struct { type argInfo struct { Addr uint64 // physical addr Idx uint64 // copyout instruction index + Ret bool } func (w *execContext) write(v uint64) { diff --git a/prog/prog.go b/prog/prog.go index fe9293433..1bec61643 100644 --- a/prog/prog.go +++ b/prog/prog.go @@ -255,7 +255,8 @@ func (arg *UnionArg) Size() uint64 { } // Used for ResourceType. -// Either holds constant value or reference another ResultArg or ReturnArg. +// This is the only argument that can be used as syscall return value. +// Either holds constant value or reference another ResultArg. type ResultArg struct { ArgCommon Res Arg // reference to arg which we use @@ -278,6 +279,14 @@ func MakeResultArg(t Type, r Arg, v uint64) *ResultArg { return arg } +func MakeReturnArg(t Type) *ResultArg { + // TODO(dvyukov): we should not create return arg at all if t is nil. + if t != nil && t.Dir() != DirOut { + panic("return arg is not out") + } + return &ResultArg{ArgCommon: ArgCommon{typ: t}} +} + func (arg *ResultArg) Size() uint64 { return arg.typ.Size() } @@ -290,25 +299,6 @@ func (arg *ResultArg) Uses() *Arg { return &arg.Res } -// Used for ResourceType and VmaType. -// This argument denotes syscall return value. -type ReturnArg struct { - ArgCommon - uses map[Arg]bool // ArgResult args that use this arg -} - -func MakeReturnArg(t Type) *ReturnArg { - return &ReturnArg{ArgCommon: ArgCommon{typ: t}} -} - -func (arg *ReturnArg) Size() uint64 { - panic("not called") -} - -func (arg *ReturnArg) Used() *map[Arg]bool { - return &arg.uses -} - // Returns inner arg for pointer args. func InnerArg(arg Arg) Arg { if t, ok := arg.Type().(*PtrType); ok { diff --git a/prog/validation.go b/prog/validation.go index 5c9275164..6dd44bc86 100644 --- a/prog/validation.go +++ b/prog/validation.go @@ -43,10 +43,6 @@ func (p *Prog) validateCall(ctx *validCtx, c *Call) error { c.Meta.Name, len(c.Meta.Args), len(c.Args)) } for _, arg := range c.Args { - if _, ok := arg.(*ReturnArg); ok { - return fmt.Errorf("syscall %v: arg '%v' has wrong return kind", - c.Meta.Name, arg.Type().Name()) - } if err := validateArg(ctx, c, arg); err != nil { return err } @@ -54,8 +50,12 @@ func (p *Prog) validateCall(ctx *validCtx, c *Call) error { if c.Ret == nil { return fmt.Errorf("syscall %v: return value is absent", c.Meta.Name) } - if _, ok := c.Ret.(*ReturnArg); !ok { + if ret, ok := c.Ret.(*ResultArg); !ok { return fmt.Errorf("syscall %v: return value has wrong kind %v", c.Meta.Name, c.Ret) + } else if ret.Type() != nil && ret.Type().Dir() != DirOut { + return fmt.Errorf("syscall %v: return value %v is not output", c.Meta.Name, c.Ret) + } else if ret.Res != nil || ret.Val != 0 || ret.OpDiv != 0 || ret.OpAdd != 0 { + return fmt.Errorf("syscall %v: return value %v is not empty", c.Meta.Name, c.Ret) } if c.Meta.Ret != nil { if err := validateArg(ctx, c, c.Ret); err != nil { @@ -129,7 +129,6 @@ func validateArg(ctx *validCtx, c *Call, arg Arg) error { return fmt.Errorf("syscall %v: out resource arg '%v' has bad const value %v", c.Meta.Name, a.Type().Name(), a.Val) } - case *ReturnArg: default: return fmt.Errorf("syscall %v: fd arg '%v' has bad kind %v", c.Meta.Name, arg.Type().Name(), arg) @@ -310,13 +309,6 @@ func validateArg(ctx *validCtx, c *Call, arg Arg) error { return fmt.Errorf("syscall %v: result arg '%v' has broken link (%+v)", c.Meta.Name, a.Type().Name(), *a.Res.(ArgUsed).Used()) } - case *ReturnArg: - switch a.Type().(type) { - case *ResourceType: - default: - return fmt.Errorf("syscall %v: result arg '%v' has bad meta type %+v", - c.Meta.Name, arg.Type().Name(), arg.Type()) - } default: return fmt.Errorf("syscall %v: unknown arg '%v' kind", c.Meta.Name, arg.Type().Name()) -- cgit mrf-deployment