From a7ce77be27d8e3728b97122a005bc5b23298cfc3 Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Tue, 24 Aug 2021 15:50:19 +0000 Subject: all: introduce call properties Call properties let us specify how each individual call within a program must be executed. So far the only way to enforce extra rules was to pass extra program-level properties (e.g. that is how fault injection was done). However, it entangles the logic and not flexible enough. Implement an ability to pass properties along with each individual call. --- prog/encodingexec.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'prog/encodingexec.go') diff --git a/prog/encodingexec.go b/prog/encodingexec.go index e0c7ec59d..296fcf0cf 100644 --- a/prog/encodingexec.go +++ b/prog/encodingexec.go @@ -6,7 +6,7 @@ // Exec format is an sequence of uint64's which encodes a sequence of calls. // The sequence is terminated by a speciall call execInstrEOF. -// Each call is (call ID, copyout index, number of arguments, arguments...). +// Each call is (call ID, call props, copyout index, number of arguments, arguments...). // Each argument is (type, size, value). // There are 4 types of arguments: // - execArgConst: value is const value @@ -22,6 +22,7 @@ package prog import ( "errors" "fmt" + "reflect" "sort" ) @@ -89,6 +90,8 @@ func (w *execContext) serializeCall(c *Call) { w.writeChecksums() // Generate the call itself. w.write(uint64(c.Meta.ID)) + // Generate call properties fragment. + w.writeCallProps(c.Props) if c.Ret != nil && len(c.Ret.uses) != 0 { if _, ok := w.args[c.Ret]; ok { panic("argInfo is already created for return value") @@ -103,6 +106,7 @@ func (w *execContext) serializeCall(c *Call) { for _, arg := range c.Args { w.writeArg(arg) } + // Generate copyout instructions that persist interesting return values. w.writeCopyout(c) } @@ -124,6 +128,17 @@ type argInfo struct { Ret bool } +func (w *execContext) writeCallProps(props CallProps) { + props.ForeachProp(func(_, _ string, value reflect.Value) { + switch kind := value.Kind(); kind { + case reflect.Int: + w.write(uint64(value.Int())) + default: + panic("Unsupported (yet) kind: " + kind.String()) + } + }) +} + func (w *execContext) writeCopyin(c *Call) { ForeachArg(c, func(arg Arg, ctx *ArgCtx) { if ctx.Base == nil { -- cgit mrf-deployment