Index: llgo/trunk/irgen/cabi.go =================================================================== --- llgo/trunk/irgen/cabi.go +++ llgo/trunk/irgen/cabi.go @@ -511,6 +511,7 @@ retAttr llvm.Attribute argInfos []argInfo retInf retInfo + chainIndex int } func (fi *functionTypeInfo) declare(m llvm.Module, name string) llvm.Value { @@ -524,8 +525,12 @@ return fn } -func (fi *functionTypeInfo) call(ctx llvm.Context, allocaBuilder llvm.Builder, builder llvm.Builder, callee llvm.Value, args []llvm.Value) []llvm.Value { +func (fi *functionTypeInfo) call(ctx llvm.Context, allocaBuilder llvm.Builder, builder llvm.Builder, callee llvm.Value, chain llvm.Value, args []llvm.Value) []llvm.Value { callArgs := make([]llvm.Value, len(fi.argAttrs)) + if chain.C == nil { + chain = llvm.Undef(llvm.PointerType(ctx.Int8Type(), 0)) + } + callArgs[fi.chainIndex] = chain for i, a := range args { fi.argInfos[i].encode(ctx, allocaBuilder, builder, callArgs, a) } @@ -539,8 +544,12 @@ return fi.retInf.decode(ctx, allocaBuilder, builder, call) } -func (fi *functionTypeInfo) invoke(ctx llvm.Context, allocaBuilder llvm.Builder, builder llvm.Builder, callee llvm.Value, args []llvm.Value, cont, lpad llvm.BasicBlock) []llvm.Value { +func (fi *functionTypeInfo) invoke(ctx llvm.Context, allocaBuilder llvm.Builder, builder llvm.Builder, callee llvm.Value, chain llvm.Value, args []llvm.Value, cont, lpad llvm.BasicBlock) []llvm.Value { callArgs := make([]llvm.Value, len(fi.argAttrs)) + if chain.C == nil { + chain = llvm.Undef(llvm.PointerType(ctx.Int8Type(), 0)) + } + callArgs[fi.chainIndex] = chain for i, a := range args { fi.argInfos[i].encode(ctx, allocaBuilder, builder, callArgs, a) } @@ -605,6 +614,11 @@ } } + // Allocate an argument for the call chain. + fi.chainIndex = len(argTypes) + argTypes = append(argTypes, llvm.PointerType(tm.ctx.Int8Type(), 0)) + fi.argAttrs = append(fi.argAttrs, llvm.NestAttribute) + // Keep track of the number of INTEGER/SSE class registers remaining. remainingInt := 6 remainingSSE := 8 Index: llgo/trunk/irgen/call.go =================================================================== --- llgo/trunk/irgen/call.go +++ llgo/trunk/irgen/call.go @@ -20,7 +20,7 @@ // createCall emits the code for a function call, // taking into account receivers, and panic/defer. -func (fr *frame) createCall(fn *govalue, argValues []*govalue) []*govalue { +func (fr *frame) createCall(fn *govalue, chain llvm.Value, argValues []*govalue) []*govalue { fntyp := fn.Type().Underlying().(*types.Signature) typinfo := fr.types.getSignatureInfo(fntyp) @@ -30,10 +30,10 @@ } var results []llvm.Value if fr.unwindBlock.IsNil() { - results = typinfo.call(fr.types.ctx, fr.allocaBuilder, fr.builder, fn.value, args) + results = typinfo.call(fr.types.ctx, fr.allocaBuilder, fr.builder, fn.value, chain, args) } else { contbb := llvm.AddBasicBlock(fr.function, "") - results = typinfo.invoke(fr.types.ctx, fr.allocaBuilder, fr.builder, fn.value, args, contbb, fr.unwindBlock) + results = typinfo.invoke(fr.types.ctx, fr.allocaBuilder, fr.builder, fn.value, chain, args, contbb, fr.unwindBlock) } resultValues := make([]*govalue, len(results)) Index: llgo/trunk/irgen/compiler.go =================================================================== --- llgo/trunk/irgen/compiler.go +++ llgo/trunk/irgen/compiler.go @@ -341,7 +341,8 @@ } func (c *compiler) createInitMainFunction(mainPkg *ssa.Package) { - ftyp := llvm.FunctionType(llvm.VoidType(), nil, false) + int8ptr := llvm.PointerType(c.types.ctx.Int8Type(), 0) + ftyp := llvm.FunctionType(llvm.VoidType(), []llvm.Type{int8ptr}, false) initMain := llvm.AddFunction(c.module.Module, "__go_init_main", ftyp) c.addCommonFunctionAttrs(initMain) entry := llvm.AddBasicBlock(initMain, "entry") @@ -350,10 +351,12 @@ defer builder.Dispose() builder.SetInsertPointAtEnd(entry) + args := []llvm.Value{llvm.Undef(int8ptr)} + if !c.GccgoABI { initfn := c.module.Module.NamedFunction("main..import") if !initfn.IsNil() { - builder.CreateCall(initfn, nil, "") + builder.CreateCall(initfn, args, "") } builder.CreateRetVoid() return @@ -366,7 +369,7 @@ if initfn.IsNil() { initfn = llvm.AddFunction(c.module.Module, init.InitFunc, ftyp) } - builder.CreateCall(initfn, nil, "") + builder.CreateCall(initfn, args, "") } builder.CreateRetVoid() Index: llgo/trunk/irgen/runtime.go =================================================================== --- llgo/trunk/irgen/runtime.go +++ llgo/trunk/irgen/runtime.go @@ -41,12 +41,12 @@ } func (rfi *runtimeFnInfo) callOnly(f *frame, args ...llvm.Value) []llvm.Value { - return rfi.fi.call(f.llvmtypes.ctx, f.allocaBuilder, f.builder, rfi.fn, args) + return rfi.fi.call(f.llvmtypes.ctx, f.allocaBuilder, f.builder, rfi.fn, llvm.Value{nil}, args) } func (rfi *runtimeFnInfo) invoke(f *frame, lpad llvm.BasicBlock, args ...llvm.Value) []llvm.Value { contbb := llvm.AddBasicBlock(f.function, "") - return rfi.fi.invoke(f.llvmtypes.ctx, f.allocaBuilder, f.builder, rfi.fn, args, contbb, lpad) + return rfi.fi.invoke(f.llvmtypes.ctx, f.allocaBuilder, f.builder, rfi.fn, llvm.Value{nil}, args, contbb, lpad) } // runtimeInterface is a struct containing references to @@ -76,7 +76,6 @@ Defer, deferredRecover, emptyInterfaceCompare, - getClosure, Go, ifaceE2I2, ifaceI2I2, @@ -117,7 +116,6 @@ selectsend, selectgo, sendBig, - setClosure, setDeferRetaddr, strcmp, stringiter2, @@ -230,11 +228,6 @@ res: []types.Type{Int}, }, { - name: "__go_get_closure", - rfi: &ri.getClosure, - res: []types.Type{UnsafePointer}, - }, - { name: "__go_go", rfi: &ri.Go, args: []types.Type{UnsafePointer, UnsafePointer}, @@ -449,11 +442,6 @@ args: []types.Type{UnsafePointer, UnsafePointer, UnsafePointer}, }, { - name: "__go_set_closure", - rfi: &ri.setClosure, - args: []types.Type{UnsafePointer}, - }, - { name: "__go_set_defer_retaddr", rfi: &ri.setDeferRetaddr, args: []types.Type{UnsafePointer}, Index: llgo/trunk/irgen/ssa.go =================================================================== --- llgo/trunk/irgen/ssa.go +++ llgo/trunk/irgen/ssa.go @@ -379,7 +379,7 @@ elemTypes[i+1] = u.llvmtypes.ToLLVM(fv.Type()) } structType := llvm.StructType(elemTypes, false) - closure := fr.runtime.getClosure.call(fr)[0] + closure := fr.function.Param(fti.chainIndex) closure = fr.builder.CreateBitCast(closure, llvm.PointerType(structType, 0), "") for i, fv := range f.FreeVars { ptr := fr.builder.CreateStructGEP(closure, i+1, "") @@ -507,14 +507,16 @@ fr.builder.SetInsertPointAtEnd(initBlock) fr.builder.CreateStore(llvm.ConstInt(llvm.Int1Type(), 1, false), initGuard) - ftyp := llvm.FunctionType(llvm.VoidType(), nil, false) + int8ptr := llvm.PointerType(fr.types.ctx.Int8Type(), 0) + ftyp := llvm.FunctionType(llvm.VoidType(), []llvm.Type{int8ptr}, false) for _, pkg := range fr.pkg.Object.Imports() { initname := ManglePackagePath(pkg.Path()) + "..import" initfn := fr.module.Module.NamedFunction(initname) if initfn.IsNil() { initfn = llvm.AddFunction(fr.module.Module, initname, ftyp) } - fr.builder.CreateCall(initfn, nil, "") + args := []llvm.Value{llvm.Undef(int8ptr)} + fr.builder.CreateCall(initfn, args, "") } return initBlock @@ -1288,6 +1290,7 @@ } var fn *govalue + var chain llvm.Value if call.IsInvoke() { var recv *govalue fn, recv = fr.interfaceMethod(fr.llvmvalue(call.Value), call.Value.Type(), call.Method) @@ -1300,9 +1303,9 @@ } else { // First-class function values are stored as *{*fnptr}, so // we must extract the function pointer. We must also - // call __go_set_closure, in case the function is a closure. + // set the chain, in case the function is a closure. fn = fr.value(call.Value) - fr.runtime.setClosure.call(fr, fn.value) + chain = fn.value fnptr := fr.builder.CreateBitCast(fn.value, llvm.PointerType(fn.value.Type(), 0), "") fnptr = fr.builder.CreateLoad(fnptr, "") fn = newValue(fnptr, fn.Type()) @@ -1315,7 +1318,7 @@ } } } - return fr.createCall(fn, args) + return fr.createCall(fn, chain, args) } func hasDefer(f *ssa.Function) bool { Index: llgo/trunk/libgo-noext.diff =================================================================== --- llgo/trunk/libgo-noext.diff +++ llgo/trunk/libgo-noext.diff @@ -1,6 +1,6 @@ -diff -r a6e10414311a libgo/runtime/chan.goc ---- a/libgo/runtime/chan.goc Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/runtime/chan.goc Fri Feb 13 16:36:07 2015 -0800 +diff -r bb70e852004f libgo/runtime/chan.goc +--- a/libgo/runtime/chan.goc Fri Jan 16 13:28:21 2015 -0800 ++++ b/libgo/runtime/chan.goc Fri Apr 03 17:31:02 2015 -0700 @@ -111,7 +111,7 @@ mysg.releasetime = -1; } @@ -207,9 +207,9 @@ } void -diff -r a6e10414311a libgo/runtime/chan.h ---- a/libgo/runtime/chan.h Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/runtime/chan.h Fri Feb 13 16:36:07 2015 -0800 +diff -r bb70e852004f libgo/runtime/chan.h +--- a/libgo/runtime/chan.h Fri Jan 16 13:28:21 2015 -0800 ++++ b/libgo/runtime/chan.h Fri Apr 03 17:31:02 2015 -0700 @@ -39,7 +39,7 @@ uintgo recvx; // receive index WaitQ recvq; // list of recv waiters @@ -219,9 +219,9 @@ }; // Buffer follows Hchan immediately in memory. -diff -r a6e10414311a libgo/runtime/heapdump.c ---- a/libgo/runtime/heapdump.c Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/runtime/heapdump.c Fri Feb 13 16:36:07 2015 -0800 +diff -r bb70e852004f libgo/runtime/heapdump.c +--- a/libgo/runtime/heapdump.c Fri Jan 16 13:28:21 2015 -0800 ++++ b/libgo/runtime/heapdump.c Fri Apr 03 17:31:02 2015 -0700 @@ -387,7 +387,7 @@ if(sp->kind != KindSpecialFinalizer) continue; @@ -240,10 +240,10 @@ dumpint(TagAllocSample); dumpint((uintptr)p); dumpint((uintptr)spp->b); -diff -r a6e10414311a libgo/runtime/malloc.goc ---- a/libgo/runtime/malloc.goc Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/runtime/malloc.goc Fri Feb 13 16:36:07 2015 -0800 -@@ -437,9 +437,9 @@ +diff -r bb70e852004f libgo/runtime/malloc.goc +--- a/libgo/runtime/malloc.goc Fri Jan 16 13:28:21 2015 -0800 ++++ b/libgo/runtime/malloc.goc Fri Apr 03 17:31:02 2015 -0700 +@@ -429,9 +429,9 @@ m->mcache->local_nlookup++; if (sizeof(void*) == 4 && m->mcache->local_nlookup >= (1<<30)) { // purge cache stats to prevent overflow @@ -255,7 +255,7 @@ } s = runtime_MHeap_LookupMaybe(&runtime_mheap, v); -@@ -736,7 +736,7 @@ +@@ -728,7 +728,7 @@ static struct { @@ -264,7 +264,7 @@ byte* pos; byte* end; } persistent; -@@ -765,19 +765,19 @@ +@@ -757,19 +757,19 @@ align = 8; if(size >= PersistentAllocMaxBlock) return runtime_SysAlloc(size, stat); @@ -287,9 +287,9 @@ if(stat != &mstats.other_sys) { // reaccount the allocation against provided stat runtime_xadd64(stat, size); -diff -r a6e10414311a libgo/runtime/malloc.h ---- a/libgo/runtime/malloc.h Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/runtime/malloc.h Fri Feb 13 16:36:07 2015 -0800 +diff -r bb70e852004f libgo/runtime/malloc.h +--- a/libgo/runtime/malloc.h Fri Jan 16 13:28:21 2015 -0800 ++++ b/libgo/runtime/malloc.h Fri Apr 03 17:31:02 2015 -0700 @@ -390,7 +390,7 @@ typedef struct SpecialFinalizer SpecialFinalizer; struct SpecialFinalizer @@ -335,9 +335,9 @@ byte pad[64]; } central[NumSizeClasses]; -diff -r a6e10414311a libgo/runtime/mcache.c ---- a/libgo/runtime/mcache.c Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/runtime/mcache.c Fri Feb 13 16:36:07 2015 -0800 +diff -r bb70e852004f libgo/runtime/mcache.c +--- a/libgo/runtime/mcache.c Fri Jan 16 13:28:21 2015 -0800 ++++ b/libgo/runtime/mcache.c Fri Apr 03 17:31:02 2015 -0700 @@ -23,9 +23,9 @@ MCache *c; int32 i; @@ -410,9 +410,9 @@ l->list = nil; l->nlist = 0; } -diff -r a6e10414311a libgo/runtime/mcentral.c ---- a/libgo/runtime/mcentral.c Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/runtime/mcentral.c Fri Feb 13 16:36:07 2015 -0800 +diff -r bb70e852004f libgo/runtime/mcentral.c +--- a/libgo/runtime/mcentral.c Fri Jan 16 13:28:21 2015 -0800 ++++ b/libgo/runtime/mcentral.c Fri Apr 03 17:31:02 2015 -0700 @@ -39,14 +39,14 @@ int32 cap, n; uint32 sg; @@ -554,9 +554,9 @@ runtime_unmarkspan((byte*)(s->start<npages<freelarge); runtime_MSpanList_Init(&h->busylarge); @@ -837,9 +837,9 @@ + runtime_unlock(&h->lock); } } -diff -r a6e10414311a libgo/runtime/netpoll.goc ---- a/libgo/runtime/netpoll.goc Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/runtime/netpoll.goc Fri Feb 13 16:36:07 2015 -0800 +diff -r bb70e852004f libgo/runtime/netpoll.goc +--- a/libgo/runtime/netpoll.goc Fri Jan 16 13:28:21 2015 -0800 ++++ b/libgo/runtime/netpoll.goc Fri Apr 03 17:31:02 2015 -0700 @@ -53,7 +53,7 @@ // pollReset, pollWait, pollWaitCanceled and runtime_netpollready (IO rediness notification) // proceed w/o taking the lock. So closing, rg, rd, wg and wd are manipulated @@ -985,9 +985,9 @@ + runtime_unlock(&pollcache.lock); return pd; } -diff -r a6e10414311a libgo/runtime/proc.c ---- a/libgo/runtime/proc.c Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/runtime/proc.c Fri Feb 13 16:36:07 2015 -0800 +diff -r bb70e852004f libgo/runtime/proc.c +--- a/libgo/runtime/proc.c Fri Jan 16 13:28:21 2015 -0800 ++++ b/libgo/runtime/proc.c Fri Apr 03 17:31:02 2015 -0700 @@ -302,7 +302,7 @@ typedef struct Sched Sched; @@ -1502,10 +1502,10 @@ return out; } -diff -r a6e10414311a libgo/runtime/runtime.h ---- a/libgo/runtime/runtime.h Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/runtime/runtime.h Fri Feb 13 16:36:07 2015 -0800 -@@ -286,7 +286,7 @@ +diff -r bb70e852004f libgo/runtime/runtime.h +--- a/libgo/runtime/runtime.h Fri Jan 16 13:28:21 2015 -0800 ++++ b/libgo/runtime/runtime.h Fri Apr 03 17:31:02 2015 -0700 +@@ -285,7 +285,7 @@ struct P { @@ -1514,7 +1514,7 @@ int32 id; uint32 status; // one of Pidle/Prunning/... -@@ -384,7 +384,7 @@ +@@ -383,7 +383,7 @@ struct Timers { @@ -1523,9 +1523,9 @@ G *timerproc; bool sleeping; bool rescheduling; -diff -r a6e10414311a libgo/runtime/sema.goc ---- a/libgo/runtime/sema.goc Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/runtime/sema.goc Fri Feb 13 16:36:07 2015 -0800 +diff -r bb70e852004f libgo/runtime/sema.goc +--- a/libgo/runtime/sema.goc Fri Jan 16 13:28:21 2015 -0800 ++++ b/libgo/runtime/sema.goc Fri Apr 03 17:31:02 2015 -0700 @@ -35,7 +35,7 @@ typedef struct SemaRoot SemaRoot; struct SemaRoot @@ -1654,9 +1654,9 @@ - runtime_unlock(s); + runtime_unlock(&s->lock); } -diff -r a6e10414311a libgo/runtime/sigqueue.goc ---- a/libgo/runtime/sigqueue.goc Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/runtime/sigqueue.goc Fri Feb 13 16:36:07 2015 -0800 +diff -r bb70e852004f libgo/runtime/sigqueue.goc +--- a/libgo/runtime/sigqueue.goc Fri Jan 16 13:28:21 2015 -0800 ++++ b/libgo/runtime/sigqueue.goc Fri Apr 03 17:31:02 2015 -0700 @@ -32,7 +32,7 @@ #include "defs.h" @@ -1695,9 +1695,9 @@ return; } -diff -r a6e10414311a libgo/runtime/time.goc ---- a/libgo/runtime/time.goc Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/runtime/time.goc Fri Feb 13 16:36:07 2015 -0800 +diff -r bb70e852004f libgo/runtime/time.goc +--- a/libgo/runtime/time.goc Fri Jan 16 13:28:21 2015 -0800 ++++ b/libgo/runtime/time.goc Fri Apr 03 17:31:02 2015 -0700 @@ -92,17 +92,17 @@ t.fv = &readyv; t.arg.__object = g; @@ -1761,10 +1761,10 @@ seq = t->seq; - runtime_unlock(&timers); + runtime_unlock(&timers.lock); - __go_set_closure(fv); - f(arg, seq); + __builtin_call_with_static_chain(f(arg, seq), fv); -@@ -247,20 +247,20 @@ + // clear f and arg to avoid leak while sleeping for next timer +@@ -246,20 +246,20 @@ arg.__object = nil; USED(&arg); Index: llgo/trunk/test/irgen/cabi.go =================================================================== --- llgo/trunk/test/irgen/cabi.go +++ llgo/trunk/test/irgen/cabi.go @@ -2,22 +2,22 @@ package foo -// CHECK: define void @foo.Test01_SI8(i8 signext) +// CHECK: define void @foo.Test01_SI8(i8* nest, i8 signext) func Test01_SI8(x int8) {} -// CHECK: define void @foo.Test02_UI8(i8 zeroext) +// CHECK: define void @foo.Test02_UI8(i8* nest, i8 zeroext) func Test02_UI8(x uint8) {} -// CHECK: define void @foo.Test03_SI16(i16 signext) +// CHECK: define void @foo.Test03_SI16(i8* nest, i16 signext) func Test03_SI16(x int16) {} -// CHECK: define void @foo.Test04_UI16(i16 zeroext) +// CHECK: define void @foo.Test04_UI16(i8* nest, i16 zeroext) func Test04_UI16(x uint16) {} -// CHECK: define void @foo.Test05_SI32(i32) +// CHECK: define void @foo.Test05_SI32(i8* nest, i32) func Test05_SI32(x int32) {} -// CHECK: define void @foo.Test06_UI32(i32) +// CHECK: define void @foo.Test06_UI32(i8* nest, i32) func Test06_UI32(x uint32) {} -// CHECK: define void @foo.Test07_SI64(i64) +// CHECK: define void @foo.Test07_SI64(i8* nest, i64) func Test07_SI64(x int64) {} -// CHECK: define void @foo.Test08_UI64(i64) +// CHECK: define void @foo.Test08_UI64(i8* nest, i64) func Test08_UI64(x uint64) {} Index: llgo/trunk/test/irgen/imports.go =================================================================== --- llgo/trunk/test/irgen/imports.go +++ llgo/trunk/test/irgen/imports.go @@ -8,7 +8,7 @@ // CHECK: @"init$guard" = internal global i1 false -// CHECK: define void @foo..import() +// CHECK: define void @foo..import(i8* nest) // CHECK-NEXT: : // CHECK-NEXT: %[[N:.*]] = load i1, i1* @"init$guard" // CHECK-NEXT: br i1 %[[N]], label %{{.*}}, label %[[L:.*]] @@ -16,5 +16,5 @@ // CHECK: ;