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