Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
385cd668
Commit
385cd668
authored
Aug 11, 2017
by
Gerrit Code Review
Browse files
Options
Browse Files
Download
Plain Diff
Merge "Merge remote-tracking branch 'origin/dev.debug' into master"
parents
9aea0e89
6f6a9398
Changes
32
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
1551 additions
and
290 deletions
+1551
-290
src/cmd/compile/fmt_test.go
src/cmd/compile/fmt_test.go
+15
-0
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/main.go
+7
-1
src/cmd/compile/internal/gc/pgen.go
src/cmd/compile/internal/gc/pgen.go
+323
-34
src/cmd/compile/internal/gc/scope.go
src/cmd/compile/internal/gc/scope.go
+1
-1
src/cmd/compile/internal/gc/sizeof_test.go
src/cmd/compile/internal/gc/sizeof_test.go
+1
-1
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/gc/ssa.go
+66
-39
src/cmd/compile/internal/gc/syntax.go
src/cmd/compile/internal/gc/syntax.go
+2
-0
src/cmd/compile/internal/ssa/cache.go
src/cmd/compile/internal/ssa/cache.go
+22
-0
src/cmd/compile/internal/ssa/debug.go
src/cmd/compile/internal/ssa/debug.go
+559
-0
src/cmd/compile/internal/ssa/decompose.go
src/cmd/compile/internal/ssa/decompose.go
+1
-0
src/cmd/compile/internal/ssa/export_test.go
src/cmd/compile/internal/ssa/export_test.go
+11
-11
src/cmd/compile/internal/ssa/gen/genericOps.go
src/cmd/compile/internal/ssa/gen/genericOps.go
+1
-0
src/cmd/compile/internal/ssa/html.go
src/cmd/compile/internal/ssa/html.go
+13
-0
src/cmd/compile/internal/ssa/location.go
src/cmd/compile/internal/ssa/location.go
+29
-3
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/opGen.go
+6
-0
src/cmd/compile/internal/ssa/regalloc.go
src/cmd/compile/internal/ssa/regalloc.go
+75
-23
src/cmd/compile/internal/ssa/sizeof_test.go
src/cmd/compile/internal/ssa/sizeof_test.go
+1
-0
src/cmd/compile/internal/ssa/stackalloc.go
src/cmd/compile/internal/ssa/stackalloc.go
+1
-1
src/cmd/compile/internal/ssa/value.go
src/cmd/compile/internal/ssa/value.go
+14
-1
src/cmd/internal/dwarf/dwarf.go
src/cmd/internal/dwarf/dwarf.go
+122
-37
src/cmd/internal/obj/link.go
src/cmd/internal/obj/link.go
+28
-25
src/cmd/internal/obj/objfile.go
src/cmd/internal/obj/objfile.go
+10
-7
src/cmd/internal/obj/plist.go
src/cmd/internal/obj/plist.go
+11
-7
src/cmd/internal/obj/x86/a.out.go
src/cmd/internal/obj/x86/a.out.go
+117
-0
src/cmd/internal/obj/x86/obj6.go
src/cmd/internal/obj/x86/obj6.go
+21
-18
src/cmd/internal/objabi/symkind.go
src/cmd/internal/objabi/symkind.go
+1
-0
src/cmd/internal/objabi/symkind_string.go
src/cmd/internal/objabi/symkind_string.go
+2
-2
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/data.go
+24
-19
src/cmd/link/internal/ld/dwarf.go
src/cmd/link/internal/ld/dwarf.go
+61
-53
src/cmd/link/internal/ld/elf.go
src/cmd/link/internal/ld/elf.go
+2
-5
src/cmd/link/internal/ld/symkind.go
src/cmd/link/internal/ld/symkind.go
+2
-0
src/cmd/link/internal/ld/symkind_string.go
src/cmd/link/internal/ld/symkind_string.go
+2
-2
No files found.
src/cmd/compile/fmt_test.go
View file @
385cd668
...
...
@@ -571,9 +571,16 @@ var knownFormats = map[string]string{
"*cmd/compile/internal/ssa.Block %s"
:
""
,
"*cmd/compile/internal/ssa.Block %v"
:
""
,
"*cmd/compile/internal/ssa.Func %s"
:
""
,
"*cmd/compile/internal/ssa.Func %v"
:
""
,
"*cmd/compile/internal/ssa.FuncDebug %v"
:
""
,
"*cmd/compile/internal/ssa.LocalSlot %+v"
:
""
,
"*cmd/compile/internal/ssa.LocalSlot %v"
:
""
,
"*cmd/compile/internal/ssa.Register %v"
:
""
,
"*cmd/compile/internal/ssa.SparseTreeNode %v"
:
""
,
"*cmd/compile/internal/ssa.Value %s"
:
""
,
"*cmd/compile/internal/ssa.Value %v"
:
""
,
"*cmd/compile/internal/ssa.VarLoc %+v"
:
""
,
"*cmd/compile/internal/ssa.VarLoc %v"
:
""
,
"*cmd/compile/internal/ssa.sparseTreeMapEntry %v"
:
""
,
"*cmd/compile/internal/types.Field %p"
:
""
,
"*cmd/compile/internal/types.Field %v"
:
""
,
...
...
@@ -592,6 +599,7 @@ var knownFormats = map[string]string{
"*cmd/compile/internal/types.Type %p"
:
""
,
"*cmd/compile/internal/types.Type %s"
:
""
,
"*cmd/compile/internal/types.Type %v"
:
""
,
"*cmd/internal/dwarf.Location %#v"
:
""
,
"*cmd/internal/obj.Addr %v"
:
""
,
"*cmd/internal/obj.LSym %v"
:
""
,
"*cmd/internal/obj.Prog %s"
:
""
,
...
...
@@ -600,17 +608,21 @@ var knownFormats = map[string]string{
"[16]byte %x"
:
""
,
"[]*cmd/compile/internal/gc.Node %v"
:
""
,
"[]*cmd/compile/internal/gc.Sig %#v"
:
""
,
"[]*cmd/compile/internal/ssa.Block %+v"
:
""
,
"[]*cmd/compile/internal/ssa.Value %v"
:
""
,
"[][]cmd/compile/internal/ssa.SlotID %v"
:
""
,
"[]byte %s"
:
""
,
"[]byte %x"
:
""
,
"[]cmd/compile/internal/ssa.Edge %v"
:
""
,
"[]cmd/compile/internal/ssa.ID %v"
:
""
,
"[]cmd/compile/internal/ssa.VarLocList %v"
:
""
,
"[]string %v"
:
""
,
"bool %v"
:
""
,
"byte %08b"
:
""
,
"byte %c"
:
""
,
"cmd/compile/internal/arm.shift %d"
:
""
,
"cmd/compile/internal/gc.Class %d"
:
""
,
"cmd/compile/internal/gc.Class %v"
:
""
,
"cmd/compile/internal/gc.Ctype %d"
:
""
,
"cmd/compile/internal/gc.Ctype %v"
:
""
,
"cmd/compile/internal/gc.Level %d"
:
""
,
...
...
@@ -630,11 +642,13 @@ var knownFormats = map[string]string{
"cmd/compile/internal/ssa.Edge %v"
:
""
,
"cmd/compile/internal/ssa.GCNode %v"
:
""
,
"cmd/compile/internal/ssa.ID %d"
:
""
,
"cmd/compile/internal/ssa.ID %v"
:
""
,
"cmd/compile/internal/ssa.LocalSlot %v"
:
""
,
"cmd/compile/internal/ssa.Location %v"
:
""
,
"cmd/compile/internal/ssa.Op %s"
:
""
,
"cmd/compile/internal/ssa.Op %v"
:
""
,
"cmd/compile/internal/ssa.ValAndOff %s"
:
""
,
"cmd/compile/internal/ssa.VarLocList %v"
:
""
,
"cmd/compile/internal/ssa.rbrank %d"
:
""
,
"cmd/compile/internal/ssa.regMask %d"
:
""
,
"cmd/compile/internal/ssa.register %d"
:
""
,
...
...
@@ -648,6 +662,7 @@ var knownFormats = map[string]string{
"cmd/compile/internal/types.EType %d"
:
""
,
"cmd/compile/internal/types.EType %s"
:
""
,
"cmd/compile/internal/types.EType %v"
:
""
,
"cmd/internal/dwarf.Location %#v"
:
""
,
"cmd/internal/src.Pos %s"
:
""
,
"cmd/internal/src.Pos %v"
:
""
,
"error %v"
:
""
,
...
...
src/cmd/compile/internal/gc/main.go
View file @
385cd668
...
...
@@ -44,6 +44,7 @@ var (
Debug_vlog
bool
Debug_wb
int
Debug_pctab
string
Debug_locationlist
int
)
// Debug arguments.
...
...
@@ -69,6 +70,7 @@ var debugtab = []struct {
{
"wb"
,
"print information about write barriers"
,
&
Debug_wb
},
{
"export"
,
"print export data"
,
&
Debug_export
},
{
"pctab"
,
"print named pc-value table"
,
&
Debug_pctab
},
{
"locationlists"
,
"print information about DWARF location list creation"
,
&
Debug_locationlist
},
}
const
debugHelpHeader
=
`usage: -d arg[,arg]* and arg is <key>[=<value>]
...
...
@@ -192,6 +194,7 @@ func Main(archInit func(*Arch)) {
flag
.
BoolVar
(
&
pure_go
,
"complete"
,
false
,
"compiling complete package (no C or assembly)"
)
flag
.
StringVar
(
&
debugstr
,
"d"
,
""
,
"print debug information about items in `list`; try -d help"
)
flag
.
BoolVar
(
&
flagDWARF
,
"dwarf"
,
true
,
"generate DWARF symbols"
)
flag
.
BoolVar
(
&
Ctxt
.
Flag_locationlists
,
"dwarflocationlists"
,
false
,
"add location lists to DWARF in optimized mode"
)
objabi
.
Flagcount
(
"e"
,
"no limit on number of errors reported"
,
&
Debug
[
'e'
])
objabi
.
Flagcount
(
"f"
,
"debug stack frames"
,
&
Debug
[
'f'
])
objabi
.
Flagcount
(
"h"
,
"halt on error"
,
&
Debug
[
'h'
])
...
...
@@ -298,6 +301,9 @@ func Main(archInit func(*Arch)) {
if
nBackendWorkers
>
1
&&
!
concurrentBackendAllowed
()
{
log
.
Fatalf
(
"cannot use concurrent backend compilation with provided flags; invoked as %v"
,
os
.
Args
)
}
if
Ctxt
.
Flag_locationlists
&&
len
(
Ctxt
.
Arch
.
DWARFRegisters
)
==
0
{
log
.
Fatalf
(
"location lists requested but register mapping not available on %v"
,
Ctxt
.
Arch
.
Name
)
}
// parse -d argument
if
debugstr
!=
""
{
...
...
@@ -383,7 +389,7 @@ func Main(archInit func(*Arch)) {
Debug
[
'l'
]
=
1
-
Debug
[
'l'
]
}
trackScopes
=
flagDWARF
&&
Debug
[
'l'
]
==
0
&&
Debug
[
'N'
]
!=
0
trackScopes
=
flagDWARF
&&
((
Debug
[
'l'
]
==
0
&&
Debug
[
'N'
]
!=
0
)
||
Ctxt
.
Flag_locationlists
)
Widthptr
=
thearch
.
LinkArch
.
PtrSize
Widthreg
=
thearch
.
LinkArch
.
RegSize
...
...
src/cmd/compile/internal/gc/pgen.go
View file @
385cd668
This diff is collapsed.
Click to expand it.
src/cmd/compile/internal/gc/scope.go
View file @
385cd668
...
...
@@ -168,7 +168,7 @@ func (v varsByScopeAndOffset) Less(i, j int) bool {
if
v
.
scopes
[
i
]
!=
v
.
scopes
[
j
]
{
return
v
.
scopes
[
i
]
<
v
.
scopes
[
j
]
}
return
v
.
vars
[
i
]
.
Offset
<
v
.
vars
[
j
]
.
Offset
return
v
.
vars
[
i
]
.
StackOffset
<
v
.
vars
[
j
]
.
Stack
Offset
}
func
(
v
varsByScopeAndOffset
)
Swap
(
i
,
j
int
)
{
...
...
src/cmd/compile/internal/gc/sizeof_test.go
View file @
385cd668
...
...
@@ -22,7 +22,7 @@ func TestSizeof(t *testing.T) {
_32bit
uintptr
// size on 32bit platforms
_64bit
uintptr
// size on 64bit platforms
}{
{
Func
{},
12
4
,
216
},
{
Func
{},
12
8
,
224
},
{
Name
{},
36
,
56
},
{
Param
{},
28
,
56
},
{
Node
{},
76
,
128
},
...
...
src/cmd/compile/internal/gc/ssa.go
View file @
385cd668
...
...
@@ -4401,14 +4401,15 @@ func genssa(f *ssa.Func, pp *Progs) {
// Remember where each block starts.
s
.
bstart
=
make
([]
*
obj
.
Prog
,
f
.
NumBlocks
())
s
.
pp
=
pp
var
valueProgs
map
[
*
obj
.
Prog
]
*
ssa
.
Value
var
blockProgs
map
[
*
obj
.
Prog
]
*
ssa
.
Block
var
progToValue
map
[
*
obj
.
Prog
]
*
ssa
.
Value
var
progToBlock
map
[
*
obj
.
Prog
]
*
ssa
.
Block
var
valueToProg
[]
*
obj
.
Prog
var
logProgs
=
e
.
log
if
logProgs
{
valueProgs
=
make
(
map
[
*
obj
.
Prog
]
*
ssa
.
Value
,
f
.
NumValues
())
blockProgs
=
make
(
map
[
*
obj
.
Prog
]
*
ssa
.
Block
,
f
.
NumBlocks
())
progToValue
=
make
(
map
[
*
obj
.
Prog
]
*
ssa
.
Value
,
f
.
NumValues
())
progToBlock
=
make
(
map
[
*
obj
.
Prog
]
*
ssa
.
Block
,
f
.
NumBlocks
())
f
.
Logf
(
"genssa %s
\n
"
,
f
.
Name
)
blockProgs
[
s
.
pp
.
next
]
=
f
.
Blocks
[
0
]
progToBlock
[
s
.
pp
.
next
]
=
f
.
Blocks
[
0
]
}
if
thearch
.
Use387
{
...
...
@@ -4417,6 +4418,11 @@ func genssa(f *ssa.Func, pp *Progs) {
s
.
ScratchFpMem
=
e
.
scratchFpMem
logLocationLists
:=
Debug_locationlist
!=
0
if
Ctxt
.
Flag_locationlists
{
e
.
curfn
.
Func
.
DebugInfo
=
ssa
.
BuildFuncDebug
(
f
,
logLocationLists
)
valueToProg
=
make
([]
*
obj
.
Prog
,
f
.
NumValues
())
}
// Emit basic blocks
for
i
,
b
:=
range
f
.
Blocks
{
s
.
bstart
[
b
.
ID
]
=
s
.
pp
.
next
...
...
@@ -4457,15 +4463,19 @@ func genssa(f *ssa.Func, pp *Progs) {
}
case
ssa
.
OpPhi
:
CheckLoweredPhi
(
v
)
case
ssa
.
OpRegKill
:
// nothing to do
default
:
// let the backend handle it
thearch
.
SSAGenValue
(
&
s
,
v
)
}
if
Ctxt
.
Flag_locationlists
{
valueToProg
[
v
.
ID
]
=
x
}
if
logProgs
{
for
;
x
!=
s
.
pp
.
next
;
x
=
x
.
Link
{
valueProgs
[
x
]
=
v
progToValue
[
x
]
=
v
}
}
}
...
...
@@ -4483,7 +4493,23 @@ func genssa(f *ssa.Func, pp *Progs) {
thearch
.
SSAGenBlock
(
&
s
,
b
,
next
)
if
logProgs
{
for
;
x
!=
s
.
pp
.
next
;
x
=
x
.
Link
{
blockProgs
[
x
]
=
b
progToBlock
[
x
]
=
b
}
}
}
if
Ctxt
.
Flag_locationlists
{
for
_
,
locList
:=
range
e
.
curfn
.
Func
.
DebugInfo
.
Variables
{
for
_
,
loc
:=
range
locList
.
Locations
{
loc
.
StartProg
=
valueToProg
[
loc
.
Start
.
ID
]
if
loc
.
End
==
nil
{
Fatalf
(
"empty loc %v compiling %v"
,
loc
,
f
.
Name
)
}
loc
.
EndProg
=
valueToProg
[
loc
.
End
.
ID
]
if
!
logLocationLists
{
loc
.
Start
=
nil
loc
.
End
=
nil
}
}
}
}
...
...
@@ -4496,9 +4522,9 @@ func genssa(f *ssa.Func, pp *Progs) {
if
logProgs
{
for
p
:=
pp
.
Text
;
p
!=
nil
;
p
=
p
.
Link
{
var
s
string
if
v
,
ok
:=
valueProgs
[
p
];
ok
{
if
v
,
ok
:=
progToValue
[
p
];
ok
{
s
=
v
.
String
()
}
else
if
b
,
ok
:=
blockProgs
[
p
];
ok
{
}
else
if
b
,
ok
:=
progToBlock
[
p
];
ok
{
s
=
b
.
String
()
}
else
{
s
=
" "
// most value and branch strings are 2-3 characters long
...
...
@@ -4516,9 +4542,9 @@ func genssa(f *ssa.Func, pp *Progs) {
buf
.
WriteString
(
"<dl class=
\"
ssa-gen
\"
>"
)
for
p
:=
pp
.
Text
;
p
!=
nil
;
p
=
p
.
Link
{
buf
.
WriteString
(
"<dt class=
\"
ssa-prog-src
\"
>"
)
if
v
,
ok
:=
valueProgs
[
p
];
ok
{
if
v
,
ok
:=
progToValue
[
p
];
ok
{
buf
.
WriteString
(
v
.
HTML
())
}
else
if
b
,
ok
:=
blockProgs
[
p
];
ok
{
}
else
if
b
,
ok
:=
progToBlock
[
p
];
ok
{
buf
.
WriteString
(
b
.
HTML
())
}
buf
.
WriteString
(
"</dt>"
)
...
...
@@ -4895,9 +4921,9 @@ func (e *ssafn) SplitString(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) {
lenType
:=
types
.
Types
[
TINT
]
if
n
.
Class
()
==
PAUTO
&&
!
n
.
Addrtaken
()
{
// Split this string up into two separate variables.
p
:=
e
.
namedAuto
(
n
.
Sym
.
Name
+
".ptr"
,
ptrType
,
n
.
Pos
)
l
:=
e
.
namedAuto
(
n
.
Sym
.
Name
+
".len"
,
lenType
,
n
.
Pos
)
return
ssa
.
LocalSlot
{
N
:
p
,
Type
:
ptrType
,
Off
:
0
},
ssa
.
LocalSlot
{
N
:
l
,
Type
:
lenType
,
Off
:
0
}
p
:=
e
.
splitSlot
(
&
name
,
".ptr"
,
0
,
ptrType
)
l
:=
e
.
splitSlot
(
&
name
,
".len"
,
ptrType
.
Size
(),
lenType
)
return
p
,
l
}
// Return the two parts of the larger variable.
return
ssa
.
LocalSlot
{
N
:
n
,
Type
:
ptrType
,
Off
:
name
.
Off
},
ssa
.
LocalSlot
{
N
:
n
,
Type
:
lenType
,
Off
:
name
.
Off
+
int64
(
Widthptr
)}
...
...
@@ -4912,9 +4938,9 @@ func (e *ssafn) SplitInterface(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot
if
n
.
Type
.
IsEmptyInterface
()
{
f
=
".type"
}
c
:=
e
.
namedAuto
(
n
.
Sym
.
Name
+
f
,
t
,
n
.
Pos
)
d
:=
e
.
namedAuto
(
n
.
Sym
.
Name
+
".data"
,
t
,
n
.
Pos
)
return
ssa
.
LocalSlot
{
N
:
c
,
Type
:
t
,
Off
:
0
},
ssa
.
LocalSlot
{
N
:
d
,
Type
:
t
,
Off
:
0
}
c
:=
e
.
splitSlot
(
&
name
,
f
,
0
,
t
)
d
:=
e
.
splitSlot
(
&
name
,
".data"
,
t
.
Size
(),
t
)
return
c
,
d
}
// Return the two parts of the larger variable.
return
ssa
.
LocalSlot
{
N
:
n
,
Type
:
t
,
Off
:
name
.
Off
},
ssa
.
LocalSlot
{
N
:
n
,
Type
:
t
,
Off
:
name
.
Off
+
int64
(
Widthptr
)}
...
...
@@ -4926,10 +4952,10 @@ func (e *ssafn) SplitSlice(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot, ss
lenType
:=
types
.
Types
[
TINT
]
if
n
.
Class
()
==
PAUTO
&&
!
n
.
Addrtaken
()
{
// Split this slice up into three separate variables.
p
:=
e
.
namedAuto
(
n
.
Sym
.
Name
+
".ptr"
,
ptrType
,
n
.
Pos
)
l
:=
e
.
namedAuto
(
n
.
Sym
.
Name
+
".len"
,
lenType
,
n
.
Pos
)
c
:=
e
.
namedAuto
(
n
.
Sym
.
Name
+
".cap"
,
lenType
,
n
.
Pos
)
return
ssa
.
LocalSlot
{
N
:
p
,
Type
:
ptrType
,
Off
:
0
},
ssa
.
LocalSlot
{
N
:
l
,
Type
:
lenType
,
Off
:
0
},
ssa
.
LocalSlot
{
N
:
c
,
Type
:
lenType
,
Off
:
0
}
p
:=
e
.
splitSlot
(
&
name
,
".ptr"
,
0
,
ptrType
)
l
:=
e
.
splitSlot
(
&
name
,
".len"
,
ptrType
.
Size
(),
lenType
)
c
:=
e
.
splitSlot
(
&
name
,
".cap"
,
ptrType
.
Size
()
+
lenType
.
Size
(),
lenType
)
return
p
,
l
,
c
}
// Return the three parts of the larger variable.
return
ssa
.
LocalSlot
{
N
:
n
,
Type
:
ptrType
,
Off
:
name
.
Off
},
...
...
@@ -4948,9 +4974,9 @@ func (e *ssafn) SplitComplex(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot)
}
if
n
.
Class
()
==
PAUTO
&&
!
n
.
Addrtaken
()
{
// Split this complex up into two separate variables.
c
:=
e
.
namedAuto
(
n
.
Sym
.
Name
+
".real"
,
t
,
n
.
Pos
)
d
:=
e
.
namedAuto
(
n
.
Sym
.
Name
+
".imag"
,
t
,
n
.
Pos
)
return
ssa
.
LocalSlot
{
N
:
c
,
Type
:
t
,
Off
:
0
},
ssa
.
LocalSlot
{
N
:
d
,
Type
:
t
,
Off
:
0
}
r
:=
e
.
splitSlot
(
&
name
,
".real"
,
0
,
t
)
i
:=
e
.
splitSlot
(
&
name
,
".imag"
,
t
.
Size
(),
t
)
return
r
,
i
}
// Return the two parts of the larger variable.
return
ssa
.
LocalSlot
{
N
:
n
,
Type
:
t
,
Off
:
name
.
Off
},
ssa
.
LocalSlot
{
N
:
n
,
Type
:
t
,
Off
:
name
.
Off
+
s
}
...
...
@@ -4966,9 +4992,10 @@ func (e *ssafn) SplitInt64(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) {
}
if
n
.
Class
()
==
PAUTO
&&
!
n
.
Addrtaken
()
{
// Split this int64 up into two separate variables.
h
:=
e
.
namedAuto
(
n
.
Sym
.
Name
+
".hi"
,
t
,
n
.
Pos
)
l
:=
e
.
namedAuto
(
n
.
Sym
.
Name
+
".lo"
,
types
.
Types
[
TUINT32
],
n
.
Pos
)
return
ssa
.
LocalSlot
{
N
:
h
,
Type
:
t
,
Off
:
0
},
ssa
.
LocalSlot
{
N
:
l
,
Type
:
types
.
Types
[
TUINT32
],
Off
:
0
}
if
thearch
.
LinkArch
.
ByteOrder
==
binary
.
BigEndian
{
return
e
.
splitSlot
(
&
name
,
".hi"
,
0
,
t
),
e
.
splitSlot
(
&
name
,
".lo"
,
t
.
Size
(),
types
.
Types
[
TUINT32
])
}
return
e
.
splitSlot
(
&
name
,
".hi"
,
t
.
Size
(),
t
),
e
.
splitSlot
(
&
name
,
".lo"
,
0
,
types
.
Types
[
TUINT32
])
}
// Return the two parts of the larger variable.
if
thearch
.
LinkArch
.
ByteOrder
==
binary
.
BigEndian
{
...
...
@@ -4981,12 +5008,15 @@ func (e *ssafn) SplitStruct(name ssa.LocalSlot, i int) ssa.LocalSlot {
n
:=
name
.
N
.
(
*
Node
)
st
:=
name
.
Type
ft
:=
st
.
FieldType
(
i
)
var
offset
int64
for
f
:=
0
;
f
<
i
;
f
++
{
offset
+=
st
.
FieldType
(
f
)
.
Size
()
}
if
n
.
Class
()
==
PAUTO
&&
!
n
.
Addrtaken
()
{
// Note: the _ field may appear several times. But
// have no fear, identically-named but distinct Autos are
// ok, albeit maybe confusing for a debugger.
x
:=
e
.
namedAuto
(
n
.
Sym
.
Name
+
"."
+
st
.
FieldName
(
i
),
ft
,
n
.
Pos
)
return
ssa
.
LocalSlot
{
N
:
x
,
Type
:
ft
,
Off
:
0
}
return
e
.
splitSlot
(
&
name
,
"."
+
st
.
FieldName
(
i
),
offset
,
ft
)
}
return
ssa
.
LocalSlot
{
N
:
n
,
Type
:
ft
,
Off
:
name
.
Off
+
st
.
FieldOff
(
i
)}
}
...
...
@@ -4999,8 +5029,7 @@ func (e *ssafn) SplitArray(name ssa.LocalSlot) ssa.LocalSlot {
}
et
:=
at
.
ElemType
()
if
n
.
Class
()
==
PAUTO
&&
!
n
.
Addrtaken
()
{
x
:=
e
.
namedAuto
(
n
.
Sym
.
Name
+
"[0]"
,
et
,
n
.
Pos
)
return
ssa
.
LocalSlot
{
N
:
x
,
Type
:
et
,
Off
:
0
}
return
e
.
splitSlot
(
&
name
,
"[0]"
,
0
,
et
)
}
return
ssa
.
LocalSlot
{
N
:
n
,
Type
:
et
,
Off
:
name
.
Off
}
}
...
...
@@ -5009,16 +5038,14 @@ func (e *ssafn) DerefItab(it *obj.LSym, offset int64) *obj.LSym {
return
itabsym
(
it
,
offset
)
}
// namedAuto returns a new AUTO variable with the given name and type.
// These are exposed to the debugger.
func
(
e
*
ssafn
)
namedAuto
(
name
string
,
typ
*
types
.
Type
,
pos
src
.
XPos
)
ssa
.
GCNode
{
t
:=
typ
s
:=
&
types
.
Sym
{
Name
:
name
,
Pkg
:
localpkg
}
// splitSlot returns a slot representing the data of parent starting at offset.
func
(
e
*
ssafn
)
splitSlot
(
parent
*
ssa
.
LocalSlot
,
suffix
string
,
offset
int64
,
t
*
types
.
Type
)
ssa
.
LocalSlot
{
s
:=
&
types
.
Sym
{
Name
:
parent
.
N
.
(
*
Node
)
.
Sym
.
Name
+
suffix
,
Pkg
:
localpkg
}
n
:=
new
(
Node
)
n
.
Name
=
new
(
Name
)
n
.
Op
=
ONAME
n
.
Pos
=
pos
n
.
Pos
=
p
arent
.
N
.
(
*
Node
)
.
P
os
n
.
Orig
=
n
s
.
Def
=
asTypesNode
(
n
)
...
...
@@ -5031,7 +5058,7 @@ func (e *ssafn) namedAuto(name string, typ *types.Type, pos src.XPos) ssa.GCNode
n
.
Name
.
Curfn
=
e
.
curfn
e
.
curfn
.
Func
.
Dcl
=
append
(
e
.
curfn
.
Func
.
Dcl
,
n
)
dowidth
(
t
)
return
n
return
ssa
.
LocalSlot
{
N
:
n
,
Type
:
t
,
Off
:
0
,
SplitOf
:
parent
,
SplitOffset
:
offset
}
}
func
(
e
*
ssafn
)
CanSSA
(
t
*
types
.
Type
)
bool
{
...
...
src/cmd/compile/internal/gc/syntax.go
View file @
385cd668
...
...
@@ -7,6 +7,7 @@
package
gc
import
(
"cmd/compile/internal/ssa"
"cmd/compile/internal/syntax"
"cmd/compile/internal/types"
"cmd/internal/obj"
...
...
@@ -369,6 +370,7 @@ type Func struct {
Closgen
int
Outerfunc
*
Node
// outer function (for closure)
FieldTrack
map
[
*
types
.
Sym
]
struct
{}
DebugInfo
*
ssa
.
FuncDebug
Ntype
*
Node
// signature
Top
int
// top context (Ecall, Eproc, etc)
Closure
*
Node
// OCLOSURE <-> ODCLFUNC
...
...
src/cmd/compile/internal/ssa/cache.go
View file @
385cd668
...
...
@@ -14,6 +14,11 @@ type Cache struct {
blocks
[
200
]
Block
locs
[
2000
]
Location
// Storage for DWARF variable locations. Lazily allocated
// since location lists are off by default.
varLocs
[]
VarLoc
curVarLoc
int
// Reusable stackAllocState.
// See stackalloc.go's {new,put}StackAllocState.
stackAllocState
*
stackAllocState
...
...
@@ -38,4 +43,21 @@ func (c *Cache) Reset() {
for
i
:=
range
xl
{
xl
[
i
]
=
nil
}
xvl
:=
c
.
varLocs
[
:
c
.
curVarLoc
]
for
i
:=
range
xvl
{
xvl
[
i
]
=
VarLoc
{}
}
c
.
curVarLoc
=
0
}
func
(
c
*
Cache
)
NewVarLoc
()
*
VarLoc
{
if
c
.
varLocs
==
nil
{
c
.
varLocs
=
make
([]
VarLoc
,
4000
)
}
if
c
.
curVarLoc
==
len
(
c
.
varLocs
)
{
return
&
VarLoc
{}
}
vl
:=
&
c
.
varLocs
[
c
.
curVarLoc
]
c
.
curVarLoc
++
return
vl
}
src/cmd/compile/internal/ssa/debug.go
0 → 100644
View file @
385cd668
This diff is collapsed.
Click to expand it.
src/cmd/compile/internal/ssa/decompose.go
View file @
385cd668
...
...
@@ -98,6 +98,7 @@ func decomposeBuiltIn(f *Func) {
delete
(
f
.
NamedValues
,
name
)
case
t
.
IsFloat
()
:
// floats are never decomposed, even ones bigger than RegSize
newNames
=
append
(
newNames
,
name
)
case
t
.
Size
()
>
f
.
Config
.
RegSize
:
f
.
Fatalf
(
"undecomposed named type %v %v"
,
name
,
t
)
default
:
...
...
src/cmd/compile/internal/ssa/export_test.go
View file @
385cd668
...
...
@@ -82,33 +82,33 @@ func (DummyFrontend) Auto(pos src.XPos, t *types.Type) GCNode {
return
&
DummyAuto
{
t
:
t
,
s
:
"aDummyAuto"
}
}
func
(
d
DummyFrontend
)
SplitString
(
s
LocalSlot
)
(
LocalSlot
,
LocalSlot
)
{
return
LocalSlot
{
s
.
N
,
dummyTypes
.
BytePtr
,
s
.
Off
},
LocalSlot
{
s
.
N
,
dummyTypes
.
Int
,
s
.
Off
+
8
}
return
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
BytePtr
,
Off
:
s
.
Off
},
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
Int
,
Off
:
s
.
Off
+
8
}
}
func
(
d
DummyFrontend
)
SplitInterface
(
s
LocalSlot
)
(
LocalSlot
,
LocalSlot
)
{
return
LocalSlot
{
s
.
N
,
dummyTypes
.
BytePtr
,
s
.
Off
},
LocalSlot
{
s
.
N
,
dummyTypes
.
BytePtr
,
s
.
Off
+
8
}
return
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
BytePtr
,
Off
:
s
.
Off
},
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
BytePtr
,
Off
:
s
.
Off
+
8
}
}
func
(
d
DummyFrontend
)
SplitSlice
(
s
LocalSlot
)
(
LocalSlot
,
LocalSlot
,
LocalSlot
)
{
return
LocalSlot
{
s
.
N
,
s
.
Type
.
ElemType
()
.
PtrTo
(),
s
.
Off
},
LocalSlot
{
s
.
N
,
dummyTypes
.
Int
,
s
.
Off
+
8
},
LocalSlot
{
s
.
N
,
dummyTypes
.
Int
,
s
.
Off
+
16
}
return
LocalSlot
{
N
:
s
.
N
,
Type
:
s
.
Type
.
ElemType
()
.
PtrTo
(),
Off
:
s
.
Off
},
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
Int
,
Off
:
s
.
Off
+
8
},
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
Int
,
Off
:
s
.
Off
+
16
}
}
func
(
d
DummyFrontend
)
SplitComplex
(
s
LocalSlot
)
(
LocalSlot
,
LocalSlot
)
{
if
s
.
Type
.
Size
()
==
16
{
return
LocalSlot
{
s
.
N
,
dummyTypes
.
Float64
,
s
.
Off
},
LocalSlot
{
s
.
N
,
dummyTypes
.
Float64
,
s
.
Off
+
8
}
return
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
Float64
,
Off
:
s
.
Off
},
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
Float64
,
Off
:
s
.
Off
+
8
}
}
return
LocalSlot
{
s
.
N
,
dummyTypes
.
Float32
,
s
.
Off
},
LocalSlot
{
s
.
N
,
dummyTypes
.
Float32
,
s
.
Off
+
4
}
return
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
Float32
,
Off
:
s
.
Off
},
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
Float32
,
Off
:
s
.
Off
+
4
}
}
func
(
d
DummyFrontend
)
SplitInt64
(
s
LocalSlot
)
(
LocalSlot
,
LocalSlot
)
{
if
s
.
Type
.
IsSigned
()
{
return
LocalSlot
{
s
.
N
,
dummyTypes
.
Int32
,
s
.
Off
+
4
},
LocalSlot
{
s
.
N
,
dummyTypes
.
UInt32
,
s
.
Off
}
return
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
Int32
,
Off
:
s
.
Off
+
4
},
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
UInt32
,
Off
:
s
.
Off
}
}
return
LocalSlot
{
s
.
N
,
dummyTypes
.
UInt32
,
s
.
Off
+
4
},
LocalSlot
{
s
.
N
,
dummyTypes
.
UInt32
,
s
.
Off
}
return
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
UInt32
,
Off
:
s
.
Off
+
4
},
LocalSlot
{
N
:
s
.
N
,
Type
:
dummyTypes
.
UInt32
,
Off
:
s
.
Off
}
}
func
(
d
DummyFrontend
)
SplitStruct
(
s
LocalSlot
,
i
int
)
LocalSlot
{
return
LocalSlot
{
s
.
N
,
s
.
Type
.
FieldType
(
i
),
s
.
Off
+
s
.
Type
.
FieldOff
(
i
)}
return
LocalSlot
{
N
:
s
.
N
,
Type
:
s
.
Type
.
FieldType
(
i
),
Off
:
s
.
Off
+
s
.
Type
.
FieldOff
(
i
)}
}
func
(
d
DummyFrontend
)
SplitArray
(
s
LocalSlot
)
LocalSlot
{
return
LocalSlot
{
s
.
N
,
s
.
Type
.
ElemType
(),
s
.
Off
}
return
LocalSlot
{
N
:
s
.
N
,
Type
:
s
.
Type
.
ElemType
(),
Off
:
s
.
Off
}
}
func
(
DummyFrontend
)
Line
(
_
src
.
XPos
)
string
{
return
"unknown.go:0"
...
...
src/cmd/compile/internal/ssa/gen/genericOps.go
View file @
385cd668
...
...
@@ -420,6 +420,7 @@ var genericOps = []opData{
{
name
:
"VarKill"
,
argLength
:
1
,
aux
:
"Sym"
,
symEffect
:
"None"
},
// aux is a *gc.Node of a variable that is known to be dead. arg0=mem, returns mem
{
name
:
"VarLive"
,
argLength
:
1
,
aux
:
"Sym"
,
symEffect
:
"None"
},
// aux is a *gc.Node of a variable that must be kept live. arg0=mem, returns mem
{
name
:
"KeepAlive"
,
argLength
:
2
,
typ
:
"Mem"
},
// arg[0] is a value that must be kept alive until this mark. arg[1]=mem, returns mem
{
name
:
"RegKill"
},
// regalloc has determined that the value in this register is dead
// Ops for breaking 64-bit operations on 32-bit architectures
{
name
:
"Int64Make"
,
argLength
:
2
,
typ
:
"UInt64"
},
// arg0=hi, arg1=lo
...
...
src/cmd/compile/internal/ssa/html.go
View file @
385cd668
...
...
@@ -11,6 +11,7 @@ import (
"html"
"io"
"os"
"strings"
)
type
HTMLWriter
struct
{
...
...
@@ -362,6 +363,18 @@ func (v *Value) LongHTML() string {
if
int
(
v
.
ID
)
<
len
(
r
)
&&
r
[
v
.
ID
]
!=
nil
{
s
+=
" : "
+
html
.
EscapeString
(
r
[
v
.
ID
]
.
Name
())
}
var
names
[]
string
for
name
,
values
:=
range
v
.
Block
.
Func
.
NamedValues
{
for
_
,
value
:=
range
values
{
if
value
==
v
{
names
=
append
(
names
,
name
.
Name
())
break
// drop duplicates.
}
}
}
if
len
(
names
)
!=
0
{
s
+=
" ("
+
strings
.
Join
(
names
,
", "
)
+
")"
}
s
+=
"</span>"
return
s
}
...
...
src/cmd/compile/internal/ssa/location.go
View file @
385cd668
...
...
@@ -26,12 +26,38 @@ func (r *Register) Name() string {
return
r
.
name
}
// A LocalSlot is a location in the stack frame.
// It is (possibly a subpiece of) a PPARAM, PPARAMOUT, or PAUTO ONAME node.
// ObjNum returns the register number from cmd/internal/obj/$ARCH that
// corresponds to this register.
func
(
r
*
Register
)
ObjNum
()
int16
{
return
r
.
objNum
}
// A LocalSlot is a location in the stack frame, which identifies and stores
// part or all of a PPARAM, PPARAMOUT, or PAUTO ONAME node.
// It can represent a whole variable, part of a larger stack slot, or part of a
// variable that has been decomposed into multiple stack slots.
// As an example, a string could have the following configurations:
//
// stack layout LocalSlots
//
// Optimizations are disabled. s is on the stack and represented in its entirety.
// [ ------- s string ---- ] { N: s, Type: string, Off: 0 }
//
// s was not decomposed, but the SSA operates on its parts individually, so
// there is a LocalSlot for each of its fields that points into the single stack slot.
// [ ------- s string ---- ] { N: s, Type: *uint8, Off: 0 }, {N: s, Type: int, Off: 8}
//
// s was decomposed. Each of its fields is in its own stack slot and has its own LocalSLot.
// [ ptr *uint8 ] [ len int] { N: ptr, Type: *uint8, Off: 0, SplitOf: parent, SplitOffset: 0},
// { N: len, Type: int, Off: 0, SplitOf: parent, SplitOffset: 8}
// parent = &{N: s, Type: string}
type
LocalSlot
struct
{
N
GCNode
// an ONAME *gc.Node representing a
variable on the stack
N
GCNode
// an ONAME *gc.Node representing a
stack location.
Type
*
types
.
Type
// type of slot
Off
int64
// offset of slot in N
SplitOf
*
LocalSlot
// slot is a decomposition of SplitOf
SplitOffset
int64
// .. at this offset.
}
func
(
s
LocalSlot
)
Name
()
string
{
...
...
src/cmd/compile/internal/ssa/opGen.go
View file @
385cd668
...
...
@@ -1903,6 +1903,7 @@ const (
OpVarKill
OpVarLive
OpKeepAlive
OpRegKill
OpInt64Make
OpInt64Hi
OpInt64Lo
...
...
@@ -22557,6 +22558,11 @@ var opcodeTable = [...]opInfo{
argLen
:
2
,
generic
:
true
,
},
{
name
:
"RegKill"
,
argLen
:
0
,
generic
:
true
,
},
{
name
:
"Int64Make"
,
argLen
:
2
,
...
...
src/cmd/compile/internal/ssa/regalloc.go
View file @
385cd668
...
...
@@ -242,6 +242,9 @@ type regAllocState struct {
// current state of each (preregalloc) Value
values
[]
valState
// names associated with each Value
valueNames
[][]
LocalSlot
// ID of SP, SB values
sp
,
sb
ID
...
...
@@ -300,6 +303,13 @@ type startReg struct {
// freeReg frees up register r. Any current user of r is kicked out.
func
(
s
*
regAllocState
)
freeReg
(
r
register
)
{
s
.
freeOrResetReg
(
r
,
false
)
}
// freeOrResetReg frees up register r. Any current user of r is kicked out.
// resetting indicates that the operation is only for bookkeeping,
// e.g. when clearing out state upon entry to a new block.
func
(
s
*
regAllocState
)
freeOrResetReg
(
r
register
,
resetting
bool
)
{
v
:=
s
.
regs
[
r
]
.
v
if
v
==
nil
{
s
.
f
.
Fatalf
(
"tried to free an already free register %d
\n
"
,
r
)
...
...
@@ -309,6 +319,16 @@ func (s *regAllocState) freeReg(r register) {
if
s
.
f
.
pass
.
debug
>
regDebug
{
fmt
.
Printf
(
"freeReg %s (dump %s/%s)
\n
"
,
s
.
registers
[
r
]
.
Name
(),
v
,
s
.
regs
[
r
]
.
c
)
}
if
!
resetting
&&
s
.
f
.
Config
.
ctxt
.
Flag_locationlists
&&
len
(
s
.
valueNames
[
v
.
ID
])
!=
0
{
kill
:=
s
.
curBlock
.
NewValue0
(
src
.
NoXPos
,
OpRegKill
,
types
.
TypeVoid
)
for
int
(
kill
.
ID
)
>=
len
(
s
.
orig
)
{
s
.
orig
=
append
(
s
.
orig
,
nil
)
}
for
_
,
name
:=
range
s
.
valueNames
[
v
.
ID
]
{
s
.
f
.
NamedValues
[
name
]
=
append
(
s
.
f
.
NamedValues
[
name
],
kill
)
}
s
.
f
.
setHome
(
kill
,
&
s
.
registers
[
r
])
}
s
.
regs
[
r
]
=
regState
{}
s
.
values
[
v
.
ID
]
.
regs
&^=
regMask
(
1
)
<<
r
s
.
used
&^=
regMask
(
1
)
<<
r
...
...
@@ -599,6 +619,17 @@ func (s *regAllocState) init(f *Func) {
s
.
values
=
make
([]
valState
,
f
.
NumValues
())
s
.
orig
=
make
([]
*
Value
,
f
.
NumValues
())
s
.
copies
=
make
(
map
[
*
Value
]
bool
)
if
s
.
f
.
Config
.
ctxt
.
Flag_locationlists
{
s
.
valueNames
=
make
([][]
LocalSlot
,
f
.
NumValues
())
for
slot
,
values
:=
range
f
.
NamedValues
{
if
isSynthetic
(
&
slot
)
{
continue
}
for
_
,
value
:=
range
values
{
s
.
valueNames
[
value
.
ID
]
=
append
(
s
.
valueNames
[
value
.
ID
],
slot
)
}
}
}
for
_
,
b
:=
range
f
.
Blocks
{
for
_
,
v
:=
range
b
.
Values
{
if
!
v
.
Type
.
IsMemory
()
&&
!
v
.
Type
.
IsVoid
()
&&
!
v
.
Type
.
IsFlags
()
&&
!
v
.
Type
.
IsTuple
()
{
...
...
@@ -692,7 +723,9 @@ func (s *regAllocState) liveAfterCurrentInstruction(v *Value) bool {
// Sets the state of the registers to that encoded in regs.
func
(
s
*
regAllocState
)
setState
(
regs
[]
endReg
)
{
s
.
freeRegs
(
s
.
used
)
for
s
.
used
!=
0
{
s
.
freeOrResetReg
(
pickReg
(
s
.
used
),
true
)
}
for
_
,
x
:=
range
regs
{
s
.
assignReg
(
x
.
r
,
x
.
v
,
x
.
c
)
}
...
...
@@ -735,6 +768,9 @@ func (s *regAllocState) regalloc(f *Func) {
}
for
_
,
b
:=
range
f
.
Blocks
{
if
s
.
f
.
pass
.
debug
>
regDebug
{
fmt
.
Printf
(
"Begin processing block %v
\n
"
,
b
)
}
s
.
curBlock
=
b
// Initialize regValLiveSet and uses fields for this block.
...
...
@@ -830,9 +866,6 @@ func (s *regAllocState) regalloc(f *Func) {
// This is the complicated case. We have more than one predecessor,
// which means we may have Phi ops.
// Copy phi ops into new schedule.
b
.
Values
=
append
(
b
.
Values
,
phis
...
)
// Start with the final register state of the primary predecessor
idx
:=
s
.
primary
[
b
.
ID
]
if
idx
<
0
{
...
...
@@ -910,6 +943,9 @@ func (s *regAllocState) regalloc(f *Func) {
}
}
// Copy phi ops into new schedule.
b
.
Values
=
append
(
b
.
Values
,
phis
...
)
// Third pass - pick registers for phis whose inputs
// were not in a register.
for
i
,
v
:=
range
phis
{
...
...
@@ -1005,7 +1041,7 @@ func (s *regAllocState) regalloc(f *Func) {
pidx
:=
e
.
i
for
_
,
v
:=
range
succ
.
Values
{
if
v
.
Op
!=
OpPhi
{
break
continue
}
if
!
s
.
values
[
v
.
ID
]
.
needReg
{
continue
...
...
@@ -1565,6 +1601,9 @@ func (s *regAllocState) placeSpills() {
for
_
,
b
:=
range
f
.
Blocks
{
var
m
regMask
for
_
,
v
:=
range
b
.
Values
{
if
v
.
Op
==
OpRegKill
{
continue
}
if
v
.
Op
!=
OpPhi
{
break
}
...
...
@@ -1675,7 +1714,7 @@ func (s *regAllocState) placeSpills() {
for
_
,
b
:=
range
f
.
Blocks
{
nphi
:=
0
for
_
,
v
:=
range
b
.
Values
{
if
v
.
Op
!=
OpPhi
{
if
v
.
Op
!=
Op
RegKill
&&
v
.
Op
!=
Op
Phi
{
break
}
nphi
++
...
...
@@ -1800,6 +1839,9 @@ func (e *edgeState) setup(idx int, srcReg []endReg, dstReg []startReg, stacklive
}
// Phis need their args to end up in a specific location.
for
_
,
v
:=
range
e
.
b
.
Values
{
if
v
.
Op
==
OpRegKill
{
continue
}
if
v
.
Op
!=
OpPhi
{
break
}
...
...
@@ -1878,6 +1920,7 @@ func (e *edgeState) process() {
if
e
.
s
.
f
.
pass
.
debug
>
regDebug
{
fmt
.
Printf
(
"breaking cycle with v%d in %s:%s
\n
"
,
vid
,
loc
.
Name
(),
c
)
}
e
.
erase
(
r
)
if
_
,
isReg
:=
loc
.
(
*
Register
);
isReg
{
c
=
e
.
p
.
NewValue1
(
d
.
pos
,
OpCopy
,
c
.
Type
,
c
)
}
else
{
...
...
@@ -1943,6 +1986,18 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.XP
}
}
_
,
dstReg
:=
loc
.
(
*
Register
)
// Pre-clobber destination. This avoids the
// following situation:
// - v is currently held in R0 and stacktmp0.
// - We want to copy stacktmp1 to stacktmp0.
// - We choose R0 as the temporary register.
// During the copy, both R0 and stacktmp0 are
// clobbered, losing both copies of v. Oops!
// Erasing the destination early means R0 will not
// be chosen as the temp register, as it will then
// be the last copy of v.
e
.
erase
(
loc
)
var
x
*
Value
if
c
==
nil
{
if
!
e
.
s
.
values
[
vid
]
.
rematerializeable
{
...
...
@@ -1953,8 +2008,8 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.XP
}
else
{
// Rematerialize into stack slot. Need a free
// register to accomplish this.
e
.
erase
(
loc
)
// see pre-clobber comment below
r
:=
e
.
findRegFor
(
v
.
Type
)
e
.
erase
(
r
)
x
=
v
.
copyIntoNoXPos
(
e
.
p
)
e
.
set
(
r
,
vid
,
x
,
false
,
pos
)
// Make sure we spill with the size of the slot, not the
...
...
@@ -1976,20 +2031,8 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.XP
x
=
e
.
p
.
NewValue1
(
pos
,
OpLoadReg
,
c
.
Type
,
c
)
}
else
{
// mem->mem. Use temp register.
// Pre-clobber destination. This avoids the
// following situation:
// - v is currently held in R0 and stacktmp0.
// - We want to copy stacktmp1 to stacktmp0.
// - We choose R0 as the temporary register.
// During the copy, both R0 and stacktmp0 are
// clobbered, losing both copies of v. Oops!
// Erasing the destination early means R0 will not
// be chosen as the temp register, as it will then
// be the last copy of v.
e
.
erase
(
loc
)
r
:=
e
.
findRegFor
(
c
.
Type
)
e
.
erase
(
r
)
t
:=
e
.
p
.
NewValue1
(
pos
,
OpLoadReg
,
c
.
Type
,
c
)
e
.
set
(
r
,
vid
,
t
,
false
,
pos
)
x
=
e
.
p
.
NewValue1
(
pos
,
OpStoreReg
,
loc
.
(
LocalSlot
)
.
Type
,
t
)
...
...
@@ -2008,7 +2051,6 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.XP
// set changes the contents of location loc to hold the given value and its cached representative.
func
(
e
*
edgeState
)
set
(
loc
Location
,
vid
ID
,
c
*
Value
,
final
bool
,
pos
src
.
XPos
)
{
e
.
s
.
f
.
setHome
(
c
,
loc
)
e
.
erase
(
loc
)
e
.
contents
[
loc
]
=
contentRecord
{
vid
,
c
,
final
,
pos
}
a
:=
e
.
cache
[
vid
]
if
len
(
a
)
==
0
{
...
...
@@ -2059,6 +2101,16 @@ func (e *edgeState) erase(loc Location) {
fmt
.
Printf
(
"v%d no longer available in %s:%s
\n
"
,
vid
,
loc
.
Name
(),
c
)
}
a
[
i
],
a
=
a
[
len
(
a
)
-
1
],
a
[
:
len
(
a
)
-
1
]
if
e
.
s
.
f
.
Config
.
ctxt
.
Flag_locationlists
{
if
_
,
isReg
:=
loc
.
(
*
Register
);
isReg
&&
int
(
c
.
ID
)
<
len
(
e
.
s
.
valueNames
)
&&
len
(
e
.
s
.
valueNames
[
c
.
ID
])
!=
0
{
kill
:=
e
.
p
.
NewValue0
(
src
.
NoXPos
,
OpRegKill
,
types
.
TypeVoid
)
e
.
s
.
f
.
setHome
(
kill
,
loc
)
for
_
,
name
:=
range
e
.
s
.
valueNames
[
c
.
ID
]
{
e
.
s
.
f
.
NamedValues
[
name
]
=
append
(
e
.
s
.
f
.
NamedValues
[
name
],
kill
)
}
}
}
break
}
}
...
...
@@ -2118,8 +2170,8 @@ func (e *edgeState) findRegFor(typ *types.Type) Location {
// Allocate a temp location to spill a register to.
// The type of the slot is immaterial - it will not be live across
// any safepoint. Just use a type big enough to hold any register.
t
:=
LocalSlot
{
e
.
s
.
f
.
fe
.
Auto
(
c
.
Pos
,
types
.
Int64
),
types
.
Int64
,
0
}
// TODO: reuse these slots.
t
:=
LocalSlot
{
N
:
e
.
s
.
f
.
fe
.
Auto
(
c
.
Pos
,
types
.
Int64
),
Type
:
types
.
Int64
}
// TODO: reuse these slots.
They'll need to be erased first.
e
.
set
(
t
,
vid
,
x
,
false
,
c
.
Pos
)
if
e
.
s
.
f
.
pass
.
debug
>
regDebug
{
fmt
.
Printf
(
" SPILL %s->%s %s
\n
"
,
r
.
Name
(),
t
.
Name
(),
x
.
LongString
())
...
...
src/cmd/compile/internal/ssa/sizeof_test.go
View file @
385cd668
...
...
@@ -24,6 +24,7 @@ func TestSizeof(t *testing.T) {
}{
{
Value
{},
68
,
112
},
{
Block
{},
152
,
288
},
{
LocalSlot
{},
32
,
48
},
{
valState
{},
28
,
40
},
}
...
...
src/cmd/compile/internal/ssa/stackalloc.go
View file @
385cd668
...
...
@@ -151,7 +151,7 @@ func (s *stackAllocState) stackalloc() {
if
v
.
Op
!=
OpArg
{
continue
}
loc
:=
LocalSlot
{
v
.
Aux
.
(
GCNode
),
v
.
Type
,
v
.
AuxInt
}
loc
:=
LocalSlot
{
N
:
v
.
Aux
.
(
GCNode
),
Type
:
v
.
Type
,
Off
:
v
.
AuxInt
}
if
f
.
pass
.
debug
>
stackDebug
{
fmt
.
Printf
(
"stackalloc %s to %s
\n
"
,
v
,
loc
.
Name
())
}
...
...
src/cmd/compile/internal/ssa/value.go
View file @
385cd668
...
...
@@ -10,6 +10,7 @@ import (
"cmd/internal/src"
"fmt"
"math"
"strings"
)
// A Value represents a value in the SSA representation of the program.
...
...
@@ -98,7 +99,7 @@ func (v *Value) AuxValAndOff() ValAndOff {
return
ValAndOff
(
v
.
AuxInt
)
}
// long form print. v# = opcode <type> [aux] args [: reg]
// long form print. v# = opcode <type> [aux] args [: reg]
(names)
func
(
v
*
Value
)
LongString
()
string
{
s
:=
fmt
.
Sprintf
(
"v%d = %s"
,
v
.
ID
,
v
.
Op
)
s
+=
" <"
+
v
.
Type
.
String
()
+
">"
...
...
@@ -110,6 +111,18 @@ func (v *Value) LongString() string {
if
int
(
v
.
ID
)
<
len
(
r
)
&&
r
[
v
.
ID
]
!=
nil
{
s
+=
" : "
+
r
[
v
.
ID
]
.
Name
()
}
var
names
[]
string
for
name
,
values
:=
range
v
.
Block
.
Func
.
NamedValues
{
for
_
,
value
:=
range
values
{
if
value
==
v
{
names
=
append
(
names
,
name
.
Name
())
break
// drop duplicates.
}
}
}
if
len
(
names
)
!=
0
{
s
+=
" ("
+
strings
.
Join
(
names
,
", "
)
+
")"
}
return
s
}
...
...
src/cmd/internal/dwarf/dwarf.go
View file @
385cd668
...
...
@@ -15,6 +15,9 @@ import (
// InfoPrefix is the prefix for all the symbols containing DWARF info entries.
const
InfoPrefix
=
"go.info."
// RangePrefix is the prefix for all the symbols containing DWARF location lists.
const
LocPrefix
=
"go.loc."
// RangePrefix is the prefix for all the symbols containing DWARF range lists.
const
RangePrefix
=
"go.range."
...
...
@@ -23,13 +26,31 @@ type Sym interface {
Len
()
int64
}
// A Location represents a variable's location at a particular PC range.
// It becomes a location list entry in the DWARF.
type
Location
struct
{
StartPC
,
EndPC
int64
Pieces
[]
Piece
}
// A Piece represents the location of a particular part of a variable.
// It becomes part of a location list entry (a DW_OP_piece) in the DWARF.
type
Piece
struct
{
Length
int64
StackOffset
int32
RegNum
int16
Missing
bool
OnStack
bool
// if true, RegNum is unset.
}
// A Var represents a local variable or a function parameter.
type
Var
struct
{
Name
string
Abbrev
int
// Either DW_ABRV_AUTO or DW_ABRV_PARAM
Offset
int32
Scope
int32
Type
Sym
Name
string
Abbrev
int
// Either DW_ABRV_AUTO or DW_ABRV_PARAM
StackOffset
int32
LocationList
[]
Location
Scope
int32
Type
Sym
}
// A Scope represents a lexical scope. All variables declared within a
...
...
@@ -205,7 +226,7 @@ const (
)
// Index into the abbrevs table below.
// Keep in sync with ispubname() and ispubtype()
below
.
// Keep in sync with ispubname() and ispubtype()
in ld/dwarf.go
.
// ispubtype considers >= NULLTYPE public
const
(
DW_ABRV_NULL
=
iota
...
...
@@ -213,7 +234,9 @@ const (
DW_ABRV_FUNCTION
DW_ABRV_VARIABLE
DW_ABRV_AUTO
DW_ABRV_AUTO_LOCLIST
DW_ABRV_PARAM
DW_ABRV_PARAM_LOCLIST
DW_ABRV_LEXICAL_BLOCK_RANGES
DW_ABRV_LEXICAL_BLOCK_SIMPLE
DW_ABRV_STRUCTFIELD
...
...
@@ -297,6 +320,17 @@ var abbrevs = [DW_NABRV]dwAbbrev{
},
},
/* AUTO_LOCLIST */
{
DW_TAG_variable
,
DW_CHILDREN_no
,
[]
dwAttrForm
{
{
DW_AT_name
,
DW_FORM_string
},
{
DW_AT_location
,
DW_FORM_sec_offset
},
{
DW_AT_type
,
DW_FORM_ref_addr
},
},
},
/* PARAM */
{
DW_TAG_formal_parameter
,
...
...
@@ -307,6 +341,18 @@ var abbrevs = [DW_NABRV]dwAbbrev{
{
DW_AT_type
,
DW_FORM_ref_addr
},
},
},
/* PARAM_LOCLIST */
{
DW_TAG_formal_parameter
,
DW_CHILDREN_no
,
[]
dwAttrForm
{
{
DW_AT_name
,
DW_FORM_string
},
{
DW_AT_location
,
DW_FORM_sec_offset
},
{
DW_AT_type
,
DW_FORM_ref_addr
},
},
},
/* LEXICAL_BLOCK_RANGES */
{
DW_TAG_lexical_block
,
...
...
@@ -684,31 +730,30 @@ func HasChildren(die *DWDie) bool {
// PutFunc writes a DIE for a function to s.
// It also writes child DIEs for each variable in vars.
func
PutFunc
(
ctxt
Context
,
s
,
ranges
Sym
,
name
string
,
external
bool
,
startPC
Sym
,
size
int64
,
scopes
[]
Scope
)
error
{
Uleb128put
(
ctxt
,
s
,
DW_ABRV_FUNCTION
)
putattr
(
ctxt
,
s
,
DW_ABRV_FUNCTION
,
DW_FORM_string
,
DW_CLS_STRING
,
int64
(
len
(
name
)),
name
)
putattr
(
ctxt
,
s
,
DW_ABRV_FUNCTION
,
DW_FORM_addr
,
DW_CLS_ADDRESS
,
0
,
startPC
)
putattr
(
ctxt
,
s
,
DW_ABRV_FUNCTION
,
DW_FORM_addr
,
DW_CLS_ADDRESS
,
size
,
startPC
)
putattr
(
ctxt
,
s
,
DW_ABRV_FUNCTION
,
DW_FORM_block1
,
DW_CLS_BLOCK
,
1
,
[]
byte
{
DW_OP_call_frame_cfa
})
func
PutFunc
(
ctxt
Context
,
info
,
loc
,
ranges
Sym
,
name
string
,
external
bool
,
startPC
Sym
,
size
int64
,
scopes
[]
Scope
)
error
{
Uleb128put
(
ctxt
,
info
,
DW_ABRV_FUNCTION
)
putattr
(
ctxt
,
info
,
DW_ABRV_FUNCTION
,
DW_FORM_string
,
DW_CLS_STRING
,
int64
(
len
(
name
)),
name
)
putattr
(
ctxt
,
info
,
DW_ABRV_FUNCTION
,
DW_FORM_addr
,
DW_CLS_ADDRESS
,
0
,
startPC
)
putattr
(
ctxt
,
info
,
DW_ABRV_FUNCTION
,
DW_FORM_addr
,
DW_CLS_ADDRESS
,
size
,
startPC
)
putattr
(
ctxt
,
info
,
DW_ABRV_FUNCTION
,
DW_FORM_block1
,
DW_CLS_BLOCK
,
1
,
[]
byte
{
DW_OP_call_frame_cfa
})
var
ev
int64
if
external
{
ev
=
1
}
putattr
(
ctxt
,
s
,
DW_ABRV_FUNCTION
,
DW_FORM_flag
,
DW_CLS_FLAG
,
ev
,
0
)
putattr
(
ctxt
,
info
,
DW_ABRV_FUNCTION
,
DW_FORM_flag
,
DW_CLS_FLAG
,
ev
,
0
)
if
len
(
scopes
)
>
0
{
var
encbuf
[
20
]
byte
if
putscope
(
ctxt
,
s
,
ranges
,
startPC
,
0
,
scopes
,
encbuf
[
:
0
])
<
int32
(
len
(
scopes
))
{
if
putscope
(
ctxt
,
info
,
loc
,
ranges
,
startPC
,
0
,
scopes
,
encbuf
[
:
0
])
<
int32
(
len
(
scopes
))
{
return
errors
.
New
(
"multiple toplevel scopes"
)
}
}
Uleb128put
(
ctxt
,
s
,
0
)
Uleb128put
(
ctxt
,
info
,
0
)
return
nil
}
func
putscope
(
ctxt
Context
,
s
,
ranges
Sym
,
startPC
Sym
,
curscope
int32
,
scopes
[]
Scope
,
encbuf
[]
byte
)
int32
{
func
putscope
(
ctxt
Context
,
info
,
loc
,
ranges
,
startPC
Sym
,
curscope
int32
,
scopes
[]
Scope
,
encbuf
[]
byte
)
int32
{
for
_
,
v
:=
range
scopes
[
curscope
]
.
Vars
{
putvar
(
ctxt
,
s
,
v
,
encbuf
)
putvar
(
ctxt
,
info
,
loc
,
v
,
startPC
,
encbuf
)
}
this
:=
curscope
curscope
++
...
...
@@ -719,12 +764,12 @@ func putscope(ctxt Context, s, ranges Sym, startPC Sym, curscope int32, scopes [
}
if
len
(
scope
.
Ranges
)
==
1
{
Uleb128put
(
ctxt
,
s
,
DW_ABRV_LEXICAL_BLOCK_SIMPLE
)
putattr
(
ctxt
,
s
,
DW_ABRV_LEXICAL_BLOCK_SIMPLE
,
DW_FORM_addr
,
DW_CLS_ADDRESS
,
scope
.
Ranges
[
0
]
.
Start
,
startPC
)
putattr
(
ctxt
,
s
,
DW_ABRV_LEXICAL_BLOCK_SIMPLE
,
DW_FORM_addr
,
DW_CLS_ADDRESS
,
scope
.
Ranges
[
0
]
.
End
,
startPC
)
Uleb128put
(
ctxt
,
info
,
DW_ABRV_LEXICAL_BLOCK_SIMPLE
)
putattr
(
ctxt
,
info
,
DW_ABRV_LEXICAL_BLOCK_SIMPLE
,
DW_FORM_addr
,
DW_CLS_ADDRESS
,
scope
.
Ranges
[
0
]
.
Start
,
startPC
)
putattr
(
ctxt
,
info
,
DW_ABRV_LEXICAL_BLOCK_SIMPLE
,
DW_FORM_addr
,
DW_CLS_ADDRESS
,
scope
.
Ranges
[
0
]
.
End
,
startPC
)
}
else
{
Uleb128put
(
ctxt
,
s
,
DW_ABRV_LEXICAL_BLOCK_RANGES
)
putattr
(
ctxt
,
s
,
DW_ABRV_LEXICAL_BLOCK_RANGES
,
DW_FORM_sec_offset
,
DW_CLS_PTR
,
ranges
.
Len
(),
ranges
)
Uleb128put
(
ctxt
,
info
,
DW_ABRV_LEXICAL_BLOCK_RANGES
)
putattr
(
ctxt
,
info
,
DW_ABRV_LEXICAL_BLOCK_RANGES
,
DW_FORM_sec_offset
,
DW_CLS_PTR
,
ranges
.
Len
(),
ranges
)
ctxt
.
AddAddress
(
ranges
,
nil
,
-
1
)
ctxt
.
AddAddress
(
ranges
,
startPC
,
0
)
...
...
@@ -736,32 +781,72 @@ func putscope(ctxt Context, s, ranges Sym, startPC Sym, curscope int32, scopes [
ctxt
.
AddAddress
(
ranges
,
nil
,
0
)
}
curscope
=
putscope
(
ctxt
,
s
,
ranges
,
startPC
,
curscope
,
scopes
,
encbuf
)
curscope
=
putscope
(
ctxt
,
info
,
loc
,
ranges
,
startPC
,
curscope
,
scopes
,
encbuf
)
Uleb128put
(
ctxt
,
s
,
0
)
Uleb128put
(
ctxt
,
info
,
0
)
}
return
curscope
}
func
putvar
(
ctxt
Context
,
s
Sym
,
v
*
Var
,
encbuf
[]
byte
)
{
func
putvar
(
ctxt
Context
,
info
,
loc
Sym
,
v
*
Var
,
startPC
Sym
,
encbuf
[]
byte
)
{
n
:=
v
.
Name
Uleb128put
(
ctxt
,
s
,
int64
(
v
.
Abbrev
))
putattr
(
ctxt
,
s
,
v
.
Abbrev
,
DW_FORM_string
,
DW_CLS_STRING
,
int64
(
len
(
n
)),
n
)
loc
:=
append
(
encbuf
[
:
0
],
DW_OP_call_frame_cfa
)
if
v
.
Offset
!=
0
{
loc
=
append
(
loc
,
DW_OP_consts
)
loc
=
AppendSleb128
(
loc
,
int64
(
v
.
Offset
))
loc
=
append
(
loc
,
DW_OP_plus
)
Uleb128put
(
ctxt
,
info
,
int64
(
v
.
Abbrev
))
putattr
(
ctxt
,
info
,
v
.
Abbrev
,
DW_FORM_string
,
DW_CLS_STRING
,
int64
(
len
(
n
)),
n
)
if
v
.
Abbrev
==
DW_ABRV_AUTO_LOCLIST
||
v
.
Abbrev
==
DW_ABRV_PARAM_LOCLIST
{
putattr
(
ctxt
,
info
,
v
.
Abbrev
,
DW_FORM_sec_offset
,
DW_CLS_PTR
,
int64
(
loc
.
Len
()),
loc
)
addLocList
(
ctxt
,
loc
,
startPC
,
v
,
encbuf
)
}
else
{
loc
:=
append
(
encbuf
[
:
0
],
DW_OP_call_frame_cfa
)
if
v
.
StackOffset
!=
0
{
loc
=
append
(
loc
,
DW_OP_consts
)
loc
=
AppendSleb128
(
loc
,
int64
(
v
.
StackOffset
))
loc
=
append
(
loc
,
DW_OP_plus
)
}
putattr
(
ctxt
,
info
,
v
.
Abbrev
,
DW_FORM_block1
,
DW_CLS_BLOCK
,
int64
(
len
(
loc
)),
loc
)
}
putattr
(
ctxt
,
info
,
v
.
Abbrev
,
DW_FORM_ref_addr
,
DW_CLS_REFERENCE
,
0
,
v
.
Type
)
}
func
addLocList
(
ctxt
Context
,
listSym
,
startPC
Sym
,
v
*
Var
,
encbuf
[]
byte
)
{
// Base address entry: max ptr followed by the base address.
ctxt
.
AddInt
(
listSym
,
ctxt
.
PtrSize
(),
^
0
)
ctxt
.
AddAddress
(
listSym
,
startPC
,
0
)
for
_
,
entry
:=
range
v
.
LocationList
{
ctxt
.
AddInt
(
listSym
,
ctxt
.
PtrSize
(),
entry
.
StartPC
)
ctxt
.
AddInt
(
listSym
,
ctxt
.
PtrSize
(),
entry
.
EndPC
)
locBuf
:=
encbuf
[
:
0
]
for
_
,
piece
:=
range
entry
.
Pieces
{
if
!
piece
.
Missing
{
if
piece
.
OnStack
{
locBuf
=
append
(
locBuf
,
DW_OP_fbreg
)
locBuf
=
AppendSleb128
(
locBuf
,
int64
(
piece
.
StackOffset
))
}
else
{
if
piece
.
RegNum
<
32
{
locBuf
=
append
(
locBuf
,
DW_OP_reg0
+
byte
(
piece
.
RegNum
))
}
else
{
locBuf
=
append
(
locBuf
,
DW_OP_regx
)
locBuf
=
AppendUleb128
(
locBuf
,
uint64
(
piece
.
RegNum
))
}
}
}
if
len
(
entry
.
Pieces
)
>
1
{
locBuf
=
append
(
locBuf
,
DW_OP_piece
)
locBuf
=
AppendUleb128
(
locBuf
,
uint64
(
piece
.
Length
))
}
}
ctxt
.
AddInt
(
listSym
,
2
,
int64
(
len
(
locBuf
)))
ctxt
.
AddBytes
(
listSym
,
locBuf
)
}
putattr
(
ctxt
,
s
,
v
.
Abbrev
,
DW_FORM_block1
,
DW_CLS_BLOCK
,
int64
(
len
(
loc
)),
loc
)
putattr
(
ctxt
,
s
,
v
.
Abbrev
,
DW_FORM_ref_addr
,
DW_CLS_REFERENCE
,
0
,
v
.
Type
)
// End list
ctxt
.
AddInt
(
listSym
,
ctxt
.
PtrSize
(),
0
)
ctxt
.
AddInt
(
listSym
,
ctxt
.
PtrSize
(),
0
)
}
// VarsByOffset attaches the methods of sort.Interface to []*Var,
// sorting in increasing Offset.
// sorting in increasing
Stack
Offset.
type
VarsByOffset
[]
*
Var
func
(
s
VarsByOffset
)
Len
()
int
{
return
len
(
s
)
}
func
(
s
VarsByOffset
)
Less
(
i
,
j
int
)
bool
{
return
s
[
i
]
.
Offset
<
s
[
j
]
.
Offset
}
func
(
s
VarsByOffset
)
Less
(
i
,
j
int
)
bool
{
return
s
[
i
]
.
StackOffset
<
s
[
j
]
.
Stack
Offset
}
func
(
s
VarsByOffset
)
Swap
(
i
,
j
int
)
{
s
[
i
],
s
[
j
]
=
s
[
j
],
s
[
i
]
}
src/cmd/internal/obj/link.go
View file @
385cd668
...
...
@@ -330,7 +330,8 @@ type FuncInfo struct {
Autom
[]
*
Auto
Pcln
Pcln
dwarfSym
*
LSym
dwarfInfoSym
*
LSym
dwarfLocSym
*
LSym
dwarfRangesSym
*
LSym
GCArgs
LSym
...
...
@@ -476,25 +477,26 @@ type Pcdata struct {
// Link holds the context for writing object code from a compiler
// to be linker input or for reading that input into the linker.
type
Link
struct
{
Headtype
objabi
.
HeadType
Arch
*
LinkArch
Debugasm
bool
Debugvlog
bool
Debugpcln
string
Flag_shared
bool
Flag_dynlink
bool
Flag_optimize
bool
Bso
*
bufio
.
Writer
Pathname
string
hashmu
sync
.
Mutex
// protects hash
hash
map
[
string
]
*
LSym
// name -> sym mapping
statichash
map
[
string
]
*
LSym
// name -> sym mapping for static syms
PosTable
src
.
PosTable
InlTree
InlTree
// global inlining tree used by gc/inl.go
Imports
[]
string
DiagFunc
func
(
string
,
...
interface
{})
DebugInfo
func
(
fn
*
LSym
,
curfn
interface
{})
[]
dwarf
.
Scope
// if non-nil, curfn is a *gc.Node
Errors
int
Headtype
objabi
.
HeadType
Arch
*
LinkArch
Debugasm
bool
Debugvlog
bool
Debugpcln
string
Flag_shared
bool
Flag_dynlink
bool
Flag_optimize
bool
Flag_locationlists
bool
Bso
*
bufio
.
Writer
Pathname
string
hashmu
sync
.
Mutex
// protects hash
hash
map
[
string
]
*
LSym
// name -> sym mapping
statichash
map
[
string
]
*
LSym
// name -> sym mapping for static syms
PosTable
src
.
PosTable
InlTree
InlTree
// global inlining tree used by gc/inl.go
Imports
[]
string
DiagFunc
func
(
string
,
...
interface
{})
DebugInfo
func
(
fn
*
LSym
,
curfn
interface
{})
[]
dwarf
.
Scope
// if non-nil, curfn is a *gc.Node
Errors
int
Framepointer_enabled
bool
...
...
@@ -533,9 +535,10 @@ func (ctxt *Link) FixedFrameSize() int64 {
// LinkArch is the definition of a single architecture.
type
LinkArch
struct
{
*
sys
.
Arch
Init
func
(
*
Link
)
Preprocess
func
(
*
Link
,
*
LSym
,
ProgAlloc
)
Assemble
func
(
*
Link
,
*
LSym
,
ProgAlloc
)
Progedit
func
(
*
Link
,
*
Prog
,
ProgAlloc
)
UnaryDst
map
[
As
]
bool
// Instruction takes one operand, a destination.
Init
func
(
*
Link
)
Preprocess
func
(
*
Link
,
*
LSym
,
ProgAlloc
)
Assemble
func
(
*
Link
,
*
LSym
,
ProgAlloc
)
Progedit
func
(
*
Link
,
*
Prog
,
ProgAlloc
)
UnaryDst
map
[
As
]
bool
// Instruction takes one operand, a destination.
DWARFRegisters
map
[
int16
]
int16
}
src/cmd/internal/obj/objfile.go
View file @
385cd668
...
...
@@ -465,15 +465,18 @@ func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64
}
// dwarfSym returns the DWARF symbols for TEXT symbol.
func
(
ctxt
*
Link
)
dwarfSym
(
s
*
LSym
)
(
dwarfInfoSym
,
dwarfRangesSym
*
LSym
)
{
func
(
ctxt
*
Link
)
dwarfSym
(
s
*
LSym
)
(
dwarfInfoSym
,
dwarf
LocSym
,
dwarf
RangesSym
*
LSym
)
{
if
s
.
Type
!=
objabi
.
STEXT
{
ctxt
.
Diag
(
"dwarfSym of non-TEXT %v"
,
s
)
}
if
s
.
Func
.
dwarfSym
==
nil
{
s
.
Func
.
dwarfSym
=
ctxt
.
LookupDerived
(
s
,
dwarf
.
InfoPrefix
+
s
.
Name
)
if
s
.
Func
.
dwarfInfoSym
==
nil
{
s
.
Func
.
dwarfInfoSym
=
ctxt
.
LookupDerived
(
s
,
dwarf
.
InfoPrefix
+
s
.
Name
)
if
ctxt
.
Flag_locationlists
{
s
.
Func
.
dwarfLocSym
=
ctxt
.
LookupDerived
(
s
,
dwarf
.
LocPrefix
+
s
.
Name
)
}
s
.
Func
.
dwarfRangesSym
=
ctxt
.
LookupDerived
(
s
,
dwarf
.
RangePrefix
+
s
.
Name
)
}
return
s
.
Func
.
dwarfSym
,
s
.
Func
.
dwarfRangesSym
return
s
.
Func
.
dwarf
InfoSym
,
s
.
Func
.
dwarfLoc
Sym
,
s
.
Func
.
dwarfRangesSym
}
func
(
s
*
LSym
)
Len
()
int64
{
...
...
@@ -483,15 +486,15 @@ func (s *LSym) Len() int64 {
// populateDWARF fills in the DWARF Debugging Information Entries for TEXT symbol s.
// The DWARFs symbol must already have been initialized in InitTextSym.
func
(
ctxt
*
Link
)
populateDWARF
(
curfn
interface
{},
s
*
LSym
)
{
dsym
,
drsym
:=
ctxt
.
dwarfSym
(
s
)
if
dsym
.
Size
!=
0
{
info
,
loc
,
ranges
:=
ctxt
.
dwarfSym
(
s
)
if
info
.
Size
!=
0
{
ctxt
.
Diag
(
"makeFuncDebugEntry double process %v"
,
s
)
}
var
scopes
[]
dwarf
.
Scope
if
ctxt
.
DebugInfo
!=
nil
{
scopes
=
ctxt
.
DebugInfo
(
s
,
curfn
)
}
err
:=
dwarf
.
PutFunc
(
dwCtxt
{
ctxt
},
dsym
,
drsym
,
s
.
Name
,
!
s
.
Static
(),
s
,
s
.
Size
,
scopes
)
err
:=
dwarf
.
PutFunc
(
dwCtxt
{
ctxt
},
info
,
loc
,
ranges
,
s
.
Name
,
!
s
.
Static
(),
s
,
s
.
Size
,
scopes
)
if
err
!=
nil
{
ctxt
.
Diag
(
"emitting DWARF for %s failed: %v"
,
s
.
Name
,
err
)
}
...
...
src/cmd/internal/obj/plist.go
View file @
385cd668
...
...
@@ -136,13 +136,17 @@ func (ctxt *Link) InitTextSym(s *LSym, flag int) {
ctxt
.
Text
=
append
(
ctxt
.
Text
,
s
)
// Set up DWARF entries for s.
dsym
,
drsym
:=
ctxt
.
dwarfSym
(
s
)
dsym
.
Type
=
objabi
.
SDWARFINFO
dsym
.
Set
(
AttrDuplicateOK
,
s
.
DuplicateOK
())
drsym
.
Type
=
objabi
.
SDWARFRANGE
drsym
.
Set
(
AttrDuplicateOK
,
s
.
DuplicateOK
())
ctxt
.
Data
=
append
(
ctxt
.
Data
,
dsym
)
ctxt
.
Data
=
append
(
ctxt
.
Data
,
drsym
)
info
,
loc
,
ranges
:=
ctxt
.
dwarfSym
(
s
)
info
.
Type
=
objabi
.
SDWARFINFO
info
.
Set
(
AttrDuplicateOK
,
s
.
DuplicateOK
())
if
loc
!=
nil
{
loc
.
Type
=
objabi
.
SDWARFLOC
loc
.
Set
(
AttrDuplicateOK
,
s
.
DuplicateOK
())
ctxt
.
Data
=
append
(
ctxt
.
Data
,
loc
)
}
ranges
.
Type
=
objabi
.
SDWARFRANGE
ranges
.
Set
(
AttrDuplicateOK
,
s
.
DuplicateOK
())
ctxt
.
Data
=
append
(
ctxt
.
Data
,
info
,
ranges
)
// Set up the function's gcargs and gclocals.
// They will be filled in later if needed.
...
...
src/cmd/internal/obj/x86/a.out.go
View file @
385cd668
...
...
@@ -1006,3 +1006,120 @@ const (
T_64
=
1
<<
6
T_GOTYPE
=
1
<<
7
)
// https://www.uclibc.org/docs/psABI-x86_64.pdf, figure 3.36
var
AMD64DWARFRegisters
=
map
[
int16
]
int16
{
REG_AX
:
0
,
REG_DX
:
1
,
REG_CX
:
2
,
REG_BX
:
3
,
REG_SI
:
4
,
REG_DI
:
5
,
REG_BP
:
6
,
REG_SP
:
7
,
REG_R8
:
8
,
REG_R9
:
9
,
REG_R10
:
10
,
REG_R11
:
11
,
REG_R12
:
12
,
REG_R13
:
13
,
REG_R14
:
14
,
REG_R15
:
15
,
// 16 is "Return Address RA", whatever that is.
// XMM registers. %xmmN => XN.
REG_X0
:
17
,
REG_X1
:
18
,
REG_X2
:
19
,
REG_X3
:
20
,
REG_X4
:
21
,
REG_X5
:
22
,
REG_X6
:
23
,
REG_X7
:
24
,
REG_X8
:
25
,
REG_X9
:
26
,
REG_X10
:
27
,
REG_X11
:
28
,
REG_X12
:
29
,
REG_X13
:
30
,
REG_X14
:
31
,
REG_X15
:
32
,
// ST registers. %stN => FN.
REG_F0
:
33
,
REG_F1
:
34
,
REG_F2
:
35
,
REG_F3
:
36
,
REG_F4
:
37
,
REG_F5
:
38
,
REG_F6
:
39
,
REG_F7
:
40
,
// MMX registers. %mmN => MN.
REG_M0
:
41
,
REG_M1
:
42
,
REG_M2
:
43
,
REG_M3
:
44
,
REG_M4
:
45
,
REG_M5
:
46
,
REG_M6
:
47
,
REG_M7
:
48
,
// 48 is flags, which doesn't have a name.
REG_ES
:
50
,
REG_CS
:
51
,
REG_SS
:
52
,
REG_DS
:
53
,
REG_FS
:
54
,
REG_GS
:
55
,
// 58 and 59 are {fs,gs}base, which don't have names.
REG_TR
:
62
,
REG_LDTR
:
63
,
// 64-66 are mxcsr, fcw, fsw, which don't have names.
}
// https://www.uclibc.org/docs/psABI-i386.pdf, table 2.14
var
X86DWARFRegisters
=
map
[
int16
]
int16
{
REG_AX
:
0
,
REG_CX
:
1
,
REG_DX
:
2
,
REG_BX
:
3
,
REG_SP
:
4
,
REG_BP
:
5
,
REG_SI
:
6
,
REG_DI
:
7
,
// 8 is "Return Address RA", whatever that is.
// 9 is flags, which doesn't have a name.
// ST registers. %stN => FN.
REG_F0
:
11
,
REG_F1
:
12
,
REG_F2
:
13
,
REG_F3
:
14
,
REG_F4
:
15
,
REG_F5
:
16
,
REG_F6
:
17
,
REG_F7
:
18
,
// XMM registers. %xmmN => XN.
REG_X0
:
21
,
REG_X1
:
22
,
REG_X2
:
23
,
REG_X3
:
24
,
REG_X4
:
25
,
REG_X5
:
26
,
REG_X6
:
27
,
REG_X7
:
28
,
// MMX registers. %mmN => MN.
REG_M0
:
29
,
REG_M1
:
30
,
REG_M2
:
31
,
REG_M3
:
32
,
REG_M4
:
33
,
REG_M5
:
34
,
REG_M6
:
35
,
REG_M7
:
36
,
// 39 is mxcsr, which doesn't have a name.
REG_ES
:
40
,
REG_CS
:
41
,
REG_SS
:
42
,
REG_DS
:
43
,
REG_FS
:
44
,
REG_GS
:
45
,
REG_TR
:
48
,
REG_LDTR
:
49
,
}
src/cmd/internal/obj/x86/obj6.go
View file @
385cd668
...
...
@@ -1231,28 +1231,31 @@ var unaryDst = map[obj.As]bool{
}
var
Linkamd64
=
obj
.
LinkArch
{
Arch
:
sys
.
ArchAMD64
,
Init
:
instinit
,
Preprocess
:
preprocess
,
Assemble
:
span6
,
Progedit
:
progedit
,
UnaryDst
:
unaryDst
,
Arch
:
sys
.
ArchAMD64
,
Init
:
instinit
,
Preprocess
:
preprocess
,
Assemble
:
span6
,
Progedit
:
progedit
,
UnaryDst
:
unaryDst
,
DWARFRegisters
:
AMD64DWARFRegisters
,
}
var
Linkamd64p32
=
obj
.
LinkArch
{
Arch
:
sys
.
ArchAMD64P32
,
Init
:
instinit
,
Preprocess
:
preprocess
,
Assemble
:
span6
,
Progedit
:
progedit
,
UnaryDst
:
unaryDst
,
Arch
:
sys
.
ArchAMD64P32
,
Init
:
instinit
,
Preprocess
:
preprocess
,
Assemble
:
span6
,
Progedit
:
progedit
,
UnaryDst
:
unaryDst
,
DWARFRegisters
:
AMD64DWARFRegisters
,
}
var
Link386
=
obj
.
LinkArch
{
Arch
:
sys
.
Arch386
,
Init
:
instinit
,
Preprocess
:
preprocess
,
Assemble
:
span6
,
Progedit
:
progedit
,
UnaryDst
:
unaryDst
,
Arch
:
sys
.
Arch386
,
Init
:
instinit
,
Preprocess
:
preprocess
,
Assemble
:
span6
,
Progedit
:
progedit
,
UnaryDst
:
unaryDst
,
DWARFRegisters
:
AMD64DWARFRegisters
,
}
src/cmd/internal/objabi/symkind.go
View file @
385cd668
...
...
@@ -57,4 +57,5 @@ const (
// Debugging data
SDWARFINFO
SDWARFRANGE
SDWARFLOC
)
src/cmd/internal/objabi/symkind_string.go
View file @
385cd668
...
...
@@ -4,9 +4,9 @@ package objabi
import
"fmt"
const
_SymKind_name
=
"SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFINFOSDWARFRANGE"
const
_SymKind_name
=
"SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFINFOSDWARFRANGE
SDWARFLOC
"
var
_SymKind_index
=
[
...
]
uint8
{
0
,
4
,
9
,
16
,
26
,
31
,
35
,
44
,
51
,
61
,
72
}
var
_SymKind_index
=
[
...
]
uint8
{
0
,
4
,
9
,
16
,
26
,
31
,
35
,
44
,
51
,
61
,
72
,
81
}
func
(
i
SymKind
)
String
()
string
{
if
i
>=
SymKind
(
len
(
_SymKind_index
)
-
1
)
{
...
...
src/cmd/link/internal/ld/data.go
View file @
385cd668
...
...
@@ -592,15 +592,7 @@ func relocsym(ctxt *Link, s *Symbol) {
}
case
objabi
.
R_DWARFREF
:
var
sectName
string
var
vaddr
int64
switch
{
case
r
.
Sym
.
Sect
!=
nil
:
sectName
=
r
.
Sym
.
Sect
.
Name
vaddr
=
int64
(
r
.
Sym
.
Sect
.
Vaddr
)
case
r
.
Sym
.
Type
==
SDWARFRANGE
:
sectName
=
".debug_ranges"
default
:
if
r
.
Sym
.
Sect
==
nil
{
Errorf
(
s
,
"missing DWARF section for relocation target %s"
,
r
.
Sym
.
Name
)
}
...
...
@@ -615,8 +607,8 @@ func relocsym(ctxt *Link, s *Symbol) {
r
.
Type
=
objabi
.
R_ADDR
}
r
.
Xsym
=
ctxt
.
Syms
.
ROLookup
(
sect
Name
,
0
)
r
.
Xadd
=
r
.
Add
+
Symaddr
(
r
.
Sym
)
-
vaddr
r
.
Xsym
=
ctxt
.
Syms
.
ROLookup
(
r
.
Sym
.
Sect
.
Name
,
0
)
r
.
Xadd
=
r
.
Add
+
Symaddr
(
r
.
Sym
)
-
int64
(
r
.
Sym
.
Sect
.
Vaddr
)
o
=
r
.
Xadd
rs
=
r
.
Xsym
...
...
@@ -625,7 +617,7 @@ func relocsym(ctxt *Link, s *Symbol) {
}
break
}
o
=
Symaddr
(
r
.
Sym
)
+
r
.
Add
-
vaddr
o
=
Symaddr
(
r
.
Sym
)
+
r
.
Add
-
int64
(
r
.
Sym
.
Sect
.
Vaddr
)
case
objabi
.
R_WEAKADDROFF
:
if
!
r
.
Sym
.
Attr
.
Reachable
()
{
...
...
@@ -1843,9 +1835,9 @@ func (ctxt *Link) dodata() {
dwarfgeneratedebugsyms
(
ctxt
)
var
s
*
Symbol
var
i
int
for
i
,
s
=
range
dwarfp
{
for
;
i
<
len
(
dwarfp
);
i
++
{
s
:=
dwarfp
[
i
]
if
s
.
Type
!=
SDWARFSECT
{
break
}
...
...
@@ -1862,13 +1854,26 @@ func (ctxt *Link) dodata() {
}
checkdatsize
(
ctxt
,
datsize
,
SDWARFSECT
)
if
i
<
len
(
dwarfp
)
{
sect
=
addsection
(
&
Segdwarf
,
".debug_info"
,
04
)
for
i
<
len
(
dwarfp
)
{
curType
:=
dwarfp
[
i
]
.
Type
var
sect
*
Section
switch
curType
{
case
SDWARFINFO
:
sect
=
addsection
(
&
Segdwarf
,
".debug_info"
,
04
)
case
SDWARFRANGE
:
sect
=
addsection
(
&
Segdwarf
,
".debug_ranges"
,
04
)
case
SDWARFLOC
:
sect
=
addsection
(
&
Segdwarf
,
".debug_loc"
,
04
)
default
:
Errorf
(
dwarfp
[
i
],
"unknown DWARF section %v"
,
curType
)
}
sect
.
Align
=
1
datsize
=
Rnd
(
datsize
,
int64
(
sect
.
Align
))
sect
.
Vaddr
=
uint64
(
datsize
)
for
_
,
s
:=
range
dwarfp
[
i
:
]
{
if
s
.
Type
!=
SDWARFINFO
{
for
;
i
<
len
(
dwarfp
);
i
++
{
s
:=
dwarfp
[
i
]
if
s
.
Type
!=
curType
{
break
}
s
.
Sect
=
sect
...
...
@@ -1878,7 +1883,7 @@ func (ctxt *Link) dodata() {
datsize
+=
s
.
Size
}
sect
.
Length
=
uint64
(
datsize
)
-
sect
.
Vaddr
checkdatsize
(
ctxt
,
datsize
,
SDWARFINFO
)
checkdatsize
(
ctxt
,
datsize
,
curType
)
}
/* number the sections */
...
...
src/cmd/link/internal/ld/dwarf.go
View file @
385cd668
...
...
@@ -67,26 +67,15 @@ func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64
r
.
Add
=
ofs
}
/*
* Offsets and sizes of the debug_* sections in the cout file.
*/
var
abbrevsym
*
Symbol
var
arangessec
*
Symbol
var
framesec
*
Symbol
var
infosec
*
Symbol
var
linesec
*
Symbol
var
rangesec
*
Symbol
var
gdbscript
string
var
dwarfp
[]
*
Symbol
func
writeabbrev
(
ctxt
*
Link
,
syms
[]
*
Symbol
)
[]
*
Symbol
{
func
writeabbrev
(
ctxt
*
Link
)
*
Symbol
{
s
:=
ctxt
.
Syms
.
Lookup
(
".debug_abbrev"
,
0
)
s
.
Type
=
SDWARFSECT
abbrevsym
=
s
Addbytes
(
s
,
dwarf
.
GetAbbrev
())
return
append
(
syms
,
s
)
return
s
}
/*
...
...
@@ -993,13 +982,10 @@ func getCompilationDir() string {
func
writelines
(
ctxt
*
Link
,
syms
[]
*
Symbol
)
([]
*
Symbol
,
[]
*
Symbol
)
{
var
dwarfctxt
dwarf
.
Context
=
dwctxt
{
ctxt
}
if
linesec
==
nil
{
linesec
=
ctxt
.
Syms
.
Lookup
(
".debug_line"
,
0
)
}
linesec
.
Type
=
SDWARFSECT
linesec
.
R
=
linesec
.
R
[
:
0
]
ls
:=
ctxt
.
Syms
.
Lookup
(
".debug_line"
,
0
)
ls
.
Type
=
SDWARFSECT
ls
.
R
=
ls
.
R
[
:
0
]
ls
:=
linesec
syms
=
append
(
syms
,
ls
)
var
funcs
[]
*
Symbol
...
...
@@ -1019,7 +1005,7 @@ func writelines(ctxt *Link, syms []*Symbol) ([]*Symbol, []*Symbol) {
dwinfo
=
newdie
(
ctxt
,
&
dwroot
,
dwarf
.
DW_ABRV_COMPUNIT
,
"go"
,
0
)
newattr
(
dwinfo
,
dwarf
.
DW_AT_language
,
dwarf
.
DW_CLS_CONSTANT
,
int64
(
lang
),
0
)
newattr
(
dwinfo
,
dwarf
.
DW_AT_stmt_list
,
dwarf
.
DW_CLS_PTR
,
0
,
l
inesec
)
newattr
(
dwinfo
,
dwarf
.
DW_AT_stmt_list
,
dwarf
.
DW_CLS_PTR
,
0
,
l
s
)
newattr
(
dwinfo
,
dwarf
.
DW_AT_low_pc
,
dwarf
.
DW_CLS_ADDRESS
,
s
.
Value
,
s
)
// OS X linker requires compilation dir or absolute path in comp unit name to output debug info.
compDir
:=
getCompilationDir
()
...
...
@@ -1178,12 +1164,9 @@ func appendPCDeltaCFA(b []byte, deltapc, cfa int64) []byte {
func
writeframes
(
ctxt
*
Link
,
syms
[]
*
Symbol
)
[]
*
Symbol
{
var
dwarfctxt
dwarf
.
Context
=
dwctxt
{
ctxt
}
if
framesec
==
nil
{
framesec
=
ctxt
.
Syms
.
Lookup
(
".debug_frame"
,
0
)
}
framesec
.
Type
=
SDWARFSECT
framesec
.
R
=
framesec
.
R
[
:
0
]
fs
:=
framesec
fs
:=
ctxt
.
Syms
.
Lookup
(
".debug_frame"
,
0
)
fs
.
Type
=
SDWARFSECT
fs
.
R
=
fs
.
R
[
:
0
]
syms
=
append
(
syms
,
fs
)
// Emit the CIE, Section 6.4.1
...
...
@@ -1280,7 +1263,7 @@ func writeframes(ctxt *Link, syms []*Symbol) []*Symbol {
// ptrsize: address range
Adduint32
(
ctxt
,
fs
,
uint32
(
4
+
2
*
SysArch
.
PtrSize
+
len
(
deltaBuf
)))
// length (excludes itself)
if
Linkmode
==
LinkExternal
{
adddwarfref
(
ctxt
,
fs
,
f
ramesec
,
4
)
adddwarfref
(
ctxt
,
fs
,
f
s
,
4
)
}
else
{
Adduint32
(
ctxt
,
fs
,
0
)
// CIE offset
}
...
...
@@ -1292,27 +1275,24 @@ func writeframes(ctxt *Link, syms []*Symbol) []*Symbol {
}
func
writeranges
(
ctxt
*
Link
,
syms
[]
*
Symbol
)
[]
*
Symbol
{
if
rangesec
==
nil
{
rangesec
=
ctxt
.
Syms
.
Lookup
(
".debug_ranges"
,
0
)
}
rangesec
.
Type
=
SDWARFSECT
rangesec
.
Attr
|=
AttrReachable
rangesec
.
R
=
rangesec
.
R
[
:
0
]
empty
:=
true
for
_
,
s
:=
range
ctxt
.
Textp
{
rangeSym
:=
ctxt
.
Syms
.
Lookup
(
dwarf
.
RangePrefix
+
s
.
Name
,
int
(
s
.
Version
))
rangeSym
.
Attr
|=
AttrReachable
rangeSym
.
Type
=
SDWARFRANGE
rangeSym
.
Value
=
rangesec
.
Size
rangesec
.
P
=
append
(
rangesec
.
P
,
rangeSym
.
P
...
)
for
_
,
r
:=
range
rangeSym
.
R
{
r
.
Off
+=
int32
(
rangesec
.
Size
)
rangesec
.
R
=
append
(
rangesec
.
R
,
r
)
if
rangeSym
.
Size
==
0
{
continue
}
rangesec
.
Size
+=
rangeSym
.
Size
rangeSym
.
Attr
|=
AttrReachable
|
AttrNotInSymbolTable
rangeSym
.
Type
=
SDWARFRANGE
syms
=
append
(
syms
,
rangeSym
)
empty
=
false
}
if
rangesec
.
Size
>
0
{
if
!
empty
{
// PE does not like empty sections
rangesec
:=
ctxt
.
Syms
.
Lookup
(
".debug_ranges"
,
0
)
rangesec
.
Type
=
SDWARFRANGE
rangesec
.
Attr
|=
AttrReachable
rangesec
.
R
=
rangesec
.
R
[
:
0
]
syms
=
append
(
syms
,
rangesec
)
}
return
syms
...
...
@@ -1325,18 +1305,14 @@ const (
COMPUNITHEADERSIZE
=
4
+
2
+
4
+
1
)
func
writeinfo
(
ctxt
*
Link
,
syms
[]
*
Symbol
,
funcs
[]
*
Symbol
)
[]
*
Symbol
{
if
infosec
==
nil
{
infosec
=
ctxt
.
Syms
.
Lookup
(
".debug_info"
,
0
)
}
func
writeinfo
(
ctxt
*
Link
,
syms
[]
*
Symbol
,
funcs
[]
*
Symbol
,
abbrevsym
*
Symbol
)
[]
*
Symbol
{
infosec
:=
ctxt
.
Syms
.
Lookup
(
".debug_info"
,
0
)
infosec
.
R
=
infosec
.
R
[
:
0
]
infosec
.
Type
=
SDWARFINFO
infosec
.
Attr
|=
AttrReachable
syms
=
append
(
syms
,
infosec
)
if
arangessec
==
nil
{
arangessec
=
ctxt
.
Syms
.
Lookup
(
".dwarfaranges"
,
0
)
}
arangessec
:=
ctxt
.
Syms
.
Lookup
(
".dwarfaranges"
,
0
)
arangessec
.
R
=
arangessec
.
R
[
:
0
]
var
dwarfctxt
dwarf
.
Context
=
dwctxt
{
ctxt
}
...
...
@@ -1577,10 +1553,10 @@ func dwarfgeneratedebugsyms(ctxt *Link) {
genasmsym
(
ctxt
,
defdwsymb
)
syms
:=
writeabbrev
(
ctxt
,
nil
)
abbrev
:=
writeabbrev
(
ctxt
)
syms
:=
[]
*
Symbol
{
abbrev
}
syms
,
funcs
:=
writelines
(
ctxt
,
syms
)
syms
=
writeframes
(
ctxt
,
syms
)
syms
=
writeranges
(
ctxt
,
syms
)
synthesizestringtypes
(
ctxt
,
dwtypes
.
Child
)
synthesizeslicetypes
(
ctxt
,
dwtypes
.
Child
)
...
...
@@ -1596,16 +1572,42 @@ func dwarfgeneratedebugsyms(ctxt *Link) {
// Need to reorder symbols so SDWARFINFO is after all SDWARFSECT
// (but we need to generate dies before writepub)
infosyms
:=
writeinfo
(
ctxt
,
nil
,
funcs
)
infosyms
:=
writeinfo
(
ctxt
,
nil
,
funcs
,
abbrev
)
syms
=
writepub
(
ctxt
,
".debug_pubnames"
,
ispubname
,
syms
)
syms
=
writepub
(
ctxt
,
".debug_pubtypes"
,
ispubtype
,
syms
)
syms
=
writearanges
(
ctxt
,
syms
)
syms
=
writegdbscript
(
ctxt
,
syms
)
syms
=
append
(
syms
,
infosyms
...
)
syms
=
collectlocs
(
ctxt
,
syms
,
funcs
)
syms
=
writeranges
(
ctxt
,
syms
)
dwarfp
=
syms
}
func
collectlocs
(
ctxt
*
Link
,
syms
[]
*
Symbol
,
funcs
[]
*
Symbol
)
[]
*
Symbol
{
empty
:=
true
for
_
,
fn
:=
range
funcs
{
for
_
,
reloc
:=
range
fn
.
R
{
if
reloc
.
Type
==
objabi
.
R_DWARFREF
&&
strings
.
HasPrefix
(
reloc
.
Sym
.
Name
,
dwarf
.
LocPrefix
)
{
reloc
.
Sym
.
Attr
|=
AttrReachable
|
AttrNotInSymbolTable
syms
=
append
(
syms
,
reloc
.
Sym
)
empty
=
false
// One location list entry per function, but many relocations to it. Don't duplicate.
break
}
}
}
// Don't emit .debug_loc if it's empty -- it makes the ARM linker mad.
if
!
empty
{
locsym
:=
ctxt
.
Syms
.
Lookup
(
".debug_loc"
,
0
)
locsym
.
R
=
locsym
.
R
[
:
0
]
locsym
.
Type
=
SDWARFLOC
locsym
.
Attr
|=
AttrReachable
syms
=
append
(
syms
,
locsym
)
}
return
syms
}
/*
* Elf.
*/
...
...
@@ -1618,6 +1620,7 @@ func dwarfaddshstrings(ctxt *Link, shstrtab *Symbol) {
Addstring
(
shstrtab
,
".debug_aranges"
)
Addstring
(
shstrtab
,
".debug_frame"
)
Addstring
(
shstrtab
,
".debug_info"
)
Addstring
(
shstrtab
,
".debug_loc"
)
Addstring
(
shstrtab
,
".debug_line"
)
Addstring
(
shstrtab
,
".debug_pubnames"
)
Addstring
(
shstrtab
,
".debug_pubtypes"
)
...
...
@@ -1625,6 +1628,7 @@ func dwarfaddshstrings(ctxt *Link, shstrtab *Symbol) {
Addstring
(
shstrtab
,
".debug_ranges"
)
if
Linkmode
==
LinkExternal
{
Addstring
(
shstrtab
,
elfRelType
+
".debug_info"
)
Addstring
(
shstrtab
,
elfRelType
+
".debug_loc"
)
Addstring
(
shstrtab
,
elfRelType
+
".debug_aranges"
)
Addstring
(
shstrtab
,
elfRelType
+
".debug_line"
)
Addstring
(
shstrtab
,
elfRelType
+
".debug_frame"
)
...
...
@@ -1651,6 +1655,10 @@ func dwarfaddelfsectionsyms(ctxt *Link) {
putelfsectionsym
(
sym
,
sym
.
Sect
.
Elfsect
.
shnum
)
sym
=
ctxt
.
Syms
.
Lookup
(
".debug_frame"
,
0
)
putelfsectionsym
(
sym
,
sym
.
Sect
.
Elfsect
.
shnum
)
sym
=
ctxt
.
Syms
.
Lookup
(
".debug_loc"
,
0
)
if
sym
.
Sect
!=
nil
{
putelfsectionsym
(
sym
,
sym
.
Sect
.
Elfsect
.
shnum
)
}
sym
=
ctxt
.
Syms
.
Lookup
(
".debug_ranges"
,
0
)
if
sym
.
Sect
!=
nil
{
putelfsectionsym
(
sym
,
sym
.
Sect
.
Elfsect
.
shnum
)
...
...
src/cmd/link/internal/ld/elf.go
View file @
385cd668
...
...
@@ -1808,7 +1808,7 @@ func elfrelocsect(ctxt *Link, sect *Section, syms []*Symbol) {
continue
}
if
r
.
Xsym
==
nil
{
Errorf
(
sym
,
"missing xsym in relocation
"
)
Errorf
(
sym
,
"missing xsym in relocation
%#v %#v"
,
r
.
Sym
.
Name
,
sym
)
continue
}
if
r
.
Xsym
.
ElfsymForReloc
()
==
0
{
...
...
@@ -2596,12 +2596,9 @@ elfobj:
elfshreloc
(
sect
)
}
for
_
,
s
:=
range
dwarfp
{
if
len
(
s
.
R
)
>
0
||
s
.
Type
==
SDWARFINFO
{
if
len
(
s
.
R
)
>
0
||
s
.
Type
==
SDWARFINFO
||
s
.
Type
==
SDWARFLOC
{
elfshreloc
(
s
.
Sect
)
}
if
s
.
Type
==
SDWARFINFO
{
break
}
}
// add a .note.GNU-stack section to mark the stack as non-executable
sh
:=
elfshname
(
".note.GNU-stack"
)
...
...
src/cmd/link/internal/ld/symkind.go
View file @
385cd668
...
...
@@ -105,6 +105,7 @@ const (
SDWARFSECT
SDWARFINFO
SDWARFRANGE
SDWARFLOC
SSUB
=
SymKind
(
1
<<
8
)
SMASK
=
SymKind
(
SSUB
-
1
)
SHIDDEN
=
SymKind
(
1
<<
9
)
...
...
@@ -124,6 +125,7 @@ var abiSymKindToSymKind = [...]SymKind{
STLSBSS
,
SDWARFINFO
,
SDWARFRANGE
,
SDWARFLOC
,
}
// readOnly are the symbol kinds that form read-only sections. In some
...
...
src/cmd/link/internal/ld/symkind_string.go
View file @
385cd668
...
...
@@ -4,9 +4,9 @@ package ld
import
"fmt"
const
_SymKind_name
=
"SxxxSTEXTSELFRXSECTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSMACHOPLTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASBSSSNOPTRBSSSTLSBSSSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILESFILEPATHSCONSTSDYNIMPORTSHOSTOBJSDWARFSECTSDWARFINFOSDWARFRANGE"
const
_SymKind_name
=
"SxxxSTEXTSELFRXSECTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSMACHOPLTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASBSSSNOPTRBSSSTLSBSSSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILESFILEPATHSCONSTSDYNIMPORTSHOSTOBJSDWARFSECTSDWARFINFOSDWARFRANGE
SDWARFLOC
"
var
_SymKind_index
=
[
...
]
uint16
{
0
,
4
,
9
,
19
,
24
,
31
,
40
,
47
,
54
,
61
,
69
,
79
,
88
,
98
,
110
,
124
,
136
,
148
,
160
,
173
,
182
,
191
,
198
,
206
,
214
,
220
,
229
,
237
,
244
,
254
,
262
,
267
,
271
,
280
,
287
,
292
,
304
,
316
,
333
,
350
,
355
,
364
,
370
,
380
,
388
,
398
,
408
,
419
}
var
_SymKind_index
=
[
...
]
uint16
{
0
,
4
,
9
,
19
,
24
,
31
,
40
,
47
,
54
,
61
,
69
,
79
,
88
,
98
,
110
,
124
,
136
,
148
,
160
,
173
,
182
,
191
,
198
,
206
,
214
,
220
,
229
,
237
,
244
,
254
,
262
,
267
,
271
,
280
,
287
,
292
,
304
,
316
,
333
,
350
,
355
,
364
,
370
,
380
,
388
,
398
,
408
,
419
,
428
}
func
(
i
SymKind
)
String
()
string
{
if
i
<
0
||
i
>=
SymKind
(
len
(
_SymKind_index
)
-
1
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment