aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/link
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/link')
-rw-r--r--src/cmd/link/internal/ld/deadcode.go8
-rw-r--r--src/cmd/link/internal/ld/dwarf.go132
-rw-r--r--src/cmd/link/internal/ld/dwarf_test.go11
3 files changed, 136 insertions, 15 deletions
diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go
index 20609ed7bf..3d547259a1 100644
--- a/src/cmd/link/internal/ld/deadcode.go
+++ b/src/cmd/link/internal/ld/deadcode.go
@@ -552,8 +552,12 @@ func (d *deadcodePass) decodetypeMethods(ldr *loader.Loader, arch *sys.Arch, sym
off += 3 * arch.PtrSize
case abi.Chan: // reflect.chanType
off += 2 * arch.PtrSize
- case abi.Map: // reflect.mapType
- off += 4*arch.PtrSize + 8
+ case abi.Map:
+ if buildcfg.Experiment.SwissMap {
+ off += 4*arch.PtrSize + 8 // internal/abi.SwissMapType
+ } else {
+ off += 4*arch.PtrSize + 8 // internal/abi.OldMapType
+ }
case abi.Interface: // reflect.interfaceType
off += 3 * arch.PtrSize
default:
diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go
index 1dc31c2565..c44a689a10 100644
--- a/src/cmd/link/internal/ld/dwarf.go
+++ b/src/cmd/link/internal/ld/dwarf.go
@@ -864,6 +864,110 @@ func (d *dwctxt) mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valna
}
func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
+ if buildcfg.Experiment.SwissMap {
+ d.synthesizemaptypesSwiss(ctxt, die)
+ } else {
+ d.synthesizemaptypesOld(ctxt, die)
+ }
+}
+
+func (d *dwctxt) synthesizemaptypesSwiss(ctxt *Link, die *dwarf.DWDie) {
+ hash := walktypedef(d.findprotodie(ctxt, "type:runtime.hmap"))
+ bucket := walktypedef(d.findprotodie(ctxt, "type:runtime.bmap"))
+
+ if hash == nil {
+ return
+ }
+
+ for ; die != nil; die = die.Link {
+ if die.Abbrev != dwarf.DW_ABRV_MAPTYPE {
+ continue
+ }
+ gotype := loader.Sym(getattr(die, dwarf.DW_AT_type).Data.(dwSym))
+ keytype := decodetypeMapKey(d.ldr, d.arch, gotype)
+ valtype := decodetypeMapValue(d.ldr, d.arch, gotype)
+ keydata := d.ldr.Data(keytype)
+ valdata := d.ldr.Data(valtype)
+ keysize, valsize := decodetypeSize(d.arch, keydata), decodetypeSize(d.arch, valdata)
+ keytype, valtype = d.walksymtypedef(d.defgotype(keytype)), d.walksymtypedef(d.defgotype(valtype))
+
+ // compute size info like hashmap.c does.
+ indirectKey, indirectVal := false, false
+ if keysize > abi.SwissMapMaxKeyBytes {
+ keysize = int64(d.arch.PtrSize)
+ indirectKey = true
+ }
+ if valsize > abi.SwissMapMaxElemBytes {
+ valsize = int64(d.arch.PtrSize)
+ indirectVal = true
+ }
+
+ // Construct type to represent an array of BucketSize keys
+ keyname := d.nameFromDIESym(keytype)
+ dwhks := d.mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *dwarf.DWDie) {
+ newattr(dwhk, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.SwissMapBucketCount*keysize, 0)
+ t := keytype
+ if indirectKey {
+ t = d.defptrto(keytype)
+ }
+ d.newrefattr(dwhk, dwarf.DW_AT_type, t)
+ fld := d.newdie(dwhk, dwarf.DW_ABRV_ARRAYRANGE, "size")
+ newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.SwissMapBucketCount, 0)
+ d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym)
+ })
+
+ // Construct type to represent an array of BucketSize values
+ valname := d.nameFromDIESym(valtype)
+ dwhvs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *dwarf.DWDie) {
+ newattr(dwhv, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.SwissMapBucketCount*valsize, 0)
+ t := valtype
+ if indirectVal {
+ t = d.defptrto(valtype)
+ }
+ d.newrefattr(dwhv, dwarf.DW_AT_type, t)
+ fld := d.newdie(dwhv, dwarf.DW_ABRV_ARRAYRANGE, "size")
+ newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.SwissMapBucketCount, 0)
+ d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym)
+ })
+
+ // Construct bucket<K,V>
+ dwhbs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "bucket", keyname, valname, func(dwhb *dwarf.DWDie) {
+ // Copy over all fields except the field "data" from the generic
+ // bucket. "data" will be replaced with keys/values below.
+ d.copychildrenexcept(ctxt, dwhb, bucket, findchild(bucket, "data"))
+
+ fld := d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "keys")
+ d.newrefattr(fld, dwarf.DW_AT_type, dwhks)
+ newmemberoffsetattr(fld, abi.SwissMapBucketCount)
+ fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "values")
+ d.newrefattr(fld, dwarf.DW_AT_type, dwhvs)
+ newmemberoffsetattr(fld, abi.SwissMapBucketCount+abi.SwissMapBucketCount*int32(keysize))
+ fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "overflow")
+ d.newrefattr(fld, dwarf.DW_AT_type, d.defptrto(d.dtolsym(dwhb.Sym)))
+ newmemberoffsetattr(fld, abi.SwissMapBucketCount+abi.SwissMapBucketCount*(int32(keysize)+int32(valsize)))
+ if d.arch.RegSize > d.arch.PtrSize {
+ fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "pad")
+ d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym)
+ newmemberoffsetattr(fld, abi.SwissMapBucketCount+abi.SwissMapBucketCount*(int32(keysize)+int32(valsize))+int32(d.arch.PtrSize))
+ }
+
+ newattr(dwhb, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.SwissMapBucketCount+abi.SwissMapBucketCount*keysize+abi.SwissMapBucketCount*valsize+int64(d.arch.RegSize), 0)
+ })
+
+ // Construct hash<K,V>
+ dwhs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_STRUCTTYPE, "hash", keyname, valname, func(dwh *dwarf.DWDie) {
+ d.copychildren(ctxt, dwh, hash)
+ d.substitutetype(dwh, "buckets", d.defptrto(dwhbs))
+ d.substitutetype(dwh, "oldbuckets", d.defptrto(dwhbs))
+ newattr(dwh, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, getattr(hash, dwarf.DW_AT_byte_size).Value, nil)
+ })
+
+ // make map type a pointer to hash<K,V>
+ d.newrefattr(die, dwarf.DW_AT_type, d.defptrto(dwhs))
+ }
+}
+
+func (d *dwctxt) synthesizemaptypesOld(ctxt *Link, die *dwarf.DWDie) {
hash := walktypedef(d.findprotodie(ctxt, "type:runtime.hmap"))
bucket := walktypedef(d.findprotodie(ctxt, "type:runtime.bmap"))
@@ -885,11 +989,11 @@ func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
// compute size info like hashmap.c does.
indirectKey, indirectVal := false, false
- if keysize > abi.MapMaxKeyBytes {
+ if keysize > abi.OldMapMaxKeyBytes {
keysize = int64(d.arch.PtrSize)
indirectKey = true
}
- if valsize > abi.MapMaxElemBytes {
+ if valsize > abi.OldMapMaxElemBytes {
valsize = int64(d.arch.PtrSize)
indirectVal = true
}
@@ -897,28 +1001,28 @@ func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
// Construct type to represent an array of BucketSize keys
keyname := d.nameFromDIESym(keytype)
dwhks := d.mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *dwarf.DWDie) {
- newattr(dwhk, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.MapBucketCount*keysize, 0)
+ newattr(dwhk, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount*keysize, 0)
t := keytype
if indirectKey {
t = d.defptrto(keytype)
}
d.newrefattr(dwhk, dwarf.DW_AT_type, t)
fld := d.newdie(dwhk, dwarf.DW_ABRV_ARRAYRANGE, "size")
- newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.MapBucketCount, 0)
+ newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount, 0)
d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym)
})
// Construct type to represent an array of BucketSize values
valname := d.nameFromDIESym(valtype)
dwhvs := d.mkinternaltype(ctxt, dwarf.DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *dwarf.DWDie) {
- newattr(dwhv, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.MapBucketCount*valsize, 0)
+ newattr(dwhv, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount*valsize, 0)
t := valtype
if indirectVal {
t = d.defptrto(valtype)
}
d.newrefattr(dwhv, dwarf.DW_AT_type, t)
fld := d.newdie(dwhv, dwarf.DW_ABRV_ARRAYRANGE, "size")
- newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.MapBucketCount, 0)
+ newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount, 0)
d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym)
})
@@ -930,20 +1034,20 @@ func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
fld := d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "keys")
d.newrefattr(fld, dwarf.DW_AT_type, dwhks)
- newmemberoffsetattr(fld, abi.MapBucketCount)
+ newmemberoffsetattr(fld, abi.OldMapBucketCount)
fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "values")
d.newrefattr(fld, dwarf.DW_AT_type, dwhvs)
- newmemberoffsetattr(fld, abi.MapBucketCount+abi.MapBucketCount*int32(keysize))
+ newmemberoffsetattr(fld, abi.OldMapBucketCount+abi.OldMapBucketCount*int32(keysize))
fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "overflow")
d.newrefattr(fld, dwarf.DW_AT_type, d.defptrto(d.dtolsym(dwhb.Sym)))
- newmemberoffsetattr(fld, abi.MapBucketCount+abi.MapBucketCount*(int32(keysize)+int32(valsize)))
+ newmemberoffsetattr(fld, abi.OldMapBucketCount+abi.OldMapBucketCount*(int32(keysize)+int32(valsize)))
if d.arch.RegSize > d.arch.PtrSize {
fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "pad")
d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym)
- newmemberoffsetattr(fld, abi.MapBucketCount+abi.MapBucketCount*(int32(keysize)+int32(valsize))+int32(d.arch.PtrSize))
+ newmemberoffsetattr(fld, abi.OldMapBucketCount+abi.OldMapBucketCount*(int32(keysize)+int32(valsize))+int32(d.arch.PtrSize))
}
- newattr(dwhb, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.MapBucketCount+abi.MapBucketCount*keysize+abi.MapBucketCount*valsize+int64(d.arch.RegSize), 0)
+ newattr(dwhb, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, abi.OldMapBucketCount+abi.OldMapBucketCount*keysize+abi.OldMapBucketCount*valsize+int64(d.arch.RegSize), 0)
})
// Construct hash<K,V>
@@ -1782,7 +1886,6 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
"type:internal/abi.ArrayType",
"type:internal/abi.ChanType",
"type:internal/abi.FuncType",
- "type:internal/abi.MapType",
"type:internal/abi.PtrType",
"type:internal/abi.SliceType",
"type:internal/abi.StructType",
@@ -1791,6 +1894,11 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
"type:internal/abi.Imethod"} {
d.defgotype(d.lookupOrDiag(typ))
}
+ if buildcfg.Experiment.SwissMap {
+ d.defgotype(d.lookupOrDiag("type:internal/abi.SwissMapType"))
+ } else {
+ d.defgotype(d.lookupOrDiag("type:internal/abi.OldMapType"))
+ }
// fake root DIE for compile unit DIEs
var dwroot dwarf.DWDie
diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go
index 8cea573999..40202bd312 100644
--- a/src/cmd/link/internal/ld/dwarf_test.go
+++ b/src/cmd/link/internal/ld/dwarf_test.go
@@ -60,7 +60,6 @@ func TestRuntimeTypesPresent(t *testing.T) {
"internal/abi.ArrayType": true,
"internal/abi.ChanType": true,
"internal/abi.FuncType": true,
- "internal/abi.MapType": true,
"internal/abi.PtrType": true,
"internal/abi.SliceType": true,
"internal/abi.StructType": true,
@@ -72,6 +71,16 @@ func TestRuntimeTypesPresent(t *testing.T) {
if len(found) != len(want) {
t.Errorf("found %v, want %v", found, want)
}
+
+ // Must have one of OldMapType or SwissMapType.
+ want = map[string]bool{
+ "internal/abi.OldMapType": true,
+ "internal/abi.SwissMapType": true,
+ }
+ found = findTypes(t, dwarf, want)
+ if len(found) != 1 {
+ t.Errorf("map type want one of %v found %v", want, found)
+ }
}
func findTypes(t *testing.T, dw *dwarf.Data, want map[string]bool) (found map[string]bool) {