diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2019-05-10 17:15:29 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2019-05-14 19:28:01 +0200 |
| commit | 1886b2a4811a4d9adbfc509505a095848cc655eb (patch) | |
| tree | 8ab666c6f9ea59912d911abd5639480eae534eda /pkg | |
| parent | 354b388e08761dabb99236aa73a24e9b861b6e5f (diff) | |
pkg/ast: refactor COLON handling
This prepared for handling of bytesize[parent:foo:bar] expressions
by allowing multiple identifiers after colon.
No functional changes for now, just preparation for storing more
than one identifier after colon.
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/ast/ast.go | 11 | ||||
| -rw-r--r-- | pkg/ast/clone.go | 6 | ||||
| -rw-r--r-- | pkg/ast/format.go | 9 | ||||
| -rw-r--r-- | pkg/ast/parser.go | 10 | ||||
| -rw-r--r-- | pkg/ast/testdata/all.txt | 1 | ||||
| -rw-r--r-- | pkg/compiler/check.go | 31 | ||||
| -rw-r--r-- | pkg/compiler/compiler.go | 2 | ||||
| -rw-r--r-- | pkg/compiler/consts.go | 14 | ||||
| -rw-r--r-- | pkg/compiler/types.go | 88 |
9 files changed, 93 insertions, 79 deletions
diff --git a/pkg/ast/ast.go b/pkg/ast/ast.go index 1e1e97221..b692f8633 100644 --- a/pkg/ast/ast.go +++ b/pkg/ast/ast.go @@ -199,13 +199,10 @@ type Type struct { Ident string String string HasString bool - // Part after COLON (for ranges and bitfields). - HasColon bool - Pos2 Pos - Value2 uint64 - Value2Fmt IntFmt - Ident2 string - Args []*Type + // Parts after COLON (for ranges and bitfields). + Colon []*Type + // Sub-types in []. + Args []*Type } func (n *Type) Info() (Pos, string, string) { diff --git a/pkg/ast/clone.go b/pkg/ast/clone.go index 13a603ba8..a594e41f6 100644 --- a/pkg/ast/clone.go +++ b/pkg/ast/clone.go @@ -155,11 +155,7 @@ func (n *Type) Clone() Node { Ident: n.Ident, String: n.String, HasString: n.HasString, - HasColon: n.HasColon, - Pos2: n.Pos2, - Value2: n.Value2, - Value2Fmt: n.Value2Fmt, - Ident2: n.Ident2, + Colon: cloneTypes(n.Colon), Args: cloneTypes(n.Args), } } diff --git a/pkg/ast/format.go b/pkg/ast/format.go index 13cd26e2c..c3d931706 100644 --- a/pkg/ast/format.go +++ b/pkg/ast/format.go @@ -176,13 +176,8 @@ func fmtType(t *Type) string { default: v = FormatInt(t.Value, t.ValueFmt) } - if t.HasColon { - switch { - case t.Ident2 != "": - v += fmt.Sprintf(":%v", t.Ident2) - default: - v += fmt.Sprintf(":%v", FormatInt(t.Value2, t.Value2Fmt)) - } + for _, c := range t.Colon { + v += ":" + fmtType(c) } v += fmtTypeList(t.Args) return v diff --git a/pkg/ast/parser.go b/pkg/ast/parser.go index bd9d33657..b68a1a8a2 100644 --- a/pkg/ast/parser.go +++ b/pkg/ast/parser.go @@ -425,16 +425,18 @@ func (p *parser) parseType() *Type { } p.next() if allowColon && p.tryConsume(tokColon) { - arg.HasColon = true - arg.Pos2 = p.pos + col := &Type{ + Pos: p.pos, + } switch p.tok { case tokInt: - arg.Value2, arg.Value2Fmt = p.parseIntValue() + col.Value, col.ValueFmt = p.parseIntValue() case tokIdent: - arg.Ident2 = p.lit + col.Ident = p.lit default: p.expect(tokInt, tokIdent) } + arg.Colon = append(arg.Colon, col) p.next() } arg.Args = p.parseTypeList() diff --git a/pkg/ast/testdata/all.txt b/pkg/ast/testdata/all.txt index 6e4e72d2c..e5a1839dd 100644 --- a/pkg/ast/testdata/all.txt +++ b/pkg/ast/testdata/all.txt @@ -27,6 +27,7 @@ define FOO `bar` define FOO `bar ### C expression is not terminated foo(x int32[1:2:3, opt]) ### unexpected ':', expecting ']' +foo2(x int32[1[2]:2]) ### unexpected ':', expecting ']' s0 { f0 string[""] diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go index e79a161b4..c5337a63b 100644 --- a/pkg/compiler/check.go +++ b/pkg/compiler/check.go @@ -669,8 +669,8 @@ func (comp *compiler) checkStruct(ctx checkCtx, n *ast.Struct) { comp.error(attr.Pos, "unexpected %v, expect attribute", unexpected) return } - if attr.HasColon { - comp.error(attr.Pos2, "unexpected ':'") + if len(attr.Colon) != 0 { + comp.error(attr.Colon[0].Pos, "unexpected ':'") return } } @@ -745,13 +745,13 @@ func (comp *compiler) checkType(ctx checkCtx, t *ast.Type, flags checkFlags) { } func (comp *compiler) checkTypeBasic(t *ast.Type, desc *typeDesc, flags checkFlags) { - if t.HasColon { - if !desc.AllowColon { - comp.error(t.Pos2, "unexpected ':'") + for i, col := range t.Colon { + if i >= desc.MaxColon { + comp.error(col.Pos, "unexpected ':'") return } if flags&checkIsStruct == 0 { - comp.error(t.Pos2, "unexpected ':', only struct fields can be bitfields") + comp.error(col.Pos, "unexpected ':', only struct fields can be bitfields") return } } @@ -814,7 +814,7 @@ func (comp *compiler) checkTypeArgs(t *ast.Type, desc *typeDesc, flags checkFlag func (comp *compiler) replaceTypedef(ctx *checkCtx, t *ast.Type, flags checkFlags) { typedefName := t.Ident comp.usedTypedefs[typedefName] = true - if t.HasColon { + if len(t.Colon) != 0 { comp.error(t.Pos, "type alias %v with ':'", t.Ident) return } @@ -912,9 +912,12 @@ func (comp *compiler) instantiate(templ ast.Node, params []*ast.Ident, args []*a // Need more checks here. E.g. that CONST_ARG does not have subargs. // And if CONST_ARG is a value, then use concreteArg.Value. // Also need to error if CONST_ARG is a string. - if concreteArg := argMap[templArg.Ident2]; concreteArg != nil { - templArg.Ident2 = concreteArg.Ident - templArg.Pos2 = concreteArg.Pos + if len(templArg.Colon) != 0 { + col := templArg.Colon[0] + if concreteArg := argMap[col.Ident]; concreteArg != nil { + col.Ident = concreteArg.Ident + col.Pos = concreteArg.Pos + } } })) return err0 == comp.errors @@ -940,9 +943,11 @@ func (comp *compiler) checkTypeArg(t, arg *ast.Type, argDesc namedArg) { return } } - if !desc.AllowColon && arg.HasColon { - comp.error(arg.Pos2, "unexpected ':'") - return + for i, col := range arg.Colon { + if i >= desc.MaxColon { + comp.error(col.Pos, "unexpected ':'") + return + } } if len(arg.Args) > desc.MaxArgs { comp.error(arg.Pos, "%v argument has subargs", argDesc.Name) diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index 5abc8e2a8..508dc0f26 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -242,7 +242,7 @@ func (comp *compiler) parseSizeAttr(attr *ast.Type) uint64 { comp.error(sz.Pos, "unexpected %v, expect int", unexpected) return sizeUnassigned } - if sz.HasColon || len(sz.Args) != 0 { + if len(sz.Colon) != 0 || len(sz.Args) != 0 { comp.error(sz.Pos, "size attribute has colon or args") return sizeUnassigned } diff --git a/pkg/compiler/consts.go b/pkg/compiler/consts.go index d3556c047..1816bc1f6 100644 --- a/pkg/compiler/consts.go +++ b/pkg/compiler/consts.go @@ -73,9 +73,11 @@ func (comp *compiler) extractConsts() map[string]*ConstInfo { info := getConstInfo(infos, arg.Pos) info.consts[arg.Ident] = true } - if arg.Ident2 != "" { - info := getConstInfo(infos, arg.Pos2) - info.consts[arg.Ident2] = true + for _, col := range arg.Colon { + if col.Ident != "" { + info := getConstInfo(infos, col.Pos) + info.consts[col.Ident] = true + } } } } @@ -183,9 +185,9 @@ func (comp *compiler) patchConsts(consts map[string]uint64) { for i, arg := range args { if desc.Args[i].Type.Kind == kindInt { comp.patchIntConst(&arg.Value, &arg.Ident, consts, &missing) - if arg.HasColon { - comp.patchIntConst(&arg.Value2, - &arg.Ident2, consts, &missing) + for _, col := range arg.Colon { + comp.patchIntConst(&col.Value, + &col.Ident, consts, &missing) } } } diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go index 1a230458d..17fb1b93a 100644 --- a/pkg/compiler/types.go +++ b/pkg/compiler/types.go @@ -17,7 +17,7 @@ type typeDesc struct { CanBeTypedef bool // can be type alias target? CantBeOpt bool // can't be marked as opt? NeedBase bool // needs base type when used as field? - AllowColon bool // allow colon (int8:2) on fields? + MaxColon int // max number of colons (int8:2) on fields OptArgs int // number of optional arguments in Args array Args []namedArg // type arguments // CanBeArgRet returns if this type can be syscall argument/return (false if nil). @@ -38,10 +38,10 @@ type typeDesc struct { // typeArg describes a type argument. type typeArg struct { - Names []string - Kind int // int/ident/string - MaxArgs int // maxiumum number of subargs - AllowColon bool // allow colon (2:3)? + Names []string + Kind int // int/ident/string + MaxArgs int // maxiumum number of subargs + MaxColon int // max number of colons (2:3) // Check does custom verification of the arg (optional). Check func(comp *compiler, t *ast.Type) CheckConsts func(comp *compiler, t *ast.Type) @@ -67,7 +67,7 @@ var typeInt = &typeDesc{ Names: typeArgBase.Type.Names, CanBeArgRet: canBeArg, CanBeTypedef: true, - AllowColon: true, + MaxColon: 1, OptArgs: 1, Args: []namedArg{{Name: "range", Type: typeArgIntRange}}, CanBeResourceBase: func(comp *compiler, t *ast.Type) bool { @@ -85,11 +85,19 @@ var typeInt = &typeDesc{ size, be := comp.parseIntType(t.Ident) kind, rangeBegin, rangeEnd := prog.IntPlain, uint64(0), uint64(0) if len(args) > 0 { - kind, rangeBegin, rangeEnd = prog.IntRange, args[0].Value, args[0].Value2 + rangeArg := args[0] + kind, rangeBegin, rangeEnd = prog.IntRange, rangeArg.Value, rangeArg.Value + if len(rangeArg.Colon) != 0 { + rangeEnd = rangeArg.Colon[0].Value + } + } + var bitLen uint64 + if len(t.Colon) != 0 { + bitLen = t.Colon[0].Value } base.TypeSize = size return &prog.IntType{ - IntTypeCommon: genIntCommon(base.TypeCommon, t.Value2, be), + IntTypeCommon: genIntCommon(base.TypeCommon, bitLen, be), Kind: kind, RangeBegin: rangeBegin, RangeEnd: rangeEnd, @@ -139,7 +147,7 @@ var typeArray = &typeDesc{ OptArgs: 1, Args: []namedArg{{Name: "type", Type: typeArgType}, {Name: "size", Type: typeArgSizeRange}}, CheckConsts: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) { - if len(args) > 1 && args[1].Value == 0 && args[1].Value2 == 0 { + if len(args) > 1 && args[1].Value == 0 && (len(args[1].Colon) == 0 || args[1].Colon[0].Value == 0) { comp.error(args[1].Pos, "arrays of size 0 are not supported") } }, @@ -151,7 +159,7 @@ var typeArray = &typeDesc{ return true } if len(args) > 1 { - return args[1].Value != args[1].Value2 + return len(args[1].Colon) != 0 && args[1].Value != args[1].Colon[0].Value } return true }, @@ -162,7 +170,10 @@ var typeArray = &typeDesc{ elemType := comp.genType(args[0], "", base.ArgDir, false) kind, begin, end := prog.ArrayRandLen, uint64(0), uint64(0) if len(args) > 1 { - kind, begin, end = prog.ArrayRangeLen, args[1].Value, args[1].Value2 + kind, begin, end = prog.ArrayRangeLen, args[1].Value, args[1].Value + if len(args[1].Colon) != 0 { + end = args[1].Colon[0].Value + } } if it, ok := elemType.(*prog.IntType); ok && it.Kind == prog.IntPlain && it.TypeSize == 1 { // Special case: buffer is better mutated. @@ -301,9 +312,12 @@ var typeVMA = &typeDesc{ OptArgs: 1, Args: []namedArg{{Name: "size range", Type: typeArgSizeRange}}, Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type { - begin, end := uint64(0), uint64(0) + var begin, end uint64 if len(args) > 0 { - begin, end = args[0].Value, args[0].Value2 + begin, end = args[0].Value, args[0].Value + if len(args[0].Colon) != 0 { + end = args[0].Colon[0].Value + } } base.TypeSize = comp.ptrSize if t.Ident == "vma64" { @@ -762,30 +776,31 @@ var typeArgInt = &typeArg{ } var typeArgIntRange = &typeArg{ - Kind: kindInt, - AllowColon: true, + Kind: kindInt, + MaxColon: 1, CheckConsts: func(comp *compiler, t *ast.Type) { - if !t.HasColon { - t.Value2 = t.Value - t.Value2Fmt = t.ValueFmt + end := t.Value + if len(t.Colon) != 0 { + end = t.Colon[0].Value } - if t.Value2-t.Value > 1<<64-1<<32 { - comp.error(t.Pos, "bad int range [%v:%v]", t.Value, t.Value2) + if end-t.Value > 1<<64-1<<32 { + comp.error(t.Pos, "bad int range [%v:%v]", t.Value, end) } }, } // Size of array and vma's. var typeArgSizeRange = &typeArg{ - Kind: kindInt, - AllowColon: true, + Kind: kindInt, + MaxColon: 1, CheckConsts: func(comp *compiler, t *ast.Type) { - if !t.HasColon { - t.Value2 = t.Value + end := t.Value + if len(t.Colon) != 0 { + end = t.Colon[0].Value } const maxVal = 1e6 - if t.Value > t.Value2 || t.Value > maxVal || t.Value2 > maxVal { - comp.error(t.Pos, "bad size range [%v:%v]", t.Value, t.Value2) + if t.Value > end || t.Value > maxVal || end > maxVal { + comp.error(t.Pos, "bad size range [%v:%v]", t.Value, end) } }, } @@ -794,25 +809,26 @@ var typeArgSizeRange = &typeArg{ var typeArgBase = namedArg{ Name: "base type", Type: &typeArg{ - Names: []string{"int8", "int16", "int32", "int64", "int16be", "int32be", "int64be", "intptr"}, - AllowColon: true, + Names: []string{"int8", "int16", "int32", "int64", "int16be", "int32be", "int64be", "intptr"}, + MaxColon: 1, Check: func(comp *compiler, t *ast.Type) { - if t.HasColon { - if t.Ident2 != "" { - comp.error(t.Pos2, "literal const bitfield sizes are not supported") + if len(t.Colon) != 0 { + col := t.Colon[0] + if col.Ident != "" { + comp.error(col.Pos, "literal const bitfield sizes are not supported") return } - if t.Value2 == 0 { + if col.Value == 0 { // This was not supported historically // and does not work the way C bitfields of size 0 work. // We could allow this, but then we need to make // this work the way C bitfields work. - comp.error(t.Pos2, "bitfields of size 0 are not supported") + comp.error(col.Pos, "bitfields of size 0 are not supported") } size, _ := comp.parseIntType(t.Ident) - if t.Value2 > size*8 { - comp.error(t.Pos2, "bitfield of size %v is too large for base type of size %v", - t.Value2, size*8) + if col.Value > size*8 { + comp.error(col.Pos, "bitfield of size %v is too large for base type of size %v", + col.Value, size*8) } } }, |
