1
0
mirror of https://github.com/golang/go synced 2024-11-19 12:14:42 -07:00

cmd/compile: cleanup unsafenmagic

In particular, make Alignof work more like Sizeof. Other idiomatic
cleanups while here.

Passes toolstash -cmp.

Change-Id: I4def20894f3d95e49ab6a50ddba189be36fdd258
Reviewed-on: https://go-review.googlesource.com/20555
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Matthew Dempsky 2016-03-10 18:23:03 -08:00
parent d3794f88e9
commit 501b1fc3f2

View File

@ -6,11 +6,7 @@ package gc
import "cmd/internal/obj" import "cmd/internal/obj"
// look for // unsafenmagic rewrites calls to package unsafe's functions into constants.
// unsafe.Sizeof
// unsafe.Offsetof
// unsafe.Alignof
// rewrite with a constant
func unsafenmagic(nn *Node) *Node { func unsafenmagic(nn *Node) *Node {
fn := nn.Left fn := nn.Left
args := nn.List args := nn.List
@ -34,7 +30,8 @@ func unsafenmagic(nn *Node) *Node {
r := args.First() r := args.First()
var v int64 var v int64
if s.Name == "Sizeof" { switch s.Name {
case "Alignof", "Sizeof":
typecheck(&r, Erv) typecheck(&r, Erv)
defaultlit(&r, nil) defaultlit(&r, nil)
tr := r.Type tr := r.Type
@ -42,11 +39,13 @@ func unsafenmagic(nn *Node) *Node {
goto bad goto bad
} }
dowidth(tr) dowidth(tr)
v = tr.Width if s.Name == "Alignof" {
goto yes v = int64(tr.Align)
} } else {
v = tr.Width
}
if s.Name == "Offsetof" { case "Offsetof":
// must be a selector. // must be a selector.
if r.Op != OXDOT { if r.Op != OXDOT {
goto bad goto bad
@ -56,35 +55,33 @@ func unsafenmagic(nn *Node) *Node {
// Since r->left may be mutated by typechecking, check it explicitly // Since r->left may be mutated by typechecking, check it explicitly
// first to track it correctly. // first to track it correctly.
typecheck(&r.Left, Erv) typecheck(&r.Left, Erv)
base := r.Left base := r.Left
typecheck(&r, Erv) typecheck(&r, Erv)
switch r.Op { switch r.Op {
case ODOT, ODOTPTR: case ODOT, ODOTPTR:
break break
case OCALLPART: case OCALLPART:
Yyerror("invalid expression %v: argument is a method value", nn) Yyerror("invalid expression %v: argument is a method value", nn)
v = 0
goto ret goto ret
default: default:
goto bad goto bad
} }
v = 0 // Sum offsets for dots until we reach base.
for r1 := r; r1 != base; r1 = r1.Left {
// add offsets for inserted dots.
var r1 *Node
for r1 = r; r1.Left != base; r1 = r1.Left {
switch r1.Op { 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: case ODOT:
v += r1.Xoffset v += r1.Xoffset
case ODOTPTR:
Yyerror("invalid expression %v: selector implies indirection of embedded %v", nn, r1.Left)
goto ret
default: default:
Dump("unsafenmagic", r) Dump("unsafenmagic", r)
Fatalf("impossible %v node after dot insertion", Oconv(r1.Op, obj.FmtSharp)) Fatalf("impossible %v node after dot insertion", Oconv(r1.Op, obj.FmtSharp))
@ -92,51 +89,20 @@ func unsafenmagic(nn *Node) *Node {
} }
} }
v += r1.Xoffset default:
goto yes return nil
} }
if s.Name == "Alignof" {
typecheck(&r, Erv)
defaultlit(&r, nil)
tr := r.Type
if tr == nil {
goto bad
}
var f [2]*Type
f[0] = typ(TFIELD)
f[0].Type = Types[TUINT8]
f[1] = typ(TFIELD)
f[1].Type = tr
// make struct { byte; T; }
t := typ(TSTRUCT)
t.SetFields(f[:])
// compute struct widths
dowidth(t)
// the offset of T is its required alignment
v = t.Field(1).Width
goto yes
}
return nil
bad:
Yyerror("invalid expression %v", nn)
v = 0
goto ret
yes:
if args.Len() > 1 { if args.Len() > 1 {
Yyerror("extra arguments for %v", s) Yyerror("extra arguments for %v", s)
} }
goto ret
bad:
Yyerror("invalid expression %v", nn)
// any side effects disappear; ignore init
ret: ret:
// any side effects disappear; ignore init
var val Val var val Val
val.U = new(Mpint) val.U = new(Mpint)
Mpmovecfix(val.U.(*Mpint), v) Mpmovecfix(val.U.(*Mpint), v)