github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/cmd/link/dead.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Removal of dead code and data. 6 7 package main 8 9 import "debug/goobj" 10 11 // dead removes unreachable code and data from the program. 12 // It is basically a mark-sweep garbage collection: traverse all the 13 // symbols reachable from the entry (startSymID) and then delete 14 // the rest. 15 func (p *Prog) dead() { 16 p.Dead = make(map[goobj.SymID]bool) 17 reachable := make(map[goobj.SymID]bool) 18 p.walkDead(p.startSym, reachable) 19 20 for sym := range p.Syms { 21 if !reachable[sym] { 22 delete(p.Syms, sym) 23 p.Dead[sym] = true 24 } 25 } 26 27 for sym := range p.Missing { 28 if !reachable[sym] { 29 delete(p.Missing, sym) 30 p.Dead[sym] = true 31 } 32 } 33 34 p.SymOrder = removeDead(p.SymOrder, reachable) 35 36 for _, pkg := range p.Packages { 37 pkg.Syms = removeDead(pkg.Syms, reachable) 38 } 39 } 40 41 // walkDead traverses the symbols reachable from sym, adding them to reachable. 42 // The caller has verified that reachable[sym] = false. 43 func (p *Prog) walkDead(sym goobj.SymID, reachable map[goobj.SymID]bool) { 44 reachable[sym] = true 45 s := p.Syms[sym] 46 if s == nil { 47 return 48 } 49 for i := range s.Reloc { 50 r := &s.Reloc[i] 51 if !reachable[r.Sym] { 52 p.walkDead(r.Sym, reachable) 53 } 54 } 55 if s.Func != nil { 56 for _, fdata := range s.Func.FuncData { 57 if fdata.Sym.Name != "" && !reachable[fdata.Sym] { 58 p.walkDead(fdata.Sym, reachable) 59 } 60 } 61 } 62 } 63 64 // removeDead removes unreachable (dead) symbols from syms, 65 // returning a shortened slice using the same underlying array. 66 func removeDead(syms []*Sym, reachable map[goobj.SymID]bool) []*Sym { 67 keep := syms[:0] 68 for _, sym := range syms { 69 if reachable[sym.SymID] { 70 keep = append(keep, sym) 71 } 72 } 73 return keep 74 }