}
a := s.entryNewValue1I(ssa.OpOffPtr, Ptrto(fp.Type), fp.Width, s.sp)
return s.newValue2(ssa.OpLoad, fp.Type, a, call)
+
+ case OGETG:
+ return s.newValue0(ssa.OpGetG, n.Type)
+
default:
s.Unimplementedf("unhandled expr %s", opnames[n.Op])
return nil
q.From.Reg = x86.REG_AX
q.To.Type = obj.TYPE_MEM
q.To.Reg = x86.REG_AX
+ case ssa.OpAMD64LoweredGetG:
+ r := regnum(v)
+ // See the comments in cmd/internal/obj/x86/obj6.go
+ // near CanUse1InsnTLS for a detailed explanation of these instructions.
+ if x86.CanUse1InsnTLS(Ctxt) {
+ // MOVQ (TLS), r
+ p := Prog(x86.AMOVQ)
+ p.From.Type = obj.TYPE_MEM
+ p.From.Reg = x86.REG_TLS
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = r
+ } else {
+ // MOVQ TLS, r
+ // MOVQ (r)(TLS*1), r
+ p := Prog(x86.AMOVQ)
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = x86.REG_TLS
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = r
+ q := Prog(x86.AMOVQ)
+ q.From.Type = obj.TYPE_MEM
+ q.From.Reg = r
+ q.From.Index = x86.REG_TLS
+ q.From.Scale = 1
+ q.To.Type = obj.TYPE_REG
+ q.To.Reg = r
+ }
case ssa.OpAMD64CALLstatic:
p := Prog(obj.ACALL)
p.To.Type = obj.TYPE_MEM
(IsInBounds idx len) -> (SETB (CMPQ <TypeFlags> idx len))
(PanicNilCheck ptr mem) -> (LoweredPanicNilCheck ptr mem)
+(GetG) -> (LoweredGetG)
(Move [size] dst src mem) -> (REPMOVSB dst src (MOVQconst <config.Frontend().TypeUInt64()> [size]) mem)
// InvertFlags is a pseudo-op which can't appear in assembly output.
{name: "InvertFlags"}, // reverse direction of arg0
- // LoweredPanicNilCheck is a pseudo-op.
+ // Pseudo-ops
{name: "LoweredPanicNilCheck"},
+ {name: "LoweredGetG"},
}
var AMD64blocks = []blockData{
(StringLen (StringMake _ len)) -> len
(Store dst str mem) && str.Type.IsString() -> (Store (OffPtr <config.Frontend().TypeBytePtr()> [config.PtrSize] dst) (StringLen <config.Frontend().TypeUintptr()> str) (Store <TypeMem> dst (StringPtr <config.Frontend().TypeBytePtr()> str) mem))
+(If (IsNonNil (GetG)) yes no) -> (Plain nil yes)
+
(If (Not cond) yes no) -> (If cond no yes)
(If (ConstBool {c}) yes no) && c.(bool) -> (Plain nil yes)
(If (ConstBool {c}) yes no) && !c.(bool) -> (Plain nil no)
{name: "IsNonNil"}, // arg0 != nil
{name: "IsInBounds"}, // 0 <= arg0 < arg1
+ // Pseudo-ops
{name: "PanicNilCheck"}, // trigger a dereference fault; arg0=nil ptr, arg1=mem
+ {name: "GetG"}, // runtime.getg() (read g pointer)
// Indexing operations
{name: "ArrayIndex"}, // arg0=array, arg1=index. Returns a[i]
OpAMD64REPMOVSB
OpAMD64InvertFlags
OpAMD64LoweredPanicNilCheck
+ OpAMD64LoweredGetG
OpAdd8
OpAdd16
OpIsNonNil
OpIsInBounds
OpPanicNilCheck
+ OpGetG
OpArrayIndex
OpPtrIndex
OpOffPtr
name: "LoweredPanicNilCheck",
reg: regInfo{},
},
+ {
+ name: "LoweredGetG",
+ reg: regInfo{},
+ },
{
name: "Add8",
name: "PanicNilCheck",
generic: true,
},
+ {
+ name: "GetG",
+ generic: true,
+ },
{
name: "ArrayIndex",
generic: true,
goto endd30ee67afc0284c419cef70261f61452
endd30ee67afc0284c419cef70261f61452:
;
+ case OpGetG:
+ // match: (GetG)
+ // cond:
+ // result: (LoweredGetG)
+ {
+ v.Op = OpAMD64LoweredGetG
+ v.AuxInt = 0
+ v.Aux = nil
+ v.resetArgs()
+ return true
+ }
+ goto endb17140e71dd641aa4d89e14479160260
+ endb17140e71dd641aa4d89e14479160260:
+ ;
case OpGreater16:
// match: (Greater16 x y)
// cond:
func rewriteBlockgeneric(b *Block) bool {
switch b.Kind {
case BlockIf:
+ // match: (If (IsNonNil (GetG)) yes no)
+ // cond:
+ // result: (Plain nil yes)
+ {
+ v := b.Control
+ if v.Op != OpIsNonNil {
+ goto end0f2bb0111a86be0436b44210dbd83a90
+ }
+ if v.Args[0].Op != OpGetG {
+ goto end0f2bb0111a86be0436b44210dbd83a90
+ }
+ yes := b.Succs[0]
+ no := b.Succs[1]
+ b.Func.removePredecessor(b, no)
+ b.Kind = BlockPlain
+ b.Control = nil
+ b.Succs = b.Succs[:1]
+ b.Succs[0] = yes
+ b.Likely = BranchUnknown
+ return true
+ }
+ goto end0f2bb0111a86be0436b44210dbd83a90
+ end0f2bb0111a86be0436b44210dbd83a90:
+ ;
// match: (If (Not cond) yes no)
// cond:
// result: (If cond no yes)
"math"
)
-func canuse1insntls(ctxt *obj.Link) bool {
+func CanUse1InsnTLS(ctxt *obj.Link) bool {
if ctxt.Arch.Regsize == 4 {
switch ctxt.Headtype {
case obj.Hlinux,
// rewriting the instructions more comprehensively, and it only does because
// we only support a single TLS variable (g).
- if canuse1insntls(ctxt) {
+ if CanUse1InsnTLS(ctxt) {
// Reduce 2-instruction sequence to 1-instruction sequence.
// Sequences like
// MOVQ TLS, BX