blob: 3ef20ef34fae2c68fa0534548b7a802209f6d1bf [file] [log] [blame]
// 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.IsComplex():
decomposeComplexPhi(v)
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 decomposeComplexPhi(v *Value) {
fe := v.Block.Func.Config.fe
var partType Type
switch z := v.Type.Size(); z {
case 8:
partType = fe.TypeFloat32()
case 16:
partType = fe.TypeFloat64()
default:
v.Fatalf("decomposeComplexPhi: bad complex size %d", z)
}
real := v.Block.NewValue0(v.Line, OpPhi, partType)
imag := v.Block.NewValue0(v.Line, OpPhi, partType)
for _, a := range v.Args {
real.AddArg(a.Block.NewValue1(v.Line, OpComplexReal, partType, a))
imag.AddArg(a.Block.NewValue1(v.Line, OpComplexImag, partType, a))
}
v.Op = OpComplexMake
v.AuxInt = 0
v.Aux = nil
v.resetArgs()
v.AddArg(real)
v.AddArg(imag)
}
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
}