github.com/axw/llgo@v0.0.0-20160805011314-95b5fe4dca20/irgen/builtins.go (about) 1 //===- builtins.go - IR generation for builtins ---------------------------===// 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 implements IR generation for the built-in functions. 11 // 12 //===----------------------------------------------------------------------===// 13 14 package irgen 15 16 import ( 17 "llvm.org/llgo/third_party/gotools/go/types" 18 "llvm.org/llvm/bindings/go/llvm" 19 ) 20 21 func (fr *frame) callCap(arg *govalue) *govalue { 22 var v llvm.Value 23 switch typ := arg.Type().Underlying().(type) { 24 case *types.Array: 25 v = llvm.ConstInt(fr.llvmtypes.inttype, uint64(typ.Len()), false) 26 case *types.Pointer: 27 atyp := typ.Elem().Underlying().(*types.Array) 28 v = llvm.ConstInt(fr.llvmtypes.inttype, uint64(atyp.Len()), false) 29 case *types.Slice: 30 v = fr.builder.CreateExtractValue(arg.value, 2, "") 31 case *types.Chan: 32 v = fr.runtime.chanCap.call(fr, arg.value)[0] 33 } 34 return newValue(v, types.Typ[types.Int]) 35 } 36 37 func (fr *frame) callLen(arg *govalue) *govalue { 38 var lenvalue llvm.Value 39 switch typ := arg.Type().Underlying().(type) { 40 case *types.Array: 41 lenvalue = llvm.ConstInt(fr.llvmtypes.inttype, uint64(typ.Len()), false) 42 case *types.Pointer: 43 atyp := typ.Elem().Underlying().(*types.Array) 44 lenvalue = llvm.ConstInt(fr.llvmtypes.inttype, uint64(atyp.Len()), false) 45 case *types.Slice: 46 lenvalue = fr.builder.CreateExtractValue(arg.value, 1, "") 47 case *types.Map: 48 lenvalue = fr.runtime.mapLen.call(fr, arg.value)[0] 49 case *types.Basic: 50 if isString(typ) { 51 lenvalue = fr.builder.CreateExtractValue(arg.value, 1, "") 52 } 53 case *types.Chan: 54 lenvalue = fr.runtime.chanLen.call(fr, arg.value)[0] 55 } 56 return newValue(lenvalue, types.Typ[types.Int]) 57 } 58 59 // callAppend takes two slices of the same type, and yields 60 // the result of appending the second to the first. 61 func (fr *frame) callAppend(a, b *govalue) *govalue { 62 bptr := fr.builder.CreateExtractValue(b.value, 0, "") 63 blen := fr.builder.CreateExtractValue(b.value, 1, "") 64 elemsizeInt64 := fr.types.Sizeof(a.Type().Underlying().(*types.Slice).Elem()) 65 elemsize := llvm.ConstInt(fr.target.IntPtrType(), uint64(elemsizeInt64), false) 66 result := fr.runtime.append.call(fr, a.value, bptr, blen, elemsize)[0] 67 return newValue(result, a.Type()) 68 } 69 70 // callCopy takes two slices a and b of the same type, and 71 // yields the result of calling "copy(a, b)". 72 func (fr *frame) callCopy(dest, source *govalue) *govalue { 73 aptr := fr.builder.CreateExtractValue(dest.value, 0, "") 74 alen := fr.builder.CreateExtractValue(dest.value, 1, "") 75 bptr := fr.builder.CreateExtractValue(source.value, 0, "") 76 blen := fr.builder.CreateExtractValue(source.value, 1, "") 77 aless := fr.builder.CreateICmp(llvm.IntULT, alen, blen, "") 78 minlen := fr.builder.CreateSelect(aless, alen, blen, "") 79 elemsizeInt64 := fr.types.Sizeof(dest.Type().Underlying().(*types.Slice).Elem()) 80 elemsize := llvm.ConstInt(fr.types.inttype, uint64(elemsizeInt64), false) 81 bytes := fr.builder.CreateMul(minlen, elemsize, "") 82 fr.runtime.copy.call(fr, aptr, bptr, bytes) 83 return newValue(minlen, types.Typ[types.Int]) 84 } 85 86 func (fr *frame) callRecover(isDeferredRecover bool) *govalue { 87 startbb := fr.builder.GetInsertBlock() 88 recoverbb := llvm.AddBasicBlock(fr.function, "") 89 contbb := llvm.AddBasicBlock(fr.function, "") 90 canRecover := fr.builder.CreateTrunc(fr.canRecover, llvm.Int1Type(), "") 91 fr.builder.CreateCondBr(canRecover, recoverbb, contbb) 92 93 fr.builder.SetInsertPointAtEnd(recoverbb) 94 var recovered llvm.Value 95 if isDeferredRecover { 96 recovered = fr.runtime.deferredRecover.call(fr)[0] 97 } else { 98 recovered = fr.runtime.recover.call(fr)[0] 99 } 100 recoverbb = fr.builder.GetInsertBlock() 101 fr.builder.CreateBr(contbb) 102 103 fr.builder.SetInsertPointAtEnd(contbb) 104 eface := types.NewInterface(nil, nil) 105 llv := fr.builder.CreatePHI(fr.types.ToLLVM(eface), "") 106 llv.AddIncoming( 107 []llvm.Value{llvm.ConstNull(llv.Type()), recovered}, 108 []llvm.BasicBlock{startbb, recoverbb}, 109 ) 110 return newValue(llv, eface) 111 } 112 113 func (fr *frame) callPanic(arg *govalue, term bool) { 114 fr.runtime.panic.call(fr, arg.value) 115 if term { 116 fr.builder.CreateUnreachable() 117 } 118 }