mirror of
https://github.com/golang/go
synced 2024-10-05 16:41:21 -06:00
[dev.ssa] cmd/compile: add decompose pass
Decompose breaks compound objects up into pieces that can be operated on by the target architecture. The decompose pass only does phi ops, the rest is done by the rewrite rules in generic.rules. Compound objects include strings,slices,interfaces,structs,arrays. Arrays aren't decomposed because of indexing (we could support constant indexes, but dynamic indexes can't be handled using SSA). Structs will come in a subsequent CL. TODO: after this pass we have lost the association between, e.g., a string's pointer and its size. It would be nice if we could keep that information around for debugging info somehow. Change-Id: I6379ab962a7beef62297d0f68c421f22aa0a0901 Reviewed-on: https://go-review.googlesource.com/13683 Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
parent
8d23681cc8
commit
9f954db170
@ -1072,7 +1072,15 @@ func (s *state) expr(n *Node) *ssa.Value {
|
||||
case CTBOOL:
|
||||
return s.entryNewValue0A(ssa.OpConstBool, n.Type, n.Val().U)
|
||||
case CTNIL:
|
||||
return s.entryNewValue0(ssa.OpConstNil, n.Type)
|
||||
t := n.Type
|
||||
switch {
|
||||
case t.IsSlice():
|
||||
return s.entryNewValue0(ssa.OpConstSlice, t)
|
||||
case t.IsInterface():
|
||||
return s.entryNewValue0(ssa.OpConstInterface, t)
|
||||
default:
|
||||
return s.entryNewValue0(ssa.OpConstNil, t)
|
||||
}
|
||||
case CTFLT:
|
||||
f := n.Val().U.(*Mpflt)
|
||||
switch n.Type.Size() {
|
||||
@ -1470,6 +1478,10 @@ func (s *state) zeroVal(t *Type) *ssa.Value {
|
||||
return s.entryNewValue0(ssa.OpConstNil, t)
|
||||
case t.IsBoolean():
|
||||
return s.entryNewValue0A(ssa.OpConstBool, t, false) // TODO: store bools as 0/1 in AuxInt?
|
||||
case t.IsInterface():
|
||||
return s.entryNewValue0(ssa.OpConstInterface, t)
|
||||
case t.IsSlice():
|
||||
return s.entryNewValue0(ssa.OpConstSlice, t)
|
||||
}
|
||||
s.Unimplementedf("zero for type %v not implemented", t)
|
||||
return nil
|
||||
@ -1582,11 +1594,47 @@ func canSSA(n *Node) bool {
|
||||
if n.Class == PPARAMOUT {
|
||||
return false
|
||||
}
|
||||
if Isfat(n.Type) {
|
||||
return canSSAType(n.Type)
|
||||
// TODO: try to make more variables SSAable?
|
||||
}
|
||||
|
||||
// canSSA reports whether variables of type t are SSA-able.
|
||||
func canSSAType(t *Type) bool {
|
||||
dowidth(t)
|
||||
if t.Width > int64(4*Widthptr) {
|
||||
// 4*Widthptr is an arbitrary constant. We want it
|
||||
// to be at least 3*Widthptr so slices can be registerized.
|
||||
// Too big and we'll introduce too much register pressure.
|
||||
return false
|
||||
}
|
||||
return true
|
||||
// TODO: try to make more variables SSAable.
|
||||
switch t.Etype {
|
||||
case TARRAY:
|
||||
if Isslice(t) {
|
||||
return true
|
||||
}
|
||||
// We can't do arrays because dynamic indexing is
|
||||
// not supported on SSA variables.
|
||||
// TODO: maybe allow if length is <=1? All indexes
|
||||
// are constant? Might be good for the arrays
|
||||
// introduced by the compiler for variadic functions.
|
||||
return false
|
||||
case TSTRUCT:
|
||||
if countfield(t) > 4 {
|
||||
// 4 is an arbitrary constant. Same reasoning
|
||||
// as above, lots of small fields would waste
|
||||
// register space needed by other values.
|
||||
return false
|
||||
}
|
||||
for t1 := t.Type; t1 != nil; t1 = t1.Down {
|
||||
if !canSSAType(t1.Type) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false // until it is implemented
|
||||
//return true
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// nilCheck generates nil pointer checking code.
|
||||
|
91
src/cmd/compile/internal/gc/testdata/compound_ssa.go
vendored
Normal file
91
src/cmd/compile/internal/gc/testdata/compound_ssa.go
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
// run
|
||||
|
||||
// Copyright 2015 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.
|
||||
|
||||
// Test compound objects
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func string_ssa(a, b string, x bool) string {
|
||||
s := ""
|
||||
if x {
|
||||
s = a
|
||||
} else {
|
||||
s = b
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func testString() {
|
||||
a := "foo"
|
||||
b := "barz"
|
||||
if want, got := a, string_ssa(a, b, true); got != want {
|
||||
fmt.Printf("string_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := b, string_ssa(a, b, false); got != want {
|
||||
fmt.Printf("string_ssa(%v, %v, false) = %v, want %v\n", a, b, got, want)
|
||||
failed = true
|
||||
}
|
||||
}
|
||||
|
||||
func slice_ssa(a, b []byte, x bool) []byte {
|
||||
var s []byte
|
||||
if x {
|
||||
s = a
|
||||
} else {
|
||||
s = b
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func testSlice() {
|
||||
a := []byte{3, 4, 5}
|
||||
b := []byte{7, 8, 9}
|
||||
if want, got := byte(3), slice_ssa(a, b, true)[0]; got != want {
|
||||
fmt.Printf("slice_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := byte(7), slice_ssa(a, b, false)[0]; got != want {
|
||||
fmt.Printf("slice_ssa(%v, %v, false) = %v, want %v\n", a, b, got, want)
|
||||
failed = true
|
||||
}
|
||||
}
|
||||
|
||||
func interface_ssa(a, b interface{}, x bool) interface{} {
|
||||
var s interface{}
|
||||
if x {
|
||||
s = a
|
||||
} else {
|
||||
s = b
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func testInterface() {
|
||||
a := interface{}(3)
|
||||
b := interface{}(4)
|
||||
if want, got := 3, interface_ssa(a, b, true).(int); got != want {
|
||||
fmt.Printf("interface_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := 4, interface_ssa(a, b, false).(int); got != want {
|
||||
fmt.Printf("interface_ssa(%v, %v, false) = %v, want %v\n", a, b, got, want)
|
||||
failed = true
|
||||
}
|
||||
}
|
||||
|
||||
var failed = false
|
||||
|
||||
func main() {
|
||||
testString()
|
||||
testSlice()
|
||||
testInterface()
|
||||
if failed {
|
||||
panic("failed")
|
||||
}
|
||||
}
|
@ -68,6 +68,10 @@ func (t *Type) IsSlice() bool {
|
||||
return t.Etype == TARRAY && t.Bound < 0
|
||||
}
|
||||
|
||||
func (t *Type) IsInterface() bool {
|
||||
return t.Etype == TINTER
|
||||
}
|
||||
|
||||
func (t *Type) Elem() ssa.Type {
|
||||
return t.Type
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ type pass struct {
|
||||
var passes = [...]pass{
|
||||
{"phielim", phielim},
|
||||
{"copyelim", copyelim},
|
||||
{"decompose", decompose},
|
||||
{"early deadcode", deadcode}, // remove generated dead code to avoid doing pointless work during opt
|
||||
{"opt", opt},
|
||||
{"opt deadcode", deadcode}, // remove any blocks orphaned during opt
|
||||
@ -103,6 +104,8 @@ var passOrder = [...]constraint{
|
||||
// tighten will be most effective when as many values have been removed as possible
|
||||
{"generic deadcode", "tighten"},
|
||||
{"generic cse", "tighten"},
|
||||
// don't run optimization pass until we've decomposed compound objects
|
||||
{"decompose", "opt"},
|
||||
// don't layout blocks until critical edges have been removed
|
||||
{"critical", "layout"},
|
||||
// regalloc requires the removal of all critical edges
|
||||
|
93
src/cmd/compile/internal/ssa/decompose.go
Normal file
93
src/cmd/compile/internal/ssa/decompose.go
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright 2015 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 ssa
|
||||
|
||||
// decompose converts phi ops on compound types into phi
|
||||
// ops on simple types.
|
||||
// (The remaining compound ops are decomposed with rewrite rules.)
|
||||
func decompose(f *Func) {
|
||||
for _, b := range f.Blocks {
|
||||
for _, v := range b.Values {
|
||||
if v.Op != OpPhi {
|
||||
continue
|
||||
}
|
||||
switch {
|
||||
case v.Type.IsString():
|
||||
decomposeStringPhi(v)
|
||||
case v.Type.IsSlice():
|
||||
decomposeSlicePhi(v)
|
||||
case v.Type.IsInterface():
|
||||
decomposeInterfacePhi(v)
|
||||
//case v.Type.IsStruct():
|
||||
// decomposeStructPhi(v)
|
||||
case v.Type.Size() > f.Config.IntSize:
|
||||
f.Unimplementedf("undecomposed type %s", v.Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: decompose complex?
|
||||
// TODO: decompose 64-bit ops on 32-bit archs?
|
||||
}
|
||||
|
||||
func decomposeStringPhi(v *Value) {
|
||||
fe := v.Block.Func.Config.fe
|
||||
ptrType := fe.TypeBytePtr()
|
||||
lenType := fe.TypeUintptr()
|
||||
|
||||
ptr := v.Block.NewValue0(v.Line, OpPhi, ptrType)
|
||||
len := v.Block.NewValue0(v.Line, OpPhi, lenType)
|
||||
for _, a := range v.Args {
|
||||
ptr.AddArg(a.Block.NewValue1(v.Line, OpStringPtr, ptrType, a))
|
||||
len.AddArg(a.Block.NewValue1(v.Line, OpStringLen, lenType, a))
|
||||
}
|
||||
v.Op = OpStringMake
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(len)
|
||||
}
|
||||
|
||||
func decomposeSlicePhi(v *Value) {
|
||||
fe := v.Block.Func.Config.fe
|
||||
ptrType := fe.TypeBytePtr()
|
||||
lenType := fe.TypeUintptr()
|
||||
|
||||
ptr := v.Block.NewValue0(v.Line, OpPhi, ptrType)
|
||||
len := v.Block.NewValue0(v.Line, OpPhi, lenType)
|
||||
cap := v.Block.NewValue0(v.Line, OpPhi, lenType)
|
||||
for _, a := range v.Args {
|
||||
ptr.AddArg(a.Block.NewValue1(v.Line, OpSlicePtr, ptrType, a))
|
||||
len.AddArg(a.Block.NewValue1(v.Line, OpSliceLen, lenType, a))
|
||||
cap.AddArg(a.Block.NewValue1(v.Line, OpSliceCap, lenType, a))
|
||||
}
|
||||
v.Op = OpSliceMake
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(len)
|
||||
v.AddArg(cap)
|
||||
}
|
||||
|
||||
func decomposeInterfacePhi(v *Value) {
|
||||
ptrType := v.Block.Func.Config.fe.TypeBytePtr()
|
||||
|
||||
itab := v.Block.NewValue0(v.Line, OpPhi, ptrType)
|
||||
data := v.Block.NewValue0(v.Line, OpPhi, ptrType)
|
||||
for _, a := range v.Args {
|
||||
itab.AddArg(a.Block.NewValue1(v.Line, OpITab, ptrType, a))
|
||||
data.AddArg(a.Block.NewValue1(v.Line, OpIData, ptrType, a))
|
||||
}
|
||||
v.Op = OpIMake
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v.AddArg(itab)
|
||||
v.AddArg(data)
|
||||
}
|
||||
func decomposeStructPhi(v *Value) {
|
||||
// TODO
|
||||
}
|
@ -59,36 +59,90 @@
|
||||
(Com32 (Com32 x)) -> x
|
||||
(Com64 (Com64 x)) -> x
|
||||
|
||||
// tear apart slices
|
||||
// TODO: anything that generates a slice needs to go in here.
|
||||
(SlicePtr (Load ptr mem)) -> (Load ptr mem)
|
||||
(SliceLen (Load ptr mem)) -> (Load (AddPtr <ptr.Type> ptr (ConstPtr <config.Frontend().TypeUintptr()> [config.PtrSize])) mem)
|
||||
(SliceCap (Load ptr mem)) -> (Load (AddPtr <ptr.Type> ptr (ConstPtr <config.Frontend().TypeUintptr()> [config.PtrSize*2])) mem)
|
||||
|
||||
// slice and interface comparisons
|
||||
// the frontend ensures that we can only compare against nil
|
||||
// start by putting nil on the right to simplify the other rules
|
||||
(EqFat x y) && x.Op == OpConstNil && y.Op != OpConstNil -> (EqFat y x)
|
||||
(NeqFat x y) && x.Op == OpConstNil && y.Op != OpConstNil -> (NeqFat y x)
|
||||
// it suffices to check the first word (backing array for slices, dynamic type for interfaces)
|
||||
(EqFat (Load ptr mem) (ConstNil)) -> (EqPtr (Load <config.Frontend().TypeUintptr()> ptr mem) (ConstPtr <config.Frontend().TypeUintptr()> [0]))
|
||||
(NeqFat (Load ptr mem) (ConstNil)) -> (NeqPtr (Load <config.Frontend().TypeUintptr()> ptr mem) (ConstPtr <config.Frontend().TypeUintptr()> [0]))
|
||||
(EqFat (Load ptr mem) (ConstNil)) -> (EqPtr (Load <config.fe.TypeUintptr()> ptr mem) (ConstPtr <config.fe.TypeUintptr()> [0]))
|
||||
(NeqFat (Load ptr mem) (ConstNil)) -> (NeqPtr (Load <config.fe.TypeUintptr()> ptr mem) (ConstPtr <config.fe.TypeUintptr()> [0]))
|
||||
|
||||
// indexing operations
|
||||
// Note: bounds check has already been done
|
||||
(ArrayIndex (Load ptr mem) idx) -> (Load (PtrIndex <v.Type.PtrTo()> ptr idx) mem)
|
||||
(PtrIndex <t> ptr idx) -> (AddPtr ptr (MulPtr <config.Frontend().TypeUintptr()> idx (ConstPtr <config.Frontend().TypeUintptr()> [t.Elem().Size()])))
|
||||
(PtrIndex <t> ptr idx) -> (AddPtr ptr (MulPtr <config.fe.TypeUintptr()> idx (ConstPtr <config.fe.TypeUintptr()> [t.Elem().Size()])))
|
||||
(StructSelect [idx] (Load ptr mem)) -> (Load (OffPtr <v.Type.PtrTo()> [idx] ptr) mem)
|
||||
|
||||
// big-object moves
|
||||
(Store [size] dst (Load src mem) mem) && size > config.IntSize -> (Move [size] dst src mem)
|
||||
|
||||
// string ops
|
||||
(ConstString {s}) -> (StringMake (Addr <config.Frontend().TypeBytePtr()> {config.fe.StringData(s.(string))} (SB <config.Frontend().TypeUintptr()>)) (ConstPtr <config.Frontend().TypeUintptr()> [int64(len(s.(string)))]))
|
||||
(Load <t> ptr mem) && t.IsString() -> (StringMake (Load <config.Frontend().TypeBytePtr()> ptr mem) (Load <config.Frontend().TypeUintptr()> (OffPtr <config.Frontend().TypeBytePtr()> [config.PtrSize] ptr) mem))
|
||||
(StringPtr (StringMake ptr _)) -> ptr
|
||||
(StringLen (StringMake _ len)) -> len
|
||||
(Store [2*config.PtrSize] dst str mem) && str.Type.IsString() -> (Store [config.PtrSize] (OffPtr <config.Frontend().TypeBytePtr()> [config.PtrSize] dst) (StringLen <config.Frontend().TypeUintptr()> str) (Store [config.PtrSize] <TypeMem> dst (StringPtr <config.Frontend().TypeBytePtr()> str) mem))
|
||||
(ConstString {s}) ->
|
||||
(StringMake
|
||||
(Addr <config.fe.TypeBytePtr()> {config.fe.StringData(s.(string))}
|
||||
(SB <config.fe.TypeUintptr()>))
|
||||
(ConstPtr <config.fe.TypeUintptr()> [int64(len(s.(string)))]))
|
||||
(Load <t> ptr mem) && t.IsString() ->
|
||||
(StringMake
|
||||
(Load <config.fe.TypeBytePtr()> ptr mem)
|
||||
(Load <config.fe.TypeUintptr()>
|
||||
(OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] ptr)
|
||||
mem))
|
||||
(Store [2*config.PtrSize] dst (StringMake ptr len) mem) ->
|
||||
(Store [config.PtrSize]
|
||||
(OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] dst)
|
||||
len
|
||||
(Store <TypeMem> [config.PtrSize] dst ptr mem))
|
||||
|
||||
// slice ops
|
||||
(SlicePtr (SliceMake ptr _ _ )) -> ptr
|
||||
(SliceLen (SliceMake _ len _)) -> len
|
||||
(SliceCap (SliceMake _ _ cap)) -> cap
|
||||
(ConstSlice) ->
|
||||
(SliceMake
|
||||
(ConstNil <config.fe.TypeBytePtr()>)
|
||||
(ConstPtr <config.fe.TypeUintptr()>)
|
||||
(ConstPtr <config.fe.TypeUintptr()>))
|
||||
|
||||
(Load <t> ptr mem) && t.IsSlice() ->
|
||||
(SliceMake
|
||||
(Load <config.fe.TypeBytePtr()> ptr mem)
|
||||
(Load <config.fe.TypeUintptr()>
|
||||
(OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] ptr)
|
||||
mem)
|
||||
(Load <config.fe.TypeUintptr()>
|
||||
(OffPtr <config.fe.TypeUintptr().PtrTo()> [2*config.PtrSize] ptr)
|
||||
mem))
|
||||
(Store [3*config.PtrSize] dst (SliceMake ptr len cap) mem) ->
|
||||
(Store [config.PtrSize]
|
||||
(OffPtr <config.fe.TypeUintptr().PtrTo()> [2*config.PtrSize] dst)
|
||||
cap
|
||||
(Store <TypeMem> [config.PtrSize]
|
||||
(OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] dst)
|
||||
len
|
||||
(Store <TypeMem> [config.PtrSize] dst ptr mem)))
|
||||
|
||||
// interface ops
|
||||
(ITab (IMake itab _)) -> itab
|
||||
(IData (IMake _ data)) -> data
|
||||
(ConstInterface) ->
|
||||
(IMake
|
||||
(ConstNil <config.fe.TypeBytePtr()>)
|
||||
(ConstNil <config.fe.TypeBytePtr()>))
|
||||
(Load <t> ptr mem) && t.IsInterface() ->
|
||||
(IMake
|
||||
(Load <config.fe.TypeBytePtr()> ptr mem)
|
||||
(Load <config.fe.TypeBytePtr()>
|
||||
(OffPtr <config.fe.TypeBytePtr().PtrTo()> [config.PtrSize] ptr)
|
||||
mem))
|
||||
(Store [2*config.PtrSize] dst (IMake itab data) mem) ->
|
||||
(Store [config.PtrSize]
|
||||
(OffPtr <config.fe.TypeBytePtr().PtrTo()> [config.PtrSize] dst)
|
||||
data
|
||||
(Store <TypeMem> [config.PtrSize] dst itab mem))
|
||||
|
||||
// big-object moves (TODO: remove?)
|
||||
(Store [size] dst (Load src mem) mem) && size > config.IntSize -> (Move [size] dst src mem)
|
||||
|
||||
(If (IsNonNil (GetG)) yes no) -> (Plain nil yes)
|
||||
|
||||
|
@ -229,7 +229,9 @@ var genericOps = []opData{
|
||||
{name: "Const64"},
|
||||
{name: "Const32F"},
|
||||
{name: "Const64F"},
|
||||
{name: "ConstPtr"}, // pointer-sized integer constant
|
||||
{name: "ConstPtr"}, // pointer-sized integer constant
|
||||
{name: "ConstInterface"}, // nil interface
|
||||
{name: "ConstSlice"}, // nil slice
|
||||
// TODO: Const32F, ...
|
||||
|
||||
// Constant-like things
|
||||
@ -305,7 +307,9 @@ var genericOps = []opData{
|
||||
{name: "StringLen"}, // len(arg0)
|
||||
|
||||
// Interfaces
|
||||
{name: "ITab"}, // arg0=interface, returns itable field
|
||||
{name: "IMake"}, // arg0=itab, arg1=data
|
||||
{name: "ITab"}, // arg0=interface, returns itable field
|
||||
{name: "IData"}, // arg0=interface, returns data field
|
||||
|
||||
// Spill&restore ops for the register allocator. These are
|
||||
// semantically identical to OpCopy; they do not take/return
|
||||
|
@ -396,6 +396,8 @@ const (
|
||||
OpConst32F
|
||||
OpConst64F
|
||||
OpConstPtr
|
||||
OpConstInterface
|
||||
OpConstSlice
|
||||
OpArg
|
||||
OpAddr
|
||||
OpSP
|
||||
@ -442,7 +444,9 @@ const (
|
||||
OpStringMake
|
||||
OpStringPtr
|
||||
OpStringLen
|
||||
OpIMake
|
||||
OpITab
|
||||
OpIData
|
||||
OpStoreReg
|
||||
OpLoadReg
|
||||
OpFwdRef
|
||||
@ -3374,6 +3378,14 @@ var opcodeTable = [...]opInfo{
|
||||
name: "ConstPtr",
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "ConstInterface",
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "ConstSlice",
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "Arg",
|
||||
generic: true,
|
||||
@ -3558,10 +3570,18 @@ var opcodeTable = [...]opInfo{
|
||||
name: "StringLen",
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "IMake",
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "ITab",
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "IData",
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "StoreReg",
|
||||
generic: true,
|
||||
|
@ -237,10 +237,53 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
||||
goto end4d92ff3ba567d9afd38fc9ca113602ad
|
||||
end4d92ff3ba567d9afd38fc9ca113602ad:
|
||||
;
|
||||
case OpConstInterface:
|
||||
// match: (ConstInterface)
|
||||
// cond:
|
||||
// result: (IMake (ConstNil <config.fe.TypeBytePtr()>) (ConstNil <config.fe.TypeBytePtr()>))
|
||||
{
|
||||
v.Op = OpIMake
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v0 := b.NewValue0(v.Line, OpConstNil, TypeInvalid)
|
||||
v0.Type = config.fe.TypeBytePtr()
|
||||
v.AddArg(v0)
|
||||
v1 := b.NewValue0(v.Line, OpConstNil, TypeInvalid)
|
||||
v1.Type = config.fe.TypeBytePtr()
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
goto end0367bd8f20a320cc41568f2b28657f6b
|
||||
end0367bd8f20a320cc41568f2b28657f6b:
|
||||
;
|
||||
case OpConstSlice:
|
||||
// match: (ConstSlice)
|
||||
// cond:
|
||||
// result: (SliceMake (ConstNil <config.fe.TypeBytePtr()>) (ConstPtr <config.fe.TypeUintptr()>) (ConstPtr <config.fe.TypeUintptr()>))
|
||||
{
|
||||
v.Op = OpSliceMake
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v0 := b.NewValue0(v.Line, OpConstNil, TypeInvalid)
|
||||
v0.Type = config.fe.TypeBytePtr()
|
||||
v.AddArg(v0)
|
||||
v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid)
|
||||
v1.Type = config.fe.TypeUintptr()
|
||||
v.AddArg(v1)
|
||||
v2 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid)
|
||||
v2.Type = config.fe.TypeUintptr()
|
||||
v.AddArg(v2)
|
||||
return true
|
||||
}
|
||||
goto endfd2d8ffcd55eaf8a5092a20c3ae61ba3
|
||||
endfd2d8ffcd55eaf8a5092a20c3ae61ba3:
|
||||
;
|
||||
case OpConstString:
|
||||
// match: (ConstString {s})
|
||||
// cond:
|
||||
// result: (StringMake (Addr <config.Frontend().TypeBytePtr()> {config.fe.StringData(s.(string))} (SB <config.Frontend().TypeUintptr()>)) (ConstPtr <config.Frontend().TypeUintptr()> [int64(len(s.(string)))]))
|
||||
// result: (StringMake (Addr <config.fe.TypeBytePtr()> {config.fe.StringData(s.(string))} (SB <config.fe.TypeUintptr()>)) (ConstPtr <config.fe.TypeUintptr()> [int64(len(s.(string)))]))
|
||||
{
|
||||
s := v.Aux
|
||||
v.Op = OpStringMake
|
||||
@ -248,20 +291,20 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v0 := b.NewValue0(v.Line, OpAddr, TypeInvalid)
|
||||
v0.Type = config.Frontend().TypeBytePtr()
|
||||
v0.Type = config.fe.TypeBytePtr()
|
||||
v0.Aux = config.fe.StringData(s.(string))
|
||||
v1 := b.NewValue0(v.Line, OpSB, TypeInvalid)
|
||||
v1.Type = config.Frontend().TypeUintptr()
|
||||
v1.Type = config.fe.TypeUintptr()
|
||||
v0.AddArg(v1)
|
||||
v.AddArg(v0)
|
||||
v2 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid)
|
||||
v2.Type = config.Frontend().TypeUintptr()
|
||||
v2.Type = config.fe.TypeUintptr()
|
||||
v2.AuxInt = int64(len(s.(string)))
|
||||
v.AddArg(v2)
|
||||
return true
|
||||
}
|
||||
goto end68cc91679848c7c30bd8b0a8ed533843
|
||||
end68cc91679848c7c30bd8b0a8ed533843:
|
||||
goto end51a3d96f2d304db9a52f36ee6b29c14e
|
||||
end51a3d96f2d304db9a52f36ee6b29c14e:
|
||||
;
|
||||
case OpEq16:
|
||||
// match: (Eq16 x x)
|
||||
@ -362,33 +405,73 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
||||
;
|
||||
// match: (EqFat (Load ptr mem) (ConstNil))
|
||||
// cond:
|
||||
// result: (EqPtr (Load <config.Frontend().TypeUintptr()> ptr mem) (ConstPtr <config.Frontend().TypeUintptr()> [0]))
|
||||
// result: (EqPtr (Load <config.fe.TypeUintptr()> ptr mem) (ConstPtr <config.fe.TypeUintptr()> [0]))
|
||||
{
|
||||
if v.Args[0].Op != OpLoad {
|
||||
goto end540dc8dfbc66adcd3db2d7e819c534f6
|
||||
goto ende10070e5ddd3dc059674d25ccc6a63b5
|
||||
}
|
||||
ptr := v.Args[0].Args[0]
|
||||
mem := v.Args[0].Args[1]
|
||||
if v.Args[1].Op != OpConstNil {
|
||||
goto end540dc8dfbc66adcd3db2d7e819c534f6
|
||||
goto ende10070e5ddd3dc059674d25ccc6a63b5
|
||||
}
|
||||
v.Op = OpEqPtr
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
|
||||
v0.Type = config.Frontend().TypeUintptr()
|
||||
v0.Type = config.fe.TypeUintptr()
|
||||
v0.AddArg(ptr)
|
||||
v0.AddArg(mem)
|
||||
v.AddArg(v0)
|
||||
v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid)
|
||||
v1.Type = config.Frontend().TypeUintptr()
|
||||
v1.Type = config.fe.TypeUintptr()
|
||||
v1.AuxInt = 0
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
goto end540dc8dfbc66adcd3db2d7e819c534f6
|
||||
end540dc8dfbc66adcd3db2d7e819c534f6:
|
||||
goto ende10070e5ddd3dc059674d25ccc6a63b5
|
||||
ende10070e5ddd3dc059674d25ccc6a63b5:
|
||||
;
|
||||
case OpIData:
|
||||
// match: (IData (IMake _ data))
|
||||
// cond:
|
||||
// result: data
|
||||
{
|
||||
if v.Args[0].Op != OpIMake {
|
||||
goto endbfa1bb944cdc07933effb16a35152e12
|
||||
}
|
||||
data := v.Args[0].Args[1]
|
||||
v.Op = OpCopy
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v.Type = data.Type
|
||||
v.AddArg(data)
|
||||
return true
|
||||
}
|
||||
goto endbfa1bb944cdc07933effb16a35152e12
|
||||
endbfa1bb944cdc07933effb16a35152e12:
|
||||
;
|
||||
case OpITab:
|
||||
// match: (ITab (IMake itab _))
|
||||
// cond:
|
||||
// result: itab
|
||||
{
|
||||
if v.Args[0].Op != OpIMake {
|
||||
goto endfcbb9414a776ff9c8512da3e0f4d8fbd
|
||||
}
|
||||
itab := v.Args[0].Args[0]
|
||||
v.Op = OpCopy
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v.Type = itab.Type
|
||||
v.AddArg(itab)
|
||||
return true
|
||||
}
|
||||
goto endfcbb9414a776ff9c8512da3e0f4d8fbd
|
||||
endfcbb9414a776ff9c8512da3e0f4d8fbd:
|
||||
;
|
||||
case OpIsInBounds:
|
||||
// match: (IsInBounds (Const32 [c]) (Const32 [d]))
|
||||
@ -488,27 +571,27 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
||||
case OpLoad:
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: t.IsString()
|
||||
// result: (StringMake (Load <config.Frontend().TypeBytePtr()> ptr mem) (Load <config.Frontend().TypeUintptr()> (OffPtr <config.Frontend().TypeBytePtr()> [config.PtrSize] ptr) mem))
|
||||
// result: (StringMake (Load <config.fe.TypeBytePtr()> ptr mem) (Load <config.fe.TypeUintptr()> (OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] ptr) mem))
|
||||
{
|
||||
t := v.Type
|
||||
ptr := v.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(t.IsString()) {
|
||||
goto end18afa4a6fdd6d0b92ed292840898c8f6
|
||||
goto end7c75255555bf9dd796298d9f6eaf9cf2
|
||||
}
|
||||
v.Op = OpStringMake
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
|
||||
v0.Type = config.Frontend().TypeBytePtr()
|
||||
v0.Type = config.fe.TypeBytePtr()
|
||||
v0.AddArg(ptr)
|
||||
v0.AddArg(mem)
|
||||
v.AddArg(v0)
|
||||
v1 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
|
||||
v1.Type = config.Frontend().TypeUintptr()
|
||||
v1.Type = config.fe.TypeUintptr()
|
||||
v2 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid)
|
||||
v2.Type = config.Frontend().TypeBytePtr()
|
||||
v2.Type = config.fe.TypeUintptr().PtrTo()
|
||||
v2.AuxInt = config.PtrSize
|
||||
v2.AddArg(ptr)
|
||||
v1.AddArg(v2)
|
||||
@ -516,8 +599,83 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
goto end18afa4a6fdd6d0b92ed292840898c8f6
|
||||
end18afa4a6fdd6d0b92ed292840898c8f6:
|
||||
goto end7c75255555bf9dd796298d9f6eaf9cf2
|
||||
end7c75255555bf9dd796298d9f6eaf9cf2:
|
||||
;
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: t.IsSlice()
|
||||
// result: (SliceMake (Load <config.fe.TypeBytePtr()> ptr mem) (Load <config.fe.TypeUintptr()> (OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] ptr) mem) (Load <config.fe.TypeUintptr()> (OffPtr <config.fe.TypeUintptr().PtrTo()> [2*config.PtrSize] ptr) mem))
|
||||
{
|
||||
t := v.Type
|
||||
ptr := v.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(t.IsSlice()) {
|
||||
goto end12c46556d962198680eb3238859e3016
|
||||
}
|
||||
v.Op = OpSliceMake
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
|
||||
v0.Type = config.fe.TypeBytePtr()
|
||||
v0.AddArg(ptr)
|
||||
v0.AddArg(mem)
|
||||
v.AddArg(v0)
|
||||
v1 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
|
||||
v1.Type = config.fe.TypeUintptr()
|
||||
v2 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid)
|
||||
v2.Type = config.fe.TypeUintptr().PtrTo()
|
||||
v2.AuxInt = config.PtrSize
|
||||
v2.AddArg(ptr)
|
||||
v1.AddArg(v2)
|
||||
v1.AddArg(mem)
|
||||
v.AddArg(v1)
|
||||
v3 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
|
||||
v3.Type = config.fe.TypeUintptr()
|
||||
v4 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid)
|
||||
v4.Type = config.fe.TypeUintptr().PtrTo()
|
||||
v4.AuxInt = 2 * config.PtrSize
|
||||
v4.AddArg(ptr)
|
||||
v3.AddArg(v4)
|
||||
v3.AddArg(mem)
|
||||
v.AddArg(v3)
|
||||
return true
|
||||
}
|
||||
goto end12c46556d962198680eb3238859e3016
|
||||
end12c46556d962198680eb3238859e3016:
|
||||
;
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: t.IsInterface()
|
||||
// result: (IMake (Load <config.fe.TypeBytePtr()> ptr mem) (Load <config.fe.TypeBytePtr()> (OffPtr <config.fe.TypeBytePtr().PtrTo()> [config.PtrSize] ptr) mem))
|
||||
{
|
||||
t := v.Type
|
||||
ptr := v.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(t.IsInterface()) {
|
||||
goto end12671c83ebe3ccbc8e53383765ee7675
|
||||
}
|
||||
v.Op = OpIMake
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
|
||||
v0.Type = config.fe.TypeBytePtr()
|
||||
v0.AddArg(ptr)
|
||||
v0.AddArg(mem)
|
||||
v.AddArg(v0)
|
||||
v1 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
|
||||
v1.Type = config.fe.TypeBytePtr()
|
||||
v2 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid)
|
||||
v2.Type = config.fe.TypeBytePtr().PtrTo()
|
||||
v2.AuxInt = config.PtrSize
|
||||
v2.AddArg(ptr)
|
||||
v1.AddArg(v2)
|
||||
v1.AddArg(mem)
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
goto end12671c83ebe3ccbc8e53383765ee7675
|
||||
end12671c83ebe3ccbc8e53383765ee7675:
|
||||
;
|
||||
case OpMul64:
|
||||
// match: (Mul64 (Const64 [c]) (Const64 [d]))
|
||||
@ -664,33 +822,33 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
||||
;
|
||||
// match: (NeqFat (Load ptr mem) (ConstNil))
|
||||
// cond:
|
||||
// result: (NeqPtr (Load <config.Frontend().TypeUintptr()> ptr mem) (ConstPtr <config.Frontend().TypeUintptr()> [0]))
|
||||
// result: (NeqPtr (Load <config.fe.TypeUintptr()> ptr mem) (ConstPtr <config.fe.TypeUintptr()> [0]))
|
||||
{
|
||||
if v.Args[0].Op != OpLoad {
|
||||
goto end67d723bb0f39a5c897816abcf411e5cf
|
||||
goto end423eea941d60473e73140e25f5818bfb
|
||||
}
|
||||
ptr := v.Args[0].Args[0]
|
||||
mem := v.Args[0].Args[1]
|
||||
if v.Args[1].Op != OpConstNil {
|
||||
goto end67d723bb0f39a5c897816abcf411e5cf
|
||||
goto end423eea941d60473e73140e25f5818bfb
|
||||
}
|
||||
v.Op = OpNeqPtr
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
|
||||
v0.Type = config.Frontend().TypeUintptr()
|
||||
v0.Type = config.fe.TypeUintptr()
|
||||
v0.AddArg(ptr)
|
||||
v0.AddArg(mem)
|
||||
v.AddArg(v0)
|
||||
v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid)
|
||||
v1.Type = config.Frontend().TypeUintptr()
|
||||
v1.Type = config.fe.TypeUintptr()
|
||||
v1.AuxInt = 0
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
goto end67d723bb0f39a5c897816abcf411e5cf
|
||||
end67d723bb0f39a5c897816abcf411e5cf:
|
||||
goto end423eea941d60473e73140e25f5818bfb
|
||||
end423eea941d60473e73140e25f5818bfb:
|
||||
;
|
||||
case OpOr16:
|
||||
// match: (Or16 x x)
|
||||
@ -775,7 +933,7 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
||||
case OpPtrIndex:
|
||||
// match: (PtrIndex <t> ptr idx)
|
||||
// cond:
|
||||
// result: (AddPtr ptr (MulPtr <config.Frontend().TypeUintptr()> idx (ConstPtr <config.Frontend().TypeUintptr()> [t.Elem().Size()])))
|
||||
// result: (AddPtr ptr (MulPtr <config.fe.TypeUintptr()> idx (ConstPtr <config.fe.TypeUintptr()> [t.Elem().Size()])))
|
||||
{
|
||||
t := v.Type
|
||||
ptr := v.Args[0]
|
||||
@ -786,96 +944,201 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
||||
v.resetArgs()
|
||||
v.AddArg(ptr)
|
||||
v0 := b.NewValue0(v.Line, OpMulPtr, TypeInvalid)
|
||||
v0.Type = config.Frontend().TypeUintptr()
|
||||
v0.Type = config.fe.TypeUintptr()
|
||||
v0.AddArg(idx)
|
||||
v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid)
|
||||
v1.Type = config.Frontend().TypeUintptr()
|
||||
v1.Type = config.fe.TypeUintptr()
|
||||
v1.AuxInt = t.Elem().Size()
|
||||
v0.AddArg(v1)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
goto endf7546737f42c76a99699f241d41f491a
|
||||
endf7546737f42c76a99699f241d41f491a:
|
||||
goto end1e1c5ef80c11231f89a5439cdda98359
|
||||
end1e1c5ef80c11231f89a5439cdda98359:
|
||||
;
|
||||
case OpSliceCap:
|
||||
// match: (SliceCap (Load ptr mem))
|
||||
// match: (SliceCap (SliceMake _ _ cap))
|
||||
// cond:
|
||||
// result: (Load (AddPtr <ptr.Type> ptr (ConstPtr <config.Frontend().TypeUintptr()> [config.PtrSize*2])) mem)
|
||||
// result: cap
|
||||
{
|
||||
if v.Args[0].Op != OpLoad {
|
||||
goto end6696811bf6bd45e505d24c1a15c68e70
|
||||
if v.Args[0].Op != OpSliceMake {
|
||||
goto end1bd11616743632b33b410964667fb3c6
|
||||
}
|
||||
ptr := v.Args[0].Args[0]
|
||||
mem := v.Args[0].Args[1]
|
||||
v.Op = OpLoad
|
||||
cap := v.Args[0].Args[2]
|
||||
v.Op = OpCopy
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v0 := b.NewValue0(v.Line, OpAddPtr, TypeInvalid)
|
||||
v0.Type = ptr.Type
|
||||
v0.AddArg(ptr)
|
||||
v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid)
|
||||
v1.Type = config.Frontend().TypeUintptr()
|
||||
v1.AuxInt = config.PtrSize * 2
|
||||
v0.AddArg(v1)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(mem)
|
||||
v.Type = cap.Type
|
||||
v.AddArg(cap)
|
||||
return true
|
||||
}
|
||||
goto end6696811bf6bd45e505d24c1a15c68e70
|
||||
end6696811bf6bd45e505d24c1a15c68e70:
|
||||
goto end1bd11616743632b33b410964667fb3c6
|
||||
end1bd11616743632b33b410964667fb3c6:
|
||||
;
|
||||
case OpSliceLen:
|
||||
// match: (SliceLen (Load ptr mem))
|
||||
// match: (SliceLen (SliceMake _ len _))
|
||||
// cond:
|
||||
// result: (Load (AddPtr <ptr.Type> ptr (ConstPtr <config.Frontend().TypeUintptr()> [config.PtrSize])) mem)
|
||||
// result: len
|
||||
{
|
||||
if v.Args[0].Op != OpLoad {
|
||||
goto end9844ce3e290e81355493141e653e37d5
|
||||
if v.Args[0].Op != OpSliceMake {
|
||||
goto endebb2090199d13e4c2ae52fb3e778f7fd
|
||||
}
|
||||
ptr := v.Args[0].Args[0]
|
||||
mem := v.Args[0].Args[1]
|
||||
v.Op = OpLoad
|
||||
len := v.Args[0].Args[1]
|
||||
v.Op = OpCopy
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v0 := b.NewValue0(v.Line, OpAddPtr, TypeInvalid)
|
||||
v0.Type = ptr.Type
|
||||
v0.AddArg(ptr)
|
||||
v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid)
|
||||
v1.Type = config.Frontend().TypeUintptr()
|
||||
v1.AuxInt = config.PtrSize
|
||||
v0.AddArg(v1)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(mem)
|
||||
v.Type = len.Type
|
||||
v.AddArg(len)
|
||||
return true
|
||||
}
|
||||
goto end9844ce3e290e81355493141e653e37d5
|
||||
end9844ce3e290e81355493141e653e37d5:
|
||||
goto endebb2090199d13e4c2ae52fb3e778f7fd
|
||||
endebb2090199d13e4c2ae52fb3e778f7fd:
|
||||
;
|
||||
case OpSlicePtr:
|
||||
// match: (SlicePtr (Load ptr mem))
|
||||
// match: (SlicePtr (SliceMake ptr _ _ ))
|
||||
// cond:
|
||||
// result: (Load ptr mem)
|
||||
// result: ptr
|
||||
{
|
||||
if v.Args[0].Op != OpLoad {
|
||||
goto end459613b83f95b65729d45c2ed663a153
|
||||
if v.Args[0].Op != OpSliceMake {
|
||||
goto end526acc0a705137a5d25577499206720b
|
||||
}
|
||||
ptr := v.Args[0].Args[0]
|
||||
mem := v.Args[0].Args[1]
|
||||
v.Op = OpLoad
|
||||
v.Op = OpCopy
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v.Type = ptr.Type
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
goto end459613b83f95b65729d45c2ed663a153
|
||||
end459613b83f95b65729d45c2ed663a153:
|
||||
goto end526acc0a705137a5d25577499206720b
|
||||
end526acc0a705137a5d25577499206720b:
|
||||
;
|
||||
case OpStore:
|
||||
// match: (Store [2*config.PtrSize] dst (StringMake ptr len) mem)
|
||||
// cond:
|
||||
// result: (Store [config.PtrSize] (OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] dst) len (Store <TypeMem> [config.PtrSize] dst ptr mem))
|
||||
{
|
||||
if v.AuxInt != 2*config.PtrSize {
|
||||
goto end25ae4fc3dc01583a4adc45067d49940a
|
||||
}
|
||||
dst := v.Args[0]
|
||||
if v.Args[1].Op != OpStringMake {
|
||||
goto end25ae4fc3dc01583a4adc45067d49940a
|
||||
}
|
||||
ptr := v.Args[1].Args[0]
|
||||
len := v.Args[1].Args[1]
|
||||
mem := v.Args[2]
|
||||
v.Op = OpStore
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v.AuxInt = config.PtrSize
|
||||
v0 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid)
|
||||
v0.Type = config.fe.TypeUintptr().PtrTo()
|
||||
v0.AuxInt = config.PtrSize
|
||||
v0.AddArg(dst)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(len)
|
||||
v1 := b.NewValue0(v.Line, OpStore, TypeInvalid)
|
||||
v1.Type = TypeMem
|
||||
v1.AuxInt = config.PtrSize
|
||||
v1.AddArg(dst)
|
||||
v1.AddArg(ptr)
|
||||
v1.AddArg(mem)
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
goto end25ae4fc3dc01583a4adc45067d49940a
|
||||
end25ae4fc3dc01583a4adc45067d49940a:
|
||||
;
|
||||
// match: (Store [3*config.PtrSize] dst (SliceMake ptr len cap) mem)
|
||||
// cond:
|
||||
// result: (Store [config.PtrSize] (OffPtr <config.fe.TypeUintptr().PtrTo()> [2*config.PtrSize] dst) cap (Store <TypeMem> [config.PtrSize] (OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] dst) len (Store <TypeMem> [config.PtrSize] dst ptr mem)))
|
||||
{
|
||||
if v.AuxInt != 3*config.PtrSize {
|
||||
goto end39ab85d51c8cd7f5d54e3eea4fb79a96
|
||||
}
|
||||
dst := v.Args[0]
|
||||
if v.Args[1].Op != OpSliceMake {
|
||||
goto end39ab85d51c8cd7f5d54e3eea4fb79a96
|
||||
}
|
||||
ptr := v.Args[1].Args[0]
|
||||
len := v.Args[1].Args[1]
|
||||
cap := v.Args[1].Args[2]
|
||||
mem := v.Args[2]
|
||||
v.Op = OpStore
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v.AuxInt = config.PtrSize
|
||||
v0 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid)
|
||||
v0.Type = config.fe.TypeUintptr().PtrTo()
|
||||
v0.AuxInt = 2 * config.PtrSize
|
||||
v0.AddArg(dst)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(cap)
|
||||
v1 := b.NewValue0(v.Line, OpStore, TypeInvalid)
|
||||
v1.Type = TypeMem
|
||||
v1.AuxInt = config.PtrSize
|
||||
v2 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid)
|
||||
v2.Type = config.fe.TypeUintptr().PtrTo()
|
||||
v2.AuxInt = config.PtrSize
|
||||
v2.AddArg(dst)
|
||||
v1.AddArg(v2)
|
||||
v1.AddArg(len)
|
||||
v3 := b.NewValue0(v.Line, OpStore, TypeInvalid)
|
||||
v3.Type = TypeMem
|
||||
v3.AuxInt = config.PtrSize
|
||||
v3.AddArg(dst)
|
||||
v3.AddArg(ptr)
|
||||
v3.AddArg(mem)
|
||||
v1.AddArg(v3)
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
goto end39ab85d51c8cd7f5d54e3eea4fb79a96
|
||||
end39ab85d51c8cd7f5d54e3eea4fb79a96:
|
||||
;
|
||||
// match: (Store [2*config.PtrSize] dst (IMake itab data) mem)
|
||||
// cond:
|
||||
// result: (Store [config.PtrSize] (OffPtr <config.fe.TypeBytePtr().PtrTo()> [config.PtrSize] dst) data (Store <TypeMem> [config.PtrSize] dst itab mem))
|
||||
{
|
||||
if v.AuxInt != 2*config.PtrSize {
|
||||
goto end63b77ae78d92c05d496202e8b6b96ff3
|
||||
}
|
||||
dst := v.Args[0]
|
||||
if v.Args[1].Op != OpIMake {
|
||||
goto end63b77ae78d92c05d496202e8b6b96ff3
|
||||
}
|
||||
itab := v.Args[1].Args[0]
|
||||
data := v.Args[1].Args[1]
|
||||
mem := v.Args[2]
|
||||
v.Op = OpStore
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v.AuxInt = config.PtrSize
|
||||
v0 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid)
|
||||
v0.Type = config.fe.TypeBytePtr().PtrTo()
|
||||
v0.AuxInt = config.PtrSize
|
||||
v0.AddArg(dst)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(data)
|
||||
v1 := b.NewValue0(v.Line, OpStore, TypeInvalid)
|
||||
v1.Type = TypeMem
|
||||
v1.AuxInt = config.PtrSize
|
||||
v1.AddArg(dst)
|
||||
v1.AddArg(itab)
|
||||
v1.AddArg(mem)
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
goto end63b77ae78d92c05d496202e8b6b96ff3
|
||||
end63b77ae78d92c05d496202e8b6b96ff3:
|
||||
;
|
||||
// match: (Store [size] dst (Load src mem) mem)
|
||||
// cond: size > config.IntSize
|
||||
// result: (Move [size] dst src mem)
|
||||
@ -906,48 +1169,6 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
||||
goto enda18a7163888e2f4fca9f38bae56cef42
|
||||
enda18a7163888e2f4fca9f38bae56cef42:
|
||||
;
|
||||
// match: (Store [2*config.PtrSize] dst str mem)
|
||||
// cond: str.Type.IsString()
|
||||
// result: (Store [config.PtrSize] (OffPtr <config.Frontend().TypeBytePtr()> [config.PtrSize] dst) (StringLen <config.Frontend().TypeUintptr()> str) (Store [config.PtrSize] <TypeMem> dst (StringPtr <config.Frontend().TypeBytePtr()> str) mem))
|
||||
{
|
||||
if v.AuxInt != 2*config.PtrSize {
|
||||
goto end6942df62f9cb570a99ab97a5aeebfd2d
|
||||
}
|
||||
dst := v.Args[0]
|
||||
str := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(str.Type.IsString()) {
|
||||
goto end6942df62f9cb570a99ab97a5aeebfd2d
|
||||
}
|
||||
v.Op = OpStore
|
||||
v.AuxInt = 0
|
||||
v.Aux = nil
|
||||
v.resetArgs()
|
||||
v.AuxInt = config.PtrSize
|
||||
v0 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid)
|
||||
v0.Type = config.Frontend().TypeBytePtr()
|
||||
v0.AuxInt = config.PtrSize
|
||||
v0.AddArg(dst)
|
||||
v.AddArg(v0)
|
||||
v1 := b.NewValue0(v.Line, OpStringLen, TypeInvalid)
|
||||
v1.Type = config.Frontend().TypeUintptr()
|
||||
v1.AddArg(str)
|
||||
v.AddArg(v1)
|
||||
v2 := b.NewValue0(v.Line, OpStore, TypeInvalid)
|
||||
v2.AuxInt = config.PtrSize
|
||||
v2.Type = TypeMem
|
||||
v2.AddArg(dst)
|
||||
v3 := b.NewValue0(v.Line, OpStringPtr, TypeInvalid)
|
||||
v3.Type = config.Frontend().TypeBytePtr()
|
||||
v3.AddArg(str)
|
||||
v2.AddArg(v3)
|
||||
v2.AddArg(mem)
|
||||
v.AddArg(v2)
|
||||
return true
|
||||
}
|
||||
goto end6942df62f9cb570a99ab97a5aeebfd2d
|
||||
end6942df62f9cb570a99ab97a5aeebfd2d:
|
||||
;
|
||||
case OpStringLen:
|
||||
// match: (StringLen (StringMake _ len))
|
||||
// cond:
|
||||
|
@ -18,6 +18,8 @@ type Type interface {
|
||||
IsFloat() bool
|
||||
IsPtr() bool
|
||||
IsString() bool
|
||||
IsSlice() bool
|
||||
IsInterface() bool
|
||||
|
||||
IsMemory() bool // special ssa-package-only types
|
||||
IsFlags() bool
|
||||
@ -36,19 +38,21 @@ type CompilerType struct {
|
||||
Flags bool
|
||||
}
|
||||
|
||||
func (t *CompilerType) Size() int64 { return 0 }
|
||||
func (t *CompilerType) Alignment() int64 { return 0 }
|
||||
func (t *CompilerType) IsBoolean() bool { return false }
|
||||
func (t *CompilerType) IsInteger() bool { return false }
|
||||
func (t *CompilerType) IsSigned() bool { return false }
|
||||
func (t *CompilerType) IsFloat() bool { return false }
|
||||
func (t *CompilerType) IsPtr() bool { return false }
|
||||
func (t *CompilerType) IsString() bool { return false }
|
||||
func (t *CompilerType) IsMemory() bool { return t.Memory }
|
||||
func (t *CompilerType) IsFlags() bool { return t.Flags }
|
||||
func (t *CompilerType) String() string { return t.Name }
|
||||
func (t *CompilerType) Elem() Type { panic("not implemented") }
|
||||
func (t *CompilerType) PtrTo() Type { panic("not implemented") }
|
||||
func (t *CompilerType) Size() int64 { return 0 }
|
||||
func (t *CompilerType) Alignment() int64 { return 0 }
|
||||
func (t *CompilerType) IsBoolean() bool { return false }
|
||||
func (t *CompilerType) IsInteger() bool { return false }
|
||||
func (t *CompilerType) IsSigned() bool { return false }
|
||||
func (t *CompilerType) IsFloat() bool { return false }
|
||||
func (t *CompilerType) IsPtr() bool { return false }
|
||||
func (t *CompilerType) IsString() bool { return false }
|
||||
func (t *CompilerType) IsSlice() bool { return false }
|
||||
func (t *CompilerType) IsInterface() bool { return false }
|
||||
func (t *CompilerType) IsMemory() bool { return t.Memory }
|
||||
func (t *CompilerType) IsFlags() bool { return t.Flags }
|
||||
func (t *CompilerType) String() string { return t.Name }
|
||||
func (t *CompilerType) Elem() Type { panic("not implemented") }
|
||||
func (t *CompilerType) PtrTo() Type { panic("not implemented") }
|
||||
|
||||
func (t *CompilerType) Equal(u Type) bool {
|
||||
x, ok := u.(*CompilerType)
|
||||
|
@ -14,24 +14,28 @@ type TypeImpl struct {
|
||||
Float bool
|
||||
Ptr bool
|
||||
string bool
|
||||
slice bool
|
||||
inter bool
|
||||
Elem_ Type
|
||||
|
||||
Name string
|
||||
}
|
||||
|
||||
func (t *TypeImpl) Size() int64 { return t.Size_ }
|
||||
func (t *TypeImpl) Alignment() int64 { return t.Align }
|
||||
func (t *TypeImpl) IsBoolean() bool { return t.Boolean }
|
||||
func (t *TypeImpl) IsInteger() bool { return t.Integer }
|
||||
func (t *TypeImpl) IsSigned() bool { return t.Signed }
|
||||
func (t *TypeImpl) IsFloat() bool { return t.Float }
|
||||
func (t *TypeImpl) IsPtr() bool { return t.Ptr }
|
||||
func (t *TypeImpl) IsString() bool { return t.string }
|
||||
func (t *TypeImpl) IsMemory() bool { return false }
|
||||
func (t *TypeImpl) IsFlags() bool { return false }
|
||||
func (t *TypeImpl) String() string { return t.Name }
|
||||
func (t *TypeImpl) Elem() Type { return t.Elem_ }
|
||||
func (t *TypeImpl) PtrTo() Type { panic("not implemented") }
|
||||
func (t *TypeImpl) Size() int64 { return t.Size_ }
|
||||
func (t *TypeImpl) Alignment() int64 { return t.Align }
|
||||
func (t *TypeImpl) IsBoolean() bool { return t.Boolean }
|
||||
func (t *TypeImpl) IsInteger() bool { return t.Integer }
|
||||
func (t *TypeImpl) IsSigned() bool { return t.Signed }
|
||||
func (t *TypeImpl) IsFloat() bool { return t.Float }
|
||||
func (t *TypeImpl) IsPtr() bool { return t.Ptr }
|
||||
func (t *TypeImpl) IsString() bool { return t.string }
|
||||
func (t *TypeImpl) IsSlice() bool { return t.slice }
|
||||
func (t *TypeImpl) IsInterface() bool { return t.inter }
|
||||
func (t *TypeImpl) IsMemory() bool { return false }
|
||||
func (t *TypeImpl) IsFlags() bool { return false }
|
||||
func (t *TypeImpl) String() string { return t.Name }
|
||||
func (t *TypeImpl) Elem() Type { return t.Elem_ }
|
||||
func (t *TypeImpl) PtrTo() Type { panic("not implemented") }
|
||||
|
||||
func (t *TypeImpl) Equal(u Type) bool {
|
||||
x, ok := u.(*TypeImpl)
|
||||
|
Loading…
Reference in New Issue
Block a user