blob: 366069b3e101f9c260038ec2bc838093b2ec8759 [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"
Peter Collingbourne56109b72015-01-13 20:45:08 +000020 "llvm.org/llgo/third_party/gotools/go/exact"
21 "llvm.org/llgo/third_party/gotools/go/types"
Peter Collingbournead9841e2014-11-27 00:06:42 +000022 "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 value := v.value
484 strdata := fr.builder.CreateExtractValue(value, 0, "")
485 strlen := fr.builder.CreateExtractValue(value, 1, "")
486
487 // Data must be copied, to prevent changes in
488 // the byte slice from mutating the string.
489 newdata := fr.createMalloc(strlen)
490 fr.memcpy(newdata, strdata, strlen)
491
492 struct_ := llvm.Undef(fr.types.ToLLVM(dsttyp))
493 struct_ = fr.builder.CreateInsertValue(struct_, newdata, 0, "")
494 struct_ = fr.builder.CreateInsertValue(struct_, strlen, 1, "")
495 struct_ = fr.builder.CreateInsertValue(struct_, strlen, 2, "")
496 return newValue(struct_, origdsttyp)
497 }
498
499 // string -> []rune
500 if isSlice(dsttyp, types.Rune) {
501 return fr.stringToRuneSlice(v)
502 }
503 }
504
505 // []byte -> string
506 if isSlice(srctyp, types.Byte) && isString(dsttyp) {
507 value := v.value
508 data := fr.builder.CreateExtractValue(value, 0, "")
509 len := fr.builder.CreateExtractValue(value, 1, "")
510
511 // Data must be copied, to prevent changes in
512 // the byte slice from mutating the string.
513 newdata := fr.createMalloc(len)
514 fr.memcpy(newdata, data, len)
515
516 struct_ := llvm.Undef(fr.types.ToLLVM(types.Typ[types.String]))
517 struct_ = fr.builder.CreateInsertValue(struct_, newdata, 0, "")
518 struct_ = fr.builder.CreateInsertValue(struct_, len, 1, "")
519 return newValue(struct_, types.Typ[types.String])
520 }
521
522 // []rune -> string
523 if isSlice(srctyp, types.Rune) && isString(dsttyp) {
524 return fr.runeSliceToString(v)
525 }
526
527 // rune -> string
528 if isString(dsttyp) && isInteger(srctyp) {
529 return fr.runeToString(v)
530 }
531
532 // Unsafe pointer conversions.
533 llvm_type := fr.types.ToLLVM(dsttyp)
534 if dsttyp == types.Typ[types.UnsafePointer] { // X -> unsafe.Pointer
535 if _, isptr := srctyp.(*types.Pointer); isptr {
536 return newValue(v.value, origdsttyp)
537 } else if srctyp == types.Typ[types.Uintptr] {
538 value := b.CreateIntToPtr(v.value, llvm_type, "")
539 return newValue(value, origdsttyp)
540 }
541 } else if srctyp == types.Typ[types.UnsafePointer] { // unsafe.Pointer -> X
542 if _, isptr := dsttyp.(*types.Pointer); isptr {
543 return newValue(v.value, origdsttyp)
544 } else if dsttyp == types.Typ[types.Uintptr] {
545 value := b.CreatePtrToInt(v.value, llvm_type, "")
546 return newValue(value, origdsttyp)
547 }
548 }
549
550 lv := v.value
551 srcType := lv.Type()
552 switch srcType.TypeKind() {
553 case llvm.IntegerTypeKind:
554 switch llvm_type.TypeKind() {
555 case llvm.IntegerTypeKind:
556 srcBits := srcType.IntTypeWidth()
557 dstBits := llvm_type.IntTypeWidth()
558 delta := srcBits - dstBits
559 switch {
560 case delta < 0:
561 if !isUnsigned(srctyp) {
562 lv = b.CreateSExt(lv, llvm_type, "")
563 } else {
564 lv = b.CreateZExt(lv, llvm_type, "")
565 }
566 case delta > 0:
567 lv = b.CreateTrunc(lv, llvm_type, "")
568 }
569 return newValue(lv, origdsttyp)
570 case llvm.FloatTypeKind, llvm.DoubleTypeKind:
571 if !isUnsigned(v.Type()) {
572 lv = b.CreateSIToFP(lv, llvm_type, "")
573 } else {
574 lv = b.CreateUIToFP(lv, llvm_type, "")
575 }
576 return newValue(lv, origdsttyp)
577 }
578 case llvm.DoubleTypeKind:
579 switch llvm_type.TypeKind() {
580 case llvm.FloatTypeKind:
581 lv = b.CreateFPTrunc(lv, llvm_type, "")
582 return newValue(lv, origdsttyp)
583 case llvm.IntegerTypeKind:
584 if !isUnsigned(dsttyp) {
585 lv = b.CreateFPToSI(lv, llvm_type, "")
586 } else {
587 lv = b.CreateFPToUI(lv, llvm_type, "")
588 }
589 return newValue(lv, origdsttyp)
590 }
591 case llvm.FloatTypeKind:
592 switch llvm_type.TypeKind() {
593 case llvm.DoubleTypeKind:
594 lv = b.CreateFPExt(lv, llvm_type, "")
595 return newValue(lv, origdsttyp)
596 case llvm.IntegerTypeKind:
597 if !isUnsigned(dsttyp) {
598 lv = b.CreateFPToSI(lv, llvm_type, "")
599 } else {
600 lv = b.CreateFPToUI(lv, llvm_type, "")
601 }
602 return newValue(lv, origdsttyp)
603 }
604 }
605
606 // Complex -> complex. Complexes are only convertible to other
607 // complexes, contant conversions aside. So we can just check the
608 // source type here; given that the types are not identical
609 // (checked above), we can assume the destination type is the alternate
610 // complex type.
611 if isComplex(srctyp) {
612 var fpcast func(llvm.Builder, llvm.Value, llvm.Type, string) llvm.Value
613 var fptype llvm.Type
614 if srctyp == types.Typ[types.Complex64] {
615 fpcast = (llvm.Builder).CreateFPExt
616 fptype = llvm.DoubleType()
617 } else {
618 fpcast = (llvm.Builder).CreateFPTrunc
619 fptype = llvm.FloatType()
620 }
621 if fpcast != nil {
622 realv := b.CreateExtractValue(lv, 0, "")
623 imagv := b.CreateExtractValue(lv, 1, "")
624 realv = fpcast(b, realv, fptype, "")
625 imagv = fpcast(b, imagv, fptype, "")
626 lv = llvm.Undef(fr.types.ToLLVM(dsttyp))
627 lv = b.CreateInsertValue(lv, realv, 0, "")
628 lv = b.CreateInsertValue(lv, imagv, 1, "")
629 return newValue(lv, origdsttyp)
630 }
631 }
632 panic(fmt.Sprintf("unimplemented conversion: %s (%s) -> %s", v.typ, lv.Type(), origdsttyp))
633}
634
635// extractRealValue extracts the real component of a complex number.
636func (fr *frame) extractRealValue(v *govalue) *govalue {
637 component := fr.builder.CreateExtractValue(v.value, 0, "")
638 if component.Type().TypeKind() == llvm.FloatTypeKind {
639 return newValue(component, types.Typ[types.Float32])
640 }
641 return newValue(component, types.Typ[types.Float64])
642}
643
644// extractRealValue extracts the imaginary component of a complex number.
645func (fr *frame) extractImagValue(v *govalue) *govalue {
646 component := fr.builder.CreateExtractValue(v.value, 1, "")
647 if component.Type().TypeKind() == llvm.FloatTypeKind {
648 return newValue(component, types.Typ[types.Float32])
649 }
650 return newValue(component, types.Typ[types.Float64])
651}
652
653func boolLLVMValue(v bool) (lv llvm.Value) {
654 if v {
655 return llvm.ConstInt(llvm.Int8Type(), 1, false)
656 }
657 return llvm.ConstNull(llvm.Int8Type())
658}