go/src/cmd/compile/internal/gc/unsafe.go
Matthew Dempsky 980ab12ade cmd/compile/internal/gc: change flags to bool where possible
Some of the Debug[x] flags are actually boolean too, but not all, so
they need to be handled separately.

While here, change some obj.Flagstr and obj.Flagint64 calls to
directly use flag.StringVar and flag.Int64Var instead.

Change-Id: Iccedf6fed4328240ee2257f57fe6d66688f237c4
Reviewed-on: https://go-review.googlesource.com/22052
Reviewed-by: Michael Hudson-Doyle <michael.hudson@canonical.com>
2016-04-14 02:10:35 +00:00

129 lines
2.5 KiB
Go

// 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
// unsafenmagic rewrites calls to package unsafe's functions into constants.
func unsafenmagic(nn *Node) *Node {
fn := nn.Left
args := nn.List
if safemode || fn == nil || fn.Op != ONAME {
return nil
}
s := fn.Sym
if s == nil {
return nil
}
if s.Pkg != unsafepkg {
return nil
}
if args.Len() == 0 {
Yyerror("missing argument for %v", s)
return nil
}
r := args.First()
var v int64
switch s.Name {
case "Alignof", "Sizeof":
r = typecheck(r, Erv)
r = defaultlit(r, nil)
tr := r.Type
if tr == nil {
goto bad
}
dowidth(tr)
if s.Name == "Alignof" {
v = int64(tr.Align)
} else {
v = tr.Width
}
case "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.
r.Left = typecheck(r.Left, Erv)
base := r.Left
r = typecheck(r, Erv)
switch r.Op {
case ODOT, ODOTPTR:
break
case OCALLPART:
Yyerror("invalid expression %v: argument is a method value", nn)
goto ret
default:
goto bad
}
// Sum offsets for dots until we reach base.
for r1 := r; r1 != base; r1 = r1.Left {
switch r1.Op {
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
case ODOT:
v += r1.Xoffset
default:
Dump("unsafenmagic", r)
Fatalf("impossible %v node after dot insertion", Oconv(r1.Op, FmtSharp))
goto bad
}
}
default:
return nil
}
if args.Len() > 1 {
Yyerror("extra arguments for %v", s)
}
goto ret
bad:
Yyerror("invalid expression %v", nn)
ret:
// any side effects disappear; ignore init
var val Val
val.U = new(Mpint)
val.U.(*Mpint).SetInt64(v)
n := Nod(OLITERAL, nil, nil)
n.Orig = nn
n.SetVal(val)
n.Type = Types[TUINTPTR]
nn.Type = Types[TUINTPTR]
return n
}
func isunsafebuiltin(n *Node) bool {
if n == nil || n.Op != ONAME || n.Sym == nil || n.Sym.Pkg != unsafepkg {
return false
}
if n.Sym.Name == "Sizeof" {
return true
}
if n.Sym.Name == "Offsetof" {
return true
}
if n.Sym.Name == "Alignof" {
return true
}
return false
}