mirror of https://github.com/golang/go.git
91 lines
2.1 KiB
Go
91 lines
2.1 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
|
|
|
|
import (
|
|
"cmd/compile/internal/base"
|
|
"cmd/compile/internal/ir"
|
|
"cmd/compile/internal/types"
|
|
)
|
|
|
|
// evalunsafe evaluates a package unsafe operation and returns the result.
|
|
func evalunsafe(n ir.Node) int64 {
|
|
switch n.Op() {
|
|
case ir.OALIGNOF, ir.OSIZEOF:
|
|
n := n.(*ir.UnaryExpr)
|
|
n.X = typecheck(n.X, ctxExpr)
|
|
n.X = defaultlit(n.X, nil)
|
|
tr := n.X.Type()
|
|
if tr == nil {
|
|
return 0
|
|
}
|
|
types.CalcSize(tr)
|
|
if n.Op() == ir.OALIGNOF {
|
|
return int64(tr.Align)
|
|
}
|
|
return tr.Width
|
|
|
|
case ir.OOFFSETOF:
|
|
// must be a selector.
|
|
n := n.(*ir.UnaryExpr)
|
|
if n.X.Op() != ir.OXDOT {
|
|
base.Errorf("invalid expression %v", n)
|
|
return 0
|
|
}
|
|
sel := n.X.(*ir.SelectorExpr)
|
|
|
|
// 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.
|
|
sel.X = typecheck(sel.X, ctxExpr)
|
|
sbase := sel.X
|
|
|
|
tsel := typecheck(sel, ctxExpr)
|
|
n.X = tsel
|
|
if tsel.Type() == nil {
|
|
return 0
|
|
}
|
|
switch tsel.Op() {
|
|
case ir.ODOT, ir.ODOTPTR:
|
|
break
|
|
case ir.OCALLPART:
|
|
base.Errorf("invalid expression %v: argument is a method value", n)
|
|
return 0
|
|
default:
|
|
base.Errorf("invalid expression %v", n)
|
|
return 0
|
|
}
|
|
|
|
// Sum offsets for dots until we reach sbase.
|
|
var v int64
|
|
var next ir.Node
|
|
for r := tsel; r != sbase; r = next {
|
|
switch r.Op() {
|
|
case ir.ODOTPTR:
|
|
// For Offsetof(s.f), s may itself be a pointer,
|
|
// but accessing f must not otherwise involve
|
|
// indirection via embedded pointer types.
|
|
r := r.(*ir.SelectorExpr)
|
|
if r.X != sbase {
|
|
base.Errorf("invalid expression %v: selector implies indirection of embedded %v", n, r.X)
|
|
return 0
|
|
}
|
|
fallthrough
|
|
case ir.ODOT:
|
|
r := r.(*ir.SelectorExpr)
|
|
v += r.Offset
|
|
next = r.X
|
|
default:
|
|
ir.Dump("unsafenmagic", tsel)
|
|
base.Fatalf("impossible %v node after dot insertion", r.Op())
|
|
}
|
|
}
|
|
return v
|
|
}
|
|
|
|
base.Fatalf("unexpected op %v", n.Op())
|
|
return 0
|
|
}
|