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
|
|
|
|
|
|
2016-03-10 18:23:03 -08:00
|
|
|
// unsafenmagic rewrites calls to package unsafe's functions into constants.
|
2015-02-13 14:40:36 -05:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2016-03-08 15:10:26 -08:00
|
|
|
if args.Len() == 0 {
|
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
|
|
|
}
|
|
|
|
|
|
2016-03-08 15:10:26 -08:00
|
|
|
r := args.First()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-03-02 12:35:15 -05:00
|
|
|
var v int64
|
2016-03-10 18:23:03 -08:00
|
|
|
switch s.Name {
|
|
|
|
|
case "Alignof", "Sizeof":
|
2015-02-13 14:40:36 -05:00
|
|
|
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)
|
2016-03-10 18:23:03 -08:00
|
|
|
if s.Name == "Alignof" {
|
|
|
|
|
v = int64(tr.Align)
|
|
|
|
|
} else {
|
|
|
|
|
v = tr.Width
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-03-10 18:23:03 -08:00
|
|
|
case "Offsetof":
|
2015-02-13 14:40:36 -05:00
|
|
|
// 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
|
2016-03-10 18:23:03 -08:00
|
|
|
|
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
|
|
|
goto ret
|
|
|
|
|
default:
|
|
|
|
|
goto bad
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-10 18:23:03 -08:00
|
|
|
// Sum offsets for dots until we reach base.
|
|
|
|
|
for r1 := r; r1 != base; r1 = r1.Left {
|
2015-02-13 14:40:36 -05:00
|
|
|
switch r1.Op {
|
2016-03-10 18:23:03 -08:00
|
|
|
case ODOTPTR:
|
|
|
|
|
// For Offsetof(s.f), s may itself be a pointer,
|
|
|
|
|
// but accessing f must not otherwise involve
|
|
|
|
|
// indirection via embedded pointer types.
|
|
|
|
|
if r1.Left != base {
|
|
|
|
|
Yyerror("invalid expression %v: selector implies indirection of embedded %v", nn, r1.Left)
|
|
|
|
|
goto ret
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
2015-02-13 14:40:36 -05:00
|
|
|
case ODOT:
|
|
|
|
|
v += r1.Xoffset
|
|
|
|
|
default:
|
|
|
|
|
Dump("unsafenmagic", r)
|
2016-03-15 13:06:58 -07:00
|
|
|
Fatalf("impossible %v node after dot insertion", Oconv(r1.Op, FmtSharp))
|
2015-02-13 14:40:36 -05:00
|
|
|
goto bad
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-10 18:23:03 -08:00
|
|
|
default:
|
|
|
|
|
return nil
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-10 18:23:03 -08:00
|
|
|
if args.Len() > 1 {
|
|
|
|
|
Yyerror("extra arguments for %v", s)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-03-10 18:23:03 -08:00
|
|
|
goto ret
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
bad:
|
2015-04-17 12:03:22 -04:00
|
|
|
Yyerror("invalid expression %v", nn)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
ret:
|
2016-03-10 18:23:03 -08:00
|
|
|
// any side effects disappear; ignore init
|
2015-02-23 16:07:24 -05:00
|
|
|
var val Val
|
2015-05-14 17:57:42 -07:00
|
|
|
val.U = new(Mpint)
|
|
|
|
|
Mpmovecfix(val.U.(*Mpint), 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
|
2015-05-27 00:47:05 -04:00
|
|
|
n.SetVal(val)
|
2015-02-13 14:40:36 -05:00
|
|
|
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
|
|
|
}
|