...

Source file src/cmd/internal/obj/plist.go

     1	// Copyright 2013 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	package obj
     6	
     7	import (
     8		"cmd/internal/objabi"
     9		"fmt"
    10		"strings"
    11	)
    12	
    13	type Plist struct {
    14		Firstpc *Prog
    15		Curfn   interface{} // holds a *gc.Node, if non-nil
    16	}
    17	
    18	// ProgAlloc is a function that allocates Progs.
    19	// It is used to provide access to cached/bulk-allocated Progs to the assemblers.
    20	type ProgAlloc func() *Prog
    21	
    22	func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc, myimportpath string) {
    23		// Build list of symbols, and assign instructions to lists.
    24		var curtext *LSym
    25		var etext *Prog
    26		var text []*LSym
    27	
    28		var plink *Prog
    29		for p := plist.Firstpc; p != nil; p = plink {
    30			if ctxt.Debugasm > 0 && ctxt.Debugvlog {
    31				fmt.Printf("obj: %v\n", p)
    32			}
    33			plink = p.Link
    34			p.Link = nil
    35	
    36			switch p.As {
    37			case AEND:
    38				continue
    39	
    40			case ATEXT:
    41				s := p.From.Sym
    42				if s == nil {
    43					// func _() { }
    44					curtext = nil
    45					continue
    46				}
    47				text = append(text, s)
    48				etext = p
    49				curtext = s
    50				continue
    51	
    52			case AFUNCDATA:
    53				// Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information.
    54				if curtext == nil { // func _() {}
    55					continue
    56				}
    57				if p.To.Sym.Name == "go_args_stackmap" {
    58					if p.From.Type != TYPE_CONST || p.From.Offset != objabi.FUNCDATA_ArgsPointerMaps {
    59						ctxt.Diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps")
    60					}
    61					p.To.Sym = ctxt.LookupDerived(curtext, curtext.Name+".args_stackmap")
    62				}
    63	
    64			}
    65	
    66			if curtext == nil {
    67				etext = nil
    68				continue
    69			}
    70			etext.Link = p
    71			etext = p
    72		}
    73	
    74		if newprog == nil {
    75			newprog = ctxt.NewProg
    76		}
    77	
    78		// Add reference to Go arguments for C or assembly functions without them.
    79		for _, s := range text {
    80			if !strings.HasPrefix(s.Name, "\"\".") {
    81				continue
    82			}
    83			found := false
    84			for p := s.Func.Text; p != nil; p = p.Link {
    85				if p.As == AFUNCDATA && p.From.Type == TYPE_CONST && p.From.Offset == objabi.FUNCDATA_ArgsPointerMaps {
    86					found = true
    87					break
    88				}
    89			}
    90	
    91			if !found {
    92				p := Appendp(s.Func.Text, newprog)
    93				p.As = AFUNCDATA
    94				p.From.Type = TYPE_CONST
    95				p.From.Offset = objabi.FUNCDATA_ArgsPointerMaps
    96				p.To.Type = TYPE_MEM
    97				p.To.Name = NAME_EXTERN
    98				p.To.Sym = ctxt.LookupDerived(s, s.Name+".args_stackmap")
    99			}
   100		}
   101	
   102		// Turn functions into machine code images.
   103		for _, s := range text {
   104			mkfwd(s)
   105			linkpatch(ctxt, s, newprog)
   106			ctxt.Arch.Preprocess(ctxt, s, newprog)
   107			ctxt.Arch.Assemble(ctxt, s, newprog)
   108			if ctxt.Errors > 0 {
   109				continue
   110			}
   111			linkpcln(ctxt, s)
   112			ctxt.populateDWARF(plist.Curfn, s, myimportpath)
   113		}
   114	}
   115	
   116	func (ctxt *Link) InitTextSym(s *LSym, flag int) {
   117		if s == nil {
   118			// func _() { }
   119			return
   120		}
   121		if s.Func != nil {
   122			ctxt.Diag("InitTextSym double init for %s", s.Name)
   123		}
   124		s.Func = new(FuncInfo)
   125		if s.OnList() {
   126			ctxt.Diag("symbol %s listed multiple times", s.Name)
   127		}
   128		s.Set(AttrOnList, true)
   129		s.Set(AttrDuplicateOK, flag&DUPOK != 0)
   130		s.Set(AttrNoSplit, flag&NOSPLIT != 0)
   131		s.Set(AttrReflectMethod, flag&REFLECTMETHOD != 0)
   132		s.Set(AttrWrapper, flag&WRAPPER != 0)
   133		s.Set(AttrNeedCtxt, flag&NEEDCTXT != 0)
   134		s.Set(AttrNoFrame, flag&NOFRAME != 0)
   135		s.Set(AttrTopFrame, flag&TOPFRAME != 0)
   136		s.Type = objabi.STEXT
   137		ctxt.Text = append(ctxt.Text, s)
   138	
   139		// Set up DWARF entries for s.
   140		info, loc, ranges, _, isstmt := ctxt.dwarfSym(s)
   141		info.Type = objabi.SDWARFINFO
   142		info.Set(AttrDuplicateOK, s.DuplicateOK())
   143		if loc != nil {
   144			loc.Type = objabi.SDWARFLOC
   145			loc.Set(AttrDuplicateOK, s.DuplicateOK())
   146			ctxt.Data = append(ctxt.Data, loc)
   147		}
   148		ranges.Type = objabi.SDWARFRANGE
   149		ranges.Set(AttrDuplicateOK, s.DuplicateOK())
   150		ctxt.Data = append(ctxt.Data, info, ranges)
   151		isstmt.Type = objabi.SDWARFMISC
   152		isstmt.Set(AttrDuplicateOK, s.DuplicateOK())
   153		ctxt.Data = append(ctxt.Data, isstmt)
   154	}
   155	
   156	func (ctxt *Link) Globl(s *LSym, size int64, flag int) {
   157		if s.SeenGlobl() {
   158			fmt.Printf("duplicate %v\n", s)
   159		}
   160		s.Set(AttrSeenGlobl, true)
   161		if s.OnList() {
   162			ctxt.Diag("symbol %s listed multiple times", s.Name)
   163		}
   164		s.Set(AttrOnList, true)
   165		ctxt.Data = append(ctxt.Data, s)
   166		s.Size = size
   167		if s.Type == 0 {
   168			s.Type = objabi.SBSS
   169		}
   170		if flag&DUPOK != 0 {
   171			s.Set(AttrDuplicateOK, true)
   172		}
   173		if flag&RODATA != 0 {
   174			s.Type = objabi.SRODATA
   175		} else if flag&NOPTR != 0 {
   176			if s.Type == objabi.SDATA {
   177				s.Type = objabi.SNOPTRDATA
   178			} else {
   179				s.Type = objabi.SNOPTRBSS
   180			}
   181		} else if flag&TLSBSS != 0 {
   182			s.Type = objabi.STLSBSS
   183		}
   184	}
   185	
   186	// EmitEntryLiveness generates PCDATA Progs after p to switch to the
   187	// liveness map active at the entry of function s. It returns the last
   188	// Prog generated.
   189	func (ctxt *Link) EmitEntryLiveness(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
   190		pcdata := Appendp(p, newprog)
   191		pcdata.Pos = s.Func.Text.Pos
   192		pcdata.As = APCDATA
   193		pcdata.From.Type = TYPE_CONST
   194		pcdata.From.Offset = objabi.PCDATA_StackMapIndex
   195		pcdata.To.Type = TYPE_CONST
   196		pcdata.To.Offset = -1 // pcdata starts at -1 at function entry
   197	
   198		// Same, with register map.
   199		pcdata = Appendp(pcdata, newprog)
   200		pcdata.Pos = s.Func.Text.Pos
   201		pcdata.As = APCDATA
   202		pcdata.From.Type = TYPE_CONST
   203		pcdata.From.Offset = objabi.PCDATA_RegMapIndex
   204		pcdata.To.Type = TYPE_CONST
   205		pcdata.To.Offset = -1
   206	
   207		return pcdata
   208	}
   209	

View as plain text