github.com/4ad/go@v0.0.0-20161219182952-69a12818b605/src/cmd/internal/obj/sparc64/vn.go (about)

     1  // 	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     2  // 	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     3  // 	Portions Copyright © 1997-1999 Vita Nuova Limited
     4  // 	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     5  // 	Portions Copyright © 2004,2006 Bruce Ellis
     6  // 	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
     7  // 	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
     8  // 	Portions Copyright © 2009 The Go Authors.  All rights reserved.
     9  //
    10  // Permission is hereby granted, free of charge, to any person obtaining a copy
    11  // of this software and associated documentation files (the "Software"), to deal
    12  // in the Software without restriction, including without limitation the rights
    13  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    14  // copies of the Software, and to permit persons to whom the Software is
    15  // furnished to do so, subject to the following conditions:
    16  //
    17  // The above copyright notice and this permission notice shall be included in
    18  // all copies or substantial portions of the Software.
    19  //
    20  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    21  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    22  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    23  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    24  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    25  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    26  // THE SOFTWARE.
    27  
    28  // Unlike all existing ports (386, amd64, amd64p32, arm, arm64, ppc64,
    29  // ppc64le), the sparc64 back-end is truly new code, not derived from
    30  // Plan9/Inferno code from Vita Nuova. However, the sparc64 back-end
    31  // has to fit into the Inferno-derived middle-end (cmd/internal/obj),
    32  // and inherits certain idiosyncrasies. To deal with them, a small
    33  // amount of code is inherited from the arm64 port. To track copyrights,
    34  // that code is isolated in this file.
    35  //
    36  // Someday we'll refactor the middle-end, and this code will go away.
    37  
    38  package sparc64
    39  
    40  import (
    41  	"cmd/internal/obj"
    42  	"fmt"
    43  )
    44  
    45  func follow(ctxt *obj.Link, s *obj.LSym) {
    46  	ctxt.Cursym = s
    47  
    48  	firstp := ctxt.NewProg()
    49  	lastp := firstp
    50  	xfol(ctxt, s.Text, &lastp)
    51  	lastp.Link = nil
    52  	s.Text = firstp.Link
    53  }
    54  
    55  func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
    56  	var q *obj.Prog
    57  	var r *obj.Prog
    58  	var a obj.As
    59  	var i int
    60  
    61  loop:
    62  	if p == nil {
    63  		return
    64  	}
    65  	a = p.As
    66  	if a == obj.AJMP {
    67  		q = p.Pcond
    68  		if q != nil {
    69  			p.Mark |= FOLL
    70  			p = q
    71  			if !(p.Mark&FOLL != 0) {
    72  				goto loop
    73  			}
    74  		}
    75  	}
    76  
    77  	if p.Mark&FOLL != 0 {
    78  		i = 0
    79  		q = p
    80  		for ; i < 4; i, q = i+1, q.Link {
    81  			if q == *last || q == nil {
    82  				break
    83  			}
    84  			a = q.As
    85  			if a == obj.ANOP {
    86  				i--
    87  				continue
    88  			}
    89  
    90  			if a == obj.AJMP || a == obj.ARET || a == ARETRESTORE {
    91  				goto copy
    92  			}
    93  			if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
    94  				continue
    95  			}
    96  			if a != ABE && a != ABNE {
    97  				continue
    98  			}
    99  
   100  		copy:
   101  			for {
   102  				r = ctxt.NewProg()
   103  				*r = *p
   104  				if !(r.Mark&FOLL != 0) {
   105  					fmt.Printf("cant happen 1\n")
   106  				}
   107  				r.Mark |= FOLL
   108  				if p != q {
   109  					p = p.Link
   110  					(*last).Link = r
   111  					*last = r
   112  					continue
   113  				}
   114  
   115  				(*last).Link = r
   116  				*last = r
   117  				if a == obj.AJMP || a == obj.ARET || a == ARETRESTORE {
   118  					return
   119  				}
   120  				if a == ABNE {
   121  					r.As = ABE
   122  				} else {
   123  					r.As = ABNE
   124  				}
   125  				r.Pcond = p.Link
   126  				r.Link = p.Pcond
   127  				if !(r.Link.Mark&FOLL != 0) {
   128  					xfol(ctxt, r.Link, last)
   129  				}
   130  				if !(r.Pcond.Mark&FOLL != 0) {
   131  					fmt.Printf("cant happen 2\n")
   132  				}
   133  				return
   134  			}
   135  		}
   136  
   137  		a = obj.AJMP
   138  		q = ctxt.NewProg()
   139  		q.As = a
   140  		q.Lineno = p.Lineno
   141  		q.To.Type = obj.TYPE_BRANCH
   142  		q.To.Offset = p.Pc
   143  		q.Pcond = p
   144  		p = q
   145  	}
   146  
   147  	p.Mark |= FOLL
   148  	(*last).Link = p
   149  	*last = p
   150  	if a == obj.AJMP || a == obj.ARET || a == ARETRESTORE {
   151  		return
   152  	}
   153  	if p.Pcond != nil {
   154  		if a != ABL && p.Link != nil {
   155  			q = obj.Brchain(ctxt, p.Link)
   156  			if a != obj.ATEXT {
   157  				if q != nil && (q.Mark&FOLL != 0) {
   158  					p.As = relinv(a)
   159  					p.Link = p.Pcond
   160  					p.Pcond = q
   161  				}
   162  			}
   163  
   164  			xfol(ctxt, p.Link, last)
   165  			q = obj.Brchain(ctxt, p.Pcond)
   166  			if q == nil {
   167  				q = p.Pcond
   168  			}
   169  			if q.Mark&FOLL != 0 {
   170  				p.Pcond = q
   171  				return
   172  			}
   173  
   174  			p = q
   175  			goto loop
   176  		}
   177  	}
   178  
   179  	p = p.Link
   180  	goto loop
   181  
   182  }