]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: cleanup unsafenmagic
authorMatthew Dempsky <mdempsky@google.com>
Fri, 11 Mar 2016 02:23:03 +0000 (18:23 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 11 Mar 2016 05:42:59 +0000 (05:42 +0000)
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>
src/cmd/compile/internal/gc/unsafe.go

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