mirror of
https://github.com/golang/go.git
synced 2025-05-29 03:11:26 +00:00
[dev.ssa] cmd/compile/internal/ssa: implement ODOT
Implement ODOT. Similar to ArrayIndex, StructSelect selects a field out of a larger Value. We may need more ways to rewrite StructSelect, but StructSelect/Load is the typical way it is used. Change-Id: Ida7b8aab3298f4754eaf9fee733974cf8736e45d Reviewed-on: https://go-review.googlesource.com/12265 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
078ba138d3
commit
cd7e059496
@ -226,6 +226,11 @@ func (s *state) newValue1A(op ssa.Op, t ssa.Type, aux interface{}, arg *ssa.Valu
|
|||||||
return s.curBlock.NewValue1A(s.peekLine(), op, t, aux, arg)
|
return s.curBlock.NewValue1A(s.peekLine(), op, t, aux, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newValue1I adds a new value with one argument and an auxint value to the current block.
|
||||||
|
func (s *state) newValue1I(op ssa.Op, t ssa.Type, aux int64, arg *ssa.Value) *ssa.Value {
|
||||||
|
return s.curBlock.NewValue1I(s.peekLine(), op, t, aux, arg)
|
||||||
|
}
|
||||||
|
|
||||||
// newValue2 adds a new value with two arguments to the current block.
|
// newValue2 adds a new value with two arguments to the current block.
|
||||||
func (s *state) newValue2(op ssa.Op, t ssa.Type, arg0, arg1 *ssa.Value) *ssa.Value {
|
func (s *state) newValue2(op ssa.Op, t ssa.Type, arg0, arg1 *ssa.Value) *ssa.Value {
|
||||||
return s.curBlock.NewValue2(s.peekLine(), op, t, arg0, arg1)
|
return s.curBlock.NewValue2(s.peekLine(), op, t, arg0, arg1)
|
||||||
@ -556,6 +561,10 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||||||
s.nilCheck(p)
|
s.nilCheck(p)
|
||||||
return s.newValue2(ssa.OpLoad, n.Type, p, s.mem())
|
return s.newValue2(ssa.OpLoad, n.Type, p, s.mem())
|
||||||
|
|
||||||
|
case ODOT:
|
||||||
|
v := s.expr(n.Left)
|
||||||
|
return s.newValue1I(ssa.OpStructSelect, n.Type, n.Xoffset, v)
|
||||||
|
|
||||||
case ODOTPTR:
|
case ODOTPTR:
|
||||||
p := s.expr(n.Left)
|
p := s.expr(n.Left)
|
||||||
s.nilCheck(p)
|
s.nilCheck(p)
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
// Note: bounds check has already been done
|
// Note: bounds check has already been done
|
||||||
(ArrayIndex (Load ptr mem) idx) -> (Load (PtrIndex <v.Type.PtrTo()> ptr idx) mem)
|
(ArrayIndex (Load ptr mem) idx) -> (Load (PtrIndex <v.Type.PtrTo()> ptr idx) mem)
|
||||||
(PtrIndex <t> ptr idx) -> (Add ptr (Mul <config.Uintptr> idx (Const <config.Uintptr> [t.Elem().Size()])))
|
(PtrIndex <t> ptr idx) -> (Add ptr (Mul <config.Uintptr> idx (Const <config.Uintptr> [t.Elem().Size()])))
|
||||||
|
(StructSelect [idx] (Load ptr mem)) -> (Load (OffPtr <v.Type.PtrTo()> [idx] ptr) mem)
|
||||||
|
|
||||||
// big-object moves
|
// big-object moves
|
||||||
// TODO: fix size
|
// TODO: fix size
|
||||||
|
@ -71,9 +71,10 @@ var genericOps = []opData{
|
|||||||
{name: "IsInBounds"}, // 0 <= arg0 < arg1
|
{name: "IsInBounds"}, // 0 <= arg0 < arg1
|
||||||
|
|
||||||
// Indexing operations
|
// Indexing operations
|
||||||
{name: "ArrayIndex"}, // arg0=array, arg1=index. Returns a[i]
|
{name: "ArrayIndex"}, // arg0=array, arg1=index. Returns a[i]
|
||||||
{name: "PtrIndex"}, // arg0=ptr, arg1=index. Computes ptr+sizeof(*v.type)*index, where index is extended to ptrwidth type
|
{name: "PtrIndex"}, // arg0=ptr, arg1=index. Computes ptr+sizeof(*v.type)*index, where index is extended to ptrwidth type
|
||||||
{name: "OffPtr"}, // arg0 + auxint (arg0 and result are pointers)
|
{name: "OffPtr"}, // arg0 + auxint (arg0 and result are pointers)
|
||||||
|
{name: "StructSelect"}, // arg0=struct, auxint=field offset. Returns field at that offset (size=size of result type)
|
||||||
|
|
||||||
// Slices
|
// Slices
|
||||||
{name: "SliceMake"}, // arg0=ptr, arg1=len, arg2=cap
|
{name: "SliceMake"}, // arg0=ptr, arg1=len, arg2=cap
|
||||||
|
@ -146,6 +146,7 @@ const (
|
|||||||
OpArrayIndex
|
OpArrayIndex
|
||||||
OpPtrIndex
|
OpPtrIndex
|
||||||
OpOffPtr
|
OpOffPtr
|
||||||
|
OpStructSelect
|
||||||
OpSliceMake
|
OpSliceMake
|
||||||
OpSlicePtr
|
OpSlicePtr
|
||||||
OpSliceLen
|
OpSliceLen
|
||||||
@ -1232,6 +1233,15 @@ var opcodeTable = [...]opInfo{
|
|||||||
},
|
},
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "StructSelect",
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []regMask{},
|
||||||
|
clobbers: 0,
|
||||||
|
outputs: []regMask{},
|
||||||
|
},
|
||||||
|
generic: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "SliceMake",
|
name: "SliceMake",
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
|
@ -383,6 +383,32 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
|||||||
}
|
}
|
||||||
goto end061edc5d85c73ad909089af2556d9380
|
goto end061edc5d85c73ad909089af2556d9380
|
||||||
end061edc5d85c73ad909089af2556d9380:
|
end061edc5d85c73ad909089af2556d9380:
|
||||||
|
;
|
||||||
|
case OpStructSelect:
|
||||||
|
// match: (StructSelect [idx] (Load ptr mem))
|
||||||
|
// cond:
|
||||||
|
// result: (Load (OffPtr <v.Type.PtrTo()> [idx] ptr) mem)
|
||||||
|
{
|
||||||
|
idx := v.AuxInt
|
||||||
|
if v.Args[0].Op != OpLoad {
|
||||||
|
goto end16fdb45e1dd08feb36e3cc3fb5ed8935
|
||||||
|
}
|
||||||
|
ptr := v.Args[0].Args[0]
|
||||||
|
mem := v.Args[0].Args[1]
|
||||||
|
v.Op = OpLoad
|
||||||
|
v.AuxInt = 0
|
||||||
|
v.Aux = nil
|
||||||
|
v.resetArgs()
|
||||||
|
v0 := v.Block.NewValue0(v.Line, OpOffPtr, TypeInvalid)
|
||||||
|
v0.Type = v.Type.PtrTo()
|
||||||
|
v0.AuxInt = idx
|
||||||
|
v0.AddArg(ptr)
|
||||||
|
v.AddArg(v0)
|
||||||
|
v.AddArg(mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
goto end16fdb45e1dd08feb36e3cc3fb5ed8935
|
||||||
|
end16fdb45e1dd08feb36e3cc3fb5ed8935:
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user