summaryrefslogtreecommitdiff
path: root/vendor/modernc.org/ccgo/v3/lib/init.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/modernc.org/ccgo/v3/lib/init.go')
-rw-r--r--vendor/modernc.org/ccgo/v3/lib/init.go225
1 files changed, 105 insertions, 120 deletions
diff --git a/vendor/modernc.org/ccgo/v3/lib/init.go b/vendor/modernc.org/ccgo/v3/lib/init.go
index d57113a9a..ad443cd2e 100644
--- a/vendor/modernc.org/ccgo/v3/lib/init.go
+++ b/vendor/modernc.org/ccgo/v3/lib/init.go
@@ -38,7 +38,7 @@ func (p *project) initializer(f *function, n *cc.Initializer, t cc.Type, sc cc.S
}
if a.Field == nil || b.Field == nil || !a.Field.IsBitField() || !b.Field.IsBitField() {
- panic(todo("%v: internal error: %#x, %v: %#x", a.Position(), a.Offset, b.Position(), b.Offset))
+ panic(todo("%v: internal error: off %#x, %v: off %#x, t %v", a.Position(), a.Offset, b.Position(), b.Offset, t))
}
return a.Field.BitFieldOffset() < b.Field.BitFieldOffset()
@@ -87,9 +87,6 @@ func (p *project) initializerInner(tag string, off uintptr, f *function, s []*cc
if k == cc.Array && len(s) == 1 {
et := t.Elem()
- if dmesgs { //TODO-
- dmesg("%v: %v", s[0].Position(), et)
- }
switch {
case isCharType(et):
// 14: An array of character type may be initialized by a character string
@@ -147,13 +144,13 @@ func (p *project) initializerInner(tag string, off uintptr, f *function, s []*cc
case cc.Union:
p.initializerUnion(tag, off, f, s, t, sc, tld, lm, tm)
default:
- panic(todo("%v: internal error: %v %v", s[0].Position(), t, len(s)))
+ panic(todo("%v: internal error: %v alias %v %v", s[0].Position(), t, t.Alias(), len(s)))
}
}
func (p *project) initializerArray(tag string, off uintptr, f *function, s []*cc.Initializer, t cc.Type, sc cc.StorageClass, tld *tld, lm, tm map[*cc.Initializer][]cc.StringID) {
if len(s) == 0 {
- p.w("%s{}", p.typ(nil, t))
+ p.w("%s%s{}", tag, p.typ(nil, t))
return
}
@@ -172,7 +169,7 @@ func (p *project) initializerArray(tag string, off uintptr, f *function, s []*cc
for _, parts = range a {
var comma *cc.Token
comma = parts[len(parts)-1].TrailingComma()
- elemOff := parts[0].Offset - off
+ elemOff := (parts[0].Offset - off) / esz * esz
tag = ""
if mustIndex {
tag = fmt.Sprintf("%d:", elemOff/esz)
@@ -217,7 +214,7 @@ func (p *project) initializerArrayElement(off uintptr, s []*cc.Initializer, elem
func (p *project) initializerStruct(tag string, off uintptr, f *function, s []*cc.Initializer, t cc.Type, sc cc.StorageClass, tld *tld, lm, tm map[*cc.Initializer][]cc.StringID) {
if len(s) == 0 {
- p.w("%s{}", p.typ(nil, t))
+ p.w("%s%s{}", tag, p.typ(nil, t))
return
}
@@ -232,7 +229,7 @@ func (p *project) initializerStruct(tag string, off uintptr, f *function, s []*c
var fld cc.Field
for len(s) != 0 {
var comma *cc.Token
- s, fld, parts, isZero = p.initializerStructField(off, s, t)
+ s, fld, parts, isZero = p.structInitializerParts(off, s, t)
if isZero {
continue
}
@@ -246,6 +243,8 @@ func (p *project) initializerStruct(tag string, off uintptr, f *function, s []*c
ft := fld.Type()
switch {
case fld.IsBitField():
+ bft := p.bitFileType(parts[0], fld.BitFieldBlockWidth())
+ off0 := fld.Offset()
first := true
for _, v := range parts {
if v.AssignmentExpression.Operand.IsZero() {
@@ -257,12 +256,11 @@ func (p *project) initializerStruct(tag string, off uintptr, f *function, s []*c
}
first = false
bitFld := v.Field
- bft := p.bitFileType(bitFld.BitFieldBlockWidth())
p.w("%s%s", tidyComment("", v.AssignmentExpression), tag)
tag = ""
p.assignmentExpression(f, v.AssignmentExpression, bft, exprValue, fOutermost)
p.w("&%#x", uint64(1)<<uint64(bitFld.BitFieldWidth())-1)
- if o := bitFld.BitFieldOffset(); o != 0 {
+ if o := bitFld.BitFieldOffset() + 8*int((bitFld.Offset()-off0)); o != 0 {
p.w("<<%d", o)
}
}
@@ -283,154 +281,141 @@ func (p *project) preCommaSep(comma *cc.Token) {
p.w("%s", strings.TrimSpace(comma.Sep.String()))
}
-func (p *project) initializerStructField(off uintptr, s []*cc.Initializer, t cc.Type) (r []*cc.Initializer, fld cc.Field, parts []*cc.Initializer, isZero bool) {
- r = s
- isZero = true
- valueOff := s[0].Offset
- nf := t.NumField()
- nextOff := off + t.Size()
- bits := false
- for i := []int{0}; i[0] < nf; i[0]++ {
- fld2 := t.FieldByIndex(i)
- if fld2.Name() == 0 {
- continue
- }
+func (p *project) structInitializerParts(off uintptr, s []*cc.Initializer, t cc.Type) (r []*cc.Initializer, fld cc.Field, parts []*cc.Initializer, isZero bool) {
+ if len(s) == 0 {
+ return nil, nil, nil, true
+ }
- if fld == nil {
- fld = fld2
- }
- if fld2.Offset()+off > valueOff {
- nextOff = off + fld2.Offset()
+ part := s[0]
+ isZero = part.AssignmentExpression.Operand.IsZero()
+ parts = append(parts, part)
+ s = s[1:]
+ fld, _, fNext := p.containingStructField(part, off, t)
+ for len(s) != 0 {
+ part = s[0]
+ vOff := part.Offset
+ if vOff >= fNext {
break
}
- if !fld2.IsBitField() {
- fld = fld2
- continue
- }
-
- fld = fld2.BitFieldBlockFirst()
+ isZero = isZero && part.AssignmentExpression.Operand.IsZero()
+ parts = append(parts, part)
+ s = s[1:]
}
- for len(s) != 0 {
- if v := s[0]; v.Offset < nextOff || v.Type().Size() == 0 {
- if v.Field != nil && v.Field.IsBitField() {
- bits = true
- }
- s = s[1:]
- parts = append(parts, v)
- if !v.AssignmentExpression.Operand.IsZero() {
- isZero = false
- }
+ return s, fld, parts, isZero
+}
+
+func (p *project) containingStructField(part *cc.Initializer, off uintptr, t cc.Type) (f cc.Field, fOff, fNext uintptr) {
+ nf := t.NumField()
+ vOff := part.Offset
+ for i := []int{0}; i[0] < nf; i[0]++ {
+ f = t.FieldByIndex(i)
+ if f.IsBitField() && f.Name() == 0 { // Anonymous bit fields cannot be initialized.
continue
}
- break
- }
- if bits && fld.Name() == 0 {
- for _, v := range parts {
- if v.Field != nil && v.Field.Name() != 0 {
- fld = v.Field
- break
- }
+ fOff = off + f.Offset()
+ switch {
+ case f.IsBitField():
+ fNext = fOff + uintptr(f.BitFieldBlockWidth())>>3
+ default:
+ fNext = fOff + f.Type().Size()
+ }
+ if vOff >= fOff && vOff < fNext {
+ return f, fOff, fNext
}
}
- return r[len(parts):], fld, parts, isZero
+
+ panic(todo("%v: internal error", pos(part)))
}
func (p *project) initializerUnion(tag string, off uintptr, f *function, s []*cc.Initializer, t cc.Type, sc cc.StorageClass, tld *tld, lm, tm map[*cc.Initializer][]cc.StringID) {
if len(s) == 0 {
- p.w("%s{}", p.typ(nil, t))
+ p.w("%s%s{}", tag, p.typ(nil, t))
return
}
- s0 := s[0]
- var parts []*cc.Initializer
- var isZero bool
- var fld cc.Field
- s, fld, parts, isZero = p.initializerUnionField(off, s, t)
- if len(s) != 0 {
- panic(todo("%v: internal error: %v", s0.Position(), t))
- }
-
- if isZero {
- p.w("%s%s%s{", initComment(s0, lm), tag, p.typ(s0, t))
- p.w("%s}", initComment(parts[len(parts)-1], tm))
+ if t.HasFlexibleMember() {
+ p.err(s[0], "flexible array members not supported")
return
}
- if fld0 := parts[0].FirstDesignatorField(); fld0 != nil && fld0.Index() != 0 {
- if fld0.IsBitField() || fld.IsBitField() {
- panic(todo(""))
- }
-
- fld := parts[0].Field
- if fld.IsBitField() {
- panic(todo(""))
- }
-
- // tag: *(*T)(unsafe.Pointer(&struct{f: ft; pad _[n]byte}{f: expr}))
- p.w("%s *(*%s)(unsafe.Pointer(&struct{f %s", tag, p.typ(s0, t), p.typ(s0, fld.Type()))
- if pad := t.Size() - fld.Type().Size(); pad != 0 {
- p.w("; _ [%v]byte", pad)
- }
- p.w("}{")
- p.initializerInner("f:", off+fld.Offset(), f, parts, fld.Type(), sc, tld, fld, lm, tm)
- p.w("}))")
+ parts, isZero := p.initializerUnionField(off, s, t)
+ if len(parts) == 0 || isZero {
+ p.w("%s%s%s{", initComment(s[0], lm), tag, p.typ(s[0], t))
+ p.w("%s}", initComment(parts[len(parts)-1], tm))
return
}
- p.w("%s%s%s{", initComment(s0, lm), tag, p.typ(s0, t))
- ft := fld.Type()
- tag = fmt.Sprintf("%s:", p.fieldName2(parts[0], fld))
- switch {
- case fld.IsBitField():
- first := true
- for _, v := range parts {
- if v.AssignmentExpression.Operand.IsZero() {
- continue
- }
-
- if !first {
- p.w("|")
+ p.w("%sfunc() (r %s) {", tag, p.typ(parts[0], t))
+ for _, part := range parts {
+ var ft cc.Type
+ fld := part.Field
+ if fld != nil && fld.IsBitField() {
+ }
+
+ if ft == nil {
+ ft = part.Type()
+ }
+ if ft.Kind() == cc.Array {
+ et := ft.Elem()
+ switch {
+ case isCharType(et):
+ switch x := part.AssignmentExpression.Operand.Value().(type) {
+ case cc.StringValue:
+ str := cc.StringID(x).String()
+ slen := uintptr(len(str)) + 1
+ alen := ft.Len()
+ switch {
+ case alen < slen-1:
+ p.w("copy(((*[%d]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&r))+%d)))[:], (*[%d]byte)(unsafe.Pointer(%s))[:])\n", alen, part.Offset-off, alen, p.stringLiteralString(str[:alen]))
+ case alen < slen:
+ p.w("copy(((*[%d]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&r))+%d)))[:], (*[%d]byte)(unsafe.Pointer(%s))[:])\n", alen, part.Offset-off, alen, p.stringLiteralString(str))
+ default: // alen >= slen
+ p.w("copy(((*[%d]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&r))+%d)))[:], (*[%d]byte)(unsafe.Pointer(%s))[:])\n", alen, part.Offset-off, alen, p.stringLiteralString(str+strings.Repeat("\x00", int(alen-slen))))
+ }
+ continue
+ default:
+ panic(todo("%v: %v <- %T", pos(part), et, x))
+ }
+ case p.isWCharType(et):
+ panic(todo(""))
}
- first = false
- bitFld := v.Field
- bft := p.bitFileType(bitFld.BitFieldBlockWidth())
- p.w("%s%s", tidyComment("", v.AssignmentExpression), tag)
- tag = ""
- p.assignmentExpression(f, v.AssignmentExpression, bft, exprValue, fOutermost)
- p.w("&%#x", uint64(1)<<uint64(bitFld.BitFieldWidth())-1)
- if o := bitFld.BitFieldOffset(); o != 0 {
+ ft = et
+ }
+ switch {
+ case fld != nil && fld.IsBitField():
+ bft := p.bitFileType(part, fld.BitFieldBlockWidth())
+ p.w("*(*%s)(unsafe.Pointer(uintptr(unsafe.Pointer(&r))+%d)) |= ", p.typ(part, bft), part.Offset-off)
+ p.assignmentExpression(f, part.AssignmentExpression, bft, exprValue, fOutermost)
+ p.w("&%#x", uint64(1)<<uint64(fld.BitFieldWidth())-1)
+ if o := fld.BitFieldOffset(); o != 0 {
p.w("<<%d", o)
}
+ default:
+ p.w("*(*%s)(unsafe.Pointer(uintptr(unsafe.Pointer(&r))+%d)) = ", p.typ(part, ft), part.Offset-off)
+ p.assignmentExpression(f, part.AssignmentExpression, ft, exprValue, fOutermost)
}
- default:
- p.initializerInner(tag, off+fld.Offset(), f, parts, ft, sc, tld, fld, lm, tm)
+ p.w("\n")
}
- comma := parts[len(parts)-1].TrailingComma()
- p.preCommaSep(comma)
- p.w(",")
- p.w("%s}", initComment(parts[len(parts)-1], tm))
+ p.w("return r\n")
+ p.w("}()")
}
-func (p *project) initializerUnionField(off uintptr, s []*cc.Initializer, t cc.Type) (r []*cc.Initializer, fld cc.Field, parts []*cc.Initializer, isZero bool) {
- r = s
+func (p *project) initializerUnionField(off uintptr, s []*cc.Initializer, t cc.Type) (parts []*cc.Initializer, isZero bool) {
isZero = true
- fld = t.FieldByIndex([]int{0})
nextOff := off + t.Size()
for len(s) != 0 {
if v := s[0]; v.Offset < nextOff {
s = s[1:]
parts = append(parts, v)
- if !v.AssignmentExpression.Operand.IsZero() {
- isZero = false
- }
+ isZero = isZero && v.AssignmentExpression.Operand.IsZero()
continue
}
break
}
- return r[len(parts):], fld, parts, isZero
+ return parts, isZero
}
func compatibleStructOrUnion(t1, t2 cc.Type) bool {
@@ -498,7 +483,7 @@ func compatibleType(t1, t2 cc.Type) bool {
return true
}
-func (p *project) bitFileType(bits int) cc.Type {
+func (p *project) bitFileType(n cc.Node, bits int) cc.Type {
switch bits {
case 8:
return p.task.cfg.ABI.Type(cc.UChar)
@@ -509,7 +494,7 @@ func (p *project) bitFileType(bits int) cc.Type {
case 64:
return p.task.cfg.ABI.Type(cc.ULongLong)
default:
- panic(todo("%v: internal error: %v", bits))
+ panic(todo("%v: internal error: %v", n.Position(), bits))
}
}