github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/cmd/compile/internal/ssa/decompose.go (about)

     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.IsComplex():
    29  			var elemType Type
    30  			if t.Size() == 16 {
    31  				elemType = f.Config.fe.TypeFloat64()
    32  			} else {
    33  				elemType = f.Config.fe.TypeFloat32()
    34  			}
    35  			rName, iName := f.Config.fe.SplitComplex(name)
    36  			newNames = append(newNames, rName, iName)
    37  			for _, v := range f.NamedValues[name] {
    38  				r := v.Block.NewValue1(v.Line, OpComplexReal, elemType, v)
    39  				i := v.Block.NewValue1(v.Line, OpComplexImag, elemType, v)
    40  				f.NamedValues[rName] = append(f.NamedValues[rName], r)
    41  				f.NamedValues[iName] = append(f.NamedValues[iName], i)
    42  			}
    43  			delete(f.NamedValues, name)
    44  		case t.IsString():
    45  			ptrType := f.Config.fe.TypeBytePtr()
    46  			lenType := f.Config.fe.TypeInt()
    47  			ptrName, lenName := f.Config.fe.SplitString(name)
    48  			newNames = append(newNames, ptrName, lenName)
    49  			for _, v := range f.NamedValues[name] {
    50  				ptr := v.Block.NewValue1(v.Line, OpStringPtr, ptrType, v)
    51  				len := v.Block.NewValue1(v.Line, OpStringLen, lenType, v)
    52  				f.NamedValues[ptrName] = append(f.NamedValues[ptrName], ptr)
    53  				f.NamedValues[lenName] = append(f.NamedValues[lenName], len)
    54  			}
    55  			delete(f.NamedValues, name)
    56  		case t.IsSlice():
    57  			ptrType := f.Config.fe.TypeBytePtr()
    58  			lenType := f.Config.fe.TypeInt()
    59  			ptrName, lenName, capName := f.Config.fe.SplitSlice(name)
    60  			newNames = append(newNames, ptrName, lenName, capName)
    61  			for _, v := range f.NamedValues[name] {
    62  				ptr := v.Block.NewValue1(v.Line, OpSlicePtr, ptrType, v)
    63  				len := v.Block.NewValue1(v.Line, OpSliceLen, lenType, v)
    64  				cap := v.Block.NewValue1(v.Line, OpSliceCap, lenType, v)
    65  				f.NamedValues[ptrName] = append(f.NamedValues[ptrName], ptr)
    66  				f.NamedValues[lenName] = append(f.NamedValues[lenName], len)
    67  				f.NamedValues[capName] = append(f.NamedValues[capName], cap)
    68  			}
    69  			delete(f.NamedValues, name)
    70  		case t.IsInterface():
    71  			ptrType := f.Config.fe.TypeBytePtr()
    72  			typeName, dataName := f.Config.fe.SplitInterface(name)
    73  			newNames = append(newNames, typeName, dataName)
    74  			for _, v := range f.NamedValues[name] {
    75  				typ := v.Block.NewValue1(v.Line, OpITab, ptrType, v)
    76  				data := v.Block.NewValue1(v.Line, OpIData, ptrType, v)
    77  				f.NamedValues[typeName] = append(f.NamedValues[typeName], typ)
    78  				f.NamedValues[dataName] = append(f.NamedValues[dataName], data)
    79  			}
    80  			delete(f.NamedValues, name)
    81  		case t.Size() > f.Config.IntSize:
    82  			f.Unimplementedf("undecomposed named type %s %s", name, t)
    83  		default:
    84  			newNames = append(newNames, name)
    85  		}
    86  	}
    87  	f.Names = newNames
    88  }
    89  
    90  func decomposeBuiltInPhi(v *Value) {
    91  	// TODO: decompose 64-bit ops on 32-bit archs?
    92  	switch {
    93  	case v.Type.IsComplex():
    94  		decomposeComplexPhi(v)
    95  	case v.Type.IsString():
    96  		decomposeStringPhi(v)
    97  	case v.Type.IsSlice():
    98  		decomposeSlicePhi(v)
    99  	case v.Type.IsInterface():
   100  		decomposeInterfacePhi(v)
   101  	case v.Type.Size() > v.Block.Func.Config.IntSize:
   102  		v.Unimplementedf("undecomposed type %s", v.Type)
   103  	}
   104  }
   105  
   106  func decomposeStringPhi(v *Value) {
   107  	fe := v.Block.Func.Config.fe
   108  	ptrType := fe.TypeBytePtr()
   109  	lenType := fe.TypeInt()
   110  
   111  	ptr := v.Block.NewValue0(v.Line, OpPhi, ptrType)
   112  	len := v.Block.NewValue0(v.Line, OpPhi, lenType)
   113  	for _, a := range v.Args {
   114  		ptr.AddArg(a.Block.NewValue1(v.Line, OpStringPtr, ptrType, a))
   115  		len.AddArg(a.Block.NewValue1(v.Line, OpStringLen, lenType, a))
   116  	}
   117  	v.reset(OpStringMake)
   118  	v.AddArg(ptr)
   119  	v.AddArg(len)
   120  }
   121  
   122  func decomposeSlicePhi(v *Value) {
   123  	fe := v.Block.Func.Config.fe
   124  	ptrType := fe.TypeBytePtr()
   125  	lenType := fe.TypeInt()
   126  
   127  	ptr := v.Block.NewValue0(v.Line, OpPhi, ptrType)
   128  	len := v.Block.NewValue0(v.Line, OpPhi, lenType)
   129  	cap := v.Block.NewValue0(v.Line, OpPhi, lenType)
   130  	for _, a := range v.Args {
   131  		ptr.AddArg(a.Block.NewValue1(v.Line, OpSlicePtr, ptrType, a))
   132  		len.AddArg(a.Block.NewValue1(v.Line, OpSliceLen, lenType, a))
   133  		cap.AddArg(a.Block.NewValue1(v.Line, OpSliceCap, lenType, a))
   134  	}
   135  	v.reset(OpSliceMake)
   136  	v.AddArg(ptr)
   137  	v.AddArg(len)
   138  	v.AddArg(cap)
   139  }
   140  
   141  func decomposeComplexPhi(v *Value) {
   142  	fe := v.Block.Func.Config.fe
   143  	var partType Type
   144  	switch z := v.Type.Size(); z {
   145  	case 8:
   146  		partType = fe.TypeFloat32()
   147  	case 16:
   148  		partType = fe.TypeFloat64()
   149  	default:
   150  		v.Fatalf("decomposeComplexPhi: bad complex size %d", z)
   151  	}
   152  
   153  	real := v.Block.NewValue0(v.Line, OpPhi, partType)
   154  	imag := v.Block.NewValue0(v.Line, OpPhi, partType)
   155  	for _, a := range v.Args {
   156  		real.AddArg(a.Block.NewValue1(v.Line, OpComplexReal, partType, a))
   157  		imag.AddArg(a.Block.NewValue1(v.Line, OpComplexImag, partType, a))
   158  	}
   159  	v.reset(OpComplexMake)
   160  	v.AddArg(real)
   161  	v.AddArg(imag)
   162  }
   163  
   164  func decomposeInterfacePhi(v *Value) {
   165  	ptrType := v.Block.Func.Config.fe.TypeBytePtr()
   166  
   167  	itab := v.Block.NewValue0(v.Line, OpPhi, ptrType)
   168  	data := v.Block.NewValue0(v.Line, OpPhi, ptrType)
   169  	for _, a := range v.Args {
   170  		itab.AddArg(a.Block.NewValue1(v.Line, OpITab, ptrType, a))
   171  		data.AddArg(a.Block.NewValue1(v.Line, OpIData, ptrType, a))
   172  	}
   173  	v.reset(OpIMake)
   174  	v.AddArg(itab)
   175  	v.AddArg(data)
   176  }
   177  
   178  func decomposeUser(f *Func) {
   179  	for _, b := range f.Blocks {
   180  		for _, v := range b.Values {
   181  			if v.Op != OpPhi {
   182  				continue
   183  			}
   184  			decomposeUserPhi(v)
   185  		}
   186  	}
   187  	// Split up named values into their components.
   188  	// NOTE: the component values we are making are dead at this point.
   189  	// We must do the opt pass before any deadcode elimination or we will
   190  	// lose the name->value correspondence.
   191  	i := 0
   192  	var fnames []LocalSlot
   193  	var newNames []LocalSlot
   194  	for _, name := range f.Names {
   195  		t := name.Type
   196  		switch {
   197  		case t.IsStruct():
   198  			n := t.NumFields()
   199  			fnames = fnames[:0]
   200  			for i := 0; i < n; i++ {
   201  				fnames = append(fnames, f.Config.fe.SplitStruct(name, i))
   202  			}
   203  			for _, v := range f.NamedValues[name] {
   204  				for i := 0; i < n; i++ {
   205  					x := v.Block.NewValue1I(v.Line, OpStructSelect, t.FieldType(i), int64(i), v)
   206  					f.NamedValues[fnames[i]] = append(f.NamedValues[fnames[i]], x)
   207  				}
   208  			}
   209  			delete(f.NamedValues, name)
   210  			newNames = append(newNames, fnames...)
   211  		default:
   212  			f.Names[i] = name
   213  			i++
   214  		}
   215  	}
   216  	f.Names = f.Names[:i]
   217  	f.Names = append(f.Names, newNames...)
   218  }
   219  
   220  func decomposeUserPhi(v *Value) {
   221  	switch {
   222  	case v.Type.IsStruct():
   223  		decomposeStructPhi(v)
   224  	}
   225  	// TODO: Arrays of length 1?
   226  }
   227  
   228  func decomposeStructPhi(v *Value) {
   229  	t := v.Type
   230  	n := t.NumFields()
   231  	var fields [MaxStruct]*Value
   232  	for i := 0; i < n; i++ {
   233  		fields[i] = v.Block.NewValue0(v.Line, OpPhi, t.FieldType(i))
   234  	}
   235  	for _, a := range v.Args {
   236  		for i := 0; i < n; i++ {
   237  			fields[i].AddArg(a.Block.NewValue1I(v.Line, OpStructSelect, t.FieldType(i), int64(i), a))
   238  		}
   239  	}
   240  	v.reset(StructMakeOp(n))
   241  	v.AddArgs(fields[:n]...)
   242  
   243  	// Recursively decompose phis for each field.
   244  	for _, f := range fields[:n] {
   245  		if f.Type.IsStruct() {
   246  			decomposeStructPhi(f)
   247  		}
   248  	}
   249  }
   250  
   251  // MaxStruct is the maximum number of fields a struct
   252  // can have and still be SSAable.
   253  const MaxStruct = 4
   254  
   255  // StructMakeOp returns the opcode to construct a struct with the
   256  // given number of fields.
   257  func StructMakeOp(nf int) Op {
   258  	switch nf {
   259  	case 0:
   260  		return OpStructMake0
   261  	case 1:
   262  		return OpStructMake1
   263  	case 2:
   264  		return OpStructMake2
   265  	case 3:
   266  		return OpStructMake3
   267  	case 4:
   268  		return OpStructMake4
   269  	}
   270  	panic("too many fields in an SSAable struct")
   271  }