github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/unsafe.go (about)

     1  // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/gc/unsafe.go
     2  
     3  // Copyright 2009 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  package gc
     8  
     9  import "rsc.io/tmp/bootstrap/internal/obj"
    10  
    11  /*
    12   * look for
    13   *	unsafe.Sizeof
    14   *	unsafe.Offsetof
    15   *	unsafe.Alignof
    16   * rewrite with a constant
    17   */
    18  func unsafenmagic(nn *Node) *Node {
    19  	fn := nn.Left
    20  	args := nn.List
    21  
    22  	if safemode != 0 || fn == nil || fn.Op != ONAME {
    23  		return nil
    24  	}
    25  	s := fn.Sym
    26  	if s == nil {
    27  		return nil
    28  	}
    29  	if s.Pkg != unsafepkg {
    30  		return nil
    31  	}
    32  
    33  	if args == nil {
    34  		Yyerror("missing argument for %v", s)
    35  		return nil
    36  	}
    37  
    38  	r := args.N
    39  
    40  	var v int64
    41  	if s.Name == "Sizeof" {
    42  		typecheck(&r, Erv)
    43  		defaultlit(&r, nil)
    44  		tr := r.Type
    45  		if tr == nil {
    46  			goto bad
    47  		}
    48  		dowidth(tr)
    49  		v = tr.Width
    50  		goto yes
    51  	}
    52  
    53  	if s.Name == "Offsetof" {
    54  		// must be a selector.
    55  		if r.Op != OXDOT {
    56  			goto bad
    57  		}
    58  
    59  		// Remember base of selector to find it back after dot insertion.
    60  		// Since r->left may be mutated by typechecking, check it explicitly
    61  		// first to track it correctly.
    62  		typecheck(&r.Left, Erv)
    63  
    64  		base := r.Left
    65  		typecheck(&r, Erv)
    66  		switch r.Op {
    67  		case ODOT, ODOTPTR:
    68  			break
    69  
    70  		case OCALLPART:
    71  			Yyerror("invalid expression %v: argument is a method value", nn)
    72  			v = 0
    73  			goto ret
    74  
    75  		default:
    76  			goto bad
    77  		}
    78  
    79  		v = 0
    80  
    81  		// add offsets for inserted dots.
    82  		var r1 *Node
    83  		for r1 = r; r1.Left != base; r1 = r1.Left {
    84  			switch r1.Op {
    85  			case ODOT:
    86  				v += r1.Xoffset
    87  
    88  			case ODOTPTR:
    89  				Yyerror("invalid expression %v: selector implies indirection of embedded %v", nn, r1.Left)
    90  				goto ret
    91  
    92  			default:
    93  				Dump("unsafenmagic", r)
    94  				Fatal("impossible %v node after dot insertion", Oconv(int(r1.Op), obj.FmtSharp))
    95  				goto bad
    96  			}
    97  		}
    98  
    99  		v += r1.Xoffset
   100  		goto yes
   101  	}
   102  
   103  	if s.Name == "Alignof" {
   104  		typecheck(&r, Erv)
   105  		defaultlit(&r, nil)
   106  		tr := r.Type
   107  		if tr == nil {
   108  			goto bad
   109  		}
   110  
   111  		// make struct { byte; T; }
   112  		t := typ(TSTRUCT)
   113  
   114  		t.Type = typ(TFIELD)
   115  		t.Type.Type = Types[TUINT8]
   116  		t.Type.Down = typ(TFIELD)
   117  		t.Type.Down.Type = tr
   118  
   119  		// compute struct widths
   120  		dowidth(t)
   121  
   122  		// the offset of T is its required alignment
   123  		v = t.Type.Down.Width
   124  
   125  		goto yes
   126  	}
   127  
   128  	return nil
   129  
   130  bad:
   131  	Yyerror("invalid expression %v", nn)
   132  	v = 0
   133  	goto ret
   134  
   135  yes:
   136  	if args.Next != nil {
   137  		Yyerror("extra arguments for %v", s)
   138  	}
   139  
   140  	// any side effects disappear; ignore init
   141  ret:
   142  	var val Val
   143  	val.Ctype = CTINT
   144  
   145  	val.U.Xval = new(Mpint)
   146  	Mpmovecfix(val.U.Xval, v)
   147  	n := Nod(OLITERAL, nil, nil)
   148  	n.Orig = nn
   149  	n.Val = val
   150  	n.Type = Types[TUINTPTR]
   151  	nn.Type = Types[TUINTPTR]
   152  	return n
   153  }
   154  
   155  func isunsafebuiltin(n *Node) bool {
   156  	if n == nil || n.Op != ONAME || n.Sym == nil || n.Sym.Pkg != unsafepkg {
   157  		return false
   158  	}
   159  	if n.Sym.Name == "Sizeof" {
   160  		return true
   161  	}
   162  	if n.Sym.Name == "Offsetof" {
   163  		return true
   164  	}
   165  	if n.Sym.Name == "Alignof" {
   166  		return true
   167  	}
   168  	return false
   169  }