// 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 ptr mem) && t.IsComplex() && t.Size() == 8 => (ComplexMake (Load ptr mem) (Load (OffPtr [4] ptr) mem) ) (Store {t} dst (ComplexMake real imag) mem) && t.Size() == 8 => (Store {typ.Float32} (OffPtr [4] dst) imag (Store {typ.Float32} dst real mem)) (Load ptr mem) && t.IsComplex() && t.Size() == 16 => (ComplexMake (Load ptr mem) (Load (OffPtr [8] ptr) mem) ) (Store {t} dst (ComplexMake real imag) mem) && t.Size() == 16 => (Store {typ.Float64} (OffPtr [8] dst) imag (Store {typ.Float64} dst real mem)) // string ops (StringPtr (StringMake ptr _)) => ptr (StringLen (StringMake _ len)) => len (Load ptr mem) && t.IsString() => (StringMake (Load ptr mem) (Load (OffPtr [config.PtrSize] ptr) mem)) (Store dst (StringMake ptr len) mem) => (Store {typ.Int} (OffPtr [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 ptr mem) && t.IsSlice() => (SliceMake (Load ptr mem) (Load (OffPtr [config.PtrSize] ptr) mem) (Load (OffPtr [2*config.PtrSize] ptr) mem)) (Store {t} dst (SliceMake ptr len cap) mem) => (Store {typ.Int} (OffPtr [2*config.PtrSize] dst) cap (Store {typ.Int} (OffPtr [config.PtrSize] dst) len (Store {t.Elem().PtrTo()} dst ptr mem))) // interface ops (ITab (IMake itab _)) => itab (IData (IMake _ data)) => data (Load ptr mem) && t.IsInterface() => (IMake (Load ptr mem) (Load (OffPtr [config.PtrSize] ptr) mem)) (Store dst (IMake itab data) mem) => (Store {typ.BytePtr} (OffPtr [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 f0) mem) => (Store {t.FieldType(0)} (OffPtr [0] dst) f0 mem) (Store dst (StructMake2 f0 f1) mem) => (Store {t.FieldType(1)} (OffPtr [t.FieldOff(1)] dst) f1 (Store {t.FieldType(0)} (OffPtr [0] dst) f0 mem)) (Store dst (StructMake3 f0 f1 f2) mem) => (Store {t.FieldType(2)} (OffPtr [t.FieldOff(2)] dst) f2 (Store {t.FieldType(1)} (OffPtr [t.FieldOff(1)] dst) f1 (Store {t.FieldType(0)} (OffPtr [0] dst) f0 mem))) (Store dst (StructMake4 f0 f1 f2 f3) mem) => (Store {t.FieldType(3)} (OffPtr [t.FieldOff(3)] dst) f3 (Store {t.FieldType(2)} (OffPtr [t.FieldOff(2)] dst) f2 (Store {t.FieldType(1)} (OffPtr [t.FieldOff(1)] dst) f1 (Store {t.FieldType(0)} (OffPtr [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 ptr mem)) => @x.Block (Load (OffPtr [t.Elem().Size()*i] ptr) mem) (StringPtr x:(Load ptr mem)) && t.IsString() => @x.Block (Load ptr mem) (StringLen x:(Load ptr mem)) && t.IsString() => @x.Block (Load (OffPtr [config.PtrSize] ptr) mem) // NOTE removed must-not-be-SSA condition. (StructSelect [i] x:(Load ptr mem)) => @x.Block (Load (OffPtr [t.FieldOff(int(i))] ptr) mem) (ITab x:(Load ptr mem)) && t.IsInterface() => @x.Block (Load ptr mem) (IData x:(Load ptr mem)) && t.IsInterface() => @x.Block (Load (OffPtr [config.PtrSize] ptr) mem) (SlicePtr x:(Load ptr mem)) && t.IsSlice() => @x.Block (Load ptr mem) (SliceLen x:(Load ptr mem)) && t.IsSlice() => @x.Block (Load (OffPtr [config.PtrSize] ptr) mem) (SliceCap x:(Load ptr mem)) && t.IsSlice() => @x.Block (Load (OffPtr [2*config.PtrSize] ptr) mem) (ComplexReal x:(Load ptr mem)) && t.IsComplex() && t.Size() == 8 => @x.Block (Load ptr mem) (ComplexImag x:(Load ptr mem)) && t.IsComplex() && t.Size() == 8 => @x.Block (Load (OffPtr [4] ptr) mem) (ComplexReal x:(Load ptr mem)) && t.IsComplex() && t.Size() == 16 => @x.Block (Load ptr mem) (ComplexImag x:(Load ptr mem)) && t.IsComplex() && t.Size() == 16 => @x.Block (Load (OffPtr [8] ptr) mem)