control.mx raw
1 package emit
2
3 import (
4 "git.smesh.lol/moxie/pkg/syntax"
5 "git.smesh.lol/moxie/pkg/ssa"
6 "git.smesh.lol/moxie/pkg/token"
7 "git.smesh.lol/moxie/pkg/types"
8 )
9
10 func (e *irEmitter) emitPhi(p *ssa.SSAPhi) {
11 reg := e.regName(p)
12 typ := e.llvmType(p.SSAType())
13 e.w(" ")
14 e.w(reg)
15 e.w(" = phi ")
16 e.w(typ)
17 e.w(" ")
18 blk := p.InstrBlock()
19 if blk == nil {
20 return
21 }
22 for i, edge := range p.Edges {
23 if i > 0 {
24 e.w(", ")
25 }
26 e.w("[")
27 e.w(e.operand(edge))
28 e.w(", ")
29 if blk != nil && i < len(blk.Preds) {
30 pred := blk.Preds[i]
31 if pred != nil {
32 if exitLbl, ok := e.blockExitLabel[pred.Index]; ok {
33 e.w(exitLbl)
34 } else {
35 e.w(e.blockLabel(pred))
36 }
37 } else {
38 e.w("%unknown")
39 }
40 } else {
41 e.w("%unknown")
42 }
43 e.w("]")
44 }
45 e.w("\n")
46 }
47
48 func isNumericLiteral(s string) bool {
49 if len(s) == 0 {
50 return false
51 }
52 c := s[0]
53 if c == '-' && len(s) > 1 {
54 c = s[1]
55 }
56 return c >= '0' && c <= '9'
57 }
58
59 func (e *irEmitter) coerceInt(valReg string, fromType string, toType string) string {
60 if fromType == toType {
61 return valReg
62 }
63 fromBits := e.intBits(fromType)
64 toBits := e.intBits(toType)
65 if fromBits == 0 || toBits == 0 {
66 return valReg
67 }
68 if isNumericLiteral(valReg) {
69 return valReg
70 }
71 e.nextReg++
72 r := "%rc" | irItoa(e.nextReg)
73 if fromBits > toBits {
74 e.w(" ") ; e.w(r) ; e.w(" = trunc ") ; e.w(fromType) ; e.w(" ") ; e.w(valReg) ; e.w(" to ") ; e.w(toType) ; e.w("\n")
75 } else {
76 e.w(" ") ; e.w(r) ; e.w(" = sext ") ; e.w(fromType) ; e.w(" ") ; e.w(valReg) ; e.w(" to ") ; e.w(toType) ; e.w("\n")
77 }
78 return r
79 }
80
81 func (e *irEmitter) intBits(ty string) int32 {
82 switch ty {
83 case "i1":
84 return 1
85 case "i8":
86 return 8
87 case "i16":
88 return 16
89 case "i32":
90 return 32
91 case "i64":
92 return 64
93 }
94 return 0
95 }
96
97 func (e *irEmitter) intToFloat(valReg string, fromType string, toType string) string {
98 if rt, ok := e.regTypes[valReg]; ok && (rt == "double" || rt == "float") {
99 return valReg
100 }
101 e.nextReg++
102 r := "%itf" | irItoa(e.nextReg)
103 e.w(" ") ; e.w(r) ; e.w(" = sitofp ") ; e.w(fromType) ; e.w(" ") ; e.w(valReg) ; e.w(" to ") ; e.w(toType) ; e.w("\n")
104 return r
105 }
106
107 func (e *irEmitter) floatBinOp(op ssa.SSAOp) string {
108 switch op {
109 case ssa.OpAdd: return "fadd"
110 case ssa.OpSub: return "fsub"
111 case ssa.OpMul: return "fmul"
112 case ssa.OpQuo: return "fdiv"
113 case ssa.OpEql: return "fcmp oeq"
114 case ssa.OpNeq: return "fcmp une"
115 case ssa.OpLss: return "fcmp olt"
116 case ssa.OpGtr: return "fcmp ogt"
117 case ssa.OpLeq: return "fcmp ole"
118 case ssa.OpGeq: return "fcmp oge"
119 }
120 return "fadd"
121 }
122
123 func (e *irEmitter) arrayElemType(arrType string) string {
124 // "[6 x double]" -> "double"
125 xPos := -1
126 for i := 0; i < len(arrType); i++ {
127 if arrType[i] == 'x' && i > 0 && arrType[i-1] == ' ' {
128 xPos = i
129 break
130 }
131 }
132 if xPos < 0 || xPos+2 >= len(arrType) {
133 return arrType
134 }
135 end := len(arrType)
136 if arrType[end-1] == ']' {
137 end = end - 1
138 }
139 return arrType[xPos+2 : end]
140 }
141
142 func (e *irEmitter) namedResultType(nr *ssa.SSAAlloc) string {
143 if p, ok := types.SafeUnderlying(nr.SSAType()).(*types.Pointer); ok && p.Elem() != nil {
144 return e.llvmType(p.Elem())
145 }
146 return e.llvmType(nr.SSAType())
147 }
148
149 func (e *irEmitter) emitReturn(r *ssa.SSAReturn) {
150 if len(e.deferList) > 0 {
151 e.emitRunDefers()
152 }
153 e.deallocBeforeReturn(r)
154 frt := e.funcRetType(e.curFunc)
155 if len(r.Results) == 0 {
156 rt := e.funcRetType(e.curFunc)
157 if rt == "void" {
158 e.w(" ret void\n")
159 } else if len(e.curFunc.NamedResults) > 0 {
160 if len(e.curFunc.NamedResults) == 1 {
161 nr := e.curFunc.NamedResults[0]
162 nrt := e.namedResultType(nr)
163 e.nextReg++
164 tmp := "%nr" | irItoa(e.nextReg)
165 e.w(" ") ; e.w(tmp) ; e.w(" = load ") ; e.w(nrt) ; e.w(", ptr ") ; e.w(e.regName(nr)) ; e.w("\n")
166 e.w(" ret ") ; e.w(nrt) ; e.w(" ") ; e.w(tmp) ; e.w("\n")
167 } else {
168 retType := rt
169 e.nextReg++
170 agg := "%nr" | irItoa(e.nextReg)
171 e.w(" ") ; e.w(agg) ; e.w(" = alloca ") ; e.w(retType) ; e.w("\n")
172 e.w(" store ") ; e.w(retType) ; e.w(" zeroinitializer, ptr ") ; e.w(agg) ; e.w("\n")
173 for i, nr := range e.curFunc.NamedResults {
174 nrt := e.namedResultType(nr)
175 e.nextReg++
176 tmp := "%nr" | irItoa(e.nextReg)
177 e.w(" ") ; e.w(tmp) ; e.w(" = load ") ; e.w(nrt) ; e.w(", ptr ") ; e.w(e.regName(nr)) ; e.w("\n")
178 e.nextReg++
179 gep := "%nr" | irItoa(e.nextReg)
180 e.w(" ") ; e.w(gep) ; e.w(" = getelementptr ") ; e.w(retType) ; e.w(", ptr ") ; e.w(agg) ; e.w(", i32 0, i32 ") ; e.w(irItoa(i)) ; e.w("\n")
181 e.w(" store ") ; e.w(nrt) ; e.w(" ") ; e.w(tmp) ; e.w(", ptr ") ; e.w(gep) ; e.w("\n")
182 }
183 e.nextReg++
184 rv := "%nr" | irItoa(e.nextReg)
185 e.w(" ") ; e.w(rv) ; e.w(" = load ") ; e.w(retType) ; e.w(", ptr ") ; e.w(agg) ; e.w("\n")
186 e.w(" ret ") ; e.w(retType) ; e.w(" ") ; e.w(rv) ; e.w("\n")
187 }
188 } else {
189 e.w(" ret ") ; e.w(rt) ; e.w(" zeroinitializer\n")
190 }
191 return
192 }
193 sig := e.curFunc.Signature
194 if len(r.Results) == 1 {
195 typ := e.llvmType(r.Results[0].SSAType())
196 rtyp := e.resolvedType(r.Results[0], typ)
197 if rtyp != typ {
198 typ = rtyp
199 }
200 val := e.operand(r.Results[0])
201 expectType := typ
202 if sig != nil && sig.Results() != nil && sig.Results().Len() == 1 {
203 expectType = e.llvmType(sig.Results().At(0).Type())
204 }
205 if typ == "void" { typ = frt }
206 if expectType == "void" { expectType = frt }
207 if val == "null" && expectType != "ptr" {
208 val = "zeroinitializer"
209 } else {
210 val = e.coerceInt(val, typ, expectType)
211 }
212 if typ != expectType && val != "zeroinitializer" {
213 if expectType == "ptr" && e.intBits(typ) > 0 {
214 e.nextReg++
215 rc := "%rc" | irItoa(e.nextReg)
216 e.w(" ") ; e.w(rc) ; e.w(" = inttoptr ") ; e.w(typ) ; e.w(" ") ; e.w(val) ; e.w(" to ptr\n")
217 val = rc
218 typ = "ptr"
219 } else if typ == "ptr" && e.intBits(expectType) > 0 {
220 e.nextReg++
221 rc := "%rc" | irItoa(e.nextReg)
222 e.w(" ") ; e.w(rc) ; e.w(" = ptrtoint ptr ") ; e.w(val) ; e.w(" to ") ; e.w(expectType) ; e.w("\n")
223 val = rc
224 typ = expectType
225 } else if typ == "double" && expectType == "float" {
226 e.nextReg++
227 rc := "%rc" | irItoa(e.nextReg)
228 e.w(" ") ; e.w(rc) ; e.w(" = fptrunc double ") ; e.w(val) ; e.w(" to float\n")
229 val = rc
230 typ = "float"
231 } else if typ == "float" && expectType == "double" {
232 e.nextReg++
233 rc := "%rc" | irItoa(e.nextReg)
234 e.w(" ") ; e.w(rc) ; e.w(" = fpext float ") ; e.w(val) ; e.w(" to double\n")
235 val = rc
236 typ = "double"
237 }
238 if typ != expectType {
239 val = "zeroinitializer"
240 }
241 }
242 e.w(" ret ")
243 e.w(expectType)
244 e.w(" ")
245 e.w(val)
246 e.w("\n")
247 return
248 }
249 var expectTypes []string
250 if sig != nil && sig.Results() != nil {
251 for i := 0; i < sig.Results().Len(); i++ {
252 expectTypes = append(expectTypes, e.resolveResultType(sig.Results().At(i).Type()))
253 }
254 }
255 retType := "{"
256 for i := 0; i < len(r.Results); i++ {
257 res := r.Results[i]
258 if i > 0 {
259 retType = retType | ", "
260 }
261 if i < len(expectTypes) {
262 retType = retType | expectTypes[i]
263 } else {
264 retType = retType | e.llvmType(res.SSAType())
265 }
266 }
267 retType = retType | "}"
268 prev := "undef"
269 for i := 0; i < len(r.Results); i++ {
270 res := r.Results[i]
271 valType := e.llvmType(res.SSAType())
272 valOp := e.operand(res)
273 if _, ok := res.(*ssa.SSACall); ok && i < len(expectTypes) {
274 if valType != expectTypes[i] && len(valType) > 0 && valType[0] == '{' {
275 field := extractTupleField(valType, i)
276 if field == expectTypes[i] {
277 e.nextReg++
278 exReg := "%rex" | irItoa(e.nextReg)
279 e.w(" ") ; e.w(exReg) ; e.w(" = extractvalue ") ; e.w(valType) ; e.w(" ") ; e.w(valOp) ; e.w(", ") ; e.w(irItoa(i)) ; e.w("\n")
280 valOp = exReg
281 valType = expectTypes[i]
282 }
283 }
284 }
285 elemType := valType
286 if i < len(expectTypes) {
287 elemType = expectTypes[i]
288 if valOp == "null" && elemType != "ptr" {
289 valOp = "zeroinitializer"
290 } else if (elemType == "double" || elemType == "float") && isConstOperand(valOp) {
291 valOp = ensureTokenFloatLit(valOp)
292 } else if (elemType == "double" || elemType == "float") && e.intBits(valType) > 0 {
293 valOp = e.intToFloat(valOp, valType, elemType)
294 } else if valType == "double" && elemType == "float" {
295 e.nextReg++
296 fc := "%fc" | irItoa(e.nextReg)
297 e.w(" ") ; e.w(fc) ; e.w(" = fptrunc double ") ; e.w(valOp) ; e.w(" to float\n")
298 valOp = fc
299 } else if valType == "float" && elemType == "double" {
300 e.nextReg++
301 fc := "%fc" | irItoa(e.nextReg)
302 e.w(" ") ; e.w(fc) ; e.w(" = fpext float ") ; e.w(valOp) ; e.w(" to double\n")
303 valOp = fc
304 } else {
305 valOp = e.coerceInt(valOp, valType, elemType)
306 }
307 }
308 e.nextReg++
309 cur := "%rv" | irItoa(e.nextReg)
310 e.w(" ")
311 e.w(cur)
312 e.w(" = insertvalue ")
313 e.w(retType)
314 e.w(" ")
315 e.w(prev)
316 e.w(", ")
317 e.w(elemType)
318 e.w(" ")
319 e.w(valOp)
320 e.w(", ")
321 e.w(irItoa(i))
322 e.w("\n")
323 prev = cur
324 }
325 e.w(" ret ")
326 e.w(retType)
327 e.w(" ")
328 e.w(prev)
329 e.w("\n")
330 }
331
332 func blockHasReturn(b *ssa.SSABasicBlock) bool {
333 for _, instr := range b.Instrs {
334 if _, ok := instr.(*ssa.SSAReturn); ok {
335 return true
336 }
337 }
338 return false
339 }
340
341 func (e *irEmitter) emitJump(j *ssa.SSAJump) {
342 blk := j.InstrBlock()
343 if blk == nil {
344 return
345 }
346 if len(blk.Succs) > 0 {
347 target := blk.Succs[0]
348 if blk.ScopeID > 0 && target.ScopeID != blk.ScopeID && !blockHasReturn(target) {
349 e.emitScopeFreesTo(blk.ScopeID)
350 }
351 e.w(" br label ")
352 e.w(e.blockLabel(target))
353 e.w("\n")
354 }
355 }
356
357 func isComparisonOp(op ssa.SSAOp) bool {
358 return op == ssa.OpEql || op == ssa.OpNeq || op == ssa.OpLss || op == ssa.OpLeq || op == ssa.OpGtr || op == ssa.OpGeq
359 }
360
361 func (e *irEmitter) emitIf(i *ssa.SSAIf) {
362 blk := i.InstrBlock()
363 if i.Cond == nil {
364 if len(blk.Succs) >= 2 {
365 e.w(" br label ")
366 e.w(e.blockLabel(blk.Succs[1]))
367 e.w("\n")
368 } else {
369 e.w(" unreachable\n")
370 }
371 return
372 }
373 cond := e.operand(i.Cond)
374 condType := e.llvmType(i.Cond.SSAType())
375 if at, ok := e.allocTypes[i.Cond]; ok {
376 condType = at
377 }
378 if bop, ok := i.Cond.(*ssa.SSABinOp); ok && isComparisonOp(bop.Op) {
379 condType = "i1"
380 }
381 if cond == "true" || cond == "false" {
382 condType = "i1"
383 }
384 if _, isNot := i.Cond.(*ssa.SSAUnOp); isNot {
385 if rt, ok2 := e.regTypes[e.regName(i.Cond)]; ok2 && rt == "i1" {
386 condType = "i1"
387 }
388 }
389 if condType != "i1" && condType != "" && condType != "void" {
390 e.nextReg++
391 truncReg := "%ift" | irItoa(e.nextReg)
392 if condType == "ptr" {
393 e.w(" ") ; e.w(truncReg) ; e.w(" = icmp ne ptr ") ; e.w(cond) ; e.w(", null\n")
394 } else if len(condType) > 0 && condType[0] == '{' {
395 e.nextReg++
396 extReg := "%ife" | irItoa(e.nextReg)
397 e.w(" ") ; e.w(extReg) ; e.w(" = extractvalue ") ; e.w(condType) ; e.w(" ") ; e.w(cond) ; e.w(", 0\n")
398 e.w(" ") ; e.w(truncReg) ; e.w(" = icmp ne ptr ") ; e.w(extReg) ; e.w(", null\n")
399 } else {
400 e.w(" ") ; e.w(truncReg) ; e.w(" = trunc ") ; e.w(condType) ; e.w(" ") ; e.w(cond) ; e.w(" to i1\n")
401 }
402 cond = truncReg
403 }
404 if len(blk.Succs) >= 2 {
405 e.w(" br i1 ")
406 e.w(cond)
407 e.w(", label ")
408 e.w(e.blockLabel(blk.Succs[0]))
409 e.w(", label ")
410 e.w(e.blockLabel(blk.Succs[1]))
411 e.w("\n")
412 }
413 }
414
415 func (e *irEmitter) emitConvert(c *ssa.SSAConvert) {
416 reg := e.regName(c)
417 srcType := e.llvmType(c.X.SSAType())
418 dstType := e.llvmType(c.SSAType())
419 val := e.operand(c.X)
420
421 if srcType != "ptr" {
422 resolved := e.resolvedType(c.X, srcType)
423 if resolved != srcType {
424 srcType = resolved
425 }
426 }
427
428 if srcType == "void" || c.X.SSAType() == nil {
429 if dstType == "ptr" {
430 e.valName[c] = "null"
431 } else {
432 e.valName[c] = "zeroinitializer"
433 }
434 return
435 }
436
437 if srcType == dstType {
438 e.valName[c] = val
439 e.allocTypes[c] = srcType
440 return
441 }
442
443 if srcType == e.sliceType() && len(dstType) > 0 && dstType[0] == '[' {
444 dp := e.nextReg2("cv")
445 e.w(" ") ; e.w(dp) ; e.w(" = extractvalue ") ; e.w(srcType) ; e.w(" ") ; e.w(val) ; e.w(", 0\n")
446 e.w(" ") ; e.w(reg) ; e.w(" = load ") ; e.w(dstType) ; e.w(", ptr ") ; e.w(dp) ; e.w("\n")
447 return
448 }
449
450 srcIsInt := false
451 if b, ok := types.SafeUnderlying(c.X.SSAType()).(*types.Basic); ok {
452 srcIsInt = b.Info()&types.IsInteger != 0
453 }
454 if !srcIsInt && len(srcType) > 0 && srcType[0] == 'i' {
455 srcIsInt = true
456 }
457 if (e.isStringLike(c.SSAType()) || dstType == e.sliceType()) && srcIsInt {
458 if k, ok := c.X.(*ssa.SSAConst); ok {
459 rv := int64(0)
460 if ci, ok2 := k.Value().(*types.ConstInt); ok2 {
461 rv = ci.V
462 }
463 s := runeToUTF8(rune(rv))
464 idx := e.addStringConst(s)
465 ipt := e.intptrType()
466 slen := irItoa64(int64(len(s)))
467 e.valName[c] = "{ ptr " | e.strConstGlobal(idx) | ", " | ipt | " " | slen | ", " | ipt | " " | slen | " }"
468 return
469 }
470 e.declareRuntime("runtime.stringFromUnicode", e.sliceType(), "i32, ptr")
471 srcVal := val
472 if srcType != "i32" {
473 e.nextReg++
474 srcVal = "%cv" | irItoa(e.nextReg)
475 if e.typeBits(c.X.SSAType()) < 32 {
476 e.w(" ") ; e.w(srcVal) ; e.w(" = sext ") ; e.w(srcType) ; e.w(" ") ; e.w(val) ; e.w(" to i32\n")
477 } else if e.typeBits(c.X.SSAType()) > 32 {
478 e.w(" ") ; e.w(srcVal) ; e.w(" = trunc ") ; e.w(srcType) ; e.w(" ") ; e.w(val) ; e.w(" to i32\n")
479 }
480 }
481 e.w(" ") ; e.w(reg) ; e.w(" = call ") ; e.w(e.sliceType()) ; e.w(" @runtime.stringFromUnicode(i32 ") ; e.w(srcVal) ; e.w(", ptr null)\n")
482 return
483 }
484
485 op := e.conversionOp(c.X.SSAType(), c.SSAType())
486 srcBitsLLVM := e.intBits(srcType)
487 dstBitsLLVM := e.intBits(dstType)
488 if (op == "sext" || op == "zext") && srcBitsLLVM > 0 && dstBitsLLVM > 0 && srcBitsLLVM > dstBitsLLVM {
489 op = "trunc"
490 } else if op == "trunc" && srcBitsLLVM > 0 && dstBitsLLVM > 0 && srcBitsLLVM < dstBitsLLVM {
491 op = "sext"
492 }
493 srcIsFloat := srcType == "double" || srcType == "float"
494 dstIsFloat := dstType == "double" || dstType == "float"
495 if op == "trunc" && srcIsFloat && !dstIsFloat {
496 op = "fptosi"
497 } else if op == "trunc" && !srcIsFloat && dstIsFloat {
498 op = "sitofp"
499 } else if (op == "sext" || op == "zext") && !srcIsFloat && dstIsFloat {
500 op = "sitofp"
501 } else if (op == "sext" || op == "zext") && srcIsFloat && !dstIsFloat {
502 op = "fptosi"
503 } else if op == "bitcast" && srcIsFloat != dstIsFloat {
504 if srcIsFloat {
505 op = "fptosi"
506 } else {
507 op = "sitofp"
508 }
509 } else if (op == "sext" || op == "zext" || op == "trunc") && srcIsFloat && dstIsFloat {
510 if e.intBits(srcType) < e.intBits(dstType) {
511 op = "fpext"
512 } else {
513 op = "fptrunc"
514 }
515 }
516 if op == "ptrtoint" && e.intBits(dstType) == 0 {
517 if dstType == e.ifaceType() {
518 typeid := e.typeIDGlobal(c.X.SSAType())
519 t1 := e.nextReg2("cv")
520 e.w(" ") ; e.w(t1) ; e.w(" = insertvalue {ptr, ptr} undef, ptr ") ; e.w(typeid) ; e.w(", 0\n")
521 e.w(" ") ; e.w(reg) ; e.w(" = insertvalue {ptr, ptr} ") ; e.w(t1) ; e.w(", ptr ") ; e.w(val) ; e.w(", 1\n")
522 } else {
523 e.valName[c] = "zeroinitializer"
524 }
525 return
526 }
527 if op == "inttoptr" && e.intBits(srcType) == 0 {
528 if srcType == e.ifaceType() {
529 e.nextReg++
530 r := "%cv" | irItoa(e.nextReg)
531 e.w(" ") ; e.w(r) ; e.w(" = extractvalue {ptr, ptr} ") ; e.w(val) ; e.w(", 1\n")
532 e.valName[c] = r
533 } else {
534 e.valName[c] = "null"
535 }
536 return
537 }
538 e.w(" ")
539 e.w(reg)
540 e.w(" = ")
541 e.w(op)
542 e.w(" ")
543 e.w(srcType)
544 e.w(" ")
545 e.w(val)
546 e.w(" to ")
547 e.w(dstType)
548 e.w("\n")
549 if e.intBits(dstType) > 0 || dstType == "ptr" {
550 e.setRegType(c, reg, dstType)
551 }
552 }
553
554 func (e *irEmitter) conversionOp(from, to syntax.Type) string {
555 fromBits := e.typeBits(from)
556 toBits := e.typeBits(to)
557
558 fromFloat := false
559 toFloat := false
560 fromSigned := true
561 if b, ok := types.SafeUnderlying(from).(*types.Basic); ok {
562 fromFloat = b.Info()&types.IsFloat != 0
563 if b.Info()&types.IsUnsigned != 0 {
564 fromSigned = false
565 }
566 }
567 if b, ok := types.SafeUnderlying(to).(*types.Basic); ok {
568 toFloat = b.Info()&types.IsFloat != 0
569 }
570
571 if fromFloat && toFloat {
572 if fromBits < toBits {
573 return "fpext"
574 }
575 return "fptrunc"
576 }
577 if fromFloat && !toFloat {
578 if fromSigned {
579 return "fptosi"
580 }
581 return "fptoui"
582 }
583 if !fromFloat && toFloat {
584 if fromSigned {
585 return "sitofp"
586 }
587 return "uitofp"
588 }
589
590 _, fromPtr := types.SafeUnderlying(from).(*types.Pointer)
591 _, toPtr := types.SafeUnderlying(to).(*types.Pointer)
592 if !fromPtr && e.llvmType(from) == "ptr" {
593 fromPtr = true
594 }
595 if !toPtr && e.llvmType(to) == "ptr" {
596 toPtr = true
597 }
598 if fromPtr && !toPtr {
599 return "ptrtoint"
600 }
601 if !fromPtr && toPtr {
602 return "inttoptr"
603 }
604
605 if fromBits < toBits {
606 toUnsigned := false
607 if b, ok := types.SafeUnderlying(to).(*types.Basic); ok && b.Info()&types.IsUnsigned != 0 {
608 toUnsigned = true
609 }
610 if fromSigned && !toUnsigned {
611 return "sext"
612 }
613 return "zext"
614 }
615 if fromBits > toBits {
616 return "trunc"
617 }
618 return "bitcast"
619 }
620
621 func (e *irEmitter) typeBits(t syntax.Type) int32 {
622 if t == nil {
623 return 0
624 }
625 switch t := types.SafeUnderlying(t).(type) {
626 case *types.Basic:
627 switch t.Kind() {
628 case types.Bool:
629 return 1
630 case types.Int8, types.Uint8:
631 return 8
632 case types.Int16, types.Uint16:
633 return 16
634 case types.Int32, types.Uint32:
635 return 32
636 case types.Int64, types.Uint64:
637 return 64
638 case types.Float32:
639 return 32
640 case types.Float64:
641 return 64
642 case types.UntypedInt, types.UntypedRune:
643 return 32
644 case types.UntypedFloat:
645 return 64
646 case types.UnsafePointer:
647 return e.ptrBits
648 }
649 case *types.Pointer:
650 return e.ptrBits
651 }
652 return 0
653 }
654
655 func (e *irEmitter) emitChangeType(c *ssa.SSAChangeType) {
656 srcType := e.llvmType(c.X.SSAType())
657 dstType := e.llvmType(c.SSAType())
658 if at, ok := e.allocTypes[c.X]; ok && at != "ptr" && at != "void" {
659 srcType = at
660 }
661 if srcType == dstType || (srcType == "ptr" && dstType == "ptr") {
662 e.valName[c] = e.operand(c.X)
663 return
664 }
665 reg := e.regName(c)
666 val := e.operand(c.X)
667 e.nextReg++
668 tmp := "%ct" | irItoa(e.nextReg)
669 e.w(" ") ; e.w(tmp) ; e.w(" = alloca ") ; e.w(dstType) ; e.w("\n")
670 e.w(" store ") ; e.w(srcType) ; e.w(" ") ; e.w(val) ; e.w(", ptr ") ; e.w(tmp) ; e.w("\n")
671 e.w(" ") ; e.w(reg) ; e.w(" = load ") ; e.w(dstType) ; e.w(", ptr ") ; e.w(tmp) ; e.w("\n")
672 }
673