blob: 7944947e062b9134a320c82ac57327bb95f2ea4e [file] [log] [blame]
// 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)