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