github.com/axw/llgo@v0.0.0-20160805011314-95b5fe4dca20/irgen/value.go (about) 1 //===- value.go - govalue and operations ----------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the govalue type, which combines an LLVM value with its Go 11 // type, and implements various basic operations on govalues. 12 // 13 //===----------------------------------------------------------------------===// 14 15 package irgen 16 17 import ( 18 "fmt" 19 "go/token" 20 21 "llvm.org/llgo/third_party/gotools/go/exact" 22 "llvm.org/llgo/third_party/gotools/go/types" 23 "llvm.org/llvm/bindings/go/llvm" 24 ) 25 26 // govalue contains an LLVM value and a Go type, 27 // representing the result of a Go expression. 28 type govalue struct { 29 value llvm.Value 30 typ types.Type 31 } 32 33 func (v *govalue) String() string { 34 return fmt.Sprintf("[llgo.govalue typ:%s value:%v]", v.typ, v.value) 35 } 36 37 // Create a new dynamic value from a (LLVM Value, Type) pair. 38 func newValue(v llvm.Value, t types.Type) *govalue { 39 return &govalue{v, t} 40 } 41 42 // TODO(axw) remove this, use .typ directly 43 func (v *govalue) Type() types.Type { 44 return v.typ 45 } 46 47 // newValueFromConst converts a constant value to an LLVM value. 48 func (fr *frame) newValueFromConst(v exact.Value, typ types.Type) *govalue { 49 switch { 50 case v == nil: 51 llvmtyp := fr.types.ToLLVM(typ) 52 return newValue(llvm.ConstNull(llvmtyp), typ) 53 54 case isString(typ): 55 if isUntyped(typ) { 56 typ = types.Typ[types.String] 57 } 58 llvmtyp := fr.types.ToLLVM(typ) 59 strval := exact.StringVal(v) 60 strlen := len(strval) 61 i8ptr := llvm.PointerType(llvm.Int8Type(), 0) 62 var ptr llvm.Value 63 if strlen > 0 { 64 init := llvm.ConstString(strval, false) 65 ptr = llvm.AddGlobal(fr.module.Module, init.Type(), "") 66 ptr.SetInitializer(init) 67 ptr.SetLinkage(llvm.InternalLinkage) 68 ptr = llvm.ConstBitCast(ptr, i8ptr) 69 } else { 70 ptr = llvm.ConstNull(i8ptr) 71 } 72 len_ := llvm.ConstInt(fr.types.inttype, uint64(strlen), false) 73 llvmvalue := llvm.Undef(llvmtyp) 74 llvmvalue = llvm.ConstInsertValue(llvmvalue, ptr, []uint32{0}) 75 llvmvalue = llvm.ConstInsertValue(llvmvalue, len_, []uint32{1}) 76 return newValue(llvmvalue, typ) 77 78 case isInteger(typ): 79 if isUntyped(typ) { 80 typ = types.Typ[types.Int] 81 } 82 llvmtyp := fr.types.ToLLVM(typ) 83 var llvmvalue llvm.Value 84 if isUnsigned(typ) { 85 v, _ := exact.Uint64Val(v) 86 llvmvalue = llvm.ConstInt(llvmtyp, v, false) 87 } else { 88 v, _ := exact.Int64Val(v) 89 llvmvalue = llvm.ConstInt(llvmtyp, uint64(v), true) 90 } 91 return newValue(llvmvalue, typ) 92 93 case isBoolean(typ): 94 if isUntyped(typ) { 95 typ = types.Typ[types.Bool] 96 } 97 return newValue(boolLLVMValue(exact.BoolVal(v)), typ) 98 99 case isFloat(typ): 100 if isUntyped(typ) { 101 typ = types.Typ[types.Float64] 102 } 103 llvmtyp := fr.types.ToLLVM(typ) 104 floatval, _ := exact.Float64Val(v) 105 llvmvalue := llvm.ConstFloat(llvmtyp, floatval) 106 return newValue(llvmvalue, typ) 107 108 case typ == types.Typ[types.UnsafePointer]: 109 llvmtyp := fr.types.ToLLVM(typ) 110 v, _ := exact.Uint64Val(v) 111 llvmvalue := llvm.ConstInt(fr.types.inttype, v, false) 112 llvmvalue = llvm.ConstIntToPtr(llvmvalue, llvmtyp) 113 return newValue(llvmvalue, typ) 114 115 case isComplex(typ): 116 if isUntyped(typ) { 117 typ = types.Typ[types.Complex128] 118 } 119 llvmtyp := fr.types.ToLLVM(typ) 120 floattyp := llvmtyp.StructElementTypes()[0] 121 llvmvalue := llvm.ConstNull(llvmtyp) 122 realv := exact.Real(v) 123 imagv := exact.Imag(v) 124 realfloatval, _ := exact.Float64Val(realv) 125 imagfloatval, _ := exact.Float64Val(imagv) 126 llvmre := llvm.ConstFloat(floattyp, realfloatval) 127 llvmim := llvm.ConstFloat(floattyp, imagfloatval) 128 llvmvalue = llvm.ConstInsertValue(llvmvalue, llvmre, []uint32{0}) 129 llvmvalue = llvm.ConstInsertValue(llvmvalue, llvmim, []uint32{1}) 130 return newValue(llvmvalue, typ) 131 } 132 133 // Special case for string -> [](byte|rune) 134 if u, ok := typ.Underlying().(*types.Slice); ok && isInteger(u.Elem()) { 135 if v.Kind() == exact.String { 136 strval := fr.newValueFromConst(v, types.Typ[types.String]) 137 return fr.convert(strval, typ) 138 } 139 } 140 141 panic(fmt.Sprintf("unhandled: t=%s(%T), v=%v(%T)", typ, typ, v, v)) 142 } 143 144 func (fr *frame) binaryOp(lhs *govalue, op token.Token, rhs *govalue) *govalue { 145 if op == token.NEQ { 146 result := fr.binaryOp(lhs, token.EQL, rhs) 147 return fr.unaryOp(result, token.NOT) 148 } 149 150 var result llvm.Value 151 b := fr.builder 152 153 switch typ := lhs.typ.Underlying().(type) { 154 case *types.Struct: 155 // TODO(axw) use runtime equality algorithm (will be suitably inlined). 156 // For now, we use compare all fields unconditionally and bitwise AND 157 // to avoid branching (i.e. so we don't create additional blocks). 158 value := newValue(boolLLVMValue(true), types.Typ[types.Bool]) 159 for i := 0; i < typ.NumFields(); i++ { 160 t := typ.Field(i).Type() 161 lhs := newValue(b.CreateExtractValue(lhs.value, i, ""), t) 162 rhs := newValue(b.CreateExtractValue(rhs.value, i, ""), t) 163 value = fr.binaryOp(value, token.AND, fr.binaryOp(lhs, token.EQL, rhs)) 164 } 165 return value 166 167 case *types.Array: 168 // TODO(pcc): as above. 169 value := newValue(boolLLVMValue(true), types.Typ[types.Bool]) 170 t := typ.Elem() 171 for i := int64(0); i < typ.Len(); i++ { 172 lhs := newValue(b.CreateExtractValue(lhs.value, int(i), ""), t) 173 rhs := newValue(b.CreateExtractValue(rhs.value, int(i), ""), t) 174 value = fr.binaryOp(value, token.AND, fr.binaryOp(lhs, token.EQL, rhs)) 175 } 176 return value 177 178 case *types.Slice: 179 // []T == nil or nil == []T 180 lhsptr := b.CreateExtractValue(lhs.value, 0, "") 181 rhsptr := b.CreateExtractValue(rhs.value, 0, "") 182 isnil := b.CreateICmp(llvm.IntEQ, lhsptr, rhsptr, "") 183 isnil = b.CreateZExt(isnil, llvm.Int8Type(), "") 184 return newValue(isnil, types.Typ[types.Bool]) 185 186 case *types.Signature: 187 // func == nil or nil == func 188 isnil := b.CreateICmp(llvm.IntEQ, lhs.value, rhs.value, "") 189 isnil = b.CreateZExt(isnil, llvm.Int8Type(), "") 190 return newValue(isnil, types.Typ[types.Bool]) 191 192 case *types.Interface: 193 return fr.compareInterfaces(lhs, rhs) 194 } 195 196 // Strings. 197 if isString(lhs.typ) { 198 if isString(rhs.typ) { 199 switch op { 200 case token.ADD: 201 return fr.concatenateStrings(lhs, rhs) 202 case token.EQL, token.LSS, token.GTR, token.LEQ, token.GEQ: 203 return fr.compareStrings(lhs, rhs, op) 204 default: 205 panic(fmt.Sprint("Unimplemented operator: ", op)) 206 } 207 } 208 panic("unimplemented") 209 } 210 211 // Complex numbers. 212 if isComplex(lhs.typ) { 213 // XXX Should we represent complex numbers as vectors? 214 lhsval := lhs.value 215 rhsval := rhs.value 216 a_ := b.CreateExtractValue(lhsval, 0, "") 217 b_ := b.CreateExtractValue(lhsval, 1, "") 218 c_ := b.CreateExtractValue(rhsval, 0, "") 219 d_ := b.CreateExtractValue(rhsval, 1, "") 220 switch op { 221 case token.QUO: 222 // (a+bi)/(c+di) = (ac+bd)/(c**2+d**2) + (bc-ad)/(c**2+d**2)i 223 ac := b.CreateFMul(a_, c_, "") 224 bd := b.CreateFMul(b_, d_, "") 225 bc := b.CreateFMul(b_, c_, "") 226 ad := b.CreateFMul(a_, d_, "") 227 cpow2 := b.CreateFMul(c_, c_, "") 228 dpow2 := b.CreateFMul(d_, d_, "") 229 denom := b.CreateFAdd(cpow2, dpow2, "") 230 realnumer := b.CreateFAdd(ac, bd, "") 231 imagnumer := b.CreateFSub(bc, ad, "") 232 real_ := b.CreateFDiv(realnumer, denom, "") 233 imag_ := b.CreateFDiv(imagnumer, denom, "") 234 lhsval = b.CreateInsertValue(lhsval, real_, 0, "") 235 result = b.CreateInsertValue(lhsval, imag_, 1, "") 236 case token.MUL: 237 // (a+bi)(c+di) = (ac-bd)+(bc+ad)i 238 ac := b.CreateFMul(a_, c_, "") 239 bd := b.CreateFMul(b_, d_, "") 240 bc := b.CreateFMul(b_, c_, "") 241 ad := b.CreateFMul(a_, d_, "") 242 real_ := b.CreateFSub(ac, bd, "") 243 imag_ := b.CreateFAdd(bc, ad, "") 244 lhsval = b.CreateInsertValue(lhsval, real_, 0, "") 245 result = b.CreateInsertValue(lhsval, imag_, 1, "") 246 case token.ADD: 247 real_ := b.CreateFAdd(a_, c_, "") 248 imag_ := b.CreateFAdd(b_, d_, "") 249 lhsval = b.CreateInsertValue(lhsval, real_, 0, "") 250 result = b.CreateInsertValue(lhsval, imag_, 1, "") 251 case token.SUB: 252 real_ := b.CreateFSub(a_, c_, "") 253 imag_ := b.CreateFSub(b_, d_, "") 254 lhsval = b.CreateInsertValue(lhsval, real_, 0, "") 255 result = b.CreateInsertValue(lhsval, imag_, 1, "") 256 case token.EQL: 257 realeq := b.CreateFCmp(llvm.FloatOEQ, a_, c_, "") 258 imageq := b.CreateFCmp(llvm.FloatOEQ, b_, d_, "") 259 result = b.CreateAnd(realeq, imageq, "") 260 result = b.CreateZExt(result, llvm.Int8Type(), "") 261 return newValue(result, types.Typ[types.Bool]) 262 default: 263 panic(fmt.Errorf("unhandled operator: %v", op)) 264 } 265 return newValue(result, lhs.typ) 266 } 267 268 // Floats and integers. 269 // TODO determine the NaN rules. 270 271 switch op { 272 case token.MUL: 273 if isFloat(lhs.typ) { 274 result = b.CreateFMul(lhs.value, rhs.value, "") 275 } else { 276 result = b.CreateMul(lhs.value, rhs.value, "") 277 } 278 return newValue(result, lhs.typ) 279 case token.QUO: 280 switch { 281 case isFloat(lhs.typ): 282 result = b.CreateFDiv(lhs.value, rhs.value, "") 283 case !isUnsigned(lhs.typ): 284 result = b.CreateSDiv(lhs.value, rhs.value, "") 285 default: 286 result = b.CreateUDiv(lhs.value, rhs.value, "") 287 } 288 return newValue(result, lhs.typ) 289 case token.REM: 290 switch { 291 case isFloat(lhs.typ): 292 result = b.CreateFRem(lhs.value, rhs.value, "") 293 case !isUnsigned(lhs.typ): 294 result = b.CreateSRem(lhs.value, rhs.value, "") 295 default: 296 result = b.CreateURem(lhs.value, rhs.value, "") 297 } 298 return newValue(result, lhs.typ) 299 case token.ADD: 300 if isFloat(lhs.typ) { 301 result = b.CreateFAdd(lhs.value, rhs.value, "") 302 } else { 303 result = b.CreateAdd(lhs.value, rhs.value, "") 304 } 305 return newValue(result, lhs.typ) 306 case token.SUB: 307 if isFloat(lhs.typ) { 308 result = b.CreateFSub(lhs.value, rhs.value, "") 309 } else { 310 result = b.CreateSub(lhs.value, rhs.value, "") 311 } 312 return newValue(result, lhs.typ) 313 case token.SHL, token.SHR: 314 return fr.shift(lhs, rhs, op) 315 case token.EQL: 316 if isFloat(lhs.typ) { 317 result = b.CreateFCmp(llvm.FloatOEQ, lhs.value, rhs.value, "") 318 } else { 319 result = b.CreateICmp(llvm.IntEQ, lhs.value, rhs.value, "") 320 } 321 result = b.CreateZExt(result, llvm.Int8Type(), "") 322 return newValue(result, types.Typ[types.Bool]) 323 case token.LSS: 324 switch { 325 case isFloat(lhs.typ): 326 result = b.CreateFCmp(llvm.FloatOLT, lhs.value, rhs.value, "") 327 case !isUnsigned(lhs.typ): 328 result = b.CreateICmp(llvm.IntSLT, lhs.value, rhs.value, "") 329 default: 330 result = b.CreateICmp(llvm.IntULT, lhs.value, rhs.value, "") 331 } 332 result = b.CreateZExt(result, llvm.Int8Type(), "") 333 return newValue(result, types.Typ[types.Bool]) 334 case token.LEQ: 335 switch { 336 case isFloat(lhs.typ): 337 result = b.CreateFCmp(llvm.FloatOLE, lhs.value, rhs.value, "") 338 case !isUnsigned(lhs.typ): 339 result = b.CreateICmp(llvm.IntSLE, lhs.value, rhs.value, "") 340 default: 341 result = b.CreateICmp(llvm.IntULE, lhs.value, rhs.value, "") 342 } 343 result = b.CreateZExt(result, llvm.Int8Type(), "") 344 return newValue(result, types.Typ[types.Bool]) 345 case token.GTR: 346 switch { 347 case isFloat(lhs.typ): 348 result = b.CreateFCmp(llvm.FloatOGT, lhs.value, rhs.value, "") 349 case !isUnsigned(lhs.typ): 350 result = b.CreateICmp(llvm.IntSGT, lhs.value, rhs.value, "") 351 default: 352 result = b.CreateICmp(llvm.IntUGT, lhs.value, rhs.value, "") 353 } 354 result = b.CreateZExt(result, llvm.Int8Type(), "") 355 return newValue(result, types.Typ[types.Bool]) 356 case token.GEQ: 357 switch { 358 case isFloat(lhs.typ): 359 result = b.CreateFCmp(llvm.FloatOGE, lhs.value, rhs.value, "") 360 case !isUnsigned(lhs.typ): 361 result = b.CreateICmp(llvm.IntSGE, lhs.value, rhs.value, "") 362 default: 363 result = b.CreateICmp(llvm.IntUGE, lhs.value, rhs.value, "") 364 } 365 result = b.CreateZExt(result, llvm.Int8Type(), "") 366 return newValue(result, types.Typ[types.Bool]) 367 case token.AND: // a & b 368 result = b.CreateAnd(lhs.value, rhs.value, "") 369 return newValue(result, lhs.typ) 370 case token.AND_NOT: // a &^ b 371 rhsval := rhs.value 372 rhsval = b.CreateXor(rhsval, llvm.ConstAllOnes(rhsval.Type()), "") 373 result = b.CreateAnd(lhs.value, rhsval, "") 374 return newValue(result, lhs.typ) 375 case token.OR: // a | b 376 result = b.CreateOr(lhs.value, rhs.value, "") 377 return newValue(result, lhs.typ) 378 case token.XOR: // a ^ b 379 result = b.CreateXor(lhs.value, rhs.value, "") 380 return newValue(result, lhs.typ) 381 default: 382 panic(fmt.Sprint("Unimplemented operator: ", op)) 383 } 384 panic("unreachable") 385 } 386 387 func (fr *frame) shift(lhs *govalue, rhs *govalue, op token.Token) *govalue { 388 rhs = fr.convert(rhs, lhs.Type()) 389 lhsval := lhs.value 390 bits := rhs.value 391 unsigned := isUnsigned(lhs.Type()) 392 // Shifting >= width of lhs yields undefined behaviour, so we must select. 393 max := llvm.ConstInt(bits.Type(), uint64(lhsval.Type().IntTypeWidth()-1), false) 394 var result llvm.Value 395 lessEqualWidth := fr.builder.CreateICmp(llvm.IntULE, bits, max, "") 396 if !unsigned && op == token.SHR { 397 bits := fr.builder.CreateSelect(lessEqualWidth, bits, max, "") 398 result = fr.builder.CreateAShr(lhsval, bits, "") 399 } else { 400 if op == token.SHL { 401 result = fr.builder.CreateShl(lhsval, bits, "") 402 } else { 403 result = fr.builder.CreateLShr(lhsval, bits, "") 404 } 405 zero := llvm.ConstNull(lhsval.Type()) 406 result = fr.builder.CreateSelect(lessEqualWidth, result, zero, "") 407 } 408 return newValue(result, lhs.typ) 409 } 410 411 func (fr *frame) unaryOp(v *govalue, op token.Token) *govalue { 412 switch op { 413 case token.SUB: 414 var value llvm.Value 415 if isComplex(v.typ) { 416 realv := fr.builder.CreateExtractValue(v.value, 0, "") 417 imagv := fr.builder.CreateExtractValue(v.value, 1, "") 418 negzero := llvm.ConstFloatFromString(realv.Type(), "-0") 419 realv = fr.builder.CreateFSub(negzero, realv, "") 420 imagv = fr.builder.CreateFSub(negzero, imagv, "") 421 value = llvm.Undef(v.value.Type()) 422 value = fr.builder.CreateInsertValue(value, realv, 0, "") 423 value = fr.builder.CreateInsertValue(value, imagv, 1, "") 424 } else if isFloat(v.typ) { 425 negzero := llvm.ConstFloatFromString(fr.types.ToLLVM(v.Type()), "-0") 426 value = fr.builder.CreateFSub(negzero, v.value, "") 427 } else { 428 value = fr.builder.CreateNeg(v.value, "") 429 } 430 return newValue(value, v.typ) 431 case token.ADD: 432 return v // No-op 433 case token.NOT: 434 value := fr.builder.CreateXor(v.value, boolLLVMValue(true), "") 435 return newValue(value, v.typ) 436 case token.XOR: 437 lhs := v.value 438 rhs := llvm.ConstAllOnes(lhs.Type()) 439 value := fr.builder.CreateXor(lhs, rhs, "") 440 return newValue(value, v.typ) 441 default: 442 panic(fmt.Sprintf("Unhandled operator: %s", op)) 443 } 444 } 445 446 func (fr *frame) convert(v *govalue, dsttyp types.Type) *govalue { 447 b := fr.builder 448 449 // If it's a stack allocated value, we'll want to compare the 450 // value type, not the pointer type. 451 srctyp := v.typ 452 453 // Get the underlying type, if any. 454 origdsttyp := dsttyp 455 dsttyp = dsttyp.Underlying() 456 srctyp = srctyp.Underlying() 457 458 // Identical (underlying) types? Just swap in the destination type. 459 if types.Identical(srctyp, dsttyp) { 460 return newValue(v.value, origdsttyp) 461 } 462 463 // Both pointer types with identical underlying types? Same as above. 464 if srctyp, ok := srctyp.(*types.Pointer); ok { 465 if dsttyp, ok := dsttyp.(*types.Pointer); ok { 466 srctyp := srctyp.Elem().Underlying() 467 dsttyp := dsttyp.Elem().Underlying() 468 if types.Identical(srctyp, dsttyp) { 469 return newValue(v.value, origdsttyp) 470 } 471 } 472 } 473 474 // string -> 475 if isString(srctyp) { 476 // (untyped) string -> string 477 // XXX should untyped strings be able to escape go/types? 478 if isString(dsttyp) { 479 return newValue(v.value, origdsttyp) 480 } 481 482 // string -> []byte 483 if isSlice(dsttyp, types.Byte) { 484 sliceValue := fr.runtime.stringToByteArray.callOnly(fr, v.value)[0] 485 return newValue(sliceValue, origdsttyp) 486 } 487 488 // string -> []rune 489 if isSlice(dsttyp, types.Rune) { 490 return fr.stringToRuneSlice(v) 491 } 492 } 493 494 // []byte -> string 495 if isSlice(srctyp, types.Byte) && isString(dsttyp) { 496 data := fr.builder.CreateExtractValue(v.value, 0, "") 497 len := fr.builder.CreateExtractValue(v.value, 1, "") 498 stringValue := fr.runtime.byteArrayToString.callOnly(fr, data, len)[0] 499 return newValue(stringValue, dsttyp) 500 } 501 502 // []rune -> string 503 if isSlice(srctyp, types.Rune) && isString(dsttyp) { 504 return fr.runeSliceToString(v) 505 } 506 507 // rune -> string 508 if isString(dsttyp) && isInteger(srctyp) { 509 return fr.runeToString(v) 510 } 511 512 // Unsafe pointer conversions. 513 llvm_type := fr.types.ToLLVM(dsttyp) 514 if dsttyp == types.Typ[types.UnsafePointer] { // X -> unsafe.Pointer 515 if _, isptr := srctyp.(*types.Pointer); isptr { 516 return newValue(v.value, origdsttyp) 517 } else if srctyp == types.Typ[types.Uintptr] { 518 value := b.CreateIntToPtr(v.value, llvm_type, "") 519 return newValue(value, origdsttyp) 520 } 521 } else if srctyp == types.Typ[types.UnsafePointer] { // unsafe.Pointer -> X 522 if _, isptr := dsttyp.(*types.Pointer); isptr { 523 return newValue(v.value, origdsttyp) 524 } else if dsttyp == types.Typ[types.Uintptr] { 525 value := b.CreatePtrToInt(v.value, llvm_type, "") 526 return newValue(value, origdsttyp) 527 } 528 } 529 530 lv := v.value 531 srcType := lv.Type() 532 switch srcType.TypeKind() { 533 case llvm.IntegerTypeKind: 534 switch llvm_type.TypeKind() { 535 case llvm.IntegerTypeKind: 536 srcBits := srcType.IntTypeWidth() 537 dstBits := llvm_type.IntTypeWidth() 538 delta := srcBits - dstBits 539 switch { 540 case delta < 0: 541 if !isUnsigned(srctyp) { 542 lv = b.CreateSExt(lv, llvm_type, "") 543 } else { 544 lv = b.CreateZExt(lv, llvm_type, "") 545 } 546 case delta > 0: 547 lv = b.CreateTrunc(lv, llvm_type, "") 548 } 549 return newValue(lv, origdsttyp) 550 case llvm.FloatTypeKind, llvm.DoubleTypeKind: 551 if !isUnsigned(v.Type()) { 552 lv = b.CreateSIToFP(lv, llvm_type, "") 553 } else { 554 lv = b.CreateUIToFP(lv, llvm_type, "") 555 } 556 return newValue(lv, origdsttyp) 557 } 558 case llvm.DoubleTypeKind: 559 switch llvm_type.TypeKind() { 560 case llvm.FloatTypeKind: 561 lv = b.CreateFPTrunc(lv, llvm_type, "") 562 return newValue(lv, origdsttyp) 563 case llvm.IntegerTypeKind: 564 if !isUnsigned(dsttyp) { 565 lv = b.CreateFPToSI(lv, llvm_type, "") 566 } else { 567 lv = b.CreateFPToUI(lv, llvm_type, "") 568 } 569 return newValue(lv, origdsttyp) 570 } 571 case llvm.FloatTypeKind: 572 switch llvm_type.TypeKind() { 573 case llvm.DoubleTypeKind: 574 lv = b.CreateFPExt(lv, llvm_type, "") 575 return newValue(lv, origdsttyp) 576 case llvm.IntegerTypeKind: 577 if !isUnsigned(dsttyp) { 578 lv = b.CreateFPToSI(lv, llvm_type, "") 579 } else { 580 lv = b.CreateFPToUI(lv, llvm_type, "") 581 } 582 return newValue(lv, origdsttyp) 583 } 584 } 585 586 // Complex -> complex. Complexes are only convertible to other 587 // complexes, contant conversions aside. So we can just check the 588 // source type here; given that the types are not identical 589 // (checked above), we can assume the destination type is the alternate 590 // complex type. 591 if isComplex(srctyp) { 592 var fpcast func(llvm.Builder, llvm.Value, llvm.Type, string) llvm.Value 593 var fptype llvm.Type 594 if srctyp == types.Typ[types.Complex64] { 595 fpcast = (llvm.Builder).CreateFPExt 596 fptype = llvm.DoubleType() 597 } else { 598 fpcast = (llvm.Builder).CreateFPTrunc 599 fptype = llvm.FloatType() 600 } 601 if fpcast != nil { 602 realv := b.CreateExtractValue(lv, 0, "") 603 imagv := b.CreateExtractValue(lv, 1, "") 604 realv = fpcast(b, realv, fptype, "") 605 imagv = fpcast(b, imagv, fptype, "") 606 lv = llvm.Undef(fr.types.ToLLVM(dsttyp)) 607 lv = b.CreateInsertValue(lv, realv, 0, "") 608 lv = b.CreateInsertValue(lv, imagv, 1, "") 609 return newValue(lv, origdsttyp) 610 } 611 } 612 panic(fmt.Sprintf("unimplemented conversion: %s (%s) -> %s", v.typ, lv.Type(), origdsttyp)) 613 } 614 615 // extractRealValue extracts the real component of a complex number. 616 func (fr *frame) extractRealValue(v *govalue) *govalue { 617 component := fr.builder.CreateExtractValue(v.value, 0, "") 618 if component.Type().TypeKind() == llvm.FloatTypeKind { 619 return newValue(component, types.Typ[types.Float32]) 620 } 621 return newValue(component, types.Typ[types.Float64]) 622 } 623 624 // extractRealValue extracts the imaginary component of a complex number. 625 func (fr *frame) extractImagValue(v *govalue) *govalue { 626 component := fr.builder.CreateExtractValue(v.value, 1, "") 627 if component.Type().TypeKind() == llvm.FloatTypeKind { 628 return newValue(component, types.Typ[types.Float32]) 629 } 630 return newValue(component, types.Typ[types.Float64]) 631 } 632 633 func boolLLVMValue(v bool) (lv llvm.Value) { 634 if v { 635 return llvm.ConstInt(llvm.Int8Type(), 1, false) 636 } 637 return llvm.ConstNull(llvm.Int8Type()) 638 }