aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2019-05-16 18:05:05 +0200
committerDmitry Vyukov <dvyukov@google.com>2019-05-16 18:05:05 +0200
commit76fc461b55cfe334e8d4be121f61fa25d079f8ba (patch)
tree88cc3472e7352c2cd74f3234acb4bd2083ff61d4 /pkg/compiler
parentf59a9cb554a8dfcbe13c8a0775542ee7a0d8a353 (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.go7
-rw-r--r--pkg/compiler/testdata/all.txt2
-rw-r--r--pkg/compiler/testdata/errors2.txt2
-rw-r--r--pkg/compiler/types.go7
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,
}
},
}