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  }