From 76fc461b55cfe334e8d4be121f61fa25d079f8ba Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 16 May 2019 18:05:05 +0200 Subject: 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. --- pkg/compiler/check.go | 7 ++++++- pkg/compiler/testdata/all.txt | 2 ++ pkg/compiler/testdata/errors2.txt | 2 ++ pkg/compiler/types.go | 7 ++++++- 4 files changed, 16 insertions(+), 2 deletions(-) (limited to 'pkg/compiler') 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, } }, } -- cgit mrf-deployment