ir_iter.mx raw
1 package main
2
3 import (
4 . "git.smesh.lol/moxie/pkg/types"
5 )
6
7 func (e *irEmitter) emitRange(r *SSARange) {
8 reg := e.regName(r)
9 ipt := e.intptrType()
10 if _, ok := SafeUnderlying(r.X.SSAType()).(*TCMap); ok {
11 e.w(" ") ; e.w(reg) ; e.w(" = alloca [48 x i8]\n")
12 e.w(" call void @llvm.memset.p0." | ipt | "(ptr ") ; e.w(reg) ; e.w(", i8 0, " | ipt | " 48, i1 false)\n")
13 e.declareRuntime("llvm.memset.p0." | ipt, "void", "ptr, i8, " | ipt | ", i1")
14 return
15 }
16 ipt := e.intptrType()
17 e.w(" ") ; e.w(reg) ; e.w(" = alloca ") ; e.w(ipt) ; e.w("\n")
18 e.w(" store ") ; e.w(ipt) ; e.w(" 0, ptr ") ; e.w(reg) ; e.w("\n")
19 }
20
21 func (e *irEmitter) emitNext(n *SSANext) {
22 reg := e.regName(n)
23 rangeInstr := n.Iter.(*SSARange)
24 iterPtr := e.regName(rangeInstr)
25 collVal := e.operand(rangeInstr.X)
26 if mt, ok := SafeUnderlying(rangeInstr.X.SSAType()).(*TCMap); ok {
27 e.emitNextMap(reg, iterPtr, collVal, mt, n)
28 return
29 }
30 if arr, ok := SafeUnderlying(rangeInstr.X.SSAType()).(*Array); ok && arr.Len >= 0 {
31 e.emitNextArray(reg, iterPtr, collVal, arr, n)
32 return
33 }
34 if p, ok := SafeUnderlying(rangeInstr.X.SSAType()).(*Pointer); ok {
35 if ar, ok2 := SafeUnderlying(p.Base).(*Array); ok2 && ar.Len >= 0 {
36 e.emitNextPtrArray(reg, iterPtr, collVal, ar, n)
37 return
38 }
39 }
40 collLLVM := e.llvmType(rangeInstr.X.SSAType())
41 if len(collLLVM) > 0 && collLLVM[0] == 'i' {
42 tupType := e.llvmType(n.SSAType())
43 if at, ok := e.allocTypes[n]; ok {
44 tupType = at
45 }
46 e.w(" ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" zeroinitializer, i1 false, 0\n")
47 return
48 }
49 e.emitNextSlice(reg, iterPtr, collVal, rangeInstr, n)
50 }
51
52 func (e *irEmitter) emitNextSlice(reg, iterPtr, collVal string, rangeInstr *SSARange, n *SSANext) {
53 ipt := e.intptrType()
54 sty := e.sliceType()
55 idx := e.nextReg2("rn")
56 e.w(" ") ; e.w(idx) ; e.w(" = load ") ; e.w(ipt) ; e.w(", ptr ") ; e.w(iterPtr) ; e.w("\n")
57 slLen := e.nextReg2("rn")
58 e.w(" ") ; e.w(slLen) ; e.w(" = extractvalue ") ; e.w(sty) ; e.w(" ") ; e.w(collVal) ; e.w(", 1\n")
59 ok := e.nextReg2("rn")
60 e.w(" ") ; e.w(ok) ; e.w(" = icmp ult ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w(", ") ; e.w(slLen) ; e.w("\n")
61 key := e.nextReg2("rn")
62 e.truncToI32(key, idx)
63 dataPtr := e.nextReg2("rn")
64 e.w(" ") ; e.w(dataPtr) ; e.w(" = extractvalue ") ; e.w(sty) ; e.w(" ") ; e.w(collVal) ; e.w(", 0\n")
65 elemType := "i32"
66 if sl, ok2 := SafeUnderlying(rangeInstr.X.SSAType()).(*Slice); ok2 {
67 elemType = e.llvmType(sl.Elem)
68 }
69 eptr := e.nextReg2("rn")
70 e.w(" ") ; e.w(eptr) ; e.w(" = getelementptr ") ; e.w(elemType)
71 e.w(", ptr ") ; e.w(dataPtr) ; e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w("\n")
72 fallback := e.nextReg2("rn")
73 e.w(" ") ; e.w(fallback) ; e.w(" = alloca ") ; e.w(elemType) ; e.w("\n")
74 e.w(" store ") ; e.w(elemType) ; e.w(" zeroinitializer, ptr ") ; e.w(fallback) ; e.w("\n")
75 safePtr := e.nextReg2("rn")
76 e.w(" ") ; e.w(safePtr) ; e.w(" = select i1 ") ; e.w(ok) ; e.w(", ptr ") ; e.w(eptr)
77 e.w(", ptr ") ; e.w(fallback) ; e.w("\n")
78 elem := e.nextReg2("rn")
79 e.w(" ") ; e.w(elem) ; e.w(" = load ") ; e.w(elemType) ; e.w(", ptr ") ; e.w(safePtr) ; e.w("\n")
80 inc := e.nextReg2("rn")
81 e.w(" ") ; e.w(inc) ; e.w(" = add ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w(", 1\n")
82 newCnt := e.nextReg2("rn")
83 e.w(" ") ; e.w(newCnt) ; e.w(" = select i1 ") ; e.w(ok) ; e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(inc)
84 e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w("\n")
85 e.w(" store ") ; e.w(ipt) ; e.w(" ") ; e.w(newCnt) ; e.w(", ptr ") ; e.w(iterPtr) ; e.w("\n")
86 tupType := "{i1, i32, " | elemType | "}"
87 e.allocTypes[n] = tupType
88 t1 := e.nextReg2("rn")
89 e.w(" ") ; e.w(t1) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" undef, i1 ") ; e.w(ok) ; e.w(", 0\n")
90 t2 := e.nextReg2("rn")
91 e.w(" ") ; e.w(t2) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t1) ; e.w(", i32 ") ; e.w(key) ; e.w(", 1\n")
92 e.w(" ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t2) ; e.w(", ") ; e.w(elemType) ; e.w(" ") ; e.w(elem) ; e.w(", 2\n")
93 }
94
95 func (e *irEmitter) emitNextArray(reg, iterPtr, collVal string, arr *Array, n *SSANext) {
96 ipt := e.intptrType()
97 arrLen := arr.Len
98 elemType := e.llvmType(arr.Elem)
99 arrType := "[" | irItoa(int32(arrLen)) | " x " | elemType | "]"
100 idx := e.nextReg2("rn")
101 e.w(" ") ; e.w(idx) ; e.w(" = load ") ; e.w(ipt) ; e.w(", ptr ") ; e.w(iterPtr) ; e.w("\n")
102 ok := e.nextReg2("rn")
103 e.w(" ") ; e.w(ok) ; e.w(" = icmp ult ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w(", ") ; e.w(irItoa(int32(arrLen))) ; e.w("\n")
104 key := e.nextReg2("rn")
105 e.truncToI32(key, idx)
106 // Store array to memory to get element pointer via GEP
107 arrAlloca := e.nextReg2("rn")
108 e.w(" ") ; e.w(arrAlloca) ; e.w(" = alloca ") ; e.w(arrType) ; e.w("\n")
109 e.w(" store ") ; e.w(arrType) ; e.w(" ") ; e.w(collVal) ; e.w(", ptr ") ; e.w(arrAlloca) ; e.w("\n")
110 eptr := e.nextReg2("rn")
111 e.w(" ") ; e.w(eptr) ; e.w(" = getelementptr inbounds ") ; e.w(arrType)
112 e.w(", ptr ") ; e.w(arrAlloca) ; e.w(", i32 0, ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w("\n")
113 fallback := e.nextReg2("rn")
114 e.w(" ") ; e.w(fallback) ; e.w(" = alloca ") ; e.w(elemType) ; e.w("\n")
115 e.w(" store ") ; e.w(elemType) ; e.w(" zeroinitializer, ptr ") ; e.w(fallback) ; e.w("\n")
116 safePtr := e.nextReg2("rn")
117 e.w(" ") ; e.w(safePtr) ; e.w(" = select i1 ") ; e.w(ok) ; e.w(", ptr ") ; e.w(eptr)
118 e.w(", ptr ") ; e.w(fallback) ; e.w("\n")
119 elem := e.nextReg2("rn")
120 e.w(" ") ; e.w(elem) ; e.w(" = load ") ; e.w(elemType) ; e.w(", ptr ") ; e.w(safePtr) ; e.w("\n")
121 inc := e.nextReg2("rn")
122 e.w(" ") ; e.w(inc) ; e.w(" = add ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w(", 1\n")
123 newCnt := e.nextReg2("rn")
124 e.w(" ") ; e.w(newCnt) ; e.w(" = select i1 ") ; e.w(ok) ; e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(inc)
125 e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w("\n")
126 e.w(" store ") ; e.w(ipt) ; e.w(" ") ; e.w(newCnt) ; e.w(", ptr ") ; e.w(iterPtr) ; e.w("\n")
127 tupType := "{i1, i32, " | elemType | "}"
128 e.allocTypes[n] = tupType
129 t1 := e.nextReg2("rn")
130 e.w(" ") ; e.w(t1) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" undef, i1 ") ; e.w(ok) ; e.w(", 0\n")
131 t2 := e.nextReg2("rn")
132 e.w(" ") ; e.w(t2) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t1) ; e.w(", i32 ") ; e.w(key) ; e.w(", 1\n")
133 e.w(" ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t2) ; e.w(", ") ; e.w(elemType) ; e.w(" ") ; e.w(elem) ; e.w(", 2\n")
134 }
135
136 func (e *irEmitter) emitNextPtrArray(reg, iterPtr, collVal string, arr *Array, n *SSANext) {
137 ipt := e.intptrType()
138 arrLen := arr.Len
139 elemType := e.llvmType(arr.Elem)
140 arrType := "[" | irItoa(int32(arrLen)) | " x " | elemType | "]"
141 idx := e.nextReg2("rn")
142 e.w(" ") ; e.w(idx) ; e.w(" = load ") ; e.w(ipt) ; e.w(", ptr ") ; e.w(iterPtr) ; e.w("\n")
143 ok := e.nextReg2("rn")
144 e.w(" ") ; e.w(ok) ; e.w(" = icmp ult ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w(", ") ; e.w(irItoa(int32(arrLen))) ; e.w("\n")
145 key := e.nextReg2("rn")
146 e.truncToI32(key, idx)
147 eptr := e.nextReg2("rn")
148 e.w(" ") ; e.w(eptr) ; e.w(" = getelementptr inbounds ") ; e.w(arrType)
149 e.w(", ptr ") ; e.w(collVal) ; e.w(", i32 0, ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w("\n")
150 fallback := e.nextReg2("rn")
151 e.w(" ") ; e.w(fallback) ; e.w(" = alloca ") ; e.w(elemType) ; e.w("\n")
152 e.w(" store ") ; e.w(elemType) ; e.w(" zeroinitializer, ptr ") ; e.w(fallback) ; e.w("\n")
153 safePtr := e.nextReg2("rn")
154 e.w(" ") ; e.w(safePtr) ; e.w(" = select i1 ") ; e.w(ok) ; e.w(", ptr ") ; e.w(eptr)
155 e.w(", ptr ") ; e.w(fallback) ; e.w("\n")
156 elem := e.nextReg2("rn")
157 e.w(" ") ; e.w(elem) ; e.w(" = load ") ; e.w(elemType) ; e.w(", ptr ") ; e.w(safePtr) ; e.w("\n")
158 inc := e.nextReg2("rn")
159 e.w(" ") ; e.w(inc) ; e.w(" = add ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w(", 1\n")
160 newCnt := e.nextReg2("rn")
161 e.w(" ") ; e.w(newCnt) ; e.w(" = select i1 ") ; e.w(ok) ; e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(inc)
162 e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w("\n")
163 e.w(" store ") ; e.w(ipt) ; e.w(" ") ; e.w(newCnt) ; e.w(", ptr ") ; e.w(iterPtr) ; e.w("\n")
164 tupType := "{i1, i32, " | elemType | "}"
165 e.allocTypes[n] = tupType
166 t1 := e.nextReg2("rn")
167 e.w(" ") ; e.w(t1) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" undef, i1 ") ; e.w(ok) ; e.w(", 0\n")
168 t2 := e.nextReg2("rn")
169 e.w(" ") ; e.w(t2) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t1) ; e.w(", i32 ") ; e.w(key) ; e.w(", 1\n")
170 e.w(" ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t2) ; e.w(", ") ; e.w(elemType) ; e.w(" ") ; e.w(elem) ; e.w(", 2\n")
171 }
172
173 func (e *irEmitter) emitNextMap(reg, iterPtr, collVal string, mt *TCMap, n *SSANext) {
174 keyType := e.llvmType(mt.Key)
175 valType := e.llvmType(mt.Elem)
176 keyAlloca := e.nextReg2("mn")
177 e.w(" ") ; e.w(keyAlloca) ; e.w(" = alloca ") ; e.w(keyType) ; e.w("\n")
178 valAlloca := e.nextReg2("mn")
179 e.w(" ") ; e.w(valAlloca) ; e.w(" = alloca ") ; e.w(valType) ; e.w("\n")
180 ok := e.nextReg2("mn")
181 e.w(" ") ; e.w(ok) ; e.w(" = call i1 @runtime.hashmapNext(ptr ") ; e.w(collVal)
182 e.w(", ptr ") ; e.w(iterPtr)
183 e.w(", ptr ") ; e.w(keyAlloca)
184 e.w(", ptr ") ; e.w(valAlloca) ; e.w(", ptr null)\n")
185 key := e.nextReg2("mn")
186 e.w(" ") ; e.w(key) ; e.w(" = load ") ; e.w(keyType) ; e.w(", ptr ") ; e.w(keyAlloca) ; e.w("\n")
187 val := e.nextReg2("mn")
188 e.w(" ") ; e.w(val) ; e.w(" = load ") ; e.w(valType) ; e.w(", ptr ") ; e.w(valAlloca) ; e.w("\n")
189 tupType := e.llvmType(n.SSAType())
190 t1 := e.nextReg2("mn")
191 e.w(" ") ; e.w(t1) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" undef, i1 ") ; e.w(ok) ; e.w(", 0\n")
192 t2 := e.nextReg2("mn")
193 e.w(" ") ; e.w(t2) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t1) ; e.w(", ") ; e.w(keyType) ; e.w(" ") ; e.w(key) ; e.w(", 1\n")
194 e.w(" ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t2) ; e.w(", ") ; e.w(valType) ; e.w(" ") ; e.w(val) ; e.w(", 2\n")
195 e.declareRuntime("runtime.hashmapNext", "i1", "ptr, ptr, ptr, ptr")
196 }
197