| // Copyright 2016 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. |
| |
| // This file contains rules to decompose builtin compound types |
| // (complex,string,slice,interface) into their constituent |
| // types. These rules work together with the decomposeBuiltIn |
| // pass which handles phis of these types. |
| |
| (Store {t} _ _ mem) && t.Size() == 0 => mem |
| |
| // complex ops |
| (ComplexReal (ComplexMake real _ )) => real |
| (ComplexImag (ComplexMake _ imag )) => imag |
| |
| (Load <t> ptr mem) && t.IsComplex() && t.Size() == 8 => |
| (ComplexMake |
| (Load <typ.Float32> ptr mem) |
| (Load <typ.Float32> |
| (OffPtr <typ.Float32Ptr> [4] ptr) |
| mem) |
| ) |
| (Store {t} dst (ComplexMake real imag) mem) && t.Size() == 8 => |
| (Store {typ.Float32} |
| (OffPtr <typ.Float32Ptr> [4] dst) |
| imag |
| (Store {typ.Float32} dst real mem)) |
| (Load <t> ptr mem) && t.IsComplex() && t.Size() == 16 => |
| (ComplexMake |
| (Load <typ.Float64> ptr mem) |
| (Load <typ.Float64> |
| (OffPtr <typ.Float64Ptr> [8] ptr) |
| mem) |
| ) |
| (Store {t} dst (ComplexMake real imag) mem) && t.Size() == 16 => |
| (Store {typ.Float64} |
| (OffPtr <typ.Float64Ptr> [8] dst) |
| imag |
| (Store {typ.Float64} dst real mem)) |
| |
| // string ops |
| (StringPtr (StringMake ptr _)) => ptr |
| (StringLen (StringMake _ len)) => len |
| |
| (Load <t> ptr mem) && t.IsString() => |
| (StringMake |
| (Load <typ.BytePtr> ptr mem) |
| (Load <typ.Int> |
| (OffPtr <typ.IntPtr> [config.PtrSize] ptr) |
| mem)) |
| (Store dst (StringMake ptr len) mem) => |
| (Store {typ.Int} |
| (OffPtr <typ.IntPtr> [config.PtrSize] dst) |
| len |
| (Store {typ.BytePtr} dst ptr mem)) |
| |
| // slice ops |
| (SlicePtr (SliceMake ptr _ _ )) => ptr |
| (SliceLen (SliceMake _ len _)) => len |
| (SliceCap (SliceMake _ _ cap)) => cap |
| (SlicePtrUnchecked (SliceMake ptr _ _ )) => ptr |
| |
| (Load <t> ptr mem) && t.IsSlice() => |
| (SliceMake |
| (Load <t.Elem().PtrTo()> ptr mem) |
| (Load <typ.Int> |
| (OffPtr <typ.IntPtr> [config.PtrSize] ptr) |
| mem) |
| (Load <typ.Int> |
| (OffPtr <typ.IntPtr> [2*config.PtrSize] ptr) |
| mem)) |
| (Store {t} dst (SliceMake ptr len cap) mem) => |
| (Store {typ.Int} |
| (OffPtr <typ.IntPtr> [2*config.PtrSize] dst) |
| cap |
| (Store {typ.Int} |
| (OffPtr <typ.IntPtr> [config.PtrSize] dst) |
| len |
| (Store {t.Elem().PtrTo()} dst ptr mem))) |
| |
| // interface ops |
| (ITab (IMake itab _)) => itab |
| (IData (IMake _ data)) => data |
| |
| (Load <t> ptr mem) && t.IsInterface() => |
| (IMake |
| (Load <typ.Uintptr> ptr mem) |
| (Load <typ.BytePtr> |
| (OffPtr <typ.BytePtrPtr> [config.PtrSize] ptr) |
| mem)) |
| (Store dst (IMake itab data) mem) => |
| (Store {typ.BytePtr} |
| (OffPtr <typ.BytePtrPtr> [config.PtrSize] dst) |
| data |
| (Store {typ.Uintptr} dst itab mem)) |
| |
| // Helpers for expand calls |
| // Some of these are copied from generic.rules |
| |
| (IMake _typ (StructMake1 val)) => (IMake _typ val) |
| (StructSelect [0] (IData x)) => (IData x) |
| |
| (StructSelect (StructMake1 x)) => x |
| (StructSelect [0] (StructMake2 x _)) => x |
| (StructSelect [1] (StructMake2 _ x)) => x |
| (StructSelect [0] (StructMake3 x _ _)) => x |
| (StructSelect [1] (StructMake3 _ x _)) => x |
| (StructSelect [2] (StructMake3 _ _ x)) => x |
| (StructSelect [0] (StructMake4 x _ _ _)) => x |
| (StructSelect [1] (StructMake4 _ x _ _)) => x |
| (StructSelect [2] (StructMake4 _ _ x _)) => x |
| (StructSelect [3] (StructMake4 _ _ _ x)) => x |
| |
| // Special case coming from immediate interface rewriting |
| // Typical case: (StructSelect [0] (IData (IMake typ dat)) rewrites to (StructSelect [0] dat) |
| // but because the interface is immediate, the type of "IData" is a one-element struct containing |
| // a pointer that is not the pointer type of dat (can be a *uint8). |
| // More annoying case: (ArraySelect[0] (StructSelect[0] isAPtr)) |
| // There, result of the StructSelect is an Array (not a pointer) and |
| // the pre-rewrite input to the ArraySelect is a struct, not a pointer. |
| (StructSelect [0] x) && x.Type.IsPtrShaped() => x |
| (ArraySelect [0] x) && x.Type.IsPtrShaped() => x |
| |
| // These, too. Bits is bits. |
| (ArrayMake1 x) && x.Type.IsPtrShaped() => x |
| (StructMake1 x) && x.Type.IsPtrShaped() => x |
| |
| (Store dst (StructMake1 <t> f0) mem) => |
| (Store {t.FieldType(0)} (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem) |
| (Store dst (StructMake2 <t> f0 f1) mem) => |
| (Store {t.FieldType(1)} |
| (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst) |
| f1 |
| (Store {t.FieldType(0)} |
| (OffPtr <t.FieldType(0).PtrTo()> [0] dst) |
| f0 mem)) |
| (Store dst (StructMake3 <t> f0 f1 f2) mem) => |
| (Store {t.FieldType(2)} |
| (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst) |
| f2 |
| (Store {t.FieldType(1)} |
| (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst) |
| f1 |
| (Store {t.FieldType(0)} |
| (OffPtr <t.FieldType(0).PtrTo()> [0] dst) |
| f0 mem))) |
| (Store dst (StructMake4 <t> f0 f1 f2 f3) mem) => |
| (Store {t.FieldType(3)} |
| (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] dst) |
| f3 |
| (Store {t.FieldType(2)} |
| (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst) |
| f2 |
| (Store {t.FieldType(1)} |
| (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst) |
| f1 |
| (Store {t.FieldType(0)} |
| (OffPtr <t.FieldType(0).PtrTo()> [0] dst) |
| f0 mem)))) |
| |
| (ArraySelect (ArrayMake1 x)) => x |
| (ArraySelect [0] (IData x)) => (IData x) |
| |
| (Store dst (ArrayMake1 e) mem) => (Store {e.Type} dst e mem) |
| |
| // NOTE removed must-not-be-SSA condition. |
| (ArraySelect [i] x:(Load <t> ptr mem)) => |
| @x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.Elem().Size()*i] ptr) mem) |
| |
| (StringPtr x:(Load <t> ptr mem)) && t.IsString() => @x.Block (Load <typ.BytePtr> ptr mem) |
| (StringLen x:(Load <t> ptr mem)) && t.IsString() => @x.Block (Load <typ.Int> |
| (OffPtr <typ.IntPtr> [config.PtrSize] ptr) |
| mem) |
| |
| // NOTE removed must-not-be-SSA condition. |
| (StructSelect [i] x:(Load <t> ptr mem)) => |
| @x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem) |
| |
| (ITab x:(Load <t> ptr mem)) && t.IsInterface() => @x.Block (Load <typ.Uintptr> ptr mem) |
| |
| (IData x:(Load <t> ptr mem)) && t.IsInterface() => @x.Block (Load <typ.BytePtr> |
| (OffPtr <typ.BytePtrPtr> [config.PtrSize] ptr) |
| mem) |
| |
| (SlicePtr x:(Load <t> ptr mem)) && t.IsSlice() => @x.Block (Load <t.Elem().PtrTo()> ptr mem) |
| (SliceLen x:(Load <t> ptr mem)) && t.IsSlice() => @x.Block (Load <typ.Int> |
| (OffPtr <typ.IntPtr> [config.PtrSize] ptr) |
| mem) |
| (SliceCap x:(Load <t> ptr mem)) && t.IsSlice() => @x.Block (Load <typ.Int> |
| (OffPtr <typ.IntPtr> [2*config.PtrSize] ptr) |
| mem) |
| |
| (ComplexReal x:(Load <t> ptr mem)) && t.IsComplex() && t.Size() == 8 => @x.Block (Load <typ.Float32> ptr mem) |
| (ComplexImag x:(Load <t> ptr mem)) && t.IsComplex() && t.Size() == 8 => @x.Block (Load <typ.Float32> |
| (OffPtr <typ.Float32Ptr> [4] ptr) |
| mem) |
| |
| (ComplexReal x:(Load <t> ptr mem)) && t.IsComplex() && t.Size() == 16 => @x.Block (Load <typ.Float64> ptr mem) |
| (ComplexImag x:(Load <t> ptr mem)) && t.IsComplex() && t.Size() == 16 => @x.Block (Load <typ.Float64> |
| (OffPtr <typ.Float64Ptr> [8] ptr) |
| mem) |