github.com/Rookout/GoSDK@v0.1.48/pkg/services/assembler/internal/obj/plist.go (about)

     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.assembler file.
     4  
     5  package obj
     6  
     7  import (
     8  	"github.com/Rookout/GoSDK/pkg/services/assembler/internal/objabi"
     9  	"github.com/Rookout/GoSDK/pkg/services/assembler/internal/src"
    10  	"fmt"
    11  	"github.com/Rookout/GoSDK/pkg/services/assembler/internal/abi"
    12  	"strings"
    13  )
    14  
    15  type Plist struct {
    16  	Firstpc *Prog
    17  	Curfn   interface{} 
    18  }
    19  
    20  
    21  
    22  type ProgAlloc func() *Prog
    23  
    24  func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc, myimportpath string) {
    25  	
    26  	var curtext *LSym
    27  	var etext *Prog
    28  	var text []*LSym
    29  
    30  	var plink *Prog
    31  	for p := plist.Firstpc; p != nil; p = plink {
    32  		if ctxt.Debugasm > 0 && ctxt.Debugvlog {
    33  			fmt.Printf("obj: %v\n", p)
    34  		}
    35  		plink = p.Link
    36  		p.Link = nil
    37  
    38  		switch p.As {
    39  		case AEND:
    40  			continue
    41  
    42  		case ATEXT:
    43  			s := p.From.Sym
    44  			if s == nil {
    45  				
    46  				curtext = nil
    47  				continue
    48  			}
    49  			text = append(text, s)
    50  			etext = p
    51  			curtext = s
    52  			continue
    53  
    54  		case AFUNCDATA:
    55  			
    56  			if curtext == nil { 
    57  				continue
    58  			}
    59  			switch p.To.Sym.Name {
    60  			case "go_args_stackmap":
    61  				if p.From.Type != TYPE_CONST || p.From.Offset != abi.FUNCDATA_ArgsPointerMaps {
    62  					ctxt.Diag("%s: FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps", p.Pos)
    63  				}
    64  				p.To.Sym = ctxt.LookupDerived(curtext, curtext.Name+".args_stackmap")
    65  			case "no_pointers_stackmap":
    66  				if p.From.Type != TYPE_CONST || p.From.Offset != abi.FUNCDATA_LocalsPointerMaps {
    67  					ctxt.Diag("%s: FUNCDATA use of no_pointers_stackmap(SB) without FUNCDATA_LocalsPointerMaps", p.Pos)
    68  				}
    69  				
    70  				
    71  				
    72  				
    73  				
    74  				b := make([]byte, 8)
    75  				ctxt.Arch.ByteOrder.PutUint32(b, 2)
    76  				s := ctxt.GCLocalsSym(b)
    77  				if !s.OnList() {
    78  					ctxt.Globl(s, int64(len(s.P)), int(RODATA|DUPOK))
    79  				}
    80  				p.To.Sym = s
    81  			}
    82  
    83  		}
    84  
    85  		if curtext == nil {
    86  			etext = nil
    87  			continue
    88  		}
    89  		etext.Link = p
    90  		etext = p
    91  	}
    92  
    93  	if newprog == nil {
    94  		newprog = ctxt.NewProg
    95  	}
    96  
    97  	
    98  	if ctxt.IsAsm {
    99  		for _, s := range text {
   100  			if !strings.HasPrefix(s.Name, "\"\".") {
   101  				continue
   102  			}
   103  			
   104  			
   105  			
   106  			
   107  			if s.ABI() != ABI0 {
   108  				continue
   109  			}
   110  			foundArgMap, foundArgInfo := false, false
   111  			for p := s.Func().Text; p != nil; p = p.Link {
   112  				if p.As == AFUNCDATA && p.From.Type == TYPE_CONST {
   113  					if p.From.Offset == abi.FUNCDATA_ArgsPointerMaps {
   114  						foundArgMap = true
   115  					}
   116  					if p.From.Offset == abi.FUNCDATA_ArgInfo {
   117  						foundArgInfo = true
   118  					}
   119  					if foundArgMap && foundArgInfo {
   120  						break
   121  					}
   122  				}
   123  			}
   124  			if !foundArgMap {
   125  				p := Appendp(s.Func().Text, newprog)
   126  				p.As = AFUNCDATA
   127  				p.From.Type = TYPE_CONST
   128  				p.From.Offset = abi.FUNCDATA_ArgsPointerMaps
   129  				p.To.Type = TYPE_MEM
   130  				p.To.Name = NAME_EXTERN
   131  				p.To.Sym = ctxt.LookupDerived(s, s.Name+".args_stackmap")
   132  			}
   133  			if !foundArgInfo {
   134  				p := Appendp(s.Func().Text, newprog)
   135  				p.As = AFUNCDATA
   136  				p.From.Type = TYPE_CONST
   137  				p.From.Offset = abi.FUNCDATA_ArgInfo
   138  				p.To.Type = TYPE_MEM
   139  				p.To.Name = NAME_EXTERN
   140  				p.To.Sym = ctxt.LookupDerived(s, fmt.Sprintf("%s.arginfo%d", s.Name, s.ABI()))
   141  			}
   142  		}
   143  	}
   144  
   145  	
   146  	for _, s := range text {
   147  		mkfwd(s)
   148  		if ctxt.Arch.ErrorCheck != nil {
   149  			ctxt.Arch.ErrorCheck(ctxt, s)
   150  		}
   151  		linkpatch(ctxt, s, newprog)
   152  		ctxt.Arch.Preprocess(ctxt, s, newprog)
   153  		ctxt.Arch.Assemble(ctxt, s, newprog)
   154  		if ctxt.Errors > 0 {
   155  			continue
   156  		}
   157  		linkpcln(ctxt, s)
   158  		if myimportpath != "" {
   159  			ctxt.populateDWARF(plist.Curfn, s, myimportpath)
   160  		}
   161  		if ctxt.Headtype == objabi.Hwindows && ctxt.Arch.SEH != nil {
   162  			s.Func().sehUnwindInfoSym = ctxt.Arch.SEH(ctxt, s)
   163  		}
   164  	}
   165  }
   166  
   167  func (ctxt *Link) InitTextSym(s *LSym, flag int, start src.XPos) {
   168  	if s == nil {
   169  		
   170  		return
   171  	}
   172  	if s.Func() != nil {
   173  		ctxt.Diag("%s: symbol %s redeclared\n\t%s: other declaration of symbol %s", ctxt.PosTable.Pos(start), s.Name, ctxt.PosTable.Pos(s.Func().Text.Pos), s.Name)
   174  		return
   175  	}
   176  	s.NewFuncInfo()
   177  	if s.OnList() {
   178  		ctxt.Diag("%s: symbol %s redeclared", ctxt.PosTable.Pos(start), s.Name)
   179  		return
   180  	}
   181  
   182  	
   183  	
   184  	
   185  	_, startLine := ctxt.getFileSymbolAndLine(start)
   186  
   187  	
   188  	name := strings.Replace(s.Name, "\"\"", ctxt.Pkgpath, -1)
   189  	s.Func().FuncID = objabi.GetFuncID(name, flag&WRAPPER != 0 || flag&ABIWRAPPER != 0)
   190  	s.Func().FuncFlag = ctxt.toFuncFlag(flag)
   191  	s.Func().StartLine = startLine
   192  	s.Set(AttrOnList, true)
   193  	s.Set(AttrDuplicateOK, flag&DUPOK != 0)
   194  	s.Set(AttrNoSplit, flag&NOSPLIT != 0)
   195  	s.Set(AttrReflectMethod, flag&REFLECTMETHOD != 0)
   196  	s.Set(AttrWrapper, flag&WRAPPER != 0)
   197  	s.Set(AttrABIWrapper, flag&ABIWRAPPER != 0)
   198  	s.Set(AttrNeedCtxt, flag&NEEDCTXT != 0)
   199  	s.Set(AttrNoFrame, flag&NOFRAME != 0)
   200  	s.Set(AttrPkgInit, flag&PKGINIT != 0)
   201  	s.Type = objabi.STEXT
   202  	ctxt.Text = append(ctxt.Text, s)
   203  
   204  	
   205  	ctxt.dwarfSym(s)
   206  }
   207  
   208  func (ctxt *Link) toFuncFlag(flag int) abi.FuncFlag {
   209  	var out abi.FuncFlag
   210  	if flag&TOPFRAME != 0 {
   211  		out |= abi.FuncFlagTopFrame
   212  	}
   213  	if ctxt.IsAsm {
   214  		out |= abi.FuncFlagAsm
   215  	}
   216  	return out
   217  }
   218  
   219  func (ctxt *Link) Globl(s *LSym, size int64, flag int) {
   220  	ctxt.GloblPos(s, size, flag, src.NoXPos)
   221  }
   222  func (ctxt *Link) GloblPos(s *LSym, size int64, flag int, pos src.XPos) {
   223  	if s.OnList() {
   224  		
   225  		ctxt.Diag("%s: symbol %s redeclared", ctxt.PosTable.Pos(pos), s.Name)
   226  	}
   227  	s.Set(AttrOnList, true)
   228  	ctxt.Data = append(ctxt.Data, s)
   229  	s.Size = size
   230  	if s.Type == 0 {
   231  		s.Type = objabi.SBSS
   232  	}
   233  	if flag&DUPOK != 0 {
   234  		s.Set(AttrDuplicateOK, true)
   235  	}
   236  	if flag&RODATA != 0 {
   237  		s.Type = objabi.SRODATA
   238  	} else if flag&NOPTR != 0 {
   239  		if s.Type == objabi.SDATA {
   240  			s.Type = objabi.SNOPTRDATA
   241  		} else {
   242  			s.Type = objabi.SNOPTRBSS
   243  		}
   244  	} else if flag&TLSBSS != 0 {
   245  		s.Type = objabi.STLSBSS
   246  	}
   247  }
   248  
   249  
   250  
   251  
   252  func (ctxt *Link) EmitEntryLiveness(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
   253  	pcdata := ctxt.EmitEntryStackMap(s, p, newprog)
   254  	pcdata = ctxt.EmitEntryUnsafePoint(s, pcdata, newprog)
   255  	return pcdata
   256  }
   257  
   258  
   259  func (ctxt *Link) EmitEntryStackMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
   260  	pcdata := Appendp(p, newprog)
   261  	pcdata.Pos = s.Func().Text.Pos
   262  	pcdata.As = APCDATA
   263  	pcdata.From.Type = TYPE_CONST
   264  	pcdata.From.Offset = abi.PCDATA_StackMapIndex
   265  	pcdata.To.Type = TYPE_CONST
   266  	pcdata.To.Offset = -1 
   267  
   268  	return pcdata
   269  }
   270  
   271  
   272  func (ctxt *Link) EmitEntryUnsafePoint(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
   273  	pcdata := Appendp(p, newprog)
   274  	pcdata.Pos = s.Func().Text.Pos
   275  	pcdata.As = APCDATA
   276  	pcdata.From.Type = TYPE_CONST
   277  	pcdata.From.Offset = abi.PCDATA_UnsafePoint
   278  	pcdata.To.Type = TYPE_CONST
   279  	pcdata.To.Offset = -1
   280  
   281  	return pcdata
   282  }
   283  
   284  
   285  
   286  
   287  
   288  func (ctxt *Link) StartUnsafePoint(p *Prog, newprog ProgAlloc) *Prog {
   289  	pcdata := Appendp(p, newprog)
   290  	pcdata.As = APCDATA
   291  	pcdata.From.Type = TYPE_CONST
   292  	pcdata.From.Offset = abi.PCDATA_UnsafePoint
   293  	pcdata.To.Type = TYPE_CONST
   294  	pcdata.To.Offset = abi.UnsafePointUnsafe
   295  
   296  	return pcdata
   297  }
   298  
   299  
   300  
   301  
   302  
   303  func (ctxt *Link) EndUnsafePoint(p *Prog, newprog ProgAlloc, oldval int64) *Prog {
   304  	pcdata := Appendp(p, newprog)
   305  	pcdata.As = APCDATA
   306  	pcdata.From.Type = TYPE_CONST
   307  	pcdata.From.Offset = abi.PCDATA_UnsafePoint
   308  	pcdata.To.Type = TYPE_CONST
   309  	pcdata.To.Offset = oldval
   310  
   311  	return pcdata
   312  }
   313  
   314  
   315  
   316  
   317  
   318  
   319  
   320  
   321  
   322  
   323  
   324  func MarkUnsafePoints(ctxt *Link, p0 *Prog, newprog ProgAlloc, isUnsafePoint, isRestartable func(*Prog) bool) {
   325  	if isRestartable == nil {
   326  		
   327  		isRestartable = func(*Prog) bool { return false }
   328  	}
   329  	prev := p0
   330  	prevPcdata := int64(-1) 
   331  	prevRestart := int64(0)
   332  	for p := prev.Link; p != nil; p, prev = p.Link, p {
   333  		if p.As == APCDATA && p.From.Offset == abi.PCDATA_UnsafePoint {
   334  			prevPcdata = p.To.Offset
   335  			continue
   336  		}
   337  		if prevPcdata == abi.UnsafePointUnsafe {
   338  			continue 
   339  		}
   340  		if isUnsafePoint(p) {
   341  			q := ctxt.StartUnsafePoint(prev, newprog)
   342  			q.Pc = p.Pc
   343  			q.Link = p
   344  			
   345  			for p.Link != nil && isUnsafePoint(p.Link) {
   346  				p = p.Link
   347  			}
   348  			if p.Link == nil {
   349  				break 
   350  			}
   351  			p = ctxt.EndUnsafePoint(p, newprog, prevPcdata)
   352  			p.Pc = p.Link.Pc
   353  			continue
   354  		}
   355  		if isRestartable(p) {
   356  			val := int64(abi.UnsafePointRestart1)
   357  			if val == prevRestart {
   358  				val = abi.UnsafePointRestart2
   359  			}
   360  			prevRestart = val
   361  			q := Appendp(prev, newprog)
   362  			q.As = APCDATA
   363  			q.From.Type = TYPE_CONST
   364  			q.From.Offset = abi.PCDATA_UnsafePoint
   365  			q.To.Type = TYPE_CONST
   366  			q.To.Offset = val
   367  			q.Pc = p.Pc
   368  			q.Link = p
   369  
   370  			if p.Link == nil {
   371  				break 
   372  			}
   373  			if isRestartable(p.Link) {
   374  				
   375  				
   376  				continue
   377  			}
   378  			p = Appendp(p, newprog)
   379  			p.As = APCDATA
   380  			p.From.Type = TYPE_CONST
   381  			p.From.Offset = abi.PCDATA_UnsafePoint
   382  			p.To.Type = TYPE_CONST
   383  			p.To.Offset = prevPcdata
   384  			p.Pc = p.Link.Pc
   385  		}
   386  	}
   387  }