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:
parent
d3794f88e9
commit
501b1fc3f2
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user