Initial commit of llgo.
llvm-svn: 222857
diff --git a/llgo/irgen/builtins.go b/llgo/irgen/builtins.go
new file mode 100644
index 0000000..404962f
--- /dev/null
+++ b/llgo/irgen/builtins.go
@@ -0,0 +1,116 @@
+//===- builtins.go - IR generation for builtins ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements IR generation for the built-in functions.
+//
+//===----------------------------------------------------------------------===//
+
+package irgen
+
+import (
+ "llvm.org/llgo/third_party/go.tools/go/types"
+ "llvm.org/llvm/bindings/go/llvm"
+)
+
+func (fr *frame) callCap(arg *govalue) *govalue {
+ var v llvm.Value
+ switch typ := arg.Type().Underlying().(type) {
+ case *types.Array:
+ v = llvm.ConstInt(fr.llvmtypes.inttype, uint64(typ.Len()), false)
+ case *types.Pointer:
+ atyp := typ.Elem().Underlying().(*types.Array)
+ v = llvm.ConstInt(fr.llvmtypes.inttype, uint64(atyp.Len()), false)
+ case *types.Slice:
+ v = fr.builder.CreateExtractValue(arg.value, 2, "")
+ case *types.Chan:
+ v = fr.runtime.chanCap.call(fr, arg.value)[0]
+ }
+ return newValue(v, types.Typ[types.Int])
+}
+
+func (fr *frame) callLen(arg *govalue) *govalue {
+ var lenvalue llvm.Value
+ switch typ := arg.Type().Underlying().(type) {
+ case *types.Array:
+ lenvalue = llvm.ConstInt(fr.llvmtypes.inttype, uint64(typ.Len()), false)
+ case *types.Pointer:
+ atyp := typ.Elem().Underlying().(*types.Array)
+ lenvalue = llvm.ConstInt(fr.llvmtypes.inttype, uint64(atyp.Len()), false)
+ case *types.Slice:
+ lenvalue = fr.builder.CreateExtractValue(arg.value, 1, "")
+ case *types.Map:
+ lenvalue = fr.runtime.mapLen.call(fr, arg.value)[0]
+ case *types.Basic:
+ if isString(typ) {
+ lenvalue = fr.builder.CreateExtractValue(arg.value, 1, "")
+ }
+ case *types.Chan:
+ lenvalue = fr.runtime.chanLen.call(fr, arg.value)[0]
+ }
+ return newValue(lenvalue, types.Typ[types.Int])
+}
+
+// callAppend takes two slices of the same type, and yields
+// the result of appending the second to the first.
+func (fr *frame) callAppend(a, b *govalue) *govalue {
+ bptr := fr.builder.CreateExtractValue(b.value, 0, "")
+ blen := fr.builder.CreateExtractValue(b.value, 1, "")
+ elemsizeInt64 := fr.types.Sizeof(a.Type().Underlying().(*types.Slice).Elem())
+ elemsize := llvm.ConstInt(fr.target.IntPtrType(), uint64(elemsizeInt64), false)
+ result := fr.runtime.append.call(fr, a.value, bptr, blen, elemsize)[0]
+ return newValue(result, a.Type())
+}
+
+// callCopy takes two slices a and b of the same type, and
+// yields the result of calling "copy(a, b)".
+func (fr *frame) callCopy(dest, source *govalue) *govalue {
+ aptr := fr.builder.CreateExtractValue(dest.value, 0, "")
+ alen := fr.builder.CreateExtractValue(dest.value, 1, "")
+ bptr := fr.builder.CreateExtractValue(source.value, 0, "")
+ blen := fr.builder.CreateExtractValue(source.value, 1, "")
+ aless := fr.builder.CreateICmp(llvm.IntULT, alen, blen, "")
+ minlen := fr.builder.CreateSelect(aless, alen, blen, "")
+ elemsizeInt64 := fr.types.Sizeof(dest.Type().Underlying().(*types.Slice).Elem())
+ elemsize := llvm.ConstInt(fr.types.inttype, uint64(elemsizeInt64), false)
+ bytes := fr.builder.CreateMul(minlen, elemsize, "")
+ fr.runtime.copy.call(fr, aptr, bptr, bytes)
+ return newValue(minlen, types.Typ[types.Int])
+}
+
+func (fr *frame) callRecover(isDeferredRecover bool) *govalue {
+ startbb := fr.builder.GetInsertBlock()
+ recoverbb := llvm.AddBasicBlock(fr.function, "")
+ contbb := llvm.AddBasicBlock(fr.function, "")
+ canRecover := fr.builder.CreateTrunc(fr.canRecover, llvm.Int1Type(), "")
+ fr.builder.CreateCondBr(canRecover, recoverbb, contbb)
+
+ fr.builder.SetInsertPointAtEnd(recoverbb)
+ var recovered llvm.Value
+ if isDeferredRecover {
+ recovered = fr.runtime.deferredRecover.call(fr)[0]
+ } else {
+ recovered = fr.runtime.recover.call(fr)[0]
+ }
+ recoverbb = fr.builder.GetInsertBlock()
+ fr.builder.CreateBr(contbb)
+
+ fr.builder.SetInsertPointAtEnd(contbb)
+ eface := types.NewInterface(nil, nil)
+ llv := fr.builder.CreatePHI(fr.types.ToLLVM(eface), "")
+ llv.AddIncoming(
+ []llvm.Value{llvm.ConstNull(llv.Type()), recovered},
+ []llvm.BasicBlock{startbb, recoverbb},
+ )
+ return newValue(llv, eface)
+}
+
+func (fr *frame) callPanic(arg *govalue) {
+ fr.runtime.panic.call(fr, arg.value)
+ fr.builder.CreateUnreachable()
+}