github.com/peggyl/go@v0.0.0-20151008231540-ae315999c2d5/src/cmd/compile/internal/gc/unsafe.go (about)

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