1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ssa 6 7 // decompose converts phi ops on compound builtin types into phi 8 // ops on simple types. 9 // (The remaining compound ops are decomposed with rewrite rules.) 10 func decomposeBuiltIn(f *Func) { 11 for _, b := range f.Blocks { 12 for _, v := range b.Values { 13 if v.Op != OpPhi { 14 continue 15 } 16 decomposeBuiltInPhi(v) 17 } 18 } 19 20 // Split up named values into their components. 21 // NOTE: the component values we are making are dead at this point. 22 // We must do the opt pass before any deadcode elimination or we will 23 // lose the name->value correspondence. 24 var newNames []LocalSlot 25 for _, name := range f.Names { 26 t := name.Type 27 switch { 28 case t.IsInteger() && t.Size() == 8 && f.Config.IntSize == 4: 29 var elemType Type 30 if t.IsSigned() { 31 elemType = f.Config.fe.TypeInt32() 32 } else { 33 elemType = f.Config.fe.TypeUInt32() 34 } 35 hiName, loName := f.Config.fe.SplitInt64(name) 36 newNames = append(newNames, hiName, loName) 37 for _, v := range f.NamedValues[name] { 38 hi := v.Block.NewValue1(v.Line, OpInt64Hi, elemType, v) 39 lo := v.Block.NewValue1(v.Line, OpInt64Lo, f.Config.fe.TypeUInt32(), v) 40 f.NamedValues[hiName] = append(f.NamedValues[hiName], hi) 41 f.NamedValues[loName] = append(f.NamedValues[loName], lo) 42 } 43 delete(f.NamedValues, name) 44 case t.IsComplex(): 45 var elemType Type 46 if t.Size() == 16 { 47 elemType = f.Config.fe.TypeFloat64() 48 } else { 49 elemType = f.Config.fe.TypeFloat32() 50 } 51 rName, iName := f.Config.fe.SplitComplex(name) 52 newNames = append(newNames, rName, iName) 53 for _, v := range f.NamedValues[name] { 54 r := v.Block.NewValue1(v.Line, OpComplexReal, elemType, v) 55 i := v.Block.NewValue1(v.Line, OpComplexImag, elemType, v) 56 f.NamedValues[rName] = append(f.NamedValues[rName], r) 57 f.NamedValues[iName] = append(f.NamedValues[iName], i) 58 } 59 delete(f.NamedValues, name) 60 case t.IsString(): 61 ptrType := f.Config.fe.TypeBytePtr() 62 lenType := f.Config.fe.TypeInt() 63 ptrName, lenName := f.Config.fe.SplitString(name) 64 newNames = append(newNames, ptrName, lenName) 65 for _, v := range f.NamedValues[name] { 66 ptr := v.Block.NewValue1(v.Line, OpStringPtr, ptrType, v) 67 len := v.Block.NewValue1(v.Line, OpStringLen, lenType, v) 68 f.NamedValues[ptrName] = append(f.NamedValues[ptrName], ptr) 69 f.NamedValues[lenName] = append(f.NamedValues[lenName], len) 70 } 71 delete(f.NamedValues, name) 72 case t.IsSlice(): 73 ptrType := f.Config.fe.TypeBytePtr() 74 lenType := f.Config.fe.TypeInt() 75 ptrName, lenName, capName := f.Config.fe.SplitSlice(name) 76 newNames = append(newNames, ptrName, lenName, capName) 77 for _, v := range f.NamedValues[name] { 78 ptr := v.Block.NewValue1(v.Line, OpSlicePtr, ptrType, v) 79 len := v.Block.NewValue1(v.Line, OpSliceLen, lenType, v) 80 cap := v.Block.NewValue1(v.Line, OpSliceCap, lenType, v) 81 f.NamedValues[ptrName] = append(f.NamedValues[ptrName], ptr) 82 f.NamedValues[lenName] = append(f.NamedValues[lenName], len) 83 f.NamedValues[capName] = append(f.NamedValues[capName], cap) 84 } 85 delete(f.NamedValues, name) 86 case t.IsInterface(): 87 ptrType := f.Config.fe.TypeBytePtr() 88 typeName, dataName := f.Config.fe.SplitInterface(name) 89 newNames = append(newNames, typeName, dataName) 90 for _, v := range f.NamedValues[name] { 91 typ := v.Block.NewValue1(v.Line, OpITab, ptrType, v) 92 data := v.Block.NewValue1(v.Line, OpIData, ptrType, v) 93 f.NamedValues[typeName] = append(f.NamedValues[typeName], typ) 94 f.NamedValues[dataName] = append(f.NamedValues[dataName], data) 95 } 96 delete(f.NamedValues, name) 97 case t.IsFloat(): 98 // floats are never decomposed, even ones bigger than IntSize 99 case t.Size() > f.Config.IntSize: 100 f.Fatalf("undecomposed named type %v %v", name, t) 101 default: 102 newNames = append(newNames, name) 103 } 104 } 105 f.Names = newNames 106 } 107 108 func decomposeBuiltInPhi(v *Value) { 109 switch { 110 case v.Type.IsInteger() && v.Type.Size() == 8 && v.Block.Func.Config.IntSize == 4: 111 if v.Block.Func.Config.arch == "amd64p32" { 112 // Even though ints are 32 bits, we have 64-bit ops. 113 break 114 } 115 decomposeInt64Phi(v) 116 case v.Type.IsComplex(): 117 decomposeComplexPhi(v) 118 case v.Type.IsString(): 119 decomposeStringPhi(v) 120 case v.Type.IsSlice(): 121 decomposeSlicePhi(v) 122 case v.Type.IsInterface(): 123 decomposeInterfacePhi(v) 124 case v.Type.IsFloat(): 125 // floats are never decomposed, even ones bigger than IntSize 126 case v.Type.Size() > v.Block.Func.Config.IntSize: 127 v.Fatalf("undecomposed type %s", v.Type) 128 } 129 } 130 131 func decomposeStringPhi(v *Value) { 132 fe := v.Block.Func.Config.fe 133 ptrType := fe.TypeBytePtr() 134 lenType := fe.TypeInt() 135 136 ptr := v.Block.NewValue0(v.Line, OpPhi, ptrType) 137 len := v.Block.NewValue0(v.Line, OpPhi, lenType) 138 for _, a := range v.Args { 139 ptr.AddArg(a.Block.NewValue1(v.Line, OpStringPtr, ptrType, a)) 140 len.AddArg(a.Block.NewValue1(v.Line, OpStringLen, lenType, a)) 141 } 142 v.reset(OpStringMake) 143 v.AddArg(ptr) 144 v.AddArg(len) 145 } 146 147 func decomposeSlicePhi(v *Value) { 148 fe := v.Block.Func.Config.fe 149 ptrType := fe.TypeBytePtr() 150 lenType := fe.TypeInt() 151 152 ptr := v.Block.NewValue0(v.Line, OpPhi, ptrType) 153 len := v.Block.NewValue0(v.Line, OpPhi, lenType) 154 cap := v.Block.NewValue0(v.Line, OpPhi, lenType) 155 for _, a := range v.Args { 156 ptr.AddArg(a.Block.NewValue1(v.Line, OpSlicePtr, ptrType, a)) 157 len.AddArg(a.Block.NewValue1(v.Line, OpSliceLen, lenType, a)) 158 cap.AddArg(a.Block.NewValue1(v.Line, OpSliceCap, lenType, a)) 159 } 160 v.reset(OpSliceMake) 161 v.AddArg(ptr) 162 v.AddArg(len) 163 v.AddArg(cap) 164 } 165 166 func decomposeInt64Phi(v *Value) { 167 fe := v.Block.Func.Config.fe 168 var partType Type 169 if v.Type.IsSigned() { 170 partType = fe.TypeInt32() 171 } else { 172 partType = fe.TypeUInt32() 173 } 174 175 hi := v.Block.NewValue0(v.Line, OpPhi, partType) 176 lo := v.Block.NewValue0(v.Line, OpPhi, fe.TypeUInt32()) 177 for _, a := range v.Args { 178 hi.AddArg(a.Block.NewValue1(v.Line, OpInt64Hi, partType, a)) 179 lo.AddArg(a.Block.NewValue1(v.Line, OpInt64Lo, fe.TypeUInt32(), a)) 180 } 181 v.reset(OpInt64Make) 182 v.AddArg(hi) 183 v.AddArg(lo) 184 } 185 186 func decomposeComplexPhi(v *Value) { 187 fe := v.Block.Func.Config.fe 188 var partType Type 189 switch z := v.Type.Size(); z { 190 case 8: 191 partType = fe.TypeFloat32() 192 case 16: 193 partType = fe.TypeFloat64() 194 default: 195 v.Fatalf("decomposeComplexPhi: bad complex size %d", z) 196 } 197 198 real := v.Block.NewValue0(v.Line, OpPhi, partType) 199 imag := v.Block.NewValue0(v.Line, OpPhi, partType) 200 for _, a := range v.Args { 201 real.AddArg(a.Block.NewValue1(v.Line, OpComplexReal, partType, a)) 202 imag.AddArg(a.Block.NewValue1(v.Line, OpComplexImag, partType, a)) 203 } 204 v.reset(OpComplexMake) 205 v.AddArg(real) 206 v.AddArg(imag) 207 } 208 209 func decomposeInterfacePhi(v *Value) { 210 ptrType := v.Block.Func.Config.fe.TypeBytePtr() 211 212 itab := v.Block.NewValue0(v.Line, OpPhi, ptrType) 213 data := v.Block.NewValue0(v.Line, OpPhi, ptrType) 214 for _, a := range v.Args { 215 itab.AddArg(a.Block.NewValue1(v.Line, OpITab, ptrType, a)) 216 data.AddArg(a.Block.NewValue1(v.Line, OpIData, ptrType, a)) 217 } 218 v.reset(OpIMake) 219 v.AddArg(itab) 220 v.AddArg(data) 221 } 222 223 func decomposeUser(f *Func) { 224 for _, b := range f.Blocks { 225 for _, v := range b.Values { 226 if v.Op != OpPhi { 227 continue 228 } 229 decomposeUserPhi(v) 230 } 231 } 232 // Split up named values into their components. 233 // NOTE: the component values we are making are dead at this point. 234 // We must do the opt pass before any deadcode elimination or we will 235 // lose the name->value correspondence. 236 i := 0 237 var fnames []LocalSlot 238 var newNames []LocalSlot 239 for _, name := range f.Names { 240 t := name.Type 241 switch { 242 case t.IsStruct(): 243 n := t.NumFields() 244 fnames = fnames[:0] 245 for i := 0; i < n; i++ { 246 fnames = append(fnames, f.Config.fe.SplitStruct(name, i)) 247 } 248 for _, v := range f.NamedValues[name] { 249 for i := 0; i < n; i++ { 250 x := v.Block.NewValue1I(v.Line, OpStructSelect, t.FieldType(i), int64(i), v) 251 f.NamedValues[fnames[i]] = append(f.NamedValues[fnames[i]], x) 252 } 253 } 254 delete(f.NamedValues, name) 255 newNames = append(newNames, fnames...) 256 case t.IsArray(): 257 if t.NumElem() == 0 { 258 // TODO(khr): Not sure what to do here. Probably nothing. 259 // Names for empty arrays aren't important. 260 break 261 } 262 if t.NumElem() != 1 { 263 f.Fatalf("array not of size 1") 264 } 265 elemName := f.Config.fe.SplitArray(name) 266 for _, v := range f.NamedValues[name] { 267 e := v.Block.NewValue1I(v.Line, OpArraySelect, t.ElemType(), 0, v) 268 f.NamedValues[elemName] = append(f.NamedValues[elemName], e) 269 } 270 271 default: 272 f.Names[i] = name 273 i++ 274 } 275 } 276 f.Names = f.Names[:i] 277 f.Names = append(f.Names, newNames...) 278 } 279 280 func decomposeUserPhi(v *Value) { 281 switch { 282 case v.Type.IsStruct(): 283 decomposeStructPhi(v) 284 case v.Type.IsArray(): 285 decomposeArrayPhi(v) 286 } 287 } 288 289 // decomposeStructPhi replaces phi-of-struct with structmake(phi-for-each-field), 290 // and then recursively decomposes the phis for each field. 291 func decomposeStructPhi(v *Value) { 292 t := v.Type 293 n := t.NumFields() 294 var fields [MaxStruct]*Value 295 for i := 0; i < n; i++ { 296 fields[i] = v.Block.NewValue0(v.Line, OpPhi, t.FieldType(i)) 297 } 298 for _, a := range v.Args { 299 for i := 0; i < n; i++ { 300 fields[i].AddArg(a.Block.NewValue1I(v.Line, OpStructSelect, t.FieldType(i), int64(i), a)) 301 } 302 } 303 v.reset(StructMakeOp(n)) 304 v.AddArgs(fields[:n]...) 305 306 // Recursively decompose phis for each field. 307 for _, f := range fields[:n] { 308 decomposeUserPhi(f) 309 } 310 } 311 312 // decomposeArrayPhi replaces phi-of-array with arraymake(phi-of-array-element), 313 // and then recursively decomposes the element phi. 314 func decomposeArrayPhi(v *Value) { 315 t := v.Type 316 if t.NumElem() == 0 { 317 v.reset(OpArrayMake0) 318 return 319 } 320 if t.NumElem() != 1 { 321 v.Fatalf("SSAable array must have no more than 1 element") 322 } 323 elem := v.Block.NewValue0(v.Line, OpPhi, t.ElemType()) 324 for _, a := range v.Args { 325 elem.AddArg(a.Block.NewValue1I(v.Line, OpArraySelect, t.ElemType(), 0, a)) 326 } 327 v.reset(OpArrayMake1) 328 v.AddArg(elem) 329 330 // Recursively decompose elem phi. 331 decomposeUserPhi(elem) 332 } 333 334 // MaxStruct is the maximum number of fields a struct 335 // can have and still be SSAable. 336 const MaxStruct = 4 337 338 // StructMakeOp returns the opcode to construct a struct with the 339 // given number of fields. 340 func StructMakeOp(nf int) Op { 341 switch nf { 342 case 0: 343 return OpStructMake0 344 case 1: 345 return OpStructMake1 346 case 2: 347 return OpStructMake2 348 case 3: 349 return OpStructMake3 350 case 4: 351 return OpStructMake4 352 } 353 panic("too many fields in an SSAable struct") 354 } 355