diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2019-05-16 18:05:05 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2019-05-16 18:05:05 +0200 |
| commit | 76fc461b55cfe334e8d4be121f61fa25d079f8ba (patch) | |
| tree | 88cc3472e7352c2cd74f3234acb4bd2083ff61d4 /pkg/compiler | |
| parent | f59a9cb554a8dfcbe13c8a0775542ee7a0d8a353 (diff) | |
pkg/compiler: add offsetof type
Similar to C offsetof gives offset of a field
from the beginning of the parent struct.
We have several TODOs in descriptions asking for this.
Diffstat (limited to 'pkg/compiler')
| -rw-r--r-- | pkg/compiler/check.go | 7 | ||||
| -rw-r--r-- | pkg/compiler/testdata/all.txt | 2 | ||||
| -rw-r--r-- | pkg/compiler/testdata/errors2.txt | 2 | ||||
| -rw-r--r-- | pkg/compiler/types.go | 7 |
4 files changed, 16 insertions, 2 deletions
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go index 0b296e2ea..24acfe50f 100644 --- a/pkg/compiler/check.go +++ b/pkg/compiler/check.go @@ -415,7 +415,12 @@ func (comp *compiler) checkLenTargetRec(t0, t *ast.Type, targets []*ast.Type, parent := parents[pi] if parent.name != "" && (parent.name == target.Ident || target.Ident == prog.ParentRef) || parent.name == "" && target.Ident == prog.SyscallRef { - if len(targets) != 0 { + if len(targets) == 0 { + if t.Ident == "offsetof" { + comp.error(target.Pos, "%v must refer to fields", t.Ident) + return + } + } else { parents1 := make([]parentDesc, pi+1) copy(parents1, parents[:pi+1]) comp.checkLenTargetRec(t0, t, targets, parents1, warned) diff --git a/pkg/compiler/testdata/all.txt b/pkg/compiler/testdata/all.txt index 25461ff9a..68629c685 100644 --- a/pkg/compiler/testdata/all.txt +++ b/pkg/compiler/testdata/all.txt @@ -90,6 +90,8 @@ len_expr3 { f34 bytesize[len_expr1:f11:f22:f41, int32] f35 bytesize[len_expr2:f23:f41, int32] f36 bytesize[len_expr2:f24:f41, int32] + f37 offsetof[f32, int32] + f38 offsetof[len_expr2:f21, int32] } len_expr4 { diff --git a/pkg/compiler/testdata/errors2.txt b/pkg/compiler/testdata/errors2.txt index 311be3ea9..db8f87e25 100644 --- a/pkg/compiler/testdata/errors2.txt +++ b/pkg/compiler/testdata/errors2.txt @@ -147,6 +147,8 @@ slen1 { f5 len[slen22:f, int32] ### len path slen22 does not refer to a struct f6 len[syscall, int32] ### no argument name after syscall reference f7 len[syscall:b, int32] ### len target b does not exist + f8 offsetof[parent, int32] ### offsetof must refer to fields + f9 offsetof[slen1, int32] ### offsetof must refer to fields slen2 ptr[in, array[slen2]] slen21 slen2 slen22 array[slen2] diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go index 6d9211686..18027615d 100644 --- a/pkg/compiler/types.go +++ b/pkg/compiler/types.go @@ -204,13 +204,14 @@ var typeArray = &typeDesc{ } var typeLen = &typeDesc{ - Names: []string{"len", "bytesize", "bytesize2", "bytesize4", "bytesize8", "bitsize"}, + Names: []string{"len", "bytesize", "bytesize2", "bytesize4", "bytesize8", "bitsize", "offsetof"}, CanBeArgRet: canBeArg, CantBeOpt: true, NeedBase: true, Args: []namedArg{{Name: "len target", Type: typeArgLenTarget}}, Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type { var bitSize uint64 + var offset bool switch t.Ident { case "bytesize": bitSize = 8 @@ -219,6 +220,9 @@ var typeLen = &typeDesc{ bitSize = byteSize * 8 case "bitsize": bitSize = 1 + case "offsetof": + bitSize = 8 + offset = true } path := []string{args[0].Ident} for _, col := range args[0].Colon { @@ -228,6 +232,7 @@ var typeLen = &typeDesc{ IntTypeCommon: base, Path: path, BitSize: bitSize, + Offset: offset, } }, } |
