blob: e6bc5898e570bb0f76ff3cc0c835bd1095a0298b [file] [log] [blame]
Peter Collingbournead9841e2014-11-27 00:06:42 +00001//===- 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
15package irgen
16
17import (
18 "fmt"
19 "go/token"
Andrew Wilkins6436a4a2016-03-15 05:36:43 +000020
Peter Collingbourne56109b72015-01-13 20:45:08 +000021 "llvm.org/llgo/third_party/gotools/go/exact"
22 "llvm.org/llgo/third_party/gotools/go/types"
Peter Collingbournead9841e2014-11-27 00:06:42 +000023 "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.
28type govalue struct {
29 value llvm.Value
30 typ types.Type
31}
32
33func (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.
38func newValue(v llvm.Value, t types.Type) *govalue {
39 return &govalue{v, t}
40}
41
42// TODO(axw) remove this, use .typ directly
43func (v *govalue) Type() types.Type {
44 return v.typ
45}
46
47// newValueFromConst converts a constant value to an LLVM value.
48func (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
144func (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
387func (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
411func (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
446func (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) {
Andrew Wilkins6436a4a2016-03-15 05:36:43 +0000484 sliceValue := fr.runtime.stringToByteArray.callOnly(fr, v.value)[0]
485 return newValue(sliceValue, origdsttyp)
Peter Collingbournead9841e2014-11-27 00:06:42 +0000486 }
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) {
Andrew Wilkins6436a4a2016-03-15 05:36:43 +0000496 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)
Peter Collingbournead9841e2014-11-27 00:06:42 +0000500 }
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.
616func (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.
625func (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
633func 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}