@@ -1982,108 +1982,111 @@ func symIsROZero(sym Sym) bool {
1982
1982
return true
1983
1983
}
1984
1984
1985
- // isFixed32 returns true if the int32 at offset off in symbol sym
1986
- // is known and constant.
1987
- func isFixed32 (c * Config , sym Sym , off int64 ) bool {
1988
- return isFixed (c , sym , off , 4 )
1989
- }
1990
-
1991
- // isFixed returns true if the range [off,off+size] of the symbol sym
1992
- // is known and constant.
1993
- func isFixed (c * Config , sym Sym , off , size int64 ) bool {
1994
- lsym := sym .(* obj.LSym )
1995
- if lsym .Extra == nil {
1996
- return false
1997
- }
1998
- if _ , ok := (* lsym .Extra ).(* obj.TypeInfo ); ok {
1999
- if off == 2 * c .PtrSize && size == 4 {
2000
- return true // type hash field
2001
- }
2002
- }
2003
- return false
2004
- }
2005
- func fixed32 (c * Config , sym Sym , off int64 ) int32 {
1985
+ // isFixedLoad returns true if the load can be resolved to fixed address or constant,
1986
+ // and can be rewritten by rewriteFixedLoad.
1987
+ func isFixedLoad (v * Value , sym Sym , off int64 ) bool {
2006
1988
lsym := sym .(* obj.LSym )
2007
- if ti , ok := (* lsym .Extra ).(* obj.TypeInfo ); ok {
2008
- if off == 2 * c .PtrSize {
2009
- return int32 (types .TypeHash (ti .Type .(* types.Type )))
1989
+ if (v .Type .IsPtrShaped () || v .Type .IsUintptr ()) && lsym .Type == objabi .SRODATA {
1990
+ for _ , r := range lsym .R {
1991
+ if (r .Type == objabi .R_ADDR || r .Type == objabi .R_WEAKADDR ) && int64 (r .Off ) == off && r .Add == 0 {
1992
+ return true
1993
+ }
2010
1994
}
1995
+ return false
2011
1996
}
2012
- base .Fatalf ("fixed32 data not known for %s:%d" , sym , off )
2013
- return 0
2014
- }
2015
1997
2016
- // isPtrElem returns true if sym is an instance of abi.PtrType and off
2017
- // is equal to the offset of its Elem field.
2018
- func isPtrElem (sym Sym , off int64 ) bool {
2019
- lsym := sym .(* obj.LSym )
2020
- if strings .HasPrefix (lsym .Name , "type:*" ) {
2021
- if ti , ok := (* lsym .Extra ).(* obj.TypeInfo ); ok {
2022
- t := ti .Type .(* types.Type )
2023
- if t .Kind () == types .TPTR {
2024
- if off == rttype .PtrType .OffsetOf ("Elem" ) {
1998
+ if strings .HasPrefix (lsym .Name , "type:" ) {
1999
+ // Type symbols do not contain information about their fields, unlike the cases above.
2000
+ // Hand-implement field accesses.
2001
+ // TODO: can this be replaced with reflectdata.writeType and just use the code above?
2002
+
2003
+ t := (* lsym .Extra ).(* obj.TypeInfo ).Type .(* types.Type )
2004
+
2005
+ for _ , f := range rttype .Type .Fields () {
2006
+ if f .Offset == off && copyCompatibleType (v .Type , f .Type ) {
2007
+ switch f .Sym .Name {
2008
+ case "Hash" :
2025
2009
return true
2010
+ default :
2011
+ // fmt.Println("unknown field", f.Sym.Name)
2012
+ return false
2026
2013
}
2027
2014
}
2028
2015
}
2016
+
2017
+ if t .IsPtr () && off == rttype .PtrType .OffsetOf ("Elem" ) {
2018
+ return true
2019
+ }
2020
+
2021
+ return false
2029
2022
}
2023
+
2030
2024
return false
2031
2025
}
2032
- func ptrElem (f * Func , sym Sym , off int64 ) Sym {
2026
+
2027
+ // rewriteFixedLoad rewrites a load to a fixed address or constant, if isFixedLoad returns true.
2028
+ func rewriteFixedLoad (v * Value , sym Sym , sb * Value , off int64 ) * Value {
2029
+ b := v .Block
2030
+ f := b .Func
2031
+
2033
2032
lsym := sym .(* obj.LSym )
2034
- if strings .HasPrefix (lsym .Name , "type:*" ) {
2035
- if ti , ok := (* lsym .Extra ).(* obj.TypeInfo ); ok {
2036
- t := ti .Type .(* types.Type )
2037
- if t .Kind () == types .TPTR {
2038
- if off == rttype .PtrType .OffsetOf ("Elem" ) {
2039
- elemSym := reflectdata .TypeLinksym (t .Elem ())
2040
- reflectdata .MarkTypeSymUsedInInterface (elemSym , f .fe .Func ().Linksym ())
2041
- return elemSym
2033
+ if (v .Type .IsPtrShaped () || v .Type .IsUintptr ()) && lsym .Type == objabi .SRODATA {
2034
+ for _ , r := range lsym .R {
2035
+ if (r .Type == objabi .R_ADDR || r .Type == objabi .R_WEAKADDR ) && int64 (r .Off ) == off && r .Add == 0 {
2036
+ if strings .HasPrefix (r .Sym .Name , "type:" ) {
2037
+ // In case we're loading a type out of a dictionary, we need to record
2038
+ // that the containing function might put that type in an interface.
2039
+ // That information is currently recorded in relocations in the dictionary,
2040
+ // but if we perform this load at compile time then the dictionary
2041
+ // might be dead.
2042
+ reflectdata .MarkTypeSymUsedInInterface (r .Sym , f .fe .Func ().Linksym ())
2043
+ } else if strings .HasPrefix (r .Sym .Name , "go:itab" ) {
2044
+ // Same, but if we're using an itab we need to record that the
2045
+ // itab._type might be put in an interface.
2046
+ reflectdata .MarkTypeSymUsedInInterface (r .Sym , f .fe .Func ().Linksym ())
2042
2047
}
2048
+ v .reset (OpAddr )
2049
+ v .Aux = symToAux (r .Sym )
2050
+ v .AddArg (sb )
2051
+ return v
2043
2052
}
2044
2053
}
2054
+ base .Fatalf ("fixedLoad data not known for %s:%d" , sym , off )
2045
2055
}
2046
- base .Fatalf ("ptrElem data not known for %s:%d" , sym , off )
2047
- return nil
2048
- }
2049
2056
2050
- // isFixedSym returns true if the contents of sym at the given offset
2051
- // is known and is the constant address of another symbol.
2052
- func isFixedSym (sym Sym , off int64 ) bool {
2053
- lsym := sym .(* obj.LSym )
2054
- switch {
2055
- case lsym .Type == objabi .SRODATA :
2056
- // itabs, dictionaries
2057
- default :
2058
- return false
2059
- }
2060
- for _ , r := range lsym .R {
2061
- if (r .Type == objabi .R_ADDR || r .Type == objabi .R_WEAKADDR ) && int64 (r .Off ) == off && r .Add == 0 {
2062
- return true
2063
- }
2064
- }
2065
- return false
2066
- }
2067
- func fixedSym (f * Func , sym Sym , off int64 ) Sym {
2068
- lsym := sym .(* obj.LSym )
2069
- for _ , r := range lsym .R {
2070
- if (r .Type == objabi .R_ADDR || r .Type == objabi .R_WEAKADDR ) && int64 (r .Off ) == off {
2071
- if strings .HasPrefix (r .Sym .Name , "type:" ) {
2072
- // In case we're loading a type out of a dictionary, we need to record
2073
- // that the containing function might put that type in an interface.
2074
- // That information is currently recorded in relocations in the dictionary,
2075
- // but if we perform this load at compile time then the dictionary
2076
- // might be dead.
2077
- reflectdata .MarkTypeSymUsedInInterface (r .Sym , f .fe .Func ().Linksym ())
2078
- } else if strings .HasPrefix (r .Sym .Name , "go:itab" ) {
2079
- // Same, but if we're using an itab we need to record that the
2080
- // itab._type might be put in an interface.
2081
- reflectdata .MarkTypeSymUsedInInterface (r .Sym , f .fe .Func ().Linksym ())
2057
+ if strings .HasPrefix (lsym .Name , "type:" ) {
2058
+ // Type symbols do not contain information about their fields, unlike the cases above.
2059
+ // Hand-implement field accesses.
2060
+ // TODO: can this be replaced with reflectdata.writeType and just use the code above?
2061
+
2062
+ t := (* lsym .Extra ).(* obj.TypeInfo ).Type .(* types.Type )
2063
+
2064
+ for _ , f := range rttype .Type .Fields () {
2065
+ if f .Offset == off && copyCompatibleType (v .Type , f .Type ) {
2066
+ switch f .Sym .Name {
2067
+ case "Hash" :
2068
+ v .reset (OpConst32 )
2069
+ v .AuxInt = int64 (types .TypeHash (t ))
2070
+ return v
2071
+ default :
2072
+ base .Fatalf ("unknown field %s for fixedLoad of %s at offset %d" , f .Sym .Name , lsym .Name , off )
2073
+ }
2082
2074
}
2083
- return r .Sym
2084
2075
}
2076
+
2077
+ if t .IsPtr () && off == rttype .PtrType .OffsetOf ("Elem" ) {
2078
+ elemSym := reflectdata .TypeLinksym (t .Elem ())
2079
+ reflectdata .MarkTypeSymUsedInInterface (elemSym , f .fe .Func ().Linksym ())
2080
+ v .reset (OpAddr )
2081
+ v .Aux = symToAux (elemSym )
2082
+ v .AddArg (sb )
2083
+ return v
2084
+ }
2085
+
2086
+ base .Fatalf ("fixedLoad data not known for %s:%d" , sym , off )
2085
2087
}
2086
- base .Fatalf ("fixedSym data not known for %s:%d" , sym , off )
2088
+
2089
+ base .Fatalf ("fixedLoad data not known for %s:%d" , sym , off )
2087
2090
return nil
2088
2091
}
2089
2092
0 commit comments