2015-02-13 14:40:36 -05:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
package gc
|
|
|
|
|
|
|
|
|
|
import "cmd/internal/obj"
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* look for
|
|
|
|
|
* unsafe.Sizeof
|
|
|
|
|
* unsafe.Offsetof
|
|
|
|
|
* unsafe.Alignof
|
|
|
|
|
* rewrite with a constant
|
|
|
|
|
*/
|
|
|
|
|
func unsafenmagic(nn *Node) *Node {
|
2015-02-23 16:07:24 -05:00
|
|
|
fn := nn.Left
|
|
|
|
|
args := nn.List
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if safemode != 0 || fn == nil || fn.Op != ONAME {
|
2015-03-02 12:35:15 -05:00
|
|
|
return nil
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-02 12:35:15 -05:00
|
|
|
s := fn.Sym
|
2015-02-13 14:40:36 -05:00
|
|
|
if s == nil {
|
2015-03-02 12:35:15 -05:00
|
|
|
return nil
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if s.Pkg != unsafepkg {
|
2015-03-02 12:35:15 -05:00
|
|
|
return nil
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if args == nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("missing argument for %v", s)
|
2015-03-02 12:35:15 -05:00
|
|
|
return nil
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 12:35:15 -05:00
|
|
|
r := args.N
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-03-02 12:35:15 -05:00
|
|
|
var v int64
|
2015-02-13 14:40:36 -05:00
|
|
|
if s.Name == "Sizeof" {
|
|
|
|
|
typecheck(&r, Erv)
|
|
|
|
|
defaultlit(&r, nil)
|
2015-02-23 16:07:24 -05:00
|
|
|
tr := r.Type
|
2015-02-13 14:40:36 -05:00
|
|
|
if tr == nil {
|
|
|
|
|
goto bad
|
|
|
|
|
}
|
|
|
|
|
dowidth(tr)
|
|
|
|
|
v = tr.Width
|
|
|
|
|
goto yes
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if s.Name == "Offsetof" {
|
|
|
|
|
// must be a selector.
|
|
|
|
|
if r.Op != OXDOT {
|
|
|
|
|
goto bad
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remember base of selector to find it back after dot insertion.
|
|
|
|
|
// Since r->left may be mutated by typechecking, check it explicitly
|
|
|
|
|
// first to track it correctly.
|
|
|
|
|
typecheck(&r.Left, Erv)
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
base := r.Left
|
2015-02-13 14:40:36 -05:00
|
|
|
typecheck(&r, Erv)
|
|
|
|
|
switch r.Op {
|
2015-04-01 09:38:44 -07:00
|
|
|
case ODOT, ODOTPTR:
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
|
|
|
|
|
case OCALLPART:
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("invalid expression %v: argument is a method value", nn)
|
2015-02-13 14:40:36 -05:00
|
|
|
v = 0
|
|
|
|
|
goto ret
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
goto bad
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
v = 0
|
|
|
|
|
|
|
|
|
|
// add offsets for inserted dots.
|
2015-02-23 16:07:24 -05:00
|
|
|
var r1 *Node
|
2015-02-13 14:40:36 -05:00
|
|
|
for r1 = r; r1.Left != base; r1 = r1.Left {
|
|
|
|
|
switch r1.Op {
|
|
|
|
|
case ODOT:
|
|
|
|
|
v += r1.Xoffset
|
|
|
|
|
|
|
|
|
|
case ODOTPTR:
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("invalid expression %v: selector implies indirection of embedded %v", nn, r1.Left)
|
2015-02-13 14:40:36 -05:00
|
|
|
goto ret
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
Dump("unsafenmagic", r)
|
|
|
|
|
Fatal("impossible %v node after dot insertion", Oconv(int(r1.Op), obj.FmtSharp))
|
|
|
|
|
goto bad
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
v += r1.Xoffset
|
|
|
|
|
goto yes
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if s.Name == "Alignof" {
|
|
|
|
|
typecheck(&r, Erv)
|
|
|
|
|
defaultlit(&r, nil)
|
2015-02-23 16:07:24 -05:00
|
|
|
tr := r.Type
|
2015-02-13 14:40:36 -05:00
|
|
|
if tr == nil {
|
|
|
|
|
goto bad
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// make struct { byte; T; }
|
2015-02-23 16:07:24 -05:00
|
|
|
t := typ(TSTRUCT)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
t.Type = typ(TFIELD)
|
|
|
|
|
t.Type.Type = Types[TUINT8]
|
|
|
|
|
t.Type.Down = typ(TFIELD)
|
|
|
|
|
t.Type.Down.Type = tr
|
|
|
|
|
|
|
|
|
|
// compute struct widths
|
|
|
|
|
dowidth(t)
|
|
|
|
|
|
|
|
|
|
// the offset of T is its required alignment
|
|
|
|
|
v = t.Type.Down.Width
|
|
|
|
|
|
|
|
|
|
goto yes
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
|
|
bad:
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("invalid expression %v", nn)
|
2015-02-13 14:40:36 -05:00
|
|
|
v = 0
|
|
|
|
|
goto ret
|
|
|
|
|
|
|
|
|
|
yes:
|
|
|
|
|
if args.Next != nil {
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("extra arguments for %v", s)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// any side effects disappear; ignore init
|
|
|
|
|
ret:
|
2015-02-23 16:07:24 -05:00
|
|
|
var val Val
|
2015-02-13 14:40:36 -05:00
|
|
|
val.Ctype = CTINT
|
|
|
|
|
|
|
|
|
|
val.U.Xval = new(Mpint)
|
|
|
|
|
Mpmovecfix(val.U.Xval, v)
|
2015-02-23 16:07:24 -05:00
|
|
|
n := Nod(OLITERAL, nil, nil)
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Orig = nn
|
|
|
|
|
n.Val = val
|
|
|
|
|
n.Type = Types[TUINTPTR]
|
|
|
|
|
nn.Type = Types[TUINTPTR]
|
|
|
|
|
return n
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
func isunsafebuiltin(n *Node) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n == nil || n.Op != ONAME || n.Sym == nil || n.Sym.Pkg != unsafepkg {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if n.Sym.Name == "Sizeof" {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if n.Sym.Name == "Offsetof" {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if n.Sym.Name == "Alignof" {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|