aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-05-05 09:08:48 +0200
committerDmitry Vyukov <dvyukov@google.com>2018-05-05 09:08:48 +0200
commit5ca897bd501e4b9a3a1b130bc9ec95243a4804a0 (patch)
treeb7d6b332f0961f5a759a507c473f49c0b76d08df
parentb438ff23281a55c2976013818179423e732d179f (diff)
prog: remove ReturnArg
It's not all that needed.
-rw-r--r--prog/clone.go4
-rw-r--r--prog/encodingexec.go11
-rw-r--r--prog/prog.go30
-rw-r--r--prog/validation.go18
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())