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