ir_map.mx raw
1 package main
2
3 import (
4 . "git.smesh.lol/moxie/pkg/types"
5 )
6
7 func (e *irEmitter) emitMakeMap(m *SSAMakeMap) {
8 reg := e.regName(m)
9 ipt := e.intptrType()
10 mt, _ := SafeUnderlying(m.SSAType()).(*TCMap)
11 keyType := "i32"
12 valType := "i32"
13 alg := "0"
14 if mt != nil {
15 keyType = e.llvmType(mt.Key)
16 valType = e.llvmType(mt.Elem)
17 if e.isStringLike(mt.Key) {
18 alg = "1"
19 }
20 }
21 keySz := e.nextReg2("mm")
22 e.w(" ") ; e.w(keySz) ; e.w(" = ptrtoint ptr getelementptr (")
23 e.w(keyType) ; e.w(", ptr null, i32 1) to ") ; e.w(ipt) ; e.w("\n")
24 valSz := e.nextReg2("mm")
25 e.w(" ") ; e.w(valSz) ; e.w(" = ptrtoint ptr getelementptr (")
26 e.w(valType) ; e.w(", ptr null, i32 1) to ") ; e.w(ipt) ; e.w("\n")
27 hint := "8"
28 if m.Reserve != nil {
29 hint = e.operand(m.Reserve)
30 }
31 e.w(" ") ; e.w(reg) ; e.w(" = call ptr @runtime.hashmapMake(")
32 e.w(ipt) ; e.w(" ") ; e.w(keySz) ; e.w(", ")
33 e.w(ipt) ; e.w(" ") ; e.w(valSz) ; e.w(", ")
34 e.w(ipt) ; e.w(" ") ; e.w(hint) ; e.w(", i8 ") ; e.w(alg) ; e.w(", ptr null)\n")
35 e.declareRuntime("runtime.hashmapMake", "ptr", ipt | ", " | ipt | ", " | ipt | ", i8")
36 e.scopeTrackAlloc(reg)
37 }
38
39 func (e *irEmitter) emitMapUpdate(m *SSAMapUpdate) {
40 ipt := e.intptrType()
41 mapVal := e.operand(m.Map)
42 keyVal := e.operand(m.Key)
43 valVal := e.operand(m.Value)
44 mapType := m.Map.SSAType()
45 if pt, ok := SafeUnderlying(mapType).(*Pointer); ok {
46 mapType = pt.Base
47 }
48 mt, _ := SafeUnderlying(mapType).(*TCMap)
49 keyType := "i32"
50 valType := "i32"
51 if mt != nil {
52 keyType = e.llvmType(mt.Key)
53 valType = e.llvmType(mt.Elem)
54 } else {
55 if m.Key.SSAType() != nil {
56 keyType = e.llvmType(m.Key.SSAType())
57 }
58 if m.Value.SSAType() != nil {
59 valType = e.llvmType(m.Value.SSAType())
60 }
61 }
62 if keyVal == "null" && keyType != "ptr" { keyVal = "zeroinitializer" }
63 if valVal == "null" && valType != "ptr" { valVal = "zeroinitializer" }
64 keyAlloca := e.nextReg2("mu")
65 e.w(" ") ; e.w(keyAlloca) ; e.w(" = alloca ") ; e.w(keyType) ; e.w("\n")
66 e.w(" store ") ; e.w(keyType) ; e.w(" ") ; e.w(keyVal) ; e.w(", ptr ") ; e.w(keyAlloca) ; e.w("\n")
67 valAlloca := e.nextReg2("mu")
68 e.w(" ") ; e.w(valAlloca) ; e.w(" = alloca ") ; e.w(valType) ; e.w("\n")
69 e.w(" store ") ; e.w(valType) ; e.w(" ") ; e.w(valVal) ; e.w(", ptr ") ; e.w(valAlloca) ; e.w("\n")
70 if mt != nil && e.isStringLike(mt.Key) {
71 kd := e.nextReg2("mu")
72 kl := e.nextReg2("mu")
73 kc := e.nextReg2("mu")
74 e.w(" ") ; e.w(kd) ; e.w(" = extractvalue " | e.sliceType() | " ") ; e.w(keyVal) ; e.w(", 0\n")
75 e.w(" ") ; e.w(kl) ; e.w(" = extractvalue " | e.sliceType() | " ") ; e.w(keyVal) ; e.w(", 1\n")
76 e.w(" ") ; e.w(kc) ; e.w(" = extractvalue " | e.sliceType() | " ") ; e.w(keyVal) ; e.w(", 2\n")
77 e.w(" call void @runtime.hashmapContentSet(ptr ") ; e.w(mapVal)
78 e.w(", ptr ") ; e.w(kd)
79 e.w(", " | ipt | " ") ; e.w(kl)
80 e.w(", " | ipt | " ") ; e.w(kc)
81 e.w(", ptr ") ; e.w(valAlloca) ; e.w(", ptr null)\n")
82 e.declareRuntime("runtime.hashmapContentSet", "void", "ptr, ptr, " | ipt | ", " | ipt | ", ptr")
83 } else {
84 e.w(" call void @runtime.hashmapBinarySet(ptr ") ; e.w(mapVal)
85 e.w(", ptr ") ; e.w(keyAlloca)
86 e.w(", ptr ") ; e.w(valAlloca) ; e.w(", ptr null)\n")
87 e.declareRuntime("runtime.hashmapBinarySet", "void", "ptr, ptr, ptr")
88 }
89 }
90
91 func (e *irEmitter) emitLookup(l *SSALookup) {
92 reg := e.regName(l)
93 ipt := e.intptrType()
94 mapVal := e.operand(l.X)
95 keyVal := e.operand(l.Index)
96 mt, _ := SafeUnderlying(l.X.SSAType()).(*TCMap)
97 keyType := "i32"
98 valType := "i32"
99 if mt != nil {
100 keyType = e.llvmType(mt.Key)
101 valType = e.llvmType(mt.Elem)
102 } else {
103 if l.Index.SSAType() != nil {
104 keyType = e.llvmType(l.Index.SSAType())
105 }
106 }
107 valAlloca := e.nextReg2("ml")
108 e.w(" ") ; e.w(valAlloca) ; e.w(" = alloca ") ; e.w(valType) ; e.w("\n")
109 valSz := e.nextReg2("ml")
110 e.w(" ") ; e.w(valSz) ; e.w(" = ptrtoint ptr getelementptr (")
111 e.w(valType) ; e.w(", ptr null, i32 1) to ") ; e.w(ipt) ; e.w("\n")
112 if mt != nil && e.isStringLike(mt.Key) {
113 kd := e.nextReg2("ml")
114 kl := e.nextReg2("ml")
115 kc := e.nextReg2("ml")
116 e.w(" ") ; e.w(kd) ; e.w(" = extractvalue " | e.sliceType() | " ") ; e.w(keyVal) ; e.w(", 0\n")
117 e.w(" ") ; e.w(kl) ; e.w(" = extractvalue " | e.sliceType() | " ") ; e.w(keyVal) ; e.w(", 1\n")
118 e.w(" ") ; e.w(kc) ; e.w(" = extractvalue " | e.sliceType() | " ") ; e.w(keyVal) ; e.w(", 2\n")
119 okReg := e.nextReg2("ml")
120 e.w(" ") ; e.w(okReg) ; e.w(" = call i1 @runtime.hashmapContentGet(ptr ") ; e.w(mapVal)
121 e.w(", ptr ") ; e.w(kd)
122 e.w(", " | ipt | " ") ; e.w(kl)
123 e.w(", " | ipt | " ") ; e.w(kc)
124 e.w(", ptr ") ; e.w(valAlloca)
125 e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(valSz) ; e.w(", ptr null)\n")
126 e.declareRuntime("runtime.hashmapContentGet", "i1", "ptr, ptr, " | ipt | ", " | ipt | ", ptr, " | ipt)
127 if l.CommaOk {
128 loaded := e.nextReg2("ml")
129 e.w(" ") ; e.w(loaded) ; e.w(" = load ") ; e.w(valType) ; e.w(", ptr ") ; e.w(valAlloca) ; e.w("\n")
130 tupType := "{" | valType | ", i1}"
131 t1 := e.nextReg2("ml")
132 e.w(" ") ; e.w(t1) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" undef, ") ; e.w(valType) ; e.w(" ") ; e.w(loaded) ; e.w(", 0\n")
133 e.w(" ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t1) ; e.w(", i1 ") ; e.w(okReg) ; e.w(", 1\n")
134 } else {
135 e.w(" ") ; e.w(reg) ; e.w(" = load ") ; e.w(valType) ; e.w(", ptr ") ; e.w(valAlloca) ; e.w("\n")
136 }
137 } else {
138 keyAlloca := e.nextReg2("ml")
139 e.w(" ") ; e.w(keyAlloca) ; e.w(" = alloca ") ; e.w(keyType) ; e.w("\n")
140 e.w(" store ") ; e.w(keyType) ; e.w(" ") ; e.w(keyVal) ; e.w(", ptr ") ; e.w(keyAlloca) ; e.w("\n")
141 okReg := e.nextReg2("ml")
142 e.w(" ") ; e.w(okReg) ; e.w(" = call i1 @runtime.hashmapBinaryGet(ptr ") ; e.w(mapVal)
143 e.w(", ptr ") ; e.w(keyAlloca)
144 e.w(", ptr ") ; e.w(valAlloca)
145 e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(valSz) ; e.w(", ptr null)\n")
146 e.declareRuntime("runtime.hashmapBinaryGet", "i1", "ptr, ptr, ptr, " | ipt)
147 if l.CommaOk {
148 loaded := e.nextReg2("ml")
149 e.w(" ") ; e.w(loaded) ; e.w(" = load ") ; e.w(valType) ; e.w(", ptr ") ; e.w(valAlloca) ; e.w("\n")
150 tupType := "{" | valType | ", i1}"
151 t1 := e.nextReg2("ml")
152 e.w(" ") ; e.w(t1) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" undef, ") ; e.w(valType) ; e.w(" ") ; e.w(loaded) ; e.w(", 0\n")
153 e.w(" ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t1) ; e.w(", i1 ") ; e.w(okReg) ; e.w(", 1\n")
154 } else {
155 e.w(" ") ; e.w(reg) ; e.w(" = load ") ; e.w(valType) ; e.w(", ptr ") ; e.w(valAlloca) ; e.w("\n")
156 }
157 }
158 }
159
160 func (e *irEmitter) isStringLike(t Type) (ok bool) {
161 if t == nil {
162 return false
163 }
164 if b, ok2 := SafeUnderlying(t).(*Basic); ok2 {
165 return b.Info&IsString != 0
166 }
167 return false
168 }
169