aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler
diff options
context:
space:
mode:
authorNecip Fazil Yildiran <necip@google.com>2020-08-10 14:43:38 +0000
committerDmitry Vyukov <dvyukov@google.com>2020-08-13 13:50:25 +0200
commitf5442bde55872d703f184f8617329f706bad8149 (patch)
tree14e121020d6aacd857b80351f01546818f19a74b /pkg/compiler
parentee7cb8b69583db417b187b53f4765c3a403cd4cf (diff)
pkg, prog: add per-field direction attribute
Diffstat (limited to 'pkg/compiler')
-rw-r--r--pkg/compiler/attrs.go4
-rw-r--r--pkg/compiler/check.go24
-rw-r--r--pkg/compiler/gen.go22
-rw-r--r--pkg/compiler/testdata/all.txt10
-rw-r--r--pkg/compiler/testdata/errors.txt10
-rw-r--r--pkg/compiler/testdata/errors2.txt94
6 files changed, 155 insertions, 9 deletions
diff --git a/pkg/compiler/attrs.go b/pkg/compiler/attrs.go
index c0fa04211..5de19f884 100644
--- a/pkg/compiler/attrs.go
+++ b/pkg/compiler/attrs.go
@@ -23,9 +23,13 @@ var (
attrVarlen = &attrDesc{Name: "varlen"}
attrSize = &attrDesc{Name: "size", HasArg: true}
attrAlign = &attrDesc{Name: "align", HasArg: true}
+ attrIn = &attrDesc{Name: "in"}
+ attrOut = &attrDesc{Name: "out"}
+ attrInOut = &attrDesc{Name: "inout"}
structAttrs = makeAttrs(attrPacked, attrSize, attrAlign)
unionAttrs = makeAttrs(attrVarlen, attrSize)
+ fieldAttrs = makeAttrs(attrIn, attrOut, attrInOut)
callAttrs = make(map[string]*attrDesc)
)
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go
index 9bb8c1c0c..468b6e35e 100644
--- a/pkg/compiler/check.go
+++ b/pkg/compiler/check.go
@@ -168,6 +168,14 @@ func (comp *compiler) checkStructFields(n *ast.Struct, typ, name string) {
if len(n.Fields) < 1 {
comp.error(n.Pos, "%v %v has no fields, need at least 1 field", typ, name)
}
+ for _, f := range n.Fields {
+ attrs := comp.parseAttrs(fieldAttrs, f, f.Attrs)
+
+ if attrs[attrIn]+attrs[attrOut]+attrs[attrInOut] > 1 {
+ _, typ, _ := f.Info()
+ comp.error(f.Pos, "%v has multiple direction attributes", typ)
+ }
+ }
}
func (comp *compiler) checkFieldGroup(fields []*ast.Field, what, ctx string) {
@@ -267,6 +275,16 @@ func (comp *compiler) checkAttributeValues() {
desc.CheckConsts(comp, n, attr)
}
}
+ // Check each field's attributes.
+ st := decl.(*ast.Struct)
+ for _, f := range st.Fields {
+ for _, attr := range f.Attrs {
+ desc := fieldAttrs[attr.Ident]
+ if desc.CheckConsts != nil {
+ desc.CheckConsts(comp, f, attr)
+ }
+ }
+ }
}
}
}
@@ -614,7 +632,11 @@ func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool,
}
checked[key] = true
for _, fld := range s.Fields {
- comp.checkTypeCtors(fld.Type, dir, false, ctors, inputs, checked)
+ fldDir, fldHasDir := comp.genFieldDir(fld)
+ if !fldHasDir {
+ fldDir = dir
+ }
+ comp.checkTypeCtors(fld.Type, fldDir, false, ctors, inputs, checked)
}
return
}
diff --git a/pkg/compiler/gen.go b/pkg/compiler/gen.go
index d4834e40e..bd487432a 100644
--- a/pkg/compiler/gen.go
+++ b/pkg/compiler/gen.go
@@ -441,10 +441,28 @@ func (comp *compiler) genFieldArray(fields []*ast.Field, argSizes []uint64) []pr
return res
}
+func (comp *compiler) genFieldDir(f *ast.Field) (prog.Dir, bool) {
+ attrs := comp.parseAttrs(fieldAttrs, f, f.Attrs)
+ switch {
+ case attrs[attrIn] != 0:
+ return prog.DirIn, true
+ case attrs[attrOut] != 0:
+ return prog.DirOut, true
+ case attrs[attrInOut] != 0:
+ return prog.DirInOut, true
+ default:
+ return prog.DirIn, false
+ }
+}
+
func (comp *compiler) genField(f *ast.Field, argSize uint64) prog.Field {
+ dir, hasDir := comp.genFieldDir(f)
+
return prog.Field{
- Name: f.Name.Name,
- Type: comp.genType(f.Type, argSize),
+ Name: f.Name.Name,
+ Type: comp.genType(f.Type, argSize),
+ HasDirection: hasDir,
+ Direction: dir,
}
}
diff --git a/pkg/compiler/testdata/all.txt b/pkg/compiler/testdata/all.txt
index b9e144d73..17b7c838d 100644
--- a/pkg/compiler/testdata/all.txt
+++ b/pkg/compiler/testdata/all.txt
@@ -276,7 +276,15 @@ s4 {
f2 int8
} [size[19]]
-foo_s0(a ptr[in, s0], b ptr[in, s1], c ptr[in, s2], d ptr[in, s4])
+s5 {
+ f_in0 int32 (in)
+ f_in1 int32[0:1] (in)
+ f_out int32 (out)
+ f_inout0 int32 (inout)
+ f_inout1 int32[0:1] (inout)
+}
+
+foo_s0(a ptr[in, s0], b ptr[in, s1], c ptr[in, s2], d ptr[in, s4], e ptr[in, s5])
# Unions.
diff --git a/pkg/compiler/testdata/errors.txt b/pkg/compiler/testdata/errors.txt
index cc0f47508..d3658d239 100644
--- a/pkg/compiler/testdata/errors.txt
+++ b/pkg/compiler/testdata/errors.txt
@@ -346,3 +346,13 @@ struct$fmt0 {
f0 fmt[dec, int8:3] ### unexpected ':', only struct fields can be bitfields
f1 int32:-1 ### bitfield of size 18446744073709551615 is too large for base type of size 32
}
+
+struct$perfielddir {
+ f0 int32 (in, in) ### duplicate arg/field f0 attribute in
+ f1 int32 (out, out) ### duplicate arg/field f1 attribute out
+ f2 int32 (inout, inout) ### duplicate arg/field f2 attribute inout
+ f3 int32 (in, out) ### arg/field has multiple direction attributes
+ f4 int32 (in, inout) ### arg/field has multiple direction attributes
+ f5 int32 (out, inout) ### arg/field has multiple direction attributes
+ f6 int32 (in, out, inout) ### arg/field has multiple direction attributes
+} \ No newline at end of file
diff --git a/pkg/compiler/testdata/errors2.txt b/pkg/compiler/testdata/errors2.txt
index 68b8a66df..c862358cf 100644
--- a/pkg/compiler/testdata/errors2.txt
+++ b/pkg/compiler/testdata/errors2.txt
@@ -176,11 +176,26 @@ resource r104[int8]
resource r105[int8]
resource r106[int8] ### resource r106 can't be created (never mentioned as a syscall return value or output argument/field)
resource r107[int8] ### resource r107 can't be created (never mentioned as a syscall return value or output argument/field)
-resource r108[int8] ### resource r108 is never used as an input(such resources are not useful)
-
-foo$300(a0 r100, a1 r101, a2 r102, a3 r103, a4 r104)
-foo$301(a ptr[out, array[r103]], b ptr[in, s300], c r107) r104
-foo$302() r108
+resource r108[int8] ### resource r108 can't be created (never mentioned as a syscall return value or output argument/field)
+resource r109[int8] ### resource r109 can't be created (never mentioned as a syscall return value or output argument/field)
+resource r110[int8]
+resource r111[int8]
+resource r112[int8] ### resource r112 can't be created (never mentioned as a syscall return value or output argument/field)
+resource r113[int8]
+resource r114[int8]
+resource r115[int8] ### resource r115 can't be created (never mentioned as a syscall return value or output argument/field)
+resource r116[int8] ### resource r116 is never used as an input(such resources are not useful)
+resource r117[int8] ### resource r117 is never used as an input(such resources are not useful)
+resource r118[int8] ### resource r118 is never used as an input(such resources are not useful)
+resource r119[int8] ### resource r119 is never used as an input(such resources are not useful)
+resource r120[int8] ### resource r120 can't be created (never mentioned as a syscall return value or output argument/field)
+resource r121[int8]
+
+foo$300(a0 r100, a1 r101, a2 r102, a3 r103, a4 r104, a5 r105, a6 r106, a7 r107, a8 r108)
+foo$301(a0 r109, a1 r110, a2 r111, a3 r112, a4 r113, a5 r114, a6 r115, a7 r120, a8 r121)
+foo$302(a ptr[out, array[r103]], b ptr[in, s300], c r107) r104
+foo$303(a ptr[in, s302], b ptr[in, s303], c ptr[in, s304], d ptr[out, s305], e ptr[inout, s306], f ptr[inout, s307], g ptr[in, s308], h ptr[out, s310])
+foo$304(a ptr[out, r117], b ptr[in, s312], c ptr[in, s313], d ptr[inout, u100]) r116
s300 {
f1 ptr[inout, s301]
@@ -191,6 +206,75 @@ s301 {
f2 r105
}
+s302 {
+ f1 r108
+}
+
+s303 {
+ f1 r109 (in)
+}
+
+# ptr to struct is in, field is out (valid, resource can be created)
+s304 {
+ f1 r110 (out)
+}
+
+# ptr to struct is out, field is in (error, resource can't be created)
+s305 {
+ f1 r111 (in)
+}
+
+# ptr to struct is inout, field is inout (valid, resource can be created)
+s306 {
+ f1 r111 (inout)
+}
+
+# ptr to struct is inout, fields are in (error) and out (valid)
+s307 {
+ f1 r112 (in)
+ f2 r113 (out)
+}
+
+# recurse the out field inside two levels of in ptrs (valid, resource can be created)
+s308 {
+ f1 ptr[in, s309]
+}
+
+s309 {
+ f1 ptr[out, r114]
+}
+
+# recurse the in field inside two levels of out ptrs (error, resource can't be created)
+s310 {
+ f1 ptr[out, s311]
+}
+
+s311 {
+ f1 ptr[in, r115]
+}
+
+# ptr to struct is in, field is out (error, never used as an input)
+s312 {
+ f1 r118 (out)
+}
+
+# recurse the out field inside two levels of in ptrs (error, never used as an input)
+s313 {
+ f1 ptr[in, s314]
+}
+
+s314 {
+ f1 r119 (out)
+}
+
+u100 [
+ f1 r120 (in)
+ f2 r121 (out)
+]
+
+# TODO: Two instances of the same resource might exist in the same structure as
+# both in and out. How common is this and how to handle this?
+
# Varlen field tests.
s400 {