1// Copyright 2016 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// This file contains rules to decompose builtin compound types
6// (complex,string,slice,interface) into their constituent
7// types.  These rules work together with the decomposeBuiltIn
8// pass which handles phis of these types.
9
10(Store {t} _ _ mem) && t.Size() == 0 => mem
11
12// complex ops
13(ComplexReal (ComplexMake real _  )) => real
14(ComplexImag (ComplexMake _ imag )) => imag
15
16(Load <t> ptr mem) && t.IsComplex() && t.Size() == 8 =>
17  (ComplexMake
18    (Load <typ.Float32> ptr mem)
19    (Load <typ.Float32>
20      (OffPtr <typ.Float32Ptr> [4] ptr)
21      mem)
22    )
23(Store {t} dst (ComplexMake real imag) mem) && t.Size() == 8 =>
24  (Store {typ.Float32}
25    (OffPtr <typ.Float32Ptr> [4] dst)
26    imag
27    (Store {typ.Float32} dst real mem))
28(Load <t> ptr mem) && t.IsComplex() && t.Size() == 16 =>
29  (ComplexMake
30    (Load <typ.Float64> ptr mem)
31    (Load <typ.Float64>
32      (OffPtr <typ.Float64Ptr> [8] ptr)
33      mem)
34    )
35(Store {t} dst (ComplexMake real imag) mem) && t.Size() == 16 =>
36  (Store {typ.Float64}
37    (OffPtr <typ.Float64Ptr> [8] dst)
38    imag
39    (Store {typ.Float64} dst real mem))
40
41// string ops
42(StringPtr (StringMake ptr _)) => ptr
43(StringLen (StringMake _ len)) => len
44
45(Load <t> ptr mem) && t.IsString() =>
46  (StringMake
47    (Load <typ.BytePtr> ptr mem)
48    (Load <typ.Int>
49      (OffPtr <typ.IntPtr> [config.PtrSize] ptr)
50      mem))
51(Store dst (StringMake ptr len) mem) =>
52  (Store {typ.Int}
53    (OffPtr <typ.IntPtr> [config.PtrSize] dst)
54    len
55    (Store {typ.BytePtr} dst ptr mem))
56
57// slice ops
58(SlicePtr (SliceMake ptr _ _ )) => ptr
59(SliceLen (SliceMake _ len _)) => len
60(SliceCap (SliceMake _ _ cap)) => cap
61(SlicePtrUnchecked (SliceMake ptr _ _ )) => ptr
62
63(Load <t> ptr mem) && t.IsSlice() =>
64  (SliceMake
65    (Load <t.Elem().PtrTo()> ptr mem)
66    (Load <typ.Int>
67      (OffPtr <typ.IntPtr> [config.PtrSize] ptr)
68      mem)
69    (Load <typ.Int>
70      (OffPtr <typ.IntPtr> [2*config.PtrSize] ptr)
71      mem))
72(Store {t} dst (SliceMake ptr len cap) mem) =>
73  (Store {typ.Int}
74    (OffPtr <typ.IntPtr> [2*config.PtrSize] dst)
75    cap
76    (Store {typ.Int}
77      (OffPtr <typ.IntPtr> [config.PtrSize] dst)
78      len
79      (Store {t.Elem().PtrTo()} dst ptr mem)))
80
81// interface ops
82(ITab (IMake itab _)) => itab
83(IData (IMake _ data)) => data
84
85(Load <t> ptr mem) && t.IsInterface() =>
86  (IMake
87    (Load <typ.Uintptr> ptr mem)
88    (Load <typ.BytePtr>
89      (OffPtr <typ.BytePtrPtr> [config.PtrSize] ptr)
90      mem))
91(Store dst (IMake itab data) mem) =>
92  (Store {typ.BytePtr}
93    (OffPtr <typ.BytePtrPtr> [config.PtrSize] dst)
94    data
95    (Store {typ.Uintptr} dst itab mem))
96
97// Helpers for expand calls
98// Some of these are copied from generic.rules
99
100(IMake _typ (StructMake1 val)) => (IMake _typ val)
101(StructSelect [0] (IData x)) => (IData x)
102
103(StructSelect (StructMake1 x)) => x
104(StructSelect [0] (StructMake2 x _)) => x
105(StructSelect [1] (StructMake2 _ x)) => x
106(StructSelect [0] (StructMake3 x _ _)) => x
107(StructSelect [1] (StructMake3 _ x _)) => x
108(StructSelect [2] (StructMake3 _ _ x)) => x
109(StructSelect [0] (StructMake4 x _ _ _)) => x
110(StructSelect [1] (StructMake4 _ x _ _)) => x
111(StructSelect [2] (StructMake4 _ _ x _)) => x
112(StructSelect [3] (StructMake4 _ _ _ x)) => x
113
114// Special case coming from immediate interface rewriting
115// Typical case: (StructSelect [0] (IData (IMake typ dat)) rewrites to (StructSelect [0] dat)
116// but because the interface is immediate, the type of "IData" is a one-element struct containing
117// a pointer that is not the pointer type of dat (can be a *uint8).
118// More annoying case: (ArraySelect[0] (StructSelect[0] isAPtr))
119// There, result of the StructSelect is an Array (not a pointer) and
120// the pre-rewrite input to the ArraySelect is a struct, not a pointer.
121(StructSelect [0] x) && x.Type.IsPtrShaped()  => x
122(ArraySelect [0] x) && x.Type.IsPtrShaped()  => x
123
124// These, too.  Bits is bits.
125(ArrayMake1 x) && x.Type.IsPtrShaped() => x
126(StructMake1 x) && x.Type.IsPtrShaped() => x
127
128(Store dst (StructMake1 <t> f0) mem) =>
129  (Store {t.FieldType(0)} (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem)
130(Store dst (StructMake2 <t> f0 f1) mem) =>
131  (Store {t.FieldType(1)}
132    (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
133    f1
134    (Store {t.FieldType(0)}
135      (OffPtr <t.FieldType(0).PtrTo()> [0] dst)
136        f0 mem))
137(Store dst (StructMake3 <t> f0 f1 f2) mem) =>
138  (Store {t.FieldType(2)}
139    (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst)
140    f2
141    (Store {t.FieldType(1)}
142      (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
143      f1
144      (Store {t.FieldType(0)}
145        (OffPtr <t.FieldType(0).PtrTo()> [0] dst)
146          f0 mem)))
147(Store dst (StructMake4 <t> f0 f1 f2 f3) mem) =>
148  (Store {t.FieldType(3)}
149    (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] dst)
150    f3
151    (Store {t.FieldType(2)}
152      (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst)
153      f2
154      (Store {t.FieldType(1)}
155        (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
156        f1
157        (Store {t.FieldType(0)}
158          (OffPtr <t.FieldType(0).PtrTo()> [0] dst)
159            f0 mem))))
160
161(ArraySelect (ArrayMake1 x)) => x
162(ArraySelect [0] (IData x)) => (IData x)
163
164(Store dst (ArrayMake1 e) mem) => (Store {e.Type} dst e mem)
165
166// NOTE removed must-not-be-SSA condition.
167(ArraySelect [i] x:(Load <t> ptr mem)) =>
168  @x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.Elem().Size()*i] ptr) mem)
169
170(StringPtr x:(Load <t> ptr mem)) && t.IsString() => @x.Block (Load <typ.BytePtr> ptr mem)
171(StringLen x:(Load <t> ptr mem)) && t.IsString() => @x.Block (Load <typ.Int>
172      (OffPtr <typ.IntPtr> [config.PtrSize] ptr)
173      mem)
174
175// NOTE removed must-not-be-SSA condition.
176(StructSelect [i] x:(Load <t> ptr mem)) =>
177  @x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem)
178
179(ITab x:(Load <t> ptr mem)) && t.IsInterface() => @x.Block (Load <typ.Uintptr> ptr mem)
180
181(IData x:(Load <t> ptr mem)) && t.IsInterface() => @x.Block (Load <typ.BytePtr>
182      (OffPtr <typ.BytePtrPtr> [config.PtrSize] ptr)
183      mem)
184
185(SlicePtr x:(Load <t> ptr mem)) && t.IsSlice() => @x.Block (Load <t.Elem().PtrTo()> ptr mem)
186(SliceLen x:(Load <t> ptr mem)) && t.IsSlice() => @x.Block (Load <typ.Int>
187      (OffPtr <typ.IntPtr> [config.PtrSize] ptr)
188      mem)
189(SliceCap x:(Load <t> ptr mem)) && t.IsSlice() => @x.Block (Load <typ.Int>
190      (OffPtr <typ.IntPtr> [2*config.PtrSize] ptr)
191      mem)
192
193(ComplexReal x:(Load <t> ptr mem)) && t.IsComplex() && t.Size() == 8 => @x.Block (Load <typ.Float32> ptr mem)
194(ComplexImag x:(Load <t> ptr mem)) && t.IsComplex() && t.Size() == 8 => @x.Block (Load <typ.Float32>
195      (OffPtr <typ.Float32Ptr> [4] ptr)
196      mem)
197
198(ComplexReal x:(Load <t> ptr mem)) && t.IsComplex() && t.Size() == 16 => @x.Block (Load <typ.Float64> ptr mem)
199(ComplexImag x:(Load <t> ptr mem)) && t.IsComplex() && t.Size() == 16 => @x.Block (Load <typ.Float64>
200      (OffPtr <typ.Float64Ptr> [8] ptr)
201      mem)
202