Roll gofrontend to 07baa07598ea; roll libffi to r219477.

Incorporates https://codereview.appspot.com/198770044, which causes us to start
using the static chain register for closures instead of __go_{get,set}_closure.

Differential Revision: http://reviews.llvm.org/D8829

llvm-svn: 234135
GitOrigin-RevId: cac325993ad8872dc9bea68195c6618283171c5b
diff --git a/irgen/cabi.go b/irgen/cabi.go
index f13cf28..ba3b09f 100644
--- a/irgen/cabi.go
+++ b/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
diff --git a/irgen/call.go b/irgen/call.go
index 49876bb..9f29ac6 100644
--- a/irgen/call.go
+++ b/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))
diff --git a/irgen/compiler.go b/irgen/compiler.go
index 830c1bd..8f4e65f 100644
--- a/irgen/compiler.go
+++ b/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()
diff --git a/irgen/runtime.go b/irgen/runtime.go
index 2e13de7..c58d9df 100644
--- a/irgen/runtime.go
+++ b/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},
diff --git a/irgen/ssa.go b/irgen/ssa.go
index 90e0a44..f7a3230 100644
--- a/irgen/ssa.go
+++ b/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 {
diff --git a/libgo-noext.diff b/libgo-noext.diff
index 5a6c664..86312bb 100644
--- a/libgo-noext.diff
+++ b/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<<PageShift), s->npages<<PageShift);
  	runtime_MHeap_Free(&runtime_mheap, s, 0);
  }
-diff -r a6e10414311a libgo/runtime/mgc0.c
---- a/libgo/runtime/mgc0.c	Fri Jan 16 07:57:02 2015 -0800
-+++ b/libgo/runtime/mgc0.c	Fri Feb 13 16:36:07 2015 -0800
+diff -r bb70e852004f libgo/runtime/mgc0.c
+--- a/libgo/runtime/mgc0.c	Fri Jan 16 13:28:21 2015 -0800
++++ b/libgo/runtime/mgc0.c	Fri Apr 03 17:31:02 2015 -0700
 @@ -225,7 +225,7 @@
  	Note	alldone;
  	ParFor	*markfor;
@@ -650,9 +650,9 @@
  	return out;
  }
  
-diff -r a6e10414311a libgo/runtime/mheap.c
---- a/libgo/runtime/mheap.c	Fri Jan 16 07:57:02 2015 -0800
-+++ b/libgo/runtime/mheap.c	Fri Feb 13 16:36:07 2015 -0800
+diff -r bb70e852004f libgo/runtime/mheap.c
+--- a/libgo/runtime/mheap.c	Fri Jan 16 13:28:21 2015 -0800
++++ b/libgo/runtime/mheap.c	Fri Apr 03 17:31:02 2015 -0700
 @@ -70,7 +70,7 @@
  	runtime_MSpanList_Init(&h->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);
  
diff --git a/test/irgen/cabi.go b/test/irgen/cabi.go
index efa4489..bff2d7c 100644
--- a/test/irgen/cabi.go
+++ b/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) {}
diff --git a/test/irgen/imports.go b/test/irgen/imports.go
index 6405b02..ae6498a 100644
--- a/test/irgen/imports.go
+++ b/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: ; <label>:[[L]]
 // CHECK-NEXT: call void @__go_register_gc_roots
 // CHECK-NEXT: store i1 true, i1* @"init$guard"
-// CHECK-NEXT: call void @fmt..import()
+// CHECK-NEXT: call void @fmt..import(i8* undef)
 // CHECK-NEXT: br label
diff --git a/test/irgen/mangling-synthetic.go b/test/irgen/mangling-synthetic.go
index b88e037..ab043a6 100644
--- a/test/irgen/mangling-synthetic.go
+++ b/test/irgen/mangling-synthetic.go
@@ -5,10 +5,10 @@
 
 import "p"
 
-// CHECK-DAG: define linkonce_odr void @p.f.N3_q.T(i8*)
-// CHECK-DAG: define linkonce_odr void @p.f.pN3_q.T(i8*)
+// CHECK-DAG: define linkonce_odr void @p.f.N3_q.T(i8* nest, i8*)
+// CHECK-DAG: define linkonce_odr void @p.f.pN3_q.T(i8* nest, i8*)
 type T struct { p.U }
 
-// CHECK-DAG: declare void @q.f.N3_q.T(i8*)
-// CHECK-DAG: define linkonce_odr void @q.f.pN3_q.T(i8*)
+// CHECK-DAG: declare void @q.f.N3_q.T(i8* nest, i8*)
+// CHECK-DAG: define linkonce_odr void @q.f.pN3_q.T(i8* nest, i8*)
 func (T) f()
diff --git a/third_party/gofrontend/depcomp b/third_party/gofrontend/depcomp
index df8eea7..4e70ff0 100644
--- a/third_party/gofrontend/depcomp
+++ b/third_party/gofrontend/depcomp
@@ -1,10 +1,9 @@
 #! /bin/sh
 # depcomp - compile a program generating dependencies as side-effects
 
-scriptversion=2009-04-28.21; # UTC
+scriptversion=2013-05-30.07; # UTC
 
-# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
-# Software Foundation, Inc.
+# Copyright (C) 1999-2014 Free Software Foundation, Inc.
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -28,9 +27,9 @@
 
 case $1 in
   '')
-     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
-     exit 1;
-     ;;
+    echo "$0: No command.  Try '$0 --help' for more information." 1>&2
+    exit 1;
+    ;;
   -h | --h*)
     cat <<\EOF
 Usage: depcomp [--help] [--version] PROGRAM [ARGS]
@@ -40,11 +39,11 @@
 
 Environment variables:
   depmode     Dependency tracking mode.
-  source      Source file read by `PROGRAMS ARGS'.
-  object      Object file output by `PROGRAMS ARGS'.
+  source      Source file read by 'PROGRAMS ARGS'.
+  object      Object file output by 'PROGRAMS ARGS'.
   DEPDIR      directory where to store dependencies.
   depfile     Dependency file to output.
-  tmpdepfile  Temporary file to use when outputing dependencies.
+  tmpdepfile  Temporary file to use when outputting dependencies.
   libtool     Whether libtool is used (yes/no).
 
 Report bugs to <bug-automake@gnu.org>.
@@ -57,6 +56,66 @@
     ;;
 esac
 
+# Get the directory component of the given path, and save it in the
+# global variables '$dir'.  Note that this directory component will
+# be either empty or ending with a '/' character.  This is deliberate.
+set_dir_from ()
+{
+  case $1 in
+    */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
+      *) dir=;;
+  esac
+}
+
+# Get the suffix-stripped basename of the given path, and save it the
+# global variable '$base'.
+set_base_from ()
+{
+  base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
+}
+
+# If no dependency file was actually created by the compiler invocation,
+# we still have to create a dummy depfile, to avoid errors with the
+# Makefile "include basename.Plo" scheme.
+make_dummy_depfile ()
+{
+  echo "#dummy" > "$depfile"
+}
+
+# Factor out some common post-processing of the generated depfile.
+# Requires the auxiliary global variable '$tmpdepfile' to be set.
+aix_post_process_depfile ()
+{
+  # If the compiler actually managed to produce a dependency file,
+  # post-process it.
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form 'foo.o: dependency.h'.
+    # Do two passes, one to just change these to
+    #   $object: dependency.h
+    # and one to simply output
+    #   dependency.h:
+    # which is needed to avoid the deleted-header problem.
+    { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
+      sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
+    } > "$depfile"
+    rm -f "$tmpdepfile"
+  else
+    make_dummy_depfile
+  fi
+}
+
+# A tabulation character.
+tab='	'
+# A newline character.
+nl='
+'
+# Character ranges might be problematic outside the C locale.
+# These definitions help.
+upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
+lower=abcdefghijklmnopqrstuvwxyz
+digits=0123456789
+alpha=${upper}${lower}
+
 if test -z "$depmode" || test -z "$source" || test -z "$object"; then
   echo "depcomp: Variables source, object and depmode must be set" 1>&2
   exit 1
@@ -69,6 +128,9 @@
 
 rm -f "$tmpdepfile"
 
+# Avoid interferences from the environment.
+gccflag= dashmflag=
+
 # Some modes work just like other modes, but use different flags.  We
 # parameterize here, but still list the modes in the big case below,
 # to make depend.m4 easier to write.  Note that we *cannot* use a case
@@ -80,18 +142,32 @@
 fi
 
 if test "$depmode" = dashXmstdout; then
-   # This is just like dashmstdout with a different argument.
-   dashmflag=-xM
-   depmode=dashmstdout
+  # This is just like dashmstdout with a different argument.
+  dashmflag=-xM
+  depmode=dashmstdout
 fi
 
 cygpath_u="cygpath -u -f -"
 if test "$depmode" = msvcmsys; then
-   # This is just like msvisualcpp but w/o cygpath translation.
-   # Just convert the backslash-escaped backslashes to single forward
-   # slashes to satisfy depend.m4
-   cygpath_u="sed s,\\\\\\\\,/,g"
-   depmode=msvisualcpp
+  # This is just like msvisualcpp but w/o cygpath translation.
+  # Just convert the backslash-escaped backslashes to single forward
+  # slashes to satisfy depend.m4
+  cygpath_u='sed s,\\\\,/,g'
+  depmode=msvisualcpp
+fi
+
+if test "$depmode" = msvc7msys; then
+  # This is just like msvc7 but w/o cygpath translation.
+  # Just convert the backslash-escaped backslashes to single forward
+  # slashes to satisfy depend.m4
+  cygpath_u='sed s,\\\\,/,g'
+  depmode=msvc7
+fi
+
+if test "$depmode" = xlc; then
+  # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
+  gccflag=-qmakedep=gcc,-MF
+  depmode=gcc
 fi
 
 case "$depmode" in
@@ -114,8 +190,7 @@
   done
   "$@"
   stat=$?
-  if test $stat -eq 0; then :
-  else
+  if test $stat -ne 0; then
     rm -f "$tmpdepfile"
     exit $stat
   fi
@@ -123,13 +198,17 @@
   ;;
 
 gcc)
+## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
+## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
+## (see the conditional assignment to $gccflag above).
 ## There are various ways to get dependency output from gcc.  Here's
 ## why we pick this rather obscure method:
 ## - Don't want to use -MD because we'd like the dependencies to end
 ##   up in a subdir.  Having to rename by hand is ugly.
 ##   (We might end up doing this anyway to support other compilers.)
 ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
-##   -MM, not -M (despite what the docs say).
+##   -MM, not -M (despite what the docs say).  Also, it might not be
+##   supported by the other compilers which use the 'gcc' depmode.
 ## - Using -M directly means running the compiler twice (even worse
 ##   than renaming).
   if test -z "$gccflag"; then
@@ -137,31 +216,31 @@
   fi
   "$@" -Wp,"$gccflag$tmpdepfile"
   stat=$?
-  if test $stat -eq 0; then :
-  else
+  if test $stat -ne 0; then
     rm -f "$tmpdepfile"
     exit $stat
   fi
   rm -f "$depfile"
   echo "$object : \\" > "$depfile"
-  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
-## The second -e expression handles DOS-style file names with drive letters.
+  # The second -e expression handles DOS-style file names with drive
+  # letters.
   sed -e 's/^[^:]*: / /' \
       -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
-## This next piece of magic avoids the `deleted header file' problem.
+## This next piece of magic avoids the "deleted header file" problem.
 ## The problem is that when a header file which appears in a .P file
 ## is deleted, the dependency causes make to die (because there is
 ## typically no way to rebuild the header).  We avoid this by adding
 ## dummy dependencies for each header file.  Too bad gcc doesn't do
 ## this for us directly.
-  tr ' ' '
-' < "$tmpdepfile" |
-## Some versions of gcc put a space before the `:'.  On the theory
+## Some versions of gcc put a space before the ':'.  On the theory
 ## that the space means something, we add a space to the output as
-## well.
+## well.  hp depmode also adds that space, but also prefixes the VPATH
+## to the object.  Take care to not repeat it in the output.
 ## Some versions of the HPUX 10.20 sed can't process this invocation
 ## correctly.  Breaking it into two sed invocations is a workaround.
-    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  tr ' ' "$nl" < "$tmpdepfile" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
   rm -f "$tmpdepfile"
   ;;
 
@@ -172,59 +251,21 @@
   exit 1
   ;;
 
-sgi)
-  if test "$libtool" = yes; then
-    "$@" "-Wp,-MDupdate,$tmpdepfile"
-  else
-    "$@" -MDupdate "$tmpdepfile"
-  fi
-  stat=$?
-  if test $stat -eq 0; then :
-  else
-    rm -f "$tmpdepfile"
-    exit $stat
-  fi
-  rm -f "$depfile"
-
-  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
-    echo "$object : \\" > "$depfile"
-
-    # Clip off the initial element (the dependent).  Don't try to be
-    # clever and replace this with sed code, as IRIX sed won't handle
-    # lines with more than a fixed number of characters (4096 in
-    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
-    # the IRIX cc adds comments like `#:fec' to the end of the
-    # dependency line.
-    tr ' ' '
-' < "$tmpdepfile" \
-    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
-    tr '
-' ' ' >> "$depfile"
-    echo >> "$depfile"
-
-    # The second pass generates a dummy entry for each header file.
-    tr ' ' '
-' < "$tmpdepfile" \
-   | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
-   >> "$depfile"
-  else
-    # The sourcefile does not contain any dependencies, so just
-    # store a dummy comment line, to avoid errors with the Makefile
-    # "include basename.Plo" scheme.
-    echo "#dummy" > "$depfile"
-  fi
-  rm -f "$tmpdepfile"
+xlc)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
   ;;
 
 aix)
   # The C for AIX Compiler uses -M and outputs the dependencies
   # in a .u file.  In older versions, this file always lives in the
-  # current directory.  Also, the AIX compiler puts `$object:' at the
+  # current directory.  Also, the AIX compiler puts '$object:' at the
   # start of each line; $object doesn't have directory information.
   # Version 6 uses the directory in both cases.
-  dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
-  test "x$dir" = "x$object" && dir=
-  base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  set_dir_from "$object"
+  set_base_from "$object"
   if test "$libtool" = yes; then
     tmpdepfile1=$dir$base.u
     tmpdepfile2=$base.u
@@ -237,9 +278,7 @@
     "$@" -M
   fi
   stat=$?
-
-  if test $stat -eq 0; then :
-  else
+  if test $stat -ne 0; then
     rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
     exit $stat
   fi
@@ -248,44 +287,100 @@
   do
     test -f "$tmpdepfile" && break
   done
-  if test -f "$tmpdepfile"; then
-    # Each line is of the form `foo.o: dependent.h'.
-    # Do two passes, one to just change these to
-    # `$object: dependent.h' and one to simply `dependent.h:'.
-    sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
-    # That's a tab and a space in the [].
-    sed -e 's,^.*\.[a-z]*:[	 ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
-  else
-    # The sourcefile does not contain any dependencies, so just
-    # store a dummy comment line, to avoid errors with the Makefile
-    # "include basename.Plo" scheme.
-    echo "#dummy" > "$depfile"
+  aix_post_process_depfile
+  ;;
+
+tcc)
+  # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
+  # FIXME: That version still under development at the moment of writing.
+  #        Make that this statement remains true also for stable, released
+  #        versions.
+  # It will wrap lines (doesn't matter whether long or short) with a
+  # trailing '\', as in:
+  #
+  #   foo.o : \
+  #    foo.c \
+  #    foo.h \
+  #
+  # It will put a trailing '\' even on the last line, and will use leading
+  # spaces rather than leading tabs (at least since its commit 0394caf7
+  # "Emit spaces for -MD").
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
   fi
+  rm -f "$depfile"
+  # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
+  # We have to change lines of the first kind to '$object: \'.
+  sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
+  # And for each line of the second kind, we have to emit a 'dep.h:'
+  # dummy dependency, to avoid the deleted-header problem.
+  sed -n -e 's|^  *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
   rm -f "$tmpdepfile"
   ;;
 
-icc)
-  # Intel's C compiler understands `-MD -MF file'.  However on
-  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
-  # ICC 7.0 will fill foo.d with something like
-  #    foo.o: sub/foo.c
-  #    foo.o: sub/foo.h
-  # which is wrong.  We want:
-  #    sub/foo.o: sub/foo.c
-  #    sub/foo.o: sub/foo.h
-  #    sub/foo.c:
-  #    sub/foo.h:
-  # ICC 7.1 will output
+## The order of this option in the case statement is important, since the
+## shell code in configure will try each of these formats in the order
+## listed in this file.  A plain '-MD' option would be understood by many
+## compilers, so we must ensure this comes after the gcc and icc options.
+pgcc)
+  # Portland's C compiler understands '-MD'.
+  # Will always output deps to 'file.d' where file is the root name of the
+  # source file under compilation, even if file resides in a subdirectory.
+  # The object file name does not affect the name of the '.d' file.
+  # pgcc 10.2 will output
   #    foo.o: sub/foo.c sub/foo.h
-  # and will wrap long lines using \ :
+  # and will wrap long lines using '\' :
   #    foo.o: sub/foo.c ... \
   #     sub/foo.h ... \
   #     ...
+  set_dir_from "$object"
+  # Use the source, not the object, to determine the base name, since
+  # that's sadly what pgcc will do too.
+  set_base_from "$source"
+  tmpdepfile=$base.d
 
-  "$@" -MD -MF "$tmpdepfile"
-  stat=$?
-  if test $stat -eq 0; then :
-  else
+  # For projects that build the same source file twice into different object
+  # files, the pgcc approach of using the *source* file root name can cause
+  # problems in parallel builds.  Use a locking strategy to avoid stomping on
+  # the same $tmpdepfile.
+  lockdir=$base.d-lock
+  trap "
+    echo '$0: caught signal, cleaning up...' >&2
+    rmdir '$lockdir'
+    exit 1
+  " 1 2 13 15
+  numtries=100
+  i=$numtries
+  while test $i -gt 0; do
+    # mkdir is a portable test-and-set.
+    if mkdir "$lockdir" 2>/dev/null; then
+      # This process acquired the lock.
+      "$@" -MD
+      stat=$?
+      # Release the lock.
+      rmdir "$lockdir"
+      break
+    else
+      # If the lock is being held by a different process, wait
+      # until the winning process is done or we timeout.
+      while test -d "$lockdir" && test $i -gt 0; do
+        sleep 1
+        i=`expr $i - 1`
+      done
+    fi
+    i=`expr $i - 1`
+  done
+  trap - 1 2 13 15
+  if test $i -le 0; then
+    echo "$0: failed to acquire lock after $numtries attempts" >&2
+    echo "$0: check lockdir '$lockdir'" >&2
+    exit 1
+  fi
+
+  if test $stat -ne 0; then
     rm -f "$tmpdepfile"
     exit $stat
   fi
@@ -297,8 +392,8 @@
   sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
   # Some versions of the HPUX 10.20 sed can't process this invocation
   # correctly.  Breaking it into two sed invocations is a workaround.
-  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
-    sed -e 's/$/ :/' >> "$depfile"
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
+    | sed -e 's/$/ :/' >> "$depfile"
   rm -f "$tmpdepfile"
   ;;
 
@@ -309,9 +404,8 @@
   # 'foo.d', which lands next to the object file, wherever that
   # happens to be.
   # Much of this is similar to the tru64 case; see comments there.
-  dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
-  test "x$dir" = "x$object" && dir=
-  base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  set_dir_from  "$object"
+  set_base_from "$object"
   if test "$libtool" = yes; then
     tmpdepfile1=$dir$base.d
     tmpdepfile2=$dir.libs/$base.d
@@ -322,8 +416,7 @@
     "$@" +Maked
   fi
   stat=$?
-  if test $stat -eq 0; then :
-  else
+  if test $stat -ne 0; then
      rm -f "$tmpdepfile1" "$tmpdepfile2"
      exit $stat
   fi
@@ -333,77 +426,107 @@
     test -f "$tmpdepfile" && break
   done
   if test -f "$tmpdepfile"; then
-    sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
-    # Add `dependent.h:' lines.
+    sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
+    # Add 'dependent.h:' lines.
     sed -ne '2,${
-	       s/^ *//
-	       s/ \\*$//
-	       s/$/:/
-	       p
-	     }' "$tmpdepfile" >> "$depfile"
+               s/^ *//
+               s/ \\*$//
+               s/$/:/
+               p
+             }' "$tmpdepfile" >> "$depfile"
   else
-    echo "#dummy" > "$depfile"
+    make_dummy_depfile
   fi
   rm -f "$tmpdepfile" "$tmpdepfile2"
   ;;
 
 tru64)
-   # The Tru64 compiler uses -MD to generate dependencies as a side
-   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
-   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
-   # dependencies in `foo.d' instead, so we check for that too.
-   # Subdirectories are respected.
-   dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
-   test "x$dir" = "x$object" && dir=
-   base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  # The Tru64 compiler uses -MD to generate dependencies as a side
+  # effect.  'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
+  # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+  # dependencies in 'foo.d' instead, so we check for that too.
+  # Subdirectories are respected.
+  set_dir_from  "$object"
+  set_base_from "$object"
 
-   if test "$libtool" = yes; then
-      # With Tru64 cc, shared objects can also be used to make a
-      # static library.  This mechanism is used in libtool 1.4 series to
-      # handle both shared and static libraries in a single compilation.
-      # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
-      #
-      # With libtool 1.5 this exception was removed, and libtool now
-      # generates 2 separate objects for the 2 libraries.  These two
-      # compilations output dependencies in $dir.libs/$base.o.d and
-      # in $dir$base.o.d.  We have to check for both files, because
-      # one of the two compilations can be disabled.  We should prefer
-      # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
-      # automatically cleaned when .libs/ is deleted, while ignoring
-      # the former would cause a distcleancheck panic.
-      tmpdepfile1=$dir.libs/$base.lo.d   # libtool 1.4
-      tmpdepfile2=$dir$base.o.d          # libtool 1.5
-      tmpdepfile3=$dir.libs/$base.o.d    # libtool 1.5
-      tmpdepfile4=$dir.libs/$base.d      # Compaq CCC V6.2-504
-      "$@" -Wc,-MD
-   else
-      tmpdepfile1=$dir$base.o.d
-      tmpdepfile2=$dir$base.d
-      tmpdepfile3=$dir$base.d
-      tmpdepfile4=$dir$base.d
-      "$@" -MD
-   fi
+  if test "$libtool" = yes; then
+    # Libtool generates 2 separate objects for the 2 libraries.  These
+    # two compilations output dependencies in $dir.libs/$base.o.d and
+    # in $dir$base.o.d.  We have to check for both files, because
+    # one of the two compilations can be disabled.  We should prefer
+    # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+    # automatically cleaned when .libs/ is deleted, while ignoring
+    # the former would cause a distcleancheck panic.
+    tmpdepfile1=$dir$base.o.d          # libtool 1.5
+    tmpdepfile2=$dir.libs/$base.o.d    # Likewise.
+    tmpdepfile3=$dir.libs/$base.d      # Compaq CCC V6.2-504
+    "$@" -Wc,-MD
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    tmpdepfile3=$dir$base.d
+    "$@" -MD
+  fi
 
-   stat=$?
-   if test $stat -eq 0; then :
-   else
-      rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
-      exit $stat
-   fi
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
 
-   for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
-   do
-     test -f "$tmpdepfile" && break
-   done
-   if test -f "$tmpdepfile"; then
-      sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
-      # That's a tab and a space in the [].
-      sed -e 's,^.*\.[a-z]*:[	 ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
-   else
-      echo "#dummy" > "$depfile"
-   fi
-   rm -f "$tmpdepfile"
-   ;;
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  # Same post-processing that is required for AIX mode.
+  aix_post_process_depfile
+  ;;
+
+msvc7)
+  if test "$libtool" = yes; then
+    showIncludes=-Wc,-showIncludes
+  else
+    showIncludes=-showIncludes
+  fi
+  "$@" $showIncludes > "$tmpdepfile"
+  stat=$?
+  grep -v '^Note: including file: ' "$tmpdepfile"
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  # The first sed program below extracts the file names and escapes
+  # backslashes for cygpath.  The second sed program outputs the file
+  # name when reading, but also accumulates all include files in the
+  # hold buffer in order to output them again at the end.  This only
+  # works with sed implementations that can handle large buffers.
+  sed < "$tmpdepfile" -n '
+/^Note: including file:  *\(.*\)/ {
+  s//\1/
+  s/\\/\\\\/g
+  p
+}' | $cygpath_u | sort -u | sed -n '
+s/ /\\ /g
+s/\(.*\)/'"$tab"'\1 \\/p
+s/.\(.*\) \\/\1:/
+H
+$ {
+  s/.*/'"$tab"'/
+  G
+  p
+}' >> "$depfile"
+  echo >> "$depfile" # make sure the fragment doesn't end with a backslash
+  rm -f "$tmpdepfile"
+  ;;
+
+msvc7msys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
 
 #nosideeffect)
   # This comment above is used by automake to tell side-effect
@@ -422,7 +545,7 @@
     shift
   fi
 
-  # Remove `-o $object'.
+  # Remove '-o $object'.
   IFS=" "
   for arg
   do
@@ -442,18 +565,18 @@
   done
 
   test -z "$dashmflag" && dashmflag=-M
-  # Require at least two characters before searching for `:'
+  # Require at least two characters before searching for ':'
   # in the target name.  This is to cope with DOS-style filenames:
-  # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+  # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
   "$@" $dashmflag |
-    sed 's:^[  ]*[^: ][^:][^:]*\:[    ]*:'"$object"'\: :' > "$tmpdepfile"
+    sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
   rm -f "$depfile"
   cat < "$tmpdepfile" > "$depfile"
-  tr ' ' '
-' < "$tmpdepfile" | \
-## Some versions of the HPUX 10.20 sed can't process this invocation
-## correctly.  Breaking it into two sed invocations is a workaround.
-    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this sed invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  tr ' ' "$nl" < "$tmpdepfile" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
   rm -f "$tmpdepfile"
   ;;
 
@@ -503,12 +626,15 @@
   touch "$tmpdepfile"
   ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
   rm -f "$depfile"
-  cat < "$tmpdepfile" > "$depfile"
-  sed '1,2d' "$tmpdepfile" | tr ' ' '
-' | \
-## Some versions of the HPUX 10.20 sed can't process this invocation
-## correctly.  Breaking it into two sed invocations is a workaround.
-    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  # makedepend may prepend the VPATH from the source file name to the object.
+  # No need to regex-escape $object, excess matching of '.' is harmless.
+  sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process the last invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed '1,2d' "$tmpdepfile" \
+    | tr ' ' "$nl" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
   rm -f "$tmpdepfile" "$tmpdepfile".bak
   ;;
 
@@ -525,7 +651,7 @@
     shift
   fi
 
-  # Remove `-o $object'.
+  # Remove '-o $object'.
   IFS=" "
   for arg
   do
@@ -544,10 +670,10 @@
     esac
   done
 
-  "$@" -E |
-    sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-       -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
-    sed '$ s: \\$::' > "$tmpdepfile"
+  "$@" -E \
+    | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+             -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+    | sed '$ s: \\$::' > "$tmpdepfile"
   rm -f "$depfile"
   echo "$object : \\" > "$depfile"
   cat < "$tmpdepfile" >> "$depfile"
@@ -579,23 +705,23 @@
       shift
       ;;
     "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
-	set fnord "$@"
-	shift
-	shift
-	;;
+        set fnord "$@"
+        shift
+        shift
+        ;;
     *)
-	set fnord "$@" "$arg"
-	shift
-	shift
-	;;
+        set fnord "$@" "$arg"
+        shift
+        shift
+        ;;
     esac
   done
   "$@" -E 2>/dev/null |
   sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
   rm -f "$depfile"
   echo "$object : \\" > "$depfile"
-  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::	\1 \\:p' >> "$depfile"
-  echo "	" >> "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
+  echo "$tab" >> "$depfile"
   sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
   rm -f "$tmpdepfile"
   ;;
diff --git a/third_party/gofrontend/install-sh b/third_party/gofrontend/install-sh
index 6781b98..0b0fdcb 100644
--- a/third_party/gofrontend/install-sh
+++ b/third_party/gofrontend/install-sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 # install - install a program, script, or datafile
 
-scriptversion=2009-04-28.21; # UTC
+scriptversion=2013-12-25.23; # UTC
 
 # This originates from X11R5 (mit/util/scripts/install.sh), which was
 # later released in X11R6 (xc/config/util/install.sh) with the
@@ -35,25 +35,21 @@
 # FSF changes to this file are in the public domain.
 #
 # Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
+# 'make' implicit rules from creating a file called install from it
 # when there is no Makefile.
 #
 # This script is compatible with the BSD install script, but was written
 # from scratch.
 
+tab='	'
 nl='
 '
-IFS=" ""	$nl"
+IFS=" $tab$nl"
 
-# set DOITPROG to echo to test this script
+# Set DOITPROG to "echo" to test this script.
 
-# Don't use :- since 4.3BSD and earlier shells don't like it.
 doit=${DOITPROG-}
-if test -z "$doit"; then
-  doit_exec=exec
-else
-  doit_exec=$doit
-fi
+doit_exec=${doit:-exec}
 
 # Put in absolute file names if you don't have them in your path;
 # or use environment vars.
@@ -68,17 +64,6 @@
 rmprog=${RMPROG-rm}
 stripprog=${STRIPPROG-strip}
 
-posix_glob='?'
-initialize_posix_glob='
-  test "$posix_glob" != "?" || {
-    if (set -f) 2>/dev/null; then
-      posix_glob=
-    else
-      posix_glob=:
-    fi
-  }
-'
-
 posix_mkdir=
 
 # Desired mode of installed file.
@@ -97,7 +82,7 @@
 dst_arg=
 
 copy_on_change=false
-no_target_directory=
+is_target_a_directory=possibly
 
 usage="\
 Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
@@ -137,42 +122,57 @@
     -d) dir_arg=true;;
 
     -g) chgrpcmd="$chgrpprog $2"
-	shift;;
+        shift;;
 
     --help) echo "$usage"; exit $?;;
 
     -m) mode=$2
-	case $mode in
-	  *' '* | *'	'* | *'
-'*	  | *'*'* | *'?'* | *'['*)
-	    echo "$0: invalid mode: $mode" >&2
-	    exit 1;;
-	esac
-	shift;;
+        case $mode in
+          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
+            echo "$0: invalid mode: $mode" >&2
+            exit 1;;
+        esac
+        shift;;
 
     -o) chowncmd="$chownprog $2"
-	shift;;
+        shift;;
 
     -s) stripcmd=$stripprog;;
 
-    -t) dst_arg=$2
-	shift;;
+    -t)
+        is_target_a_directory=always
+        dst_arg=$2
+        # Protect names problematic for 'test' and other utilities.
+        case $dst_arg in
+          -* | [=\(\)!]) dst_arg=./$dst_arg;;
+        esac
+        shift;;
 
-    -T) no_target_directory=true;;
+    -T) is_target_a_directory=never;;
 
     --version) echo "$0 $scriptversion"; exit $?;;
 
-    --)	shift
-	break;;
+    --) shift
+        break;;
 
-    -*)	echo "$0: invalid option: $1" >&2
-	exit 1;;
+    -*) echo "$0: invalid option: $1" >&2
+        exit 1;;
 
     *)  break;;
   esac
   shift
 done
 
+# We allow the use of options -d and -T together, by making -d
+# take the precedence; this is for compatibility with GNU install.
+
+if test -n "$dir_arg"; then
+  if test -n "$dst_arg"; then
+    echo "$0: target directory not allowed when installing a directory." >&2
+    exit 1
+  fi
+fi
+
 if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
   # When -d is used, all remaining arguments are directories to create.
   # When -t is used, the destination is already specified.
@@ -186,6 +186,10 @@
     fi
     shift # arg
     dst_arg=$arg
+    # Protect names problematic for 'test' and other utilities.
+    case $dst_arg in
+      -* | [=\(\)!]) dst_arg=./$dst_arg;;
+    esac
   done
 fi
 
@@ -194,13 +198,26 @@
     echo "$0: no input file specified." >&2
     exit 1
   fi
-  # It's OK to call `install-sh -d' without argument.
+  # It's OK to call 'install-sh -d' without argument.
   # This can happen when creating conditional directories.
   exit 0
 fi
 
 if test -z "$dir_arg"; then
-  trap '(exit $?); exit' 1 2 13 15
+  if test $# -gt 1 || test "$is_target_a_directory" = always; then
+    if test ! -d "$dst_arg"; then
+      echo "$0: $dst_arg: Is not a directory." >&2
+      exit 1
+    fi
+  fi
+fi
+
+if test -z "$dir_arg"; then
+  do_exit='(exit $ret); exit $ret'
+  trap "ret=129; $do_exit" 1
+  trap "ret=130; $do_exit" 2
+  trap "ret=141; $do_exit" 13
+  trap "ret=143; $do_exit" 15
 
   # Set umask so as not to create temps with too-generous modes.
   # However, 'strip' requires both read and write access to temps.
@@ -211,16 +228,16 @@
 
     *[0-7])
       if test -z "$stripcmd"; then
-	u_plus_rw=
+        u_plus_rw=
       else
-	u_plus_rw='% 200'
+        u_plus_rw='% 200'
       fi
       cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
     *)
       if test -z "$stripcmd"; then
-	u_plus_rw=
+        u_plus_rw=
       else
-	u_plus_rw=,u+rw
+        u_plus_rw=,u+rw
       fi
       cp_umask=$mode$u_plus_rw;;
   esac
@@ -228,9 +245,9 @@
 
 for src
 do
-  # Protect names starting with `-'.
+  # Protect names problematic for 'test' and other utilities.
   case $src in
-    -*) src=./$src;;
+    -* | [=\(\)!]) src=./$src;;
   esac
 
   if test -n "$dir_arg"; then
@@ -252,51 +269,20 @@
       echo "$0: no destination specified." >&2
       exit 1
     fi
-
     dst=$dst_arg
-    # Protect names starting with `-'.
-    case $dst in
-      -*) dst=./$dst;;
-    esac
 
     # If destination is a directory, append the input filename; won't work
     # if double slashes aren't ignored.
     if test -d "$dst"; then
-      if test -n "$no_target_directory"; then
-	echo "$0: $dst_arg: Is a directory" >&2
-	exit 1
+      if test "$is_target_a_directory" = never; then
+        echo "$0: $dst_arg: Is a directory" >&2
+        exit 1
       fi
       dstdir=$dst
       dst=$dstdir/`basename "$src"`
       dstdir_status=0
     else
-      # Prefer dirname, but fall back on a substitute if dirname fails.
-      dstdir=`
-	(dirname "$dst") 2>/dev/null ||
-	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-	     X"$dst" : 'X\(//\)[^/]' \| \
-	     X"$dst" : 'X\(//\)$' \| \
-	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
-	echo X"$dst" |
-	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
-		   s//\1/
-		   q
-		 }
-		 /^X\(\/\/\)[^/].*/{
-		   s//\1/
-		   q
-		 }
-		 /^X\(\/\/\)$/{
-		   s//\1/
-		   q
-		 }
-		 /^X\(\/\).*/{
-		   s//\1/
-		   q
-		 }
-		 s/.*/./; q'
-      `
-
+      dstdir=`dirname "$dst"`
       test -d "$dstdir"
       dstdir_status=$?
     fi
@@ -307,74 +293,74 @@
   if test $dstdir_status != 0; then
     case $posix_mkdir in
       '')
-	# Create intermediate dirs using mode 755 as modified by the umask.
-	# This is like FreeBSD 'install' as of 1997-10-28.
-	umask=`umask`
-	case $stripcmd.$umask in
-	  # Optimize common cases.
-	  *[2367][2367]) mkdir_umask=$umask;;
-	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+        # Create intermediate dirs using mode 755 as modified by the umask.
+        # This is like FreeBSD 'install' as of 1997-10-28.
+        umask=`umask`
+        case $stripcmd.$umask in
+          # Optimize common cases.
+          *[2367][2367]) mkdir_umask=$umask;;
+          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
 
-	  *[0-7])
-	    mkdir_umask=`expr $umask + 22 \
-	      - $umask % 100 % 40 + $umask % 20 \
-	      - $umask % 10 % 4 + $umask % 2
-	    `;;
-	  *) mkdir_umask=$umask,go-w;;
-	esac
+          *[0-7])
+            mkdir_umask=`expr $umask + 22 \
+              - $umask % 100 % 40 + $umask % 20 \
+              - $umask % 10 % 4 + $umask % 2
+            `;;
+          *) mkdir_umask=$umask,go-w;;
+        esac
 
-	# With -d, create the new directory with the user-specified mode.
-	# Otherwise, rely on $mkdir_umask.
-	if test -n "$dir_arg"; then
-	  mkdir_mode=-m$mode
-	else
-	  mkdir_mode=
-	fi
+        # With -d, create the new directory with the user-specified mode.
+        # Otherwise, rely on $mkdir_umask.
+        if test -n "$dir_arg"; then
+          mkdir_mode=-m$mode
+        else
+          mkdir_mode=
+        fi
 
-	posix_mkdir=false
-	case $umask in
-	  *[123567][0-7][0-7])
-	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
-	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
-	    ;;
-	  *)
-	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
-	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+        posix_mkdir=false
+        case $umask in
+          *[123567][0-7][0-7])
+            # POSIX mkdir -p sets u+wx bits regardless of umask, which
+            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+            ;;
+          *)
+            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+            trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
 
-	    if (umask $mkdir_umask &&
-		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
-	    then
-	      if test -z "$dir_arg" || {
-		   # Check for POSIX incompatibilities with -m.
-		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
-		   # other-writeable bit of parent directory when it shouldn't.
-		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
-		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
-		   case $ls_ld_tmpdir in
-		     d????-?r-*) different_mode=700;;
-		     d????-?--*) different_mode=755;;
-		     *) false;;
-		   esac &&
-		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
-		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
-		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
-		   }
-		 }
-	      then posix_mkdir=:
-	      fi
-	      rmdir "$tmpdir/d" "$tmpdir"
-	    else
-	      # Remove any dirs left behind by ancient mkdir implementations.
-	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
-	    fi
-	    trap '' 0;;
-	esac;;
+            if (umask $mkdir_umask &&
+                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+            then
+              if test -z "$dir_arg" || {
+                   # Check for POSIX incompatibilities with -m.
+                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+                   # other-writable bit of parent directory when it shouldn't.
+                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+                   ls_ld_tmpdir=`ls -ld "$tmpdir"`
+                   case $ls_ld_tmpdir in
+                     d????-?r-*) different_mode=700;;
+                     d????-?--*) different_mode=755;;
+                     *) false;;
+                   esac &&
+                   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+                     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+                   }
+                 }
+              then posix_mkdir=:
+              fi
+              rmdir "$tmpdir/d" "$tmpdir"
+            else
+              # Remove any dirs left behind by ancient mkdir implementations.
+              rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+            fi
+            trap '' 0;;
+        esac;;
     esac
 
     if
       $posix_mkdir && (
-	umask $mkdir_umask &&
-	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+        umask $mkdir_umask &&
+        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
       )
     then :
     else
@@ -384,53 +370,51 @@
       # directory the slow way, step by step, checking for races as we go.
 
       case $dstdir in
-	/*) prefix='/';;
-	-*) prefix='./';;
-	*)  prefix='';;
+        /*) prefix='/';;
+        [-=\(\)!]*) prefix='./';;
+        *)  prefix='';;
       esac
 
-      eval "$initialize_posix_glob"
-
       oIFS=$IFS
       IFS=/
-      $posix_glob set -f
+      set -f
       set fnord $dstdir
       shift
-      $posix_glob set +f
+      set +f
       IFS=$oIFS
 
       prefixes=
 
       for d
       do
-	test -z "$d" && continue
+        test X"$d" = X && continue
 
-	prefix=$prefix$d
-	if test -d "$prefix"; then
-	  prefixes=
-	else
-	  if $posix_mkdir; then
-	    (umask=$mkdir_umask &&
-	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
-	    # Don't fail if two instances are running concurrently.
-	    test -d "$prefix" || exit 1
-	  else
-	    case $prefix in
-	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
-	      *) qprefix=$prefix;;
-	    esac
-	    prefixes="$prefixes '$qprefix'"
-	  fi
-	fi
-	prefix=$prefix/
+        prefix=$prefix$d
+        if test -d "$prefix"; then
+          prefixes=
+        else
+          if $posix_mkdir; then
+            (umask=$mkdir_umask &&
+             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+            # Don't fail if two instances are running concurrently.
+            test -d "$prefix" || exit 1
+          else
+            case $prefix in
+              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+              *) qprefix=$prefix;;
+            esac
+            prefixes="$prefixes '$qprefix'"
+          fi
+        fi
+        prefix=$prefix/
       done
 
       if test -n "$prefixes"; then
-	# Don't fail if two instances are running concurrently.
-	(umask $mkdir_umask &&
-	 eval "\$doit_exec \$mkdirprog $prefixes") ||
-	  test -d "$dstdir" || exit 1
-	obsolete_mkdir_used=true
+        # Don't fail if two instances are running concurrently.
+        (umask $mkdir_umask &&
+         eval "\$doit_exec \$mkdirprog $prefixes") ||
+          test -d "$dstdir" || exit 1
+        obsolete_mkdir_used=true
       fi
     fi
   fi
@@ -465,15 +449,12 @@
 
     # If -C, don't bother to copy if it wouldn't change the file.
     if $copy_on_change &&
-       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
-       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&
-
-       eval "$initialize_posix_glob" &&
-       $posix_glob set -f &&
+       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
+       set -f &&
        set X $old && old=:$2:$4:$5:$6 &&
        set X $new && new=:$2:$4:$5:$6 &&
-       $posix_glob set +f &&
-
+       set +f &&
        test "$old" = "$new" &&
        $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
     then
@@ -486,24 +467,24 @@
       # to itself, or perhaps because mv is so ancient that it does not
       # support -f.
       {
-	# Now remove or move aside any old file at destination location.
-	# We try this two ways since rm can't unlink itself on some
-	# systems and the destination file might be busy for other
-	# reasons.  In this case, the final cleanup might fail but the new
-	# file should still install successfully.
-	{
-	  test ! -f "$dst" ||
-	  $doit $rmcmd -f "$dst" 2>/dev/null ||
-	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
-	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
-	  } ||
-	  { echo "$0: cannot unlink or rename $dst" >&2
-	    (exit 1); exit 1
-	  }
-	} &&
+        # Now remove or move aside any old file at destination location.
+        # We try this two ways since rm can't unlink itself on some
+        # systems and the destination file might be busy for other
+        # reasons.  In this case, the final cleanup might fail but the new
+        # file should still install successfully.
+        {
+          test ! -f "$dst" ||
+          $doit $rmcmd -f "$dst" 2>/dev/null ||
+          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+          } ||
+          { echo "$0: cannot unlink or rename $dst" >&2
+            (exit 1); exit 1
+          }
+        } &&
 
-	# Now rename the file to the real destination.
-	$doit $mvcmd "$dsttmp" "$dst"
+        # Now rename the file to the real destination.
+        $doit $mvcmd "$dsttmp" "$dst"
       }
     fi || exit 1
 
diff --git a/third_party/gofrontend/libbacktrace/ChangeLog b/third_party/gofrontend/libbacktrace/ChangeLog
index adb54d8..1e70595 100644
--- a/third_party/gofrontend/libbacktrace/ChangeLog
+++ b/third_party/gofrontend/libbacktrace/ChangeLog
@@ -1,3 +1,26 @@
+2015-01-05  Jakub Jelinek  <jakub@redhat.com>
+
+	Update copyright years.
+
+2014-11-21  H.J. Lu  <hongjiu.lu@intel.com>
+
+	PR bootstrap/63784
+	* configure: Regenerated.
+
+2014-11-11  David Malcolm  <dmalcolm@redhat.com>
+
+	* ChangeLog.jit: New.
+
+2014-11-11  Francois-Xavier Coudert  <fxcoudert@gcc.gnu.org>
+
+	PR target/63610
+	* configure: Regenerate.
+
+2014-10-23  Ian Lance Taylor  <iant@google.com>
+
+	* internal.h (backtrace_atomic_load_pointer) [no atomic or sync]:
+	Fix to return void *.
+
 2014-05-08  Ian Lance Taylor  <iant@google.com>
 
 	* mmap.c (backtrace_free): If freeing a large aligned block of
diff --git a/third_party/gofrontend/libbacktrace/ChangeLog.jit b/third_party/gofrontend/libbacktrace/ChangeLog.jit
new file mode 100644
index 0000000..6b60e3b
--- /dev/null
+++ b/third_party/gofrontend/libbacktrace/ChangeLog.jit
@@ -0,0 +1,14 @@
+2014-09-24  David Malcolm  <dmalcolm@redhat.com>
+
+	* ChangeLog.jit: Add copyright footer.
+
+2013-10-03  David Malcolm  <dmalcolm@redhat.com>
+
+	* configure.ac: Add --enable-host-shared.
+	* configure: Regenerate.
+
+Copyright (C) 2013-2014 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/third_party/gofrontend/libbacktrace/Makefile.am b/third_party/gofrontend/libbacktrace/Makefile.am
index ab1a6b3..a93b82a 100644
--- a/third_party/gofrontend/libbacktrace/Makefile.am
+++ b/third_party/gofrontend/libbacktrace/Makefile.am
@@ -1,5 +1,5 @@
 # Makefile.am -- Backtrace Makefile.
-# Copyright (C) 2012-2014 Free Software Foundation, Inc.
+# Copyright (C) 2012-2015 Free Software Foundation, Inc.
 
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are
diff --git a/third_party/gofrontend/libbacktrace/alloc.c b/third_party/gofrontend/libbacktrace/alloc.c
index 37eca65..143ef68 100644
--- a/third_party/gofrontend/libbacktrace/alloc.c
+++ b/third_party/gofrontend/libbacktrace/alloc.c
@@ -1,5 +1,5 @@
 /* alloc.c -- Memory allocation without mmap.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/atomic.c b/third_party/gofrontend/libbacktrace/atomic.c
index f139d74..fdd2490 100644
--- a/third_party/gofrontend/libbacktrace/atomic.c
+++ b/third_party/gofrontend/libbacktrace/atomic.c
@@ -1,5 +1,5 @@
 /* atomic.c -- Support for atomic functions if not present.
-   Copyright (C) 2013-2014 Free Software Foundation, Inc.
+   Copyright (C) 2013-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/backtrace-supported.h.in b/third_party/gofrontend/libbacktrace/backtrace-supported.h.in
index 901e3f7..5115ce1 100644
--- a/third_party/gofrontend/libbacktrace/backtrace-supported.h.in
+++ b/third_party/gofrontend/libbacktrace/backtrace-supported.h.in
@@ -1,5 +1,5 @@
 /* backtrace-supported.h.in -- Whether stack backtrace is supported.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/backtrace.c b/third_party/gofrontend/libbacktrace/backtrace.c
index cc3105c..d352d27 100644
--- a/third_party/gofrontend/libbacktrace/backtrace.c
+++ b/third_party/gofrontend/libbacktrace/backtrace.c
@@ -1,5 +1,5 @@
 /* backtrace.c -- Entry point for stack backtrace library.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/backtrace.h b/third_party/gofrontend/libbacktrace/backtrace.h
index 03b5479..50dcd40 100644
--- a/third_party/gofrontend/libbacktrace/backtrace.h
+++ b/third_party/gofrontend/libbacktrace/backtrace.h
@@ -1,5 +1,5 @@
 /* backtrace.h -- Public header file for stack backtrace library.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/btest.c b/third_party/gofrontend/libbacktrace/btest.c
index 4b67c3d..9424a92 100644
--- a/third_party/gofrontend/libbacktrace/btest.c
+++ b/third_party/gofrontend/libbacktrace/btest.c
@@ -1,5 +1,5 @@
 /* btest.c -- Test for libbacktrace library
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/configure b/third_party/gofrontend/libbacktrace/configure
index f4f9d05..d6abc7d 100755
--- a/third_party/gofrontend/libbacktrace/configure
+++ b/third_party/gofrontend/libbacktrace/configure
@@ -7576,7 +7576,7 @@
       case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
 	10.0,*86*-darwin8*|10.0,*-darwin[91]*)
 	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
-	10.[012]*)
+	10.[012][,.]*)
 	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
 	10.*)
 	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
@@ -8879,7 +8879,7 @@
       if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
 	 && test "$tmp_diet" = no
       then
-	tmp_addflag=
+	tmp_addflag=' $pic_flag'
 	tmp_sharedflag='-shared'
 	case $cc_basename,$host_cpu in
         pgcc*)				# Portland Group C compiler
diff --git a/third_party/gofrontend/libbacktrace/configure.ac b/third_party/gofrontend/libbacktrace/configure.ac
index 878bd2c..ef88112 100644
--- a/third_party/gofrontend/libbacktrace/configure.ac
+++ b/third_party/gofrontend/libbacktrace/configure.ac
@@ -1,5 +1,5 @@
 # configure.ac -- Backtrace configure script.
-# Copyright (C) 2012-2014 Free Software Foundation, Inc.
+# Copyright (C) 2012-2015 Free Software Foundation, Inc.
 
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are
diff --git a/third_party/gofrontend/libbacktrace/dwarf.c b/third_party/gofrontend/libbacktrace/dwarf.c
index 143bb28..919b568 100644
--- a/third_party/gofrontend/libbacktrace/dwarf.c
+++ b/third_party/gofrontend/libbacktrace/dwarf.c
@@ -1,5 +1,5 @@
 /* dwarf.c -- Get file/line information from DWARF for backtraces.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/elf.c b/third_party/gofrontend/libbacktrace/elf.c
index e63aaf5..3f14b11 100644
--- a/third_party/gofrontend/libbacktrace/elf.c
+++ b/third_party/gofrontend/libbacktrace/elf.c
@@ -1,5 +1,5 @@
 /* elf.c -- Get debug data from an ELF file for backtraces.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/fileline.c b/third_party/gofrontend/libbacktrace/fileline.c
index bab5351..0acad06 100644
--- a/third_party/gofrontend/libbacktrace/fileline.c
+++ b/third_party/gofrontend/libbacktrace/fileline.c
@@ -1,5 +1,5 @@
 /* fileline.c -- Get file and line number information in a backtrace.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/internal.h b/third_party/gofrontend/libbacktrace/internal.h
index 1ae4317..30f99ca 100644
--- a/third_party/gofrontend/libbacktrace/internal.h
+++ b/third_party/gofrontend/libbacktrace/internal.h
@@ -1,5 +1,5 @@
 /* internal.h -- Internal header file for stack backtrace library.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
@@ -99,7 +99,7 @@
 /* We have neither the sync nor the atomic functions.  These will
    never be called.  */
 
-#define backtrace_atomic_load_pointer(p) (abort(), 0)
+#define backtrace_atomic_load_pointer(p) (abort(), (void *) NULL)
 #define backtrace_atomic_load_int(p) (abort(), 0)
 #define backtrace_atomic_store_pointer(p, v) abort()
 #define backtrace_atomic_store_size_t(p, v) abort()
diff --git a/third_party/gofrontend/libbacktrace/mmap.c b/third_party/gofrontend/libbacktrace/mmap.c
index 5a9f629..1ecf131 100644
--- a/third_party/gofrontend/libbacktrace/mmap.c
+++ b/third_party/gofrontend/libbacktrace/mmap.c
@@ -1,5 +1,5 @@
 /* mmap.c -- Memory allocation with mmap.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/mmapio.c b/third_party/gofrontend/libbacktrace/mmapio.c
index 72940b4..b5a787e 100644
--- a/third_party/gofrontend/libbacktrace/mmapio.c
+++ b/third_party/gofrontend/libbacktrace/mmapio.c
@@ -1,5 +1,5 @@
 /* mmapio.c -- File views using mmap.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/nounwind.c b/third_party/gofrontend/libbacktrace/nounwind.c
index 0097966..f53f906 100644
--- a/third_party/gofrontend/libbacktrace/nounwind.c
+++ b/third_party/gofrontend/libbacktrace/nounwind.c
@@ -1,5 +1,5 @@
 /* backtrace.c -- Entry point for stack backtrace library.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/posix.c b/third_party/gofrontend/libbacktrace/posix.c
index dba9e52..7fa7cd0 100644
--- a/third_party/gofrontend/libbacktrace/posix.c
+++ b/third_party/gofrontend/libbacktrace/posix.c
@@ -1,5 +1,5 @@
 /* posix.c -- POSIX file I/O routines for the backtrace library.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/print.c b/third_party/gofrontend/libbacktrace/print.c
index bd224e6..90ecaf8 100644
--- a/third_party/gofrontend/libbacktrace/print.c
+++ b/third_party/gofrontend/libbacktrace/print.c
@@ -1,5 +1,5 @@
 /* print.c -- Print the current backtrace.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/read.c b/third_party/gofrontend/libbacktrace/read.c
index c618a50..299f77b 100644
--- a/third_party/gofrontend/libbacktrace/read.c
+++ b/third_party/gofrontend/libbacktrace/read.c
@@ -1,5 +1,5 @@
 /* read.c -- File views without mmap.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/simple.c b/third_party/gofrontend/libbacktrace/simple.c
index efa8b6f..39c2e90 100644
--- a/third_party/gofrontend/libbacktrace/simple.c
+++ b/third_party/gofrontend/libbacktrace/simple.c
@@ -1,5 +1,5 @@
 /* simple.c -- The backtrace_simple function.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/sort.c b/third_party/gofrontend/libbacktrace/sort.c
index 8c4760f..bcc765e 100644
--- a/third_party/gofrontend/libbacktrace/sort.c
+++ b/third_party/gofrontend/libbacktrace/sort.c
@@ -1,5 +1,5 @@
 /* sort.c -- Sort without allocating memory
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/state.c b/third_party/gofrontend/libbacktrace/state.c
index a7d4e07..a846378 100644
--- a/third_party/gofrontend/libbacktrace/state.c
+++ b/third_party/gofrontend/libbacktrace/state.c
@@ -1,5 +1,5 @@
 /* state.c -- Create the backtrace state.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/stest.c b/third_party/gofrontend/libbacktrace/stest.c
index 5676745..ec93e68 100644
--- a/third_party/gofrontend/libbacktrace/stest.c
+++ b/third_party/gofrontend/libbacktrace/stest.c
@@ -1,5 +1,5 @@
 /* stest.c -- Test for libbacktrace internal sort function
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libbacktrace/unknown.c b/third_party/gofrontend/libbacktrace/unknown.c
index c1fe881..e89cba9 100644
--- a/third_party/gofrontend/libbacktrace/unknown.c
+++ b/third_party/gofrontend/libbacktrace/unknown.c
@@ -1,5 +1,5 @@
 /* unknown.c -- used when backtrace configury does not know file format.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/third_party/gofrontend/libffi/LICENSE b/third_party/gofrontend/libffi/LICENSE
index aa60342..a66fab4 100644
--- a/third_party/gofrontend/libffi/LICENSE
+++ b/third_party/gofrontend/libffi/LICENSE
@@ -1,4 +1,4 @@
-libffi - Copyright (c) 1996-2012  Anthony Green, Red Hat, Inc and others.
+libffi - Copyright (c) 1996-2014  Anthony Green, Red Hat, Inc and others.
 See source files for details.
 
 Permission is hereby granted, free of charge, to any person obtaining
diff --git a/third_party/gofrontend/libffi/Makefile.am b/third_party/gofrontend/libffi/Makefile.am
index 645dc12..64ff1c1 100644
--- a/third_party/gofrontend/libffi/Makefile.am
+++ b/third_party/gofrontend/libffi/Makefile.am
@@ -1,46 +1,19 @@
 ## Process this with automake to create Makefile.in
 
 AUTOMAKE_OPTIONS = foreign subdir-objects
+
 ACLOCAL_AMFLAGS = -I .. -I ../config
 
 SUBDIRS = include testsuite man
 
-EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host	\
-	 src/aarch64/ffi.c src/aarch64/ffitarget.h			\
-	 src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h		\
-	 src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h		\
-	 src/avr32/ffi.c src/avr32/sysv.S src/avr32/ffitarget.h		\
-	 src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h		\
-	 src/ia64/ffi.c src/ia64/ffitarget.h src/ia64/ia64_flags.h	\
-	 src/ia64/unix.S src/mips/ffi.c src/mips/n32.S src/mips/o32.S	\
-	 src/mips/ffitarget.h src/m32r/ffi.c src/m32r/sysv.S		\
-	 src/m32r/ffitarget.h src/m68k/ffi.c src/m68k/sysv.S		\
-	 src/m68k/ffitarget.h						\
-	src/powerpc/ffi.c src/powerpc/ffi_powerpc.h			\
-	src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c		\
-	src/powerpc/sysv.S src/powerpc/linux64.S			\
-	src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S		\
-	src/powerpc/asm.h src/powerpc/aix.S src/powerpc/darwin.S	\
-	src/powerpc/aix_closure.S src/powerpc/darwin_closure.S		\
-	src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h		\
-	src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h		\
-	src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h src/sh64/ffi.c	\
-	src/sh64/sysv.S src/sh64/ffitarget.h src/sparc/v8.S		\
-	src/sparc/v9.S src/sparc/ffitarget.h src/sparc/ffi.c		\
-	src/x86/darwin64.S src/x86/ffi.c src/x86/sysv.S			\
-	src/x86/win32.S src/x86/darwin.S src/x86/win64.S		\
-	src/x86/freebsd.S src/x86/ffi64.c src/x86/unix64.S		\
-	src/x86/ffitarget.h src/pa/ffitarget.h src/pa/ffi.c		\
-	src/pa/linux.S src/pa/hpux32.S src/frv/ffi.c src/bfin/ffi.c	\
-	src/bfin/ffitarget.h src/bfin/sysv.S src/frv/eabi.S		\
-	src/frv/ffitarget.h src/dlmalloc.c src/tile/ffi.c		\
-	src/tile/ffitarget.h src/tile/tile.S libtool-version		\
-	 ChangeLog.libffi m4/libtool.m4 m4/lt~obsolete.m4		\
+EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj			\
+	ChangeLog.libffi ChangeLog.libffi-3.1				\
+	m4/libtool.m4 m4/lt~obsolete.m4					\
 	 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4			\
-	 m4/ltversion.m4 src/arm/gentramp.sh src/debug.c msvcc.sh	\
-	generate-ios-source-and-headers.py				\
-	 generate-osx-source-and-headers.py				\
-	 libffi.xcodeproj/project.pbxproj src/arm/trampoline.S
+	 m4/ltversion.m4 src/debug.c msvcc.sh				\
+	generate-darwin-source-and-headers.py				\
+	libffi.xcodeproj/project.pbxproj				\
+	libtool-ldflags
 
 # Automake Documentation:
 # If your package has Texinfo files in many directories, you can use the
@@ -79,7 +52,6 @@
 	$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)/doc -o doc/libffi.info $(srcdir)/doc/libffi.texi
 	@touch $@
 
-
 CLEANFILES = $(STAMP_GENINSRC) $(STAMP_BUILD_INFO) doc/libffi.info
 MAINTAINERCLEANFILES = $(srcdir)/doc/libffi.info
 
@@ -93,153 +65,147 @@
 # values defined in terms of make variables, as is the case for CC and
 # friends when we are called from the top level Makefile.
 AM_MAKEFLAGS = \
-	"AR_FLAGS=$(AR_FLAGS)" \
-	"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
-	"CFLAGS=$(CFLAGS)" \
-	"CXXFLAGS=$(CXXFLAGS)" \
-	"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
-	"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
-	"INSTALL=$(INSTALL)" \
-	"INSTALL_DATA=$(INSTALL_DATA)" \
-	"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
-	"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
-	"JC1FLAGS=$(JC1FLAGS)" \
-	"LDFLAGS=$(LDFLAGS)" \
-	"LIBCFLAGS=$(LIBCFLAGS)" \
-	"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
-	"MAKE=$(MAKE)" \
-	"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
-	"PICFLAG=$(PICFLAG)" \
-	"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
-	"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
-	"SHELL=$(SHELL)" \
-	"exec_prefix=$(exec_prefix)" \
-	"infodir=$(infodir)" \
-	"libdir=$(libdir)" \
-	"mandir=$(mandir)" \
-	"prefix=$(prefix)" \
-	"AR=$(AR)" \
-	"AS=$(AS)" \
-	"CC=$(CC)" \
-	"CXX=$(CXX)" \
-	"LD=$(LD)" \
-	"NM=$(NM)" \
-	"RANLIB=$(RANLIB)" \
-	"DESTDIR=$(DESTDIR)"
+	'AR_FLAGS=$(AR_FLAGS)' \
+	'CC_FOR_BUILD=$(CC_FOR_BUILD)' \
+	'CFLAGS=$(CFLAGS)' \
+	'CXXFLAGS=$(CXXFLAGS)' \
+	'CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)' \
+	'CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)' \
+	'INSTALL=$(INSTALL)' \
+	'INSTALL_DATA=$(INSTALL_DATA)' \
+	'INSTALL_PROGRAM=$(INSTALL_PROGRAM)' \
+	'INSTALL_SCRIPT=$(INSTALL_SCRIPT)' \
+	'JC1FLAGS=$(JC1FLAGS)' \
+	'LDFLAGS=$(LDFLAGS)' \
+	'LIBCFLAGS=$(LIBCFLAGS)' \
+	'LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)' \
+	'MAKE=$(MAKE)' \
+	'MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)' \
+	'PICFLAG=$(PICFLAG)' \
+	'PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)' \
+	'RUNTESTFLAGS=$(RUNTESTFLAGS)' \
+	'SHELL=$(SHELL)' \
+	'exec_prefix=$(exec_prefix)' \
+	'infodir=$(infodir)' \
+	'libdir=$(libdir)' \
+	'mandir=$(mandir)' \
+	'prefix=$(prefix)' \
+	'AR=$(AR)' \
+	'AS=$(AS)' \
+	'CC=$(CC)' \
+	'CXX=$(CXX)' \
+	'LD=$(LD)' \
+	'NM=$(NM)' \
+	'RANLIB=$(RANLIB)' \
+	'DESTDIR=$(DESTDIR)'
 
 # Subdir rules rely on $(FLAGS_TO_PASS)
 FLAGS_TO_PASS = $(AM_MAKEFLAGS)
 
 MAKEOVERRIDES=
 
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libffi.pc
+
 toolexeclib_LTLIBRARIES = libffi.la
 noinst_LTLIBRARIES = libffi_convenience.la
 
 libffi_la_SOURCES = src/prep_cif.c src/types.c \
 		src/raw_api.c src/java_raw_api.c src/closures.c
 
-nodist_libffi_la_SOURCES =
-
 if FFI_DEBUG
-nodist_libffi_la_SOURCES += src/debug.c
+libffi_la_SOURCES += src/debug.c
 endif
 
-if MIPS
-nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S
-endif
-if BFIN
-nodist_libffi_la_SOURCES += src/bfin/ffi.c src/bfin/sysv.S
-endif
-if X86
-nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S
-endif
-if X86_FREEBSD
-nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/freebsd.S
-endif
-if X86_WIN32
-nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win32.S
-endif
-if X86_WIN64
-nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win64.S
-endif
-if X86_DARWIN
-nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
-endif
-if SPARC
-nodist_libffi_la_SOURCES += src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
-endif
-if ALPHA
-nodist_libffi_la_SOURCES += src/alpha/ffi.c src/alpha/osf.S
-endif
-if IA64
-nodist_libffi_la_SOURCES += src/ia64/ffi.c src/ia64/unix.S
-endif
-if M32R
-nodist_libffi_la_SOURCES += src/m32r/sysv.S src/m32r/ffi.c
-endif
-if M68K
-nodist_libffi_la_SOURCES += src/m68k/ffi.c src/m68k/sysv.S
-endif
-if POWERPC
-nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
-endif
-if POWERPC_AIX
-nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
-endif
-if POWERPC_DARWIN
-nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
-endif
-if POWERPC_FREEBSD
-nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
-endif
-if AARCH64
-nodist_libffi_la_SOURCES += src/aarch64/sysv.S src/aarch64/ffi.c
-endif
-if ARM
-nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c
-if FFI_EXEC_TRAMPOLINE_TABLE
-nodist_libffi_la_SOURCES += src/arm/trampoline.S
-endif
-endif
-if AVR32
-nodist_libffi_la_SOURCES += src/avr32/sysv.S src/avr32/ffi.c
-endif
-if LIBFFI_CRIS
-nodist_libffi_la_SOURCES += src/cris/sysv.S src/cris/ffi.c
-endif
-if FRV
-nodist_libffi_la_SOURCES += src/frv/eabi.S src/frv/ffi.c
-endif
-if S390
-nodist_libffi_la_SOURCES += src/s390/sysv.S src/s390/ffi.c
-endif
-if X86_64
-nodist_libffi_la_SOURCES += src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
-endif
-if SH
-nodist_libffi_la_SOURCES += src/sh/sysv.S src/sh/ffi.c
-endif
-if SH64
-nodist_libffi_la_SOURCES += src/sh64/sysv.S src/sh64/ffi.c
-endif
-if PA_LINUX
-nodist_libffi_la_SOURCES += src/pa/linux.S src/pa/ffi.c
-endif
-if PA_HPUX
-nodist_libffi_la_SOURCES += src/pa/hpux32.S src/pa/ffi.c
-endif
-if TILE
-nodist_libffi_la_SOURCES += src/tile/tile.S src/tile/ffi.c
-endif
+noinst_HEADERS = \
+	src/aarch64/ffitarget.h src/aarch64/internal.h			\
+	src/alpha/ffitarget.h src/alpha/internal.h			\
+	src/arc/ffitarget.h						\
+	src/arm/ffitarget.h src/arm/internal.h				\
+	src/avr32/ffitarget.h						\
+	src/bfin/ffitarget.h						\
+	src/cris/ffitarget.h						\
+	src/frv/ffitarget.h						\
+	src/ia64/ffitarget.h src/ia64/ia64_flags.h			\
+	src/m32r/ffitarget.h						\
+	src/m68k/ffitarget.h						\
+	src/m88k/ffitarget.h						\
+	src/metag/ffitarget.h						\
+	src/microblaze/ffitarget.h					\
+	src/mips/ffitarget.h						\
+	src/moxie/ffitarget.h						\
+	src/nios2/ffitarget.h						\
+	src/or1k/ffitarget.h						\
+	src/pa/ffitarget.h						\
+	src/powerpc/ffitarget.h src/powerpc/asm.h src/powerpc/ffi_powerpc.h \
+	src/s390/ffitarget.h						\
+	src/sh/ffitarget.h						\
+	src/sh64/ffitarget.h						\
+	src/sparc/ffitarget.h src/sparc/internal.h			\
+	src/tile/ffitarget.h						\
+	src/vax/ffitarget.h						\
+	src/x86/ffitarget.h src/x86/internal.h src/x86/internal64.h	\
+	src/xtensa/ffitarget.h						\
+	src/dlmalloc.c
+
+EXTRA_libffi_la_SOURCES = \
+	src/aarch64/ffi.c src/aarch64/sysv.S				\
+	src/alpha/ffi.c src/alpha/osf.S					\
+	src/arc/ffi.c src/arc/arcompact.S				\
+	src/arm/ffi.c src/arm/sysv.S					\
+	src/avr32/ffi.c src/avr32/sysv.S				\
+	src/bfin/ffi.c src/bfin/sysv.S					\
+	src/cris/ffi.c src/cris/sysv.S					\
+	src/frv/ffi.c src/frv/eabi.S					\
+	src/ia64/ffi.c src/ia64/unix.S					\
+	src/m32r/ffi.c src/m32r/sysv.S					\
+	src/m68k/ffi.c src/m68k/sysv.S					\
+	src/m88k/ffi.c src/m88k/obsd.S					\
+	src/metag/ffi.c src/metag/sysv.S				\
+	src/microblaze/ffi.c src/microblaze/sysv.S			\
+	src/mips/ffi.c src/mips/o32.S src/mips/n32.S			\
+	src/moxie/ffi.c src/moxie/eabi.S				\
+	src/nios2/ffi.c src/nios2/sysv.S				\
+	src/or1k/ffi.c src/or1k/sysv.S					\
+	src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S			\
+	src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c \
+	 src/powerpc/sysv.S src/powerpc/linux64.S			\
+	 src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S	\
+	 src/powerpc/aix.S src/powerpc/darwin.S src/powerpc/aix_closure.S \
+	 src/powerpc/darwin_closure.S src/powerpc/ffi_darwin.c		\
+	src/s390/ffi.c src/s390/sysv.S					\
+	src/sh/ffi.c src/sh/sysv.S					\
+	src/sh64/ffi.c src/sh64/sysv.S					\
+	src/sparc/ffi.c src/sparc/ffi64.c src/sparc/v8.S src/sparc/v9.S	\
+	src/tile/ffi.c src/tile/tile.S					\
+	src/vax/ffi.c src/vax/elfbsd.S					\
+	src/x86/ffi.c src/x86/sysv.S					\
+	 src/x86/ffiw64.c src/x86/win64.S 				\
+	 src/x86/ffi64.c src/x86/unix64.S				\
+	 src/x86/darwin64.S src/x86/darwin.S				\
+	 src/x86/darwin64_c.c src/x86/darwin_c.c			\
+	src/xtensa/ffi.c src/xtensa/sysv.S
+
+TARGET_OBJ = @TARGET_OBJ@
+libffi_la_LIBADD = $(TARGET_OBJ)
+libffi_la_DEPENDENCIES = $(TARGET_OBJ)
 
 libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
+EXTRA_libffi_convenience_la_SOURCES = $(EXTRA_libffi_la_SOURCES)
+libffi_convenience_la_LIBADD = $(libffi_la_LIBADD)
+libffi_convenience_la_DEPENDENCIES = $(libffi_la_DEPENDENCIES)
 nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
 
-AM_CFLAGS = -Wall -g -fexceptions
-
 LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
 
-libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
+AM_CFLAGS = -Wall -g -fexceptions
+if FFI_DEBUG
+# Build debug. Define FFI_DEBUG on the commandline so that, when building with
+# MSVC, it can link against the debug CRT.
+AM_CFLAGS += -DFFI_DEBUG
+endif
+
+libffi_la_LDFLAGS = -no-undefined -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
 
 AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
 AM_CCASFLAGS = $(AM_CPPFLAGS)
diff --git a/third_party/gofrontend/libffi/Makefile.in b/third_party/gofrontend/libffi/Makefile.in
index 2a04e0b..80ad274 100644
--- a/third_party/gofrontend/libffi/Makefile.in
+++ b/third_party/gofrontend/libffi/Makefile.in
@@ -15,6 +15,8 @@
 
 @SET_MAKE@
 
+
+
 VPATH = @srcdir@
 pkgdatadir = $(datadir)/@PACKAGE@
 pkgincludedir = $(includedir)/@PACKAGE@
@@ -36,41 +38,16 @@
 host_triplet = @host@
 target_triplet = @target@
 @FFI_DEBUG_TRUE@am__append_1 = src/debug.c
-@MIPS_TRUE@am__append_2 = src/mips/ffi.c src/mips/o32.S src/mips/n32.S
-@BFIN_TRUE@am__append_3 = src/bfin/ffi.c src/bfin/sysv.S
-@X86_TRUE@am__append_4 = src/x86/ffi.c src/x86/sysv.S
-@X86_FREEBSD_TRUE@am__append_5 = src/x86/ffi.c src/x86/freebsd.S
-@X86_WIN32_TRUE@am__append_6 = src/x86/ffi.c src/x86/win32.S
-@X86_WIN64_TRUE@am__append_7 = src/x86/ffi.c src/x86/win64.S
-@X86_DARWIN_TRUE@am__append_8 = src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
-@SPARC_TRUE@am__append_9 = src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
-@ALPHA_TRUE@am__append_10 = src/alpha/ffi.c src/alpha/osf.S
-@IA64_TRUE@am__append_11 = src/ia64/ffi.c src/ia64/unix.S
-@M32R_TRUE@am__append_12 = src/m32r/sysv.S src/m32r/ffi.c
-@M68K_TRUE@am__append_13 = src/m68k/ffi.c src/m68k/sysv.S
-@POWERPC_TRUE@am__append_14 = src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
-@POWERPC_AIX_TRUE@am__append_15 = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
-@POWERPC_DARWIN_TRUE@am__append_16 = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
-@POWERPC_FREEBSD_TRUE@am__append_17 = src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
-@AARCH64_TRUE@am__append_18 = src/aarch64/sysv.S src/aarch64/ffi.c
-@ARM_TRUE@am__append_19 = src/arm/sysv.S src/arm/ffi.c
-@ARM_TRUE@@FFI_EXEC_TRAMPOLINE_TABLE_TRUE@am__append_20 = src/arm/trampoline.S
-@AVR32_TRUE@am__append_21 = src/avr32/sysv.S src/avr32/ffi.c
-@LIBFFI_CRIS_TRUE@am__append_22 = src/cris/sysv.S src/cris/ffi.c
-@FRV_TRUE@am__append_23 = src/frv/eabi.S src/frv/ffi.c
-@S390_TRUE@am__append_24 = src/s390/sysv.S src/s390/ffi.c
-@X86_64_TRUE@am__append_25 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
-@SH_TRUE@am__append_26 = src/sh/sysv.S src/sh/ffi.c
-@SH64_TRUE@am__append_27 = src/sh64/sysv.S src/sh64/ffi.c
-@PA_LINUX_TRUE@am__append_28 = src/pa/linux.S src/pa/ffi.c
-@PA_HPUX_TRUE@am__append_29 = src/pa/hpux32.S src/pa/ffi.c
-@TILE_TRUE@am__append_30 = src/tile/tile.S src/tile/ffi.c
+# Build debug. Define FFI_DEBUG on the commandline so that, when building with
+# MSVC, it can link against the debug CRT.
+@FFI_DEBUG_TRUE@am__append_2 = -DFFI_DEBUG
 subdir = .
 DIST_COMMON = README ChangeLog $(srcdir)/Makefile.in \
 	$(srcdir)/Makefile.am $(top_srcdir)/configure \
 	$(am__configure_deps) $(srcdir)/fficonfig.h.in \
-	$(srcdir)/../mkinstalldirs $(srcdir)/../depcomp mdate-sh \
-	$(srcdir)/doc/version.texi $(srcdir)/doc/stamp-vti
+	$(srcdir)/../mkinstalldirs $(srcdir)/libffi.pc.in \
+	$(srcdir)/../depcomp mdate-sh $(srcdir)/doc/version.texi \
+	$(srcdir)/doc/stamp-vti $(noinst_HEADERS)
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
 	$(top_srcdir)/../config/asmcfi.m4 \
@@ -88,7 +65,7 @@
  configure.lineno config.status.lineno
 mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
 CONFIG_HEADER = fficonfig.h
-CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_FILES = libffi.pc
 CONFIG_CLEAN_VPATH_FILES =
 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
 am__vpath_adj = case $$p in \
@@ -111,89 +88,23 @@
 am__base_list = \
   sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__installdirs = "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(infodir)"
+am__installdirs = "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(infodir)" \
+	"$(DESTDIR)$(pkgconfigdir)"
 LTLIBRARIES = $(noinst_LTLIBRARIES) $(toolexeclib_LTLIBRARIES)
-libffi_la_LIBADD =
+am__DEPENDENCIES_1 =
 am__dirstamp = $(am__leading_dot)dirstamp
-am_libffi_la_OBJECTS = src/prep_cif.lo src/types.lo src/raw_api.lo \
-	src/java_raw_api.lo src/closures.lo
 @FFI_DEBUG_TRUE@am__objects_1 = src/debug.lo
-@MIPS_TRUE@am__objects_2 = src/mips/ffi.lo src/mips/o32.lo \
-@MIPS_TRUE@	src/mips/n32.lo
-@BFIN_TRUE@am__objects_3 = src/bfin/ffi.lo src/bfin/sysv.lo
-@X86_TRUE@am__objects_4 = src/x86/ffi.lo src/x86/sysv.lo
-@X86_FREEBSD_TRUE@am__objects_5 = src/x86/ffi.lo src/x86/freebsd.lo
-@X86_WIN32_TRUE@am__objects_6 = src/x86/ffi.lo src/x86/win32.lo
-@X86_WIN64_TRUE@am__objects_7 = src/x86/ffi.lo src/x86/win64.lo
-@X86_DARWIN_TRUE@am__objects_8 = src/x86/ffi.lo src/x86/darwin.lo \
-@X86_DARWIN_TRUE@	src/x86/ffi64.lo src/x86/darwin64.lo
-@SPARC_TRUE@am__objects_9 = src/sparc/ffi.lo src/sparc/v8.lo \
-@SPARC_TRUE@	src/sparc/v9.lo
-@ALPHA_TRUE@am__objects_10 = src/alpha/ffi.lo src/alpha/osf.lo
-@IA64_TRUE@am__objects_11 = src/ia64/ffi.lo src/ia64/unix.lo
-@M32R_TRUE@am__objects_12 = src/m32r/sysv.lo src/m32r/ffi.lo
-@M68K_TRUE@am__objects_13 = src/m68k/ffi.lo src/m68k/sysv.lo
-@POWERPC_TRUE@am__objects_14 = src/powerpc/ffi.lo \
-@POWERPC_TRUE@	src/powerpc/ffi_sysv.lo \
-@POWERPC_TRUE@	src/powerpc/ffi_linux64.lo src/powerpc/sysv.lo \
-@POWERPC_TRUE@	src/powerpc/ppc_closure.lo \
-@POWERPC_TRUE@	src/powerpc/linux64.lo \
-@POWERPC_TRUE@	src/powerpc/linux64_closure.lo
-@POWERPC_AIX_TRUE@am__objects_15 = src/powerpc/ffi_darwin.lo \
-@POWERPC_AIX_TRUE@	src/powerpc/aix.lo \
-@POWERPC_AIX_TRUE@	src/powerpc/aix_closure.lo
-@POWERPC_DARWIN_TRUE@am__objects_16 = src/powerpc/ffi_darwin.lo \
-@POWERPC_DARWIN_TRUE@	src/powerpc/darwin.lo \
-@POWERPC_DARWIN_TRUE@	src/powerpc/darwin_closure.lo
-@POWERPC_FREEBSD_TRUE@am__objects_17 = src/powerpc/ffi.lo \
-@POWERPC_FREEBSD_TRUE@	src/powerpc/ffi_sysv.lo \
-@POWERPC_FREEBSD_TRUE@	src/powerpc/sysv.lo \
-@POWERPC_FREEBSD_TRUE@	src/powerpc/ppc_closure.lo
-@AARCH64_TRUE@am__objects_18 = src/aarch64/sysv.lo src/aarch64/ffi.lo
-@ARM_TRUE@am__objects_19 = src/arm/sysv.lo src/arm/ffi.lo
-@ARM_TRUE@@FFI_EXEC_TRAMPOLINE_TABLE_TRUE@am__objects_20 = src/arm/trampoline.lo
-@AVR32_TRUE@am__objects_21 = src/avr32/sysv.lo src/avr32/ffi.lo
-@LIBFFI_CRIS_TRUE@am__objects_22 = src/cris/sysv.lo src/cris/ffi.lo
-@FRV_TRUE@am__objects_23 = src/frv/eabi.lo src/frv/ffi.lo
-@S390_TRUE@am__objects_24 = src/s390/sysv.lo src/s390/ffi.lo
-@X86_64_TRUE@am__objects_25 = src/x86/ffi64.lo src/x86/unix64.lo \
-@X86_64_TRUE@	src/x86/ffi.lo src/x86/sysv.lo
-@SH_TRUE@am__objects_26 = src/sh/sysv.lo src/sh/ffi.lo
-@SH64_TRUE@am__objects_27 = src/sh64/sysv.lo src/sh64/ffi.lo
-@PA_LINUX_TRUE@am__objects_28 = src/pa/linux.lo src/pa/ffi.lo
-@PA_HPUX_TRUE@am__objects_29 = src/pa/hpux32.lo src/pa/ffi.lo
-@TILE_TRUE@am__objects_30 = src/tile/tile.lo src/tile/ffi.lo
-nodist_libffi_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
-	$(am__objects_3) $(am__objects_4) $(am__objects_5) \
-	$(am__objects_6) $(am__objects_7) $(am__objects_8) \
-	$(am__objects_9) $(am__objects_10) $(am__objects_11) \
-	$(am__objects_12) $(am__objects_13) $(am__objects_14) \
-	$(am__objects_15) $(am__objects_16) $(am__objects_17) \
-	$(am__objects_18) $(am__objects_19) $(am__objects_20) \
-	$(am__objects_21) $(am__objects_22) $(am__objects_23) \
-	$(am__objects_24) $(am__objects_25) $(am__objects_26) \
-	$(am__objects_27) $(am__objects_28) $(am__objects_29) \
-	$(am__objects_30)
-libffi_la_OBJECTS = $(am_libffi_la_OBJECTS) \
-	$(nodist_libffi_la_OBJECTS)
+am_libffi_la_OBJECTS = src/prep_cif.lo src/types.lo src/raw_api.lo \
+	src/java_raw_api.lo src/closures.lo $(am__objects_1)
+libffi_la_OBJECTS = $(am_libffi_la_OBJECTS)
 libffi_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 	$(libffi_la_LDFLAGS) $(LDFLAGS) -o $@
-libffi_convenience_la_LIBADD =
-am__objects_31 = src/prep_cif.lo src/types.lo src/raw_api.lo \
-	src/java_raw_api.lo src/closures.lo
-am_libffi_convenience_la_OBJECTS = $(am__objects_31)
-am__objects_32 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
-	$(am__objects_4) $(am__objects_5) $(am__objects_6) \
-	$(am__objects_7) $(am__objects_8) $(am__objects_9) \
-	$(am__objects_10) $(am__objects_11) $(am__objects_12) \
-	$(am__objects_13) $(am__objects_14) $(am__objects_15) \
-	$(am__objects_16) $(am__objects_17) $(am__objects_18) \
-	$(am__objects_19) $(am__objects_20) $(am__objects_21) \
-	$(am__objects_22) $(am__objects_23) $(am__objects_24) \
-	$(am__objects_25) $(am__objects_26) $(am__objects_27) \
-	$(am__objects_28) $(am__objects_29) $(am__objects_30)
-nodist_libffi_convenience_la_OBJECTS = $(am__objects_32)
+am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
+am__objects_2 = src/prep_cif.lo src/types.lo src/raw_api.lo \
+	src/java_raw_api.lo src/closures.lo $(am__objects_1)
+am_libffi_convenience_la_OBJECTS = $(am__objects_2)
+nodist_libffi_convenience_la_OBJECTS =
 libffi_convenience_la_OBJECTS = $(am_libffi_convenience_la_OBJECTS) \
 	$(nodist_libffi_convenience_la_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@
@@ -214,8 +125,9 @@
 LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
 	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
 	$(LDFLAGS) -o $@
-SOURCES = $(libffi_la_SOURCES) $(nodist_libffi_la_SOURCES) \
+SOURCES = $(libffi_la_SOURCES) $(EXTRA_libffi_la_SOURCES) \
 	$(libffi_convenience_la_SOURCES) \
+	$(EXTRA_libffi_convenience_la_SOURCES) \
 	$(nodist_libffi_convenience_la_SOURCES)
 MULTISRCTOP = 
 MULTIBUILDTOP = 
@@ -242,6 +154,8 @@
 	install-pdf-recursive install-ps-recursive install-recursive \
 	installcheck-recursive installdirs-recursive pdf-recursive \
 	ps-recursive uninstall-recursive
+DATA = $(pkgconfig_DATA)
+HEADERS = $(noinst_HEADERS)
 RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
   distclean-recursive maintainer-clean-recursive
 AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
@@ -267,6 +181,10 @@
 CFLAGS = @CFLAGS@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -319,12 +237,14 @@
 STRIP = @STRIP@
 TARGET = @TARGET@
 TARGETDIR = @TARGETDIR@
+TARGET_OBJ = @TARGET_OBJ@
 VERSION = @VERSION@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
 abs_top_srcdir = @abs_top_srcdir@
 ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
 am__include = @am__include@
 am__leading_dot = @am__leading_dot@
@@ -381,42 +301,14 @@
 AUTOMAKE_OPTIONS = foreign subdir-objects
 ACLOCAL_AMFLAGS = -I .. -I ../config
 SUBDIRS = include testsuite man
-EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host	\
-	 src/aarch64/ffi.c src/aarch64/ffitarget.h			\
-	 src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h		\
-	 src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h		\
-	 src/avr32/ffi.c src/avr32/sysv.S src/avr32/ffitarget.h		\
-	 src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h		\
-	 src/ia64/ffi.c src/ia64/ffitarget.h src/ia64/ia64_flags.h	\
-	 src/ia64/unix.S src/mips/ffi.c src/mips/n32.S src/mips/o32.S	\
-	 src/mips/ffitarget.h src/m32r/ffi.c src/m32r/sysv.S		\
-	 src/m32r/ffitarget.h src/m68k/ffi.c src/m68k/sysv.S		\
-	 src/m68k/ffitarget.h						\
-	src/powerpc/ffi.c src/powerpc/ffi_powerpc.h			\
-	src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c		\
-	src/powerpc/sysv.S src/powerpc/linux64.S			\
-	src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S		\
-	src/powerpc/asm.h src/powerpc/aix.S src/powerpc/darwin.S	\
-	src/powerpc/aix_closure.S src/powerpc/darwin_closure.S		\
-	src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h		\
-	src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h		\
-	src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h src/sh64/ffi.c	\
-	src/sh64/sysv.S src/sh64/ffitarget.h src/sparc/v8.S		\
-	src/sparc/v9.S src/sparc/ffitarget.h src/sparc/ffi.c		\
-	src/x86/darwin64.S src/x86/ffi.c src/x86/sysv.S			\
-	src/x86/win32.S src/x86/darwin.S src/x86/win64.S		\
-	src/x86/freebsd.S src/x86/ffi64.c src/x86/unix64.S		\
-	src/x86/ffitarget.h src/pa/ffitarget.h src/pa/ffi.c		\
-	src/pa/linux.S src/pa/hpux32.S src/frv/ffi.c src/bfin/ffi.c	\
-	src/bfin/ffitarget.h src/bfin/sysv.S src/frv/eabi.S		\
-	src/frv/ffitarget.h src/dlmalloc.c src/tile/ffi.c		\
-	src/tile/ffitarget.h src/tile/tile.S libtool-version		\
-	 ChangeLog.libffi m4/libtool.m4 m4/lt~obsolete.m4		\
+EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj			\
+	ChangeLog.libffi ChangeLog.libffi-3.1				\
+	m4/libtool.m4 m4/lt~obsolete.m4					\
 	 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4			\
-	 m4/ltversion.m4 src/arm/gentramp.sh src/debug.c msvcc.sh	\
-	generate-ios-source-and-headers.py				\
-	 generate-osx-source-and-headers.py				\
-	 libffi.xcodeproj/project.pbxproj src/arm/trampoline.S
+	 m4/ltversion.m4 src/debug.c msvcc.sh				\
+	generate-darwin-source-and-headers.py				\
+	libffi.xcodeproj/project.pbxproj				\
+	libtool-ldflags
 
 
 # Automake Documentation:
@@ -444,65 +336,129 @@
 # values defined in terms of make variables, as is the case for CC and
 # friends when we are called from the top level Makefile.
 AM_MAKEFLAGS = \
-	"AR_FLAGS=$(AR_FLAGS)" \
-	"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
-	"CFLAGS=$(CFLAGS)" \
-	"CXXFLAGS=$(CXXFLAGS)" \
-	"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
-	"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
-	"INSTALL=$(INSTALL)" \
-	"INSTALL_DATA=$(INSTALL_DATA)" \
-	"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
-	"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
-	"JC1FLAGS=$(JC1FLAGS)" \
-	"LDFLAGS=$(LDFLAGS)" \
-	"LIBCFLAGS=$(LIBCFLAGS)" \
-	"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
-	"MAKE=$(MAKE)" \
-	"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
-	"PICFLAG=$(PICFLAG)" \
-	"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
-	"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
-	"SHELL=$(SHELL)" \
-	"exec_prefix=$(exec_prefix)" \
-	"infodir=$(infodir)" \
-	"libdir=$(libdir)" \
-	"mandir=$(mandir)" \
-	"prefix=$(prefix)" \
-	"AR=$(AR)" \
-	"AS=$(AS)" \
-	"CC=$(CC)" \
-	"CXX=$(CXX)" \
-	"LD=$(LD)" \
-	"NM=$(NM)" \
-	"RANLIB=$(RANLIB)" \
-	"DESTDIR=$(DESTDIR)"
+	'AR_FLAGS=$(AR_FLAGS)' \
+	'CC_FOR_BUILD=$(CC_FOR_BUILD)' \
+	'CFLAGS=$(CFLAGS)' \
+	'CXXFLAGS=$(CXXFLAGS)' \
+	'CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)' \
+	'CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)' \
+	'INSTALL=$(INSTALL)' \
+	'INSTALL_DATA=$(INSTALL_DATA)' \
+	'INSTALL_PROGRAM=$(INSTALL_PROGRAM)' \
+	'INSTALL_SCRIPT=$(INSTALL_SCRIPT)' \
+	'JC1FLAGS=$(JC1FLAGS)' \
+	'LDFLAGS=$(LDFLAGS)' \
+	'LIBCFLAGS=$(LIBCFLAGS)' \
+	'LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)' \
+	'MAKE=$(MAKE)' \
+	'MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)' \
+	'PICFLAG=$(PICFLAG)' \
+	'PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)' \
+	'RUNTESTFLAGS=$(RUNTESTFLAGS)' \
+	'SHELL=$(SHELL)' \
+	'exec_prefix=$(exec_prefix)' \
+	'infodir=$(infodir)' \
+	'libdir=$(libdir)' \
+	'mandir=$(mandir)' \
+	'prefix=$(prefix)' \
+	'AR=$(AR)' \
+	'AS=$(AS)' \
+	'CC=$(CC)' \
+	'CXX=$(CXX)' \
+	'LD=$(LD)' \
+	'NM=$(NM)' \
+	'RANLIB=$(RANLIB)' \
+	'DESTDIR=$(DESTDIR)'
 
 
 # Subdir rules rely on $(FLAGS_TO_PASS)
 FLAGS_TO_PASS = $(AM_MAKEFLAGS)
 MAKEOVERRIDES = 
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libffi.pc
 toolexeclib_LTLIBRARIES = libffi.la
 noinst_LTLIBRARIES = libffi_convenience.la
-libffi_la_SOURCES = src/prep_cif.c src/types.c \
-		src/raw_api.c src/java_raw_api.c src/closures.c
+libffi_la_SOURCES = src/prep_cif.c src/types.c src/raw_api.c \
+	src/java_raw_api.c src/closures.c $(am__append_1)
+noinst_HEADERS = \
+	src/aarch64/ffitarget.h src/aarch64/internal.h			\
+	src/alpha/ffitarget.h src/alpha/internal.h			\
+	src/arc/ffitarget.h						\
+	src/arm/ffitarget.h src/arm/internal.h				\
+	src/avr32/ffitarget.h						\
+	src/bfin/ffitarget.h						\
+	src/cris/ffitarget.h						\
+	src/frv/ffitarget.h						\
+	src/ia64/ffitarget.h src/ia64/ia64_flags.h			\
+	src/m32r/ffitarget.h						\
+	src/m68k/ffitarget.h						\
+	src/m88k/ffitarget.h						\
+	src/metag/ffitarget.h						\
+	src/microblaze/ffitarget.h					\
+	src/mips/ffitarget.h						\
+	src/moxie/ffitarget.h						\
+	src/nios2/ffitarget.h						\
+	src/or1k/ffitarget.h						\
+	src/pa/ffitarget.h						\
+	src/powerpc/ffitarget.h src/powerpc/asm.h src/powerpc/ffi_powerpc.h \
+	src/s390/ffitarget.h						\
+	src/sh/ffitarget.h						\
+	src/sh64/ffitarget.h						\
+	src/sparc/ffitarget.h src/sparc/internal.h			\
+	src/tile/ffitarget.h						\
+	src/vax/ffitarget.h						\
+	src/x86/ffitarget.h src/x86/internal.h src/x86/internal64.h	\
+	src/xtensa/ffitarget.h						\
+	src/dlmalloc.c
 
-nodist_libffi_la_SOURCES = $(am__append_1) $(am__append_2) \
-	$(am__append_3) $(am__append_4) $(am__append_5) \
-	$(am__append_6) $(am__append_7) $(am__append_8) \
-	$(am__append_9) $(am__append_10) $(am__append_11) \
-	$(am__append_12) $(am__append_13) $(am__append_14) \
-	$(am__append_15) $(am__append_16) $(am__append_17) \
-	$(am__append_18) $(am__append_19) $(am__append_20) \
-	$(am__append_21) $(am__append_22) $(am__append_23) \
-	$(am__append_24) $(am__append_25) $(am__append_26) \
-	$(am__append_27) $(am__append_28) $(am__append_29) \
-	$(am__append_30)
+EXTRA_libffi_la_SOURCES = \
+	src/aarch64/ffi.c src/aarch64/sysv.S				\
+	src/alpha/ffi.c src/alpha/osf.S					\
+	src/arc/ffi.c src/arc/arcompact.S				\
+	src/arm/ffi.c src/arm/sysv.S					\
+	src/avr32/ffi.c src/avr32/sysv.S				\
+	src/bfin/ffi.c src/bfin/sysv.S					\
+	src/cris/ffi.c src/cris/sysv.S					\
+	src/frv/ffi.c src/frv/eabi.S					\
+	src/ia64/ffi.c src/ia64/unix.S					\
+	src/m32r/ffi.c src/m32r/sysv.S					\
+	src/m68k/ffi.c src/m68k/sysv.S					\
+	src/m88k/ffi.c src/m88k/obsd.S					\
+	src/metag/ffi.c src/metag/sysv.S				\
+	src/microblaze/ffi.c src/microblaze/sysv.S			\
+	src/mips/ffi.c src/mips/o32.S src/mips/n32.S			\
+	src/moxie/ffi.c src/moxie/eabi.S				\
+	src/nios2/ffi.c src/nios2/sysv.S				\
+	src/or1k/ffi.c src/or1k/sysv.S					\
+	src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S			\
+	src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c \
+	 src/powerpc/sysv.S src/powerpc/linux64.S			\
+	 src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S	\
+	 src/powerpc/aix.S src/powerpc/darwin.S src/powerpc/aix_closure.S \
+	 src/powerpc/darwin_closure.S src/powerpc/ffi_darwin.c		\
+	src/s390/ffi.c src/s390/sysv.S					\
+	src/sh/ffi.c src/sh/sysv.S					\
+	src/sh64/ffi.c src/sh64/sysv.S					\
+	src/sparc/ffi.c src/sparc/ffi64.c src/sparc/v8.S src/sparc/v9.S	\
+	src/tile/ffi.c src/tile/tile.S					\
+	src/vax/ffi.c src/vax/elfbsd.S					\
+	src/x86/ffi.c src/x86/sysv.S					\
+	 src/x86/ffiw64.c src/x86/win64.S 				\
+	 src/x86/ffi64.c src/x86/unix64.S				\
+	 src/x86/darwin64.S src/x86/darwin.S				\
+	 src/x86/darwin64_c.c src/x86/darwin_c.c			\
+	src/xtensa/ffi.c src/xtensa/sysv.S
+
+libffi_la_LIBADD = $(TARGET_OBJ)
+libffi_la_DEPENDENCIES = $(TARGET_OBJ)
 libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
+EXTRA_libffi_convenience_la_SOURCES = $(EXTRA_libffi_la_SOURCES)
+libffi_convenience_la_LIBADD = $(libffi_la_LIBADD)
+libffi_convenience_la_DEPENDENCIES = $(libffi_la_DEPENDENCIES)
 nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
-AM_CFLAGS = -Wall -g -fexceptions
 LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
-libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
+AM_CFLAGS = -Wall -g -fexceptions $(am__append_2)
+libffi_la_LDFLAGS = -no-undefined -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
 AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
 AM_CCASFLAGS = $(AM_CPPFLAGS)
 all: fficonfig.h
@@ -561,6 +517,8 @@
 
 distclean-hdr:
 	-rm -f fficonfig.h stamp-h1
+libffi.pc: $(top_builddir)/config.status $(srcdir)/libffi.pc.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
 
 clean-noinstLTLIBRARIES:
 	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@@ -613,62 +571,16 @@
 src/java_raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
 src/closures.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
 src/debug.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
-src/mips/$(am__dirstamp):
-	@$(MKDIR_P) src/mips
-	@: > src/mips/$(am__dirstamp)
-src/mips/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) src/mips/$(DEPDIR)
-	@: > src/mips/$(DEPDIR)/$(am__dirstamp)
-src/mips/ffi.lo: src/mips/$(am__dirstamp) \
-	src/mips/$(DEPDIR)/$(am__dirstamp)
-src/mips/o32.lo: src/mips/$(am__dirstamp) \
-	src/mips/$(DEPDIR)/$(am__dirstamp)
-src/mips/n32.lo: src/mips/$(am__dirstamp) \
-	src/mips/$(DEPDIR)/$(am__dirstamp)
-src/bfin/$(am__dirstamp):
-	@$(MKDIR_P) src/bfin
-	@: > src/bfin/$(am__dirstamp)
-src/bfin/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) src/bfin/$(DEPDIR)
-	@: > src/bfin/$(DEPDIR)/$(am__dirstamp)
-src/bfin/ffi.lo: src/bfin/$(am__dirstamp) \
-	src/bfin/$(DEPDIR)/$(am__dirstamp)
-src/bfin/sysv.lo: src/bfin/$(am__dirstamp) \
-	src/bfin/$(DEPDIR)/$(am__dirstamp)
-src/x86/$(am__dirstamp):
-	@$(MKDIR_P) src/x86
-	@: > src/x86/$(am__dirstamp)
-src/x86/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) src/x86/$(DEPDIR)
-	@: > src/x86/$(DEPDIR)/$(am__dirstamp)
-src/x86/ffi.lo: src/x86/$(am__dirstamp) \
-	src/x86/$(DEPDIR)/$(am__dirstamp)
-src/x86/sysv.lo: src/x86/$(am__dirstamp) \
-	src/x86/$(DEPDIR)/$(am__dirstamp)
-src/x86/freebsd.lo: src/x86/$(am__dirstamp) \
-	src/x86/$(DEPDIR)/$(am__dirstamp)
-src/x86/win32.lo: src/x86/$(am__dirstamp) \
-	src/x86/$(DEPDIR)/$(am__dirstamp)
-src/x86/win64.lo: src/x86/$(am__dirstamp) \
-	src/x86/$(DEPDIR)/$(am__dirstamp)
-src/x86/darwin.lo: src/x86/$(am__dirstamp) \
-	src/x86/$(DEPDIR)/$(am__dirstamp)
-src/x86/ffi64.lo: src/x86/$(am__dirstamp) \
-	src/x86/$(DEPDIR)/$(am__dirstamp)
-src/x86/darwin64.lo: src/x86/$(am__dirstamp) \
-	src/x86/$(DEPDIR)/$(am__dirstamp)
-src/sparc/$(am__dirstamp):
-	@$(MKDIR_P) src/sparc
-	@: > src/sparc/$(am__dirstamp)
-src/sparc/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) src/sparc/$(DEPDIR)
-	@: > src/sparc/$(DEPDIR)/$(am__dirstamp)
-src/sparc/ffi.lo: src/sparc/$(am__dirstamp) \
-	src/sparc/$(DEPDIR)/$(am__dirstamp)
-src/sparc/v8.lo: src/sparc/$(am__dirstamp) \
-	src/sparc/$(DEPDIR)/$(am__dirstamp)
-src/sparc/v9.lo: src/sparc/$(am__dirstamp) \
-	src/sparc/$(DEPDIR)/$(am__dirstamp)
+src/aarch64/$(am__dirstamp):
+	@$(MKDIR_P) src/aarch64
+	@: > src/aarch64/$(am__dirstamp)
+src/aarch64/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/aarch64/$(DEPDIR)
+	@: > src/aarch64/$(DEPDIR)/$(am__dirstamp)
+src/aarch64/ffi.lo: src/aarch64/$(am__dirstamp) \
+	src/aarch64/$(DEPDIR)/$(am__dirstamp)
+src/aarch64/sysv.lo: src/aarch64/$(am__dirstamp) \
+	src/aarch64/$(DEPDIR)/$(am__dirstamp)
 src/alpha/$(am__dirstamp):
 	@$(MKDIR_P) src/alpha
 	@: > src/alpha/$(am__dirstamp)
@@ -679,6 +591,66 @@
 	src/alpha/$(DEPDIR)/$(am__dirstamp)
 src/alpha/osf.lo: src/alpha/$(am__dirstamp) \
 	src/alpha/$(DEPDIR)/$(am__dirstamp)
+src/arc/$(am__dirstamp):
+	@$(MKDIR_P) src/arc
+	@: > src/arc/$(am__dirstamp)
+src/arc/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/arc/$(DEPDIR)
+	@: > src/arc/$(DEPDIR)/$(am__dirstamp)
+src/arc/ffi.lo: src/arc/$(am__dirstamp) \
+	src/arc/$(DEPDIR)/$(am__dirstamp)
+src/arc/arcompact.lo: src/arc/$(am__dirstamp) \
+	src/arc/$(DEPDIR)/$(am__dirstamp)
+src/arm/$(am__dirstamp):
+	@$(MKDIR_P) src/arm
+	@: > src/arm/$(am__dirstamp)
+src/arm/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/arm/$(DEPDIR)
+	@: > src/arm/$(DEPDIR)/$(am__dirstamp)
+src/arm/ffi.lo: src/arm/$(am__dirstamp) \
+	src/arm/$(DEPDIR)/$(am__dirstamp)
+src/arm/sysv.lo: src/arm/$(am__dirstamp) \
+	src/arm/$(DEPDIR)/$(am__dirstamp)
+src/avr32/$(am__dirstamp):
+	@$(MKDIR_P) src/avr32
+	@: > src/avr32/$(am__dirstamp)
+src/avr32/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/avr32/$(DEPDIR)
+	@: > src/avr32/$(DEPDIR)/$(am__dirstamp)
+src/avr32/ffi.lo: src/avr32/$(am__dirstamp) \
+	src/avr32/$(DEPDIR)/$(am__dirstamp)
+src/avr32/sysv.lo: src/avr32/$(am__dirstamp) \
+	src/avr32/$(DEPDIR)/$(am__dirstamp)
+src/bfin/$(am__dirstamp):
+	@$(MKDIR_P) src/bfin
+	@: > src/bfin/$(am__dirstamp)
+src/bfin/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/bfin/$(DEPDIR)
+	@: > src/bfin/$(DEPDIR)/$(am__dirstamp)
+src/bfin/ffi.lo: src/bfin/$(am__dirstamp) \
+	src/bfin/$(DEPDIR)/$(am__dirstamp)
+src/bfin/sysv.lo: src/bfin/$(am__dirstamp) \
+	src/bfin/$(DEPDIR)/$(am__dirstamp)
+src/cris/$(am__dirstamp):
+	@$(MKDIR_P) src/cris
+	@: > src/cris/$(am__dirstamp)
+src/cris/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/cris/$(DEPDIR)
+	@: > src/cris/$(DEPDIR)/$(am__dirstamp)
+src/cris/ffi.lo: src/cris/$(am__dirstamp) \
+	src/cris/$(DEPDIR)/$(am__dirstamp)
+src/cris/sysv.lo: src/cris/$(am__dirstamp) \
+	src/cris/$(DEPDIR)/$(am__dirstamp)
+src/frv/$(am__dirstamp):
+	@$(MKDIR_P) src/frv
+	@: > src/frv/$(am__dirstamp)
+src/frv/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/frv/$(DEPDIR)
+	@: > src/frv/$(DEPDIR)/$(am__dirstamp)
+src/frv/ffi.lo: src/frv/$(am__dirstamp) \
+	src/frv/$(DEPDIR)/$(am__dirstamp)
+src/frv/eabi.lo: src/frv/$(am__dirstamp) \
+	src/frv/$(DEPDIR)/$(am__dirstamp)
 src/ia64/$(am__dirstamp):
 	@$(MKDIR_P) src/ia64
 	@: > src/ia64/$(am__dirstamp)
@@ -695,10 +667,10 @@
 src/m32r/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) src/m32r/$(DEPDIR)
 	@: > src/m32r/$(DEPDIR)/$(am__dirstamp)
-src/m32r/sysv.lo: src/m32r/$(am__dirstamp) \
-	src/m32r/$(DEPDIR)/$(am__dirstamp)
 src/m32r/ffi.lo: src/m32r/$(am__dirstamp) \
 	src/m32r/$(DEPDIR)/$(am__dirstamp)
+src/m32r/sysv.lo: src/m32r/$(am__dirstamp) \
+	src/m32r/$(DEPDIR)/$(am__dirstamp)
 src/m68k/$(am__dirstamp):
 	@$(MKDIR_P) src/m68k
 	@: > src/m68k/$(am__dirstamp)
@@ -709,6 +681,89 @@
 	src/m68k/$(DEPDIR)/$(am__dirstamp)
 src/m68k/sysv.lo: src/m68k/$(am__dirstamp) \
 	src/m68k/$(DEPDIR)/$(am__dirstamp)
+src/m88k/$(am__dirstamp):
+	@$(MKDIR_P) src/m88k
+	@: > src/m88k/$(am__dirstamp)
+src/m88k/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/m88k/$(DEPDIR)
+	@: > src/m88k/$(DEPDIR)/$(am__dirstamp)
+src/m88k/ffi.lo: src/m88k/$(am__dirstamp) \
+	src/m88k/$(DEPDIR)/$(am__dirstamp)
+src/m88k/obsd.lo: src/m88k/$(am__dirstamp) \
+	src/m88k/$(DEPDIR)/$(am__dirstamp)
+src/metag/$(am__dirstamp):
+	@$(MKDIR_P) src/metag
+	@: > src/metag/$(am__dirstamp)
+src/metag/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/metag/$(DEPDIR)
+	@: > src/metag/$(DEPDIR)/$(am__dirstamp)
+src/metag/ffi.lo: src/metag/$(am__dirstamp) \
+	src/metag/$(DEPDIR)/$(am__dirstamp)
+src/metag/sysv.lo: src/metag/$(am__dirstamp) \
+	src/metag/$(DEPDIR)/$(am__dirstamp)
+src/microblaze/$(am__dirstamp):
+	@$(MKDIR_P) src/microblaze
+	@: > src/microblaze/$(am__dirstamp)
+src/microblaze/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/microblaze/$(DEPDIR)
+	@: > src/microblaze/$(DEPDIR)/$(am__dirstamp)
+src/microblaze/ffi.lo: src/microblaze/$(am__dirstamp) \
+	src/microblaze/$(DEPDIR)/$(am__dirstamp)
+src/microblaze/sysv.lo: src/microblaze/$(am__dirstamp) \
+	src/microblaze/$(DEPDIR)/$(am__dirstamp)
+src/mips/$(am__dirstamp):
+	@$(MKDIR_P) src/mips
+	@: > src/mips/$(am__dirstamp)
+src/mips/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/mips/$(DEPDIR)
+	@: > src/mips/$(DEPDIR)/$(am__dirstamp)
+src/mips/ffi.lo: src/mips/$(am__dirstamp) \
+	src/mips/$(DEPDIR)/$(am__dirstamp)
+src/mips/o32.lo: src/mips/$(am__dirstamp) \
+	src/mips/$(DEPDIR)/$(am__dirstamp)
+src/mips/n32.lo: src/mips/$(am__dirstamp) \
+	src/mips/$(DEPDIR)/$(am__dirstamp)
+src/moxie/$(am__dirstamp):
+	@$(MKDIR_P) src/moxie
+	@: > src/moxie/$(am__dirstamp)
+src/moxie/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/moxie/$(DEPDIR)
+	@: > src/moxie/$(DEPDIR)/$(am__dirstamp)
+src/moxie/ffi.lo: src/moxie/$(am__dirstamp) \
+	src/moxie/$(DEPDIR)/$(am__dirstamp)
+src/moxie/eabi.lo: src/moxie/$(am__dirstamp) \
+	src/moxie/$(DEPDIR)/$(am__dirstamp)
+src/nios2/$(am__dirstamp):
+	@$(MKDIR_P) src/nios2
+	@: > src/nios2/$(am__dirstamp)
+src/nios2/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/nios2/$(DEPDIR)
+	@: > src/nios2/$(DEPDIR)/$(am__dirstamp)
+src/nios2/ffi.lo: src/nios2/$(am__dirstamp) \
+	src/nios2/$(DEPDIR)/$(am__dirstamp)
+src/nios2/sysv.lo: src/nios2/$(am__dirstamp) \
+	src/nios2/$(DEPDIR)/$(am__dirstamp)
+src/or1k/$(am__dirstamp):
+	@$(MKDIR_P) src/or1k
+	@: > src/or1k/$(am__dirstamp)
+src/or1k/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/or1k/$(DEPDIR)
+	@: > src/or1k/$(DEPDIR)/$(am__dirstamp)
+src/or1k/ffi.lo: src/or1k/$(am__dirstamp) \
+	src/or1k/$(DEPDIR)/$(am__dirstamp)
+src/or1k/sysv.lo: src/or1k/$(am__dirstamp) \
+	src/or1k/$(DEPDIR)/$(am__dirstamp)
+src/pa/$(am__dirstamp):
+	@$(MKDIR_P) src/pa
+	@: > src/pa/$(am__dirstamp)
+src/pa/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/pa/$(DEPDIR)
+	@: > src/pa/$(DEPDIR)/$(am__dirstamp)
+src/pa/ffi.lo: src/pa/$(am__dirstamp) src/pa/$(DEPDIR)/$(am__dirstamp)
+src/pa/linux.lo: src/pa/$(am__dirstamp) \
+	src/pa/$(DEPDIR)/$(am__dirstamp)
+src/pa/hpux32.lo: src/pa/$(am__dirstamp) \
+	src/pa/$(DEPDIR)/$(am__dirstamp)
 src/powerpc/$(am__dirstamp):
 	@$(MKDIR_P) src/powerpc
 	@: > src/powerpc/$(am__dirstamp)
@@ -723,126 +778,121 @@
 	src/powerpc/$(DEPDIR)/$(am__dirstamp)
 src/powerpc/sysv.lo: src/powerpc/$(am__dirstamp) \
 	src/powerpc/$(DEPDIR)/$(am__dirstamp)
-src/powerpc/ppc_closure.lo: src/powerpc/$(am__dirstamp) \
-	src/powerpc/$(DEPDIR)/$(am__dirstamp)
 src/powerpc/linux64.lo: src/powerpc/$(am__dirstamp) \
 	src/powerpc/$(DEPDIR)/$(am__dirstamp)
 src/powerpc/linux64_closure.lo: src/powerpc/$(am__dirstamp) \
 	src/powerpc/$(DEPDIR)/$(am__dirstamp)
-src/powerpc/ffi_darwin.lo: src/powerpc/$(am__dirstamp) \
+src/powerpc/ppc_closure.lo: src/powerpc/$(am__dirstamp) \
 	src/powerpc/$(DEPDIR)/$(am__dirstamp)
 src/powerpc/aix.lo: src/powerpc/$(am__dirstamp) \
 	src/powerpc/$(DEPDIR)/$(am__dirstamp)
-src/powerpc/aix_closure.lo: src/powerpc/$(am__dirstamp) \
-	src/powerpc/$(DEPDIR)/$(am__dirstamp)
 src/powerpc/darwin.lo: src/powerpc/$(am__dirstamp) \
 	src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/aix_closure.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
 src/powerpc/darwin_closure.lo: src/powerpc/$(am__dirstamp) \
 	src/powerpc/$(DEPDIR)/$(am__dirstamp)
-src/aarch64/$(am__dirstamp):
-	@$(MKDIR_P) src/aarch64
-	@: > src/aarch64/$(am__dirstamp)
-src/aarch64/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) src/aarch64/$(DEPDIR)
-	@: > src/aarch64/$(DEPDIR)/$(am__dirstamp)
-src/aarch64/sysv.lo: src/aarch64/$(am__dirstamp) \
-	src/aarch64/$(DEPDIR)/$(am__dirstamp)
-src/aarch64/ffi.lo: src/aarch64/$(am__dirstamp) \
-	src/aarch64/$(DEPDIR)/$(am__dirstamp)
-src/arm/$(am__dirstamp):
-	@$(MKDIR_P) src/arm
-	@: > src/arm/$(am__dirstamp)
-src/arm/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) src/arm/$(DEPDIR)
-	@: > src/arm/$(DEPDIR)/$(am__dirstamp)
-src/arm/sysv.lo: src/arm/$(am__dirstamp) \
-	src/arm/$(DEPDIR)/$(am__dirstamp)
-src/arm/ffi.lo: src/arm/$(am__dirstamp) \
-	src/arm/$(DEPDIR)/$(am__dirstamp)
-src/arm/trampoline.lo: src/arm/$(am__dirstamp) \
-	src/arm/$(DEPDIR)/$(am__dirstamp)
-src/avr32/$(am__dirstamp):
-	@$(MKDIR_P) src/avr32
-	@: > src/avr32/$(am__dirstamp)
-src/avr32/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) src/avr32/$(DEPDIR)
-	@: > src/avr32/$(DEPDIR)/$(am__dirstamp)
-src/avr32/sysv.lo: src/avr32/$(am__dirstamp) \
-	src/avr32/$(DEPDIR)/$(am__dirstamp)
-src/avr32/ffi.lo: src/avr32/$(am__dirstamp) \
-	src/avr32/$(DEPDIR)/$(am__dirstamp)
-src/cris/$(am__dirstamp):
-	@$(MKDIR_P) src/cris
-	@: > src/cris/$(am__dirstamp)
-src/cris/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) src/cris/$(DEPDIR)
-	@: > src/cris/$(DEPDIR)/$(am__dirstamp)
-src/cris/sysv.lo: src/cris/$(am__dirstamp) \
-	src/cris/$(DEPDIR)/$(am__dirstamp)
-src/cris/ffi.lo: src/cris/$(am__dirstamp) \
-	src/cris/$(DEPDIR)/$(am__dirstamp)
-src/frv/$(am__dirstamp):
-	@$(MKDIR_P) src/frv
-	@: > src/frv/$(am__dirstamp)
-src/frv/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) src/frv/$(DEPDIR)
-	@: > src/frv/$(DEPDIR)/$(am__dirstamp)
-src/frv/eabi.lo: src/frv/$(am__dirstamp) \
-	src/frv/$(DEPDIR)/$(am__dirstamp)
-src/frv/ffi.lo: src/frv/$(am__dirstamp) \
-	src/frv/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/ffi_darwin.lo: src/powerpc/$(am__dirstamp) \
+	src/powerpc/$(DEPDIR)/$(am__dirstamp)
 src/s390/$(am__dirstamp):
 	@$(MKDIR_P) src/s390
 	@: > src/s390/$(am__dirstamp)
 src/s390/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) src/s390/$(DEPDIR)
 	@: > src/s390/$(DEPDIR)/$(am__dirstamp)
-src/s390/sysv.lo: src/s390/$(am__dirstamp) \
-	src/s390/$(DEPDIR)/$(am__dirstamp)
 src/s390/ffi.lo: src/s390/$(am__dirstamp) \
 	src/s390/$(DEPDIR)/$(am__dirstamp)
-src/x86/unix64.lo: src/x86/$(am__dirstamp) \
-	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/s390/sysv.lo: src/s390/$(am__dirstamp) \
+	src/s390/$(DEPDIR)/$(am__dirstamp)
 src/sh/$(am__dirstamp):
 	@$(MKDIR_P) src/sh
 	@: > src/sh/$(am__dirstamp)
 src/sh/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) src/sh/$(DEPDIR)
 	@: > src/sh/$(DEPDIR)/$(am__dirstamp)
+src/sh/ffi.lo: src/sh/$(am__dirstamp) src/sh/$(DEPDIR)/$(am__dirstamp)
 src/sh/sysv.lo: src/sh/$(am__dirstamp) \
 	src/sh/$(DEPDIR)/$(am__dirstamp)
-src/sh/ffi.lo: src/sh/$(am__dirstamp) src/sh/$(DEPDIR)/$(am__dirstamp)
 src/sh64/$(am__dirstamp):
 	@$(MKDIR_P) src/sh64
 	@: > src/sh64/$(am__dirstamp)
 src/sh64/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) src/sh64/$(DEPDIR)
 	@: > src/sh64/$(DEPDIR)/$(am__dirstamp)
-src/sh64/sysv.lo: src/sh64/$(am__dirstamp) \
-	src/sh64/$(DEPDIR)/$(am__dirstamp)
 src/sh64/ffi.lo: src/sh64/$(am__dirstamp) \
 	src/sh64/$(DEPDIR)/$(am__dirstamp)
-src/pa/$(am__dirstamp):
-	@$(MKDIR_P) src/pa
-	@: > src/pa/$(am__dirstamp)
-src/pa/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) src/pa/$(DEPDIR)
-	@: > src/pa/$(DEPDIR)/$(am__dirstamp)
-src/pa/linux.lo: src/pa/$(am__dirstamp) \
-	src/pa/$(DEPDIR)/$(am__dirstamp)
-src/pa/ffi.lo: src/pa/$(am__dirstamp) src/pa/$(DEPDIR)/$(am__dirstamp)
-src/pa/hpux32.lo: src/pa/$(am__dirstamp) \
-	src/pa/$(DEPDIR)/$(am__dirstamp)
+src/sh64/sysv.lo: src/sh64/$(am__dirstamp) \
+	src/sh64/$(DEPDIR)/$(am__dirstamp)
+src/sparc/$(am__dirstamp):
+	@$(MKDIR_P) src/sparc
+	@: > src/sparc/$(am__dirstamp)
+src/sparc/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/sparc/$(DEPDIR)
+	@: > src/sparc/$(DEPDIR)/$(am__dirstamp)
+src/sparc/ffi.lo: src/sparc/$(am__dirstamp) \
+	src/sparc/$(DEPDIR)/$(am__dirstamp)
+src/sparc/ffi64.lo: src/sparc/$(am__dirstamp) \
+	src/sparc/$(DEPDIR)/$(am__dirstamp)
+src/sparc/v8.lo: src/sparc/$(am__dirstamp) \
+	src/sparc/$(DEPDIR)/$(am__dirstamp)
+src/sparc/v9.lo: src/sparc/$(am__dirstamp) \
+	src/sparc/$(DEPDIR)/$(am__dirstamp)
 src/tile/$(am__dirstamp):
 	@$(MKDIR_P) src/tile
 	@: > src/tile/$(am__dirstamp)
 src/tile/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) src/tile/$(DEPDIR)
 	@: > src/tile/$(DEPDIR)/$(am__dirstamp)
-src/tile/tile.lo: src/tile/$(am__dirstamp) \
-	src/tile/$(DEPDIR)/$(am__dirstamp)
 src/tile/ffi.lo: src/tile/$(am__dirstamp) \
 	src/tile/$(DEPDIR)/$(am__dirstamp)
+src/tile/tile.lo: src/tile/$(am__dirstamp) \
+	src/tile/$(DEPDIR)/$(am__dirstamp)
+src/vax/$(am__dirstamp):
+	@$(MKDIR_P) src/vax
+	@: > src/vax/$(am__dirstamp)
+src/vax/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/vax/$(DEPDIR)
+	@: > src/vax/$(DEPDIR)/$(am__dirstamp)
+src/vax/ffi.lo: src/vax/$(am__dirstamp) \
+	src/vax/$(DEPDIR)/$(am__dirstamp)
+src/vax/elfbsd.lo: src/vax/$(am__dirstamp) \
+	src/vax/$(DEPDIR)/$(am__dirstamp)
+src/x86/$(am__dirstamp):
+	@$(MKDIR_P) src/x86
+	@: > src/x86/$(am__dirstamp)
+src/x86/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/x86/$(DEPDIR)
+	@: > src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/ffi.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/sysv.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/ffiw64.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/win64.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/ffi64.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/unix64.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/darwin64.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/darwin.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/darwin64_c.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/darwin_c.lo: src/x86/$(am__dirstamp) \
+	src/x86/$(DEPDIR)/$(am__dirstamp)
+src/xtensa/$(am__dirstamp):
+	@$(MKDIR_P) src/xtensa
+	@: > src/xtensa/$(am__dirstamp)
+src/xtensa/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/xtensa/$(DEPDIR)
+	@: > src/xtensa/$(DEPDIR)/$(am__dirstamp)
+src/xtensa/ffi.lo: src/xtensa/$(am__dirstamp) \
+	src/xtensa/$(DEPDIR)/$(am__dirstamp)
+src/xtensa/sysv.lo: src/xtensa/$(am__dirstamp) \
+	src/xtensa/$(DEPDIR)/$(am__dirstamp)
 libffi.la: $(libffi_la_OBJECTS) $(libffi_la_DEPENDENCIES) 
 	$(libffi_la_LINK) -rpath $(toolexeclibdir) $(libffi_la_OBJECTS) $(libffi_la_LIBADD) $(LIBS)
 libffi_convenience.la: $(libffi_convenience_la_OBJECTS) $(libffi_convenience_la_DEPENDENCIES) 
@@ -858,12 +908,14 @@
 	-rm -f src/alpha/ffi.lo
 	-rm -f src/alpha/osf.$(OBJEXT)
 	-rm -f src/alpha/osf.lo
+	-rm -f src/arc/arcompact.$(OBJEXT)
+	-rm -f src/arc/arcompact.lo
+	-rm -f src/arc/ffi.$(OBJEXT)
+	-rm -f src/arc/ffi.lo
 	-rm -f src/arm/ffi.$(OBJEXT)
 	-rm -f src/arm/ffi.lo
 	-rm -f src/arm/sysv.$(OBJEXT)
 	-rm -f src/arm/sysv.lo
-	-rm -f src/arm/trampoline.$(OBJEXT)
-	-rm -f src/arm/trampoline.lo
 	-rm -f src/avr32/ffi.$(OBJEXT)
 	-rm -f src/avr32/ffi.lo
 	-rm -f src/avr32/sysv.$(OBJEXT)
@@ -898,12 +950,36 @@
 	-rm -f src/m68k/ffi.lo
 	-rm -f src/m68k/sysv.$(OBJEXT)
 	-rm -f src/m68k/sysv.lo
+	-rm -f src/m88k/ffi.$(OBJEXT)
+	-rm -f src/m88k/ffi.lo
+	-rm -f src/m88k/obsd.$(OBJEXT)
+	-rm -f src/m88k/obsd.lo
+	-rm -f src/metag/ffi.$(OBJEXT)
+	-rm -f src/metag/ffi.lo
+	-rm -f src/metag/sysv.$(OBJEXT)
+	-rm -f src/metag/sysv.lo
+	-rm -f src/microblaze/ffi.$(OBJEXT)
+	-rm -f src/microblaze/ffi.lo
+	-rm -f src/microblaze/sysv.$(OBJEXT)
+	-rm -f src/microblaze/sysv.lo
 	-rm -f src/mips/ffi.$(OBJEXT)
 	-rm -f src/mips/ffi.lo
 	-rm -f src/mips/n32.$(OBJEXT)
 	-rm -f src/mips/n32.lo
 	-rm -f src/mips/o32.$(OBJEXT)
 	-rm -f src/mips/o32.lo
+	-rm -f src/moxie/eabi.$(OBJEXT)
+	-rm -f src/moxie/eabi.lo
+	-rm -f src/moxie/ffi.$(OBJEXT)
+	-rm -f src/moxie/ffi.lo
+	-rm -f src/nios2/ffi.$(OBJEXT)
+	-rm -f src/nios2/ffi.lo
+	-rm -f src/nios2/sysv.$(OBJEXT)
+	-rm -f src/nios2/sysv.lo
+	-rm -f src/or1k/ffi.$(OBJEXT)
+	-rm -f src/or1k/ffi.lo
+	-rm -f src/or1k/sysv.$(OBJEXT)
+	-rm -f src/or1k/sysv.lo
 	-rm -f src/pa/ffi.$(OBJEXT)
 	-rm -f src/pa/ffi.lo
 	-rm -f src/pa/hpux32.$(OBJEXT)
@@ -952,6 +1028,8 @@
 	-rm -f src/sh64/sysv.lo
 	-rm -f src/sparc/ffi.$(OBJEXT)
 	-rm -f src/sparc/ffi.lo
+	-rm -f src/sparc/ffi64.$(OBJEXT)
+	-rm -f src/sparc/ffi64.lo
 	-rm -f src/sparc/v8.$(OBJEXT)
 	-rm -f src/sparc/v8.lo
 	-rm -f src/sparc/v9.$(OBJEXT)
@@ -962,24 +1040,34 @@
 	-rm -f src/tile/tile.lo
 	-rm -f src/types.$(OBJEXT)
 	-rm -f src/types.lo
+	-rm -f src/vax/elfbsd.$(OBJEXT)
+	-rm -f src/vax/elfbsd.lo
+	-rm -f src/vax/ffi.$(OBJEXT)
+	-rm -f src/vax/ffi.lo
 	-rm -f src/x86/darwin.$(OBJEXT)
 	-rm -f src/x86/darwin.lo
 	-rm -f src/x86/darwin64.$(OBJEXT)
 	-rm -f src/x86/darwin64.lo
+	-rm -f src/x86/darwin64_c.$(OBJEXT)
+	-rm -f src/x86/darwin64_c.lo
+	-rm -f src/x86/darwin_c.$(OBJEXT)
+	-rm -f src/x86/darwin_c.lo
 	-rm -f src/x86/ffi.$(OBJEXT)
 	-rm -f src/x86/ffi.lo
 	-rm -f src/x86/ffi64.$(OBJEXT)
 	-rm -f src/x86/ffi64.lo
-	-rm -f src/x86/freebsd.$(OBJEXT)
-	-rm -f src/x86/freebsd.lo
+	-rm -f src/x86/ffiw64.$(OBJEXT)
+	-rm -f src/x86/ffiw64.lo
 	-rm -f src/x86/sysv.$(OBJEXT)
 	-rm -f src/x86/sysv.lo
 	-rm -f src/x86/unix64.$(OBJEXT)
 	-rm -f src/x86/unix64.lo
-	-rm -f src/x86/win32.$(OBJEXT)
-	-rm -f src/x86/win32.lo
 	-rm -f src/x86/win64.$(OBJEXT)
 	-rm -f src/x86/win64.lo
+	-rm -f src/xtensa/ffi.$(OBJEXT)
+	-rm -f src/xtensa/ffi.lo
+	-rm -f src/xtensa/sysv.$(OBJEXT)
+	-rm -f src/xtensa/sysv.lo
 
 distclean-compile:
 	-rm -f *.tab.c
@@ -994,9 +1082,10 @@
 @AMDEP_TRUE@@am__include@ @am__quote@src/aarch64/$(DEPDIR)/sysv.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/ffi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/osf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/arc/$(DEPDIR)/arcompact.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/arc/$(DEPDIR)/ffi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/ffi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/sysv.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/trampoline.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/avr32/$(DEPDIR)/ffi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/avr32/$(DEPDIR)/sysv.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/bfin/$(DEPDIR)/ffi.Plo@am__quote@
@@ -1011,9 +1100,21 @@
 @AMDEP_TRUE@@am__include@ @am__quote@src/m32r/$(DEPDIR)/sysv.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/m68k/$(DEPDIR)/ffi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/m68k/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/m88k/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/m88k/$(DEPDIR)/obsd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/metag/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/metag/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/microblaze/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/microblaze/$(DEPDIR)/sysv.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/mips/$(DEPDIR)/ffi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/mips/$(DEPDIR)/n32.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/mips/$(DEPDIR)/o32.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/moxie/$(DEPDIR)/eabi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/moxie/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/nios2/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/nios2/$(DEPDIR)/sysv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/or1k/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/or1k/$(DEPDIR)/sysv.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/pa/$(DEPDIR)/ffi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/pa/$(DEPDIR)/hpux32.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/pa/$(DEPDIR)/linux.Plo@am__quote@
@@ -1036,19 +1137,25 @@
 @AMDEP_TRUE@@am__include@ @am__quote@src/sh64/$(DEPDIR)/ffi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/sh64/$(DEPDIR)/sysv.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/ffi64.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/v8.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/v9.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/tile/$(DEPDIR)/ffi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/tile/$(DEPDIR)/tile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/vax/$(DEPDIR)/elfbsd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/vax/$(DEPDIR)/ffi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin64_c.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/darwin_c.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffi64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/freebsd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffiw64.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/sysv.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/unix64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win32.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/xtensa/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/xtensa/$(DEPDIR)/sysv.Plo@am__quote@
 
 .S.o:
 @am__fastdepCCAS_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@@ -1106,6 +1213,7 @@
 	-rm -rf src/.libs src/_libs
 	-rm -rf src/aarch64/.libs src/aarch64/_libs
 	-rm -rf src/alpha/.libs src/alpha/_libs
+	-rm -rf src/arc/.libs src/arc/_libs
 	-rm -rf src/arm/.libs src/arm/_libs
 	-rm -rf src/avr32/.libs src/avr32/_libs
 	-rm -rf src/bfin/.libs src/bfin/_libs
@@ -1114,7 +1222,13 @@
 	-rm -rf src/ia64/.libs src/ia64/_libs
 	-rm -rf src/m32r/.libs src/m32r/_libs
 	-rm -rf src/m68k/.libs src/m68k/_libs
+	-rm -rf src/m88k/.libs src/m88k/_libs
+	-rm -rf src/metag/.libs src/metag/_libs
+	-rm -rf src/microblaze/.libs src/microblaze/_libs
 	-rm -rf src/mips/.libs src/mips/_libs
+	-rm -rf src/moxie/.libs src/moxie/_libs
+	-rm -rf src/nios2/.libs src/nios2/_libs
+	-rm -rf src/or1k/.libs src/or1k/_libs
 	-rm -rf src/pa/.libs src/pa/_libs
 	-rm -rf src/powerpc/.libs src/powerpc/_libs
 	-rm -rf src/s390/.libs src/s390/_libs
@@ -1122,7 +1236,9 @@
 	-rm -rf src/sh64/.libs src/sh64/_libs
 	-rm -rf src/sparc/.libs src/sparc/_libs
 	-rm -rf src/tile/.libs src/tile/_libs
+	-rm -rf src/vax/.libs src/vax/_libs
 	-rm -rf src/x86/.libs src/x86/_libs
+	-rm -rf src/xtensa/.libs src/xtensa/_libs
 
 distclean-libtool:
 	-rm -f libtool config.lt
@@ -1286,6 +1402,26 @@
 	  echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \
 	  rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \
 	done
+install-pkgconfigDATA: $(pkgconfig_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
+	@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
+	done
+
+uninstall-pkgconfigDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(pkgconfigdir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(pkgconfigdir)" && rm -f $$files
 
 # This directory's subdirectories are mostly independent; you can cd
 # into them and run `make' without going through this Makefile.
@@ -1423,11 +1559,11 @@
 	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
 check-am: all-am
 check: check-recursive
-all-am: Makefile $(INFO_DEPS) $(LTLIBRARIES) all-multi fficonfig.h \
-		all-local
+all-am: Makefile $(INFO_DEPS) $(LTLIBRARIES) all-multi $(DATA) \
+		$(HEADERS) fficonfig.h all-local
 installdirs: installdirs-recursive
 installdirs-am:
-	for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(infodir)"; do \
+	for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(infodir)" "$(DESTDIR)$(pkgconfigdir)"; do \
 	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
 	done
 install: install-recursive
@@ -1459,6 +1595,8 @@
 	-rm -f src/aarch64/$(am__dirstamp)
 	-rm -f src/alpha/$(DEPDIR)/$(am__dirstamp)
 	-rm -f src/alpha/$(am__dirstamp)
+	-rm -f src/arc/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/arc/$(am__dirstamp)
 	-rm -f src/arm/$(DEPDIR)/$(am__dirstamp)
 	-rm -f src/arm/$(am__dirstamp)
 	-rm -f src/avr32/$(DEPDIR)/$(am__dirstamp)
@@ -1475,8 +1613,20 @@
 	-rm -f src/m32r/$(am__dirstamp)
 	-rm -f src/m68k/$(DEPDIR)/$(am__dirstamp)
 	-rm -f src/m68k/$(am__dirstamp)
+	-rm -f src/m88k/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/m88k/$(am__dirstamp)
+	-rm -f src/metag/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/metag/$(am__dirstamp)
+	-rm -f src/microblaze/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/microblaze/$(am__dirstamp)
 	-rm -f src/mips/$(DEPDIR)/$(am__dirstamp)
 	-rm -f src/mips/$(am__dirstamp)
+	-rm -f src/moxie/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/moxie/$(am__dirstamp)
+	-rm -f src/nios2/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/nios2/$(am__dirstamp)
+	-rm -f src/or1k/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/or1k/$(am__dirstamp)
 	-rm -f src/pa/$(DEPDIR)/$(am__dirstamp)
 	-rm -f src/pa/$(am__dirstamp)
 	-rm -f src/powerpc/$(DEPDIR)/$(am__dirstamp)
@@ -1491,8 +1641,12 @@
 	-rm -f src/sparc/$(am__dirstamp)
 	-rm -f src/tile/$(DEPDIR)/$(am__dirstamp)
 	-rm -f src/tile/$(am__dirstamp)
+	-rm -f src/vax/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/vax/$(am__dirstamp)
 	-rm -f src/x86/$(DEPDIR)/$(am__dirstamp)
 	-rm -f src/x86/$(am__dirstamp)
+	-rm -f src/xtensa/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/xtensa/$(am__dirstamp)
 
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
@@ -1506,7 +1660,7 @@
 
 distclean: distclean-multi distclean-recursive
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-	-rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/x86/$(DEPDIR)
+	-rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arc/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/m88k/$(DEPDIR) src/metag/$(DEPDIR) src/microblaze/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/nios2/$(DEPDIR) src/or1k/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/vax/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-hdr distclean-libtool distclean-tags
@@ -1523,7 +1677,7 @@
 
 info-am: $(INFO_DEPS)
 
-install-data-am: install-info-am
+install-data-am: install-info-am install-pkgconfigDATA
 
 install-dvi: install-dvi-recursive
 
@@ -1630,7 +1784,7 @@
 maintainer-clean: maintainer-clean-multi maintainer-clean-recursive
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
 	-rm -rf $(top_srcdir)/autom4te.cache
-	-rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/x86/$(DEPDIR)
+	-rm -rf src/$(DEPDIR) src/aarch64/$(DEPDIR) src/alpha/$(DEPDIR) src/arc/$(DEPDIR) src/arm/$(DEPDIR) src/avr32/$(DEPDIR) src/bfin/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/m88k/$(DEPDIR) src/metag/$(DEPDIR) src/microblaze/$(DEPDIR) src/mips/$(DEPDIR) src/moxie/$(DEPDIR) src/nios2/$(DEPDIR) src/or1k/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/tile/$(DEPDIR) src/vax/$(DEPDIR) src/x86/$(DEPDIR) src/xtensa/$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-aminfo \
 	maintainer-clean-generic maintainer-clean-vti
@@ -1649,7 +1803,7 @@
 ps-am: $(PSS)
 
 uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \
-	uninstall-pdf-am uninstall-ps-am \
+	uninstall-pdf-am uninstall-pkgconfigDATA uninstall-ps-am \
 	uninstall-toolexeclibLTLIBRARIES
 
 .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all all-multi \
@@ -1668,7 +1822,7 @@
 	install-dvi install-dvi-am install-exec install-exec-am \
 	install-html install-html-am install-info install-info-am \
 	install-man install-multi install-pdf install-pdf-am \
-	install-ps install-ps-am install-strip \
+	install-pkgconfigDATA install-ps install-ps-am install-strip \
 	install-toolexeclibLTLIBRARIES installcheck installcheck-am \
 	installdirs installdirs-am maintainer-clean \
 	maintainer-clean-aminfo maintainer-clean-generic \
@@ -1677,7 +1831,7 @@
 	mostlyclean-libtool mostlyclean-multi mostlyclean-vti pdf \
 	pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
 	uninstall-dvi-am uninstall-html-am uninstall-info-am \
-	uninstall-pdf-am uninstall-ps-am \
+	uninstall-pdf-am uninstall-pkgconfigDATA uninstall-ps-am \
 	uninstall-toolexeclibLTLIBRARIES
 
 
diff --git a/third_party/gofrontend/libffi/README b/third_party/gofrontend/libffi/README
index a0fb717..c072101 100644
--- a/third_party/gofrontend/libffi/README
+++ b/third_party/gofrontend/libffi/README
@@ -1,8 +1,8 @@
 Status
 ======
 
-libffi-3.0.12 was released on XXXXXXX.  Check the libffi web page for
-updates: <URL:http://sourceware.org/libffi/>.
+libffi-4?? was released on TBD.  Check the libffi web
+page for updates: <URL:http://sourceware.org/libffi/>.
 
 
 What is libffi?
@@ -43,57 +43,78 @@
 For specific configuration details and testing status, please
 refer to the wiki page here:
 
- http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.11
+ http://www.moxielogic.org/wiki/index.php?title=Libffi_3.2
 
 At the time of release, the following basic configurations have been
 tested:
 
-|-----------------+------------------|
-| Architecture    | Operating System |
-|-----------------+------------------|
-| AArch64         | Linux            |
-| Alpha           | Linux            |
-| Alpha           | Tru64            |
-| ARM             | Linux            |
-| ARM             | iOS              |
-| AVR32           | Linux            |
-| Blackfin        | uClinux          |
-| HPPA            | HPUX             |
-| IA-64           | Linux            |
-| M68K            | FreeMiNT         |
-| M68K            | RTEMS            |
-| MIPS            | IRIX             |
-| MIPS            | Linux            |
-| MIPS            | RTEMS            |
-| MIPS64          | Linux            |
-| PowerPC         | AMIGA            |
-| PowerPC         | Linux            |
-| PowerPC         | Mac OSX          |
-| PowerPC         | FreeBSD          |
-| PowerPC64       | Linux            |
-| S390            | Linux            |
-| S390X           | Linux            |
-| SPARC           | Linux            |
-| SPARC           | Solaris          |
-| SPARC64         | Linux            |
-| SPARC64         | FreeBSD          |
-| TILE-Gx/TILEPro | Linux            |
-| X86             | FreeBSD          |
-| X86             | Interix          |
-| X86             | kFreeBSD         |
-| X86             | Linux            |
-| X86             | Mac OSX          |
-| X86             | OpenBSD          |
-| X86             | OS/2             |
-| X86             | Solaris          |
-| X86             | Windows/Cygwin   |
-| X86             | Windows/MingW    |
-| X86-64          | FreeBSD          |
-| X86-64          | Linux            |
-| X86-64          | Linux/x32        |
-| X86-64          | OpenBSD          |
-| X86-64          | Windows/MingW    |
-|-----------------+------------------|
+|-----------------+------------------+-------------------------|
+| Architecture    | Operating System | Compiler                |
+|-----------------+------------------+-------------------------|
+| AArch64 (ARM64) | iOS              | Clang                   |
+| AArch64         | Linux            | GCC                     |
+| Alpha           | Linux            | GCC                     |
+| Alpha           | Tru64            | GCC                     |
+| ARC             | Linux            | GCC                     |
+| ARM             | Linux            | GCC                     |
+| ARM             | iOS              | GCC                     |
+| AVR32           | Linux            | GCC                     |
+| Blackfin        | uClinux          | GCC                     |
+| HPPA            | HPUX             | GCC                     |
+| IA-64           | Linux            | GCC                     |
+| M68K            | FreeMiNT         | GCC                     |
+| M68K            | Linux            | GCC                     |
+| M68K            | RTEMS            | GCC                     |
+| M88K            | OpenBSD/mvme88k  | GCC                     |
+| Meta            | Linux            | GCC                     |
+| MicroBlaze      | Linux            | GCC                     |
+| MIPS            | IRIX             | GCC                     |
+| MIPS            | Linux            | GCC                     |
+| MIPS            | RTEMS            | GCC                     |
+| MIPS64          | Linux            | GCC                     |
+| Moxie           | Bare metal       | GCC                     |
+| Nios II         | Linux            | GCC                     |
+| OpenRISC        | Linux            | GCC                     |
+| PowerPC 32-bit  | AIX              | IBM XL C                |
+| PowerPC 64-bit  | AIX              | IBM XL C                |
+| PowerPC         | AMIGA            | GCC                     |
+| PowerPC         | Linux            | GCC                     |
+| PowerPC         | Mac OSX          | GCC                     |
+| PowerPC         | FreeBSD          | GCC                     |
+| PowerPC 64-bit  | FreeBSD          | GCC                     |
+| PowerPC 64-bit  | Linux ELFv1      | GCC                     |
+| PowerPC 64-bit  | Linux ELFv2      | GCC                     |
+| S390            | Linux            | GCC                     |
+| S390X           | Linux            | GCC                     |
+| SPARC           | Linux            | GCC                     |
+| SPARC           | Solaris          | GCC                     |
+| SPARC           | Solaris          | Oracle Solaris Studio C |
+| SPARC64         | Linux            | GCC                     |
+| SPARC64         | FreeBSD          | GCC                     |
+| SPARC64         | Solaris          | Oracle Solaris Studio C |
+| TILE-Gx/TILEPro | Linux            | GCC                     |
+| VAX             | OpenBSD/vax      | GCC                     |
+| X86             | FreeBSD          | GCC                     |
+| X86             | GNU HURD         | GCC                     |
+| X86             | Interix          | GCC                     |
+| X86             | kFreeBSD         | GCC                     |
+| X86             | Linux            | GCC                     |
+| X86             | Mac OSX          | GCC                     |
+| X86             | OpenBSD          | GCC                     |
+| X86             | OS/2             | GCC                     |
+| X86             | Solaris          | GCC                     |
+| X86             | Solaris          | Oracle Solaris Studio C |
+| X86             | Windows/Cygwin   | GCC                     |
+| X86             | Windows/MingW    | GCC                     |
+| X86-64          | FreeBSD          | GCC                     |
+| X86-64          | Linux            | GCC                     |
+| X86-64          | Linux/x32        | GCC                     |
+| X86-64          | OpenBSD          | GCC                     |
+| X86-64          | Solaris          | Oracle Solaris Studio C |
+| X86-64          | Windows/Cygwin   | GCC                     |
+| X86-64          | Windows/MingW    | GCC                     |
+| Xtensa          | Linux            | GCC                     |
+|-----------------+------------------+-------------------------|
 
 Please send additional platform test results to
 libffi-discuss@sourceware.org and feel free to update the wiki page
@@ -107,6 +128,9 @@
 "configure" program found in the root directory of the libffi source
 distribution.
 
+If you're building libffi directly from version control, configure won't
+exist yet; run ./autogen.sh first.
+
 You may want to tell configure where to install the libffi library and
 header files. To do that, use the --prefix configure switch.  Libffi
 will install under /usr/local by default. 
@@ -124,20 +148,28 @@
 Microsoft's Visual C++ compiler.  In this case, use the msvcc.sh
 wrapper script during configuration like so:
 
-path/to/configure CC=path/to/msvcc.sh LD=link CPP=\"cl -nologo -EP\"
+path/to/configure CC=path/to/msvcc.sh CXX=path/to/msvcc.sh LD=link CPP="cl -nologo -EP"
 
-For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64".
-You may also need to specify --build appropriately. When building with MSVC
-under a MingW environment, you may need to remove the line in configure
-that sets 'fix_srcfile_path' to a 'cygpath' command. ('cygpath' is not
-present in MingW, and is not required when using MingW-style paths.)
+For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64" and
+CXX="path/to/msvcc.sh -m64".  You may also need to specify --build
+appropriately.
+
+It is also possible to build libffi on Windows platforms with the LLVM
+project's clang-cl compiler, like below:
+
+path/to/configure CC="path/to/msvcc.sh -clang-cl" CXX="path/to/msvcc.sh -clang-cl" LD=link CPP="clang-cl -EP"
+
+When building with MSVC under a MingW environment, you may need to
+remove the line in configure that sets 'fix_srcfile_path' to a 'cygpath'
+command.  ('cygpath' is not present in MingW, and is not required when
+using MingW-style paths.)
 
 For iOS builds, the 'libffi.xcodeproj' Xcode project is available.
 
 Configure has many other options. Use "configure --help" to see them all.
 
 Once configure has finished, type "make". Note that you must be using
-GNU make.  You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
+GNU make.  You can ftp GNU make from ftp.gnu.org:/pub/gnu/make .
 
 To ensure that libffi is working as advertised, type "make check".
 This will require that you have DejaGNU installed.
@@ -148,17 +180,59 @@
 History
 =======
 
-See the ChangeLog files for details.
+See the git log for details at http://github.com/atgreen/libffi.
 
-3.0.12 XXX-XX-XX
+4.0 TBD
+        New API in support of GO closures.
+
+3.2.1 Nov-12-14
+        Build fix for non-iOS AArch64 targets.
+
+3.2 Nov-11-14
+        Add C99 Complex Type support (currently only supported on
+          s390).
+	Add support for PASCAL and REGISTER calling conventions on x86
+	  Windows/Linux.
+	Add OpenRISC and Cygwin-64 support.
+        Bug fixes.
+
+3.1 May-19-14
+        Add AArch64 (ARM64) iOS support.
+        Add Nios II support.
+        Add m88k and DEC VAX support.
+	Add support for stdcall, thiscall, and fastcall on non-Windows
+	  32-bit x86 targets such as Linux.
+	Various Android, MIPS N32, x86, FreeBSD and UltraSPARC IIi
+	  fixes.
+	Make the testsuite more robust: eliminate several spurious
+	  failures, and respect the $CC and $CXX environment variables.
+	Archive off the manually maintained ChangeLog in favor of git
+	  log.
+
+3.0.13 Mar-17-13
+	Add Meta support.
+	Add missing Moxie bits.
+	Fix stack alignment bug on 32-bit x86.
+	Build fix for m68000 targets.
+	Build fix for soft-float Power targets.
+	Fix the install dir location for some platforms when building
+	  with GCC (OS X, Solaris).
+	Fix Cygwin regression.
+
+3.0.12 Feb-11-13
+        Add Moxie support.
+	Add AArch64 support.
 	Add Blackfin support.
 	Add TILE-Gx/TILEPro support.
-	Add AArch64 support.
+	Add MicroBlaze support.
+	Add Xtensa support.
 	Add support for PaX enabled kernels with MPROTECT.
+	Add support for native vendor compilers on
+	  Solaris and AIX.
+	Work around LLVM/GCC interoperability issue on x86_64.
 
 3.0.11 Apr-11-12
         Lots of build fixes.
-	Add Amiga newer MacOS support.
 	Add support for variadic functions (ffi_prep_cif_var).
 	Add Linux/x32 support.
 	Add thiscall, fastcall and MSVC cdecl support on Windows.
@@ -167,7 +241,6 @@
 	Integration with iOS' xcode build tools.
 	Fix Octeon and MC68881 support.
 	Fix code pessimizations.
-	Lots of build fixes.
 
 3.0.10 Aug-23-11
         Add support for Apple's iOS.
@@ -311,7 +384,7 @@
 Authors & Credits
 =================
 
-libffi was originally written by Anthony Green <green@redhat.com>.
+libffi was originally written by Anthony Green <green@moxielogic.com>.
 
 The developers of the GNU Compiler Collection project have made
 innumerable valuable contributions.  See the ChangeLog file for
@@ -335,8 +408,13 @@
 ia64		Hans Boehm
 m32r		Kazuhiro Inaoka
 m68k		Andreas Schwab
+m88k		Miod Vallat
+microblaze	Nathan Rossi
 mips		Anthony Green, Casey Marshall
 mips64		David Daney
+moxie		Anthony Green
+nios ii		Sandra Loosemore
+openrisc        Sebastian Macke
 pa		Randolph Chung, Dave Anglin, Andreas Tobler
 powerpc		Geoffrey Keating, Andreas Tobler, 
 			 David Edelsohn, John Hornkvist
@@ -346,8 +424,10 @@
 sh64		Kaz Kojima
 sparc		Anthony Green, Gordon Irlam
 tile-gx/tilepro Walter Lee
+vax		Miod Vallat
 x86		Anthony Green, Jon Beniston
 x86-64		Bo Thorsen
+xtensa		Chris Zankel
 
 Jesper Skov and Andrew Haley both did more than their fair share of
 stepping through the code and tracking down bugs.
diff --git a/third_party/gofrontend/libffi/build-ios.sh b/third_party/gofrontend/libffi/build-ios.sh
deleted file mode 100755
index 3dea242..0000000
--- a/third_party/gofrontend/libffi/build-ios.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/sh
-
-PLATFORM_IOS=/Developer/Platforms/iPhoneOS.platform/
-PLATFORM_IOS_SIM=/Developer/Platforms/iPhoneSimulator.platform/
-SDK_IOS_VERSION="4.2"
-MIN_IOS_VERSION="3.0"
-OUTPUT_DIR="universal-ios"
-
-build_target () {
-    local platform=$1
-    local sdk=$2
-    local arch=$3
-    local triple=$4
-    local builddir=$5
-
-    mkdir -p "${builddir}"
-    pushd "${builddir}"
-    export CC="${platform}"/Developer/usr/bin/gcc-4.2
-    export CFLAGS="-arch ${arch} -isysroot ${sdk} -miphoneos-version-min=${MIN_IOS_VERSION}"
-    ../configure --host=${triple} && make
-    popd
-}
-
-# Build all targets
-build_target "${PLATFORM_IOS}" "${PLATFORM_IOS}/Developer/SDKs/iPhoneOS${SDK_IOS_VERSION}.sdk/" armv6 arm-apple-darwin10 armv6-ios
-build_target "${PLATFORM_IOS}" "${PLATFORM_IOS}/Developer/SDKs/iPhoneOS${SDK_IOS_VERSION}.sdk/" armv7 arm-apple-darwin10 armv7-ios
-build_target "${PLATFORM_IOS_SIM}" "${PLATFORM_IOS_SIM}/Developer/SDKs/iPhoneSimulator${SDK_IOS_VERSION}.sdk/" i386 i386-apple-darwin10 i386-ios-sim
-
-# Create universal output directories
-mkdir -p "${OUTPUT_DIR}"
-mkdir -p "${OUTPUT_DIR}/include"
-mkdir -p "${OUTPUT_DIR}/include/armv6"
-mkdir -p "${OUTPUT_DIR}/include/armv7"
-mkdir -p "${OUTPUT_DIR}/include/i386"
-
-# Create the universal binary
-lipo -create armv6-ios/.libs/libffi.a armv7-ios/.libs/libffi.a i386-ios-sim/.libs/libffi.a -output "${OUTPUT_DIR}/libffi.a"
-
-# Copy in the headers
-copy_headers () {
-    local src=$1
-    local dest=$2
-
-    # Fix non-relative header reference
-    sed 's/<ffitarget.h>/"ffitarget.h"/' < "${src}/include/ffi.h" > "${dest}/ffi.h"
-    cp "${src}/include/ffitarget.h" "${dest}"
-}
-
-copy_headers armv6-ios "${OUTPUT_DIR}/include/armv6"
-copy_headers armv7-ios "${OUTPUT_DIR}/include/armv7"
-copy_headers i386-ios-sim "${OUTPUT_DIR}/include/i386"
-
-# Create top-level header
-(
-cat << EOF
-#ifdef __arm__
-  #include <arm/arch.h>
-  #ifdef _ARM_ARCH_6
-    #include "include/armv6/ffi.h"
-  #elif _ARM_ARCH_7
-    #include "include/armv7/ffi.h"
-  #endif
-#elif defined(__i386__)
-  #include "include/i386/ffi.h"
-#endif
-EOF
-) > "${OUTPUT_DIR}/ffi.h"
diff --git a/third_party/gofrontend/libffi/configure b/third_party/gofrontend/libffi/configure
index 4c53cf9..f580af0 100755
--- a/third_party/gofrontend/libffi/configure
+++ b/third_party/gofrontend/libffi/configure
@@ -1,8 +1,8 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.64 for libffi 3.0.11.
+# Generated by GNU Autoconf 2.64 for libffi 3.99999.
 #
-# Report bugs to <http://gcc.gnu.org/bugs.html>.
+# Report bugs to <http://github.com/atgreen/libffi/issues>.
 #
 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
 # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
@@ -237,8 +237,8 @@
     $as_echo "$0: be upgraded to zsh 4.3.4 or later."
   else
     $as_echo "$0: Please tell bug-autoconf@gnu.org and
-$0: http://gcc.gnu.org/bugs.html about your system,
-$0: including any error possibly output before this
+$0: http://github.com/atgreen/libffi/issues about your
+$0: system, including any error possibly output before this
 $0: message. Then install a modern shell, or manually run
 $0: the script under such a shell if you do have one."
   fi
@@ -559,9 +559,9 @@
 # Identity of this package.
 PACKAGE_NAME='libffi'
 PACKAGE_TARNAME='libffi'
-PACKAGE_VERSION='3.0.11'
-PACKAGE_STRING='libffi 3.0.11'
-PACKAGE_BUGREPORT='http://gcc.gnu.org/bugs.html'
+PACKAGE_VERSION='3.99999'
+PACKAGE_STRING='libffi 3.99999'
+PACKAGE_BUGREPORT='http://github.com/atgreen/libffi/issues'
 PACKAGE_URL=''
 
 # Factoring default headers for most tests.
@@ -608,6 +608,7 @@
 toolexecdir
 FFI_DEBUG_FALSE
 FFI_DEBUG_TRUE
+TARGET_OBJ
 TARGETDIR
 TARGET
 FFI_EXEC_TRAMPOLINE_TABLE
@@ -616,64 +617,6 @@
 HAVE_LONG_DOUBLE_VARIANT
 HAVE_LONG_DOUBLE
 ALLOCA
-TILE_FALSE
-TILE_TRUE
-PA64_HPUX_FALSE
-PA64_HPUX_TRUE
-PA_HPUX_FALSE
-PA_HPUX_TRUE
-PA_LINUX_FALSE
-PA_LINUX_TRUE
-SH64_FALSE
-SH64_TRUE
-SH_FALSE
-SH_TRUE
-X86_64_FALSE
-X86_64_TRUE
-S390_FALSE
-S390_TRUE
-FRV_FALSE
-FRV_TRUE
-LIBFFI_CRIS_FALSE
-LIBFFI_CRIS_TRUE
-AVR32_FALSE
-AVR32_TRUE
-ARM_FALSE
-ARM_TRUE
-AARCH64_FALSE
-AARCH64_TRUE
-POWERPC_FREEBSD_FALSE
-POWERPC_FREEBSD_TRUE
-POWERPC_DARWIN_FALSE
-POWERPC_DARWIN_TRUE
-POWERPC_AIX_FALSE
-POWERPC_AIX_TRUE
-POWERPC_FALSE
-POWERPC_TRUE
-M68K_FALSE
-M68K_TRUE
-M32R_FALSE
-M32R_TRUE
-IA64_FALSE
-IA64_TRUE
-ALPHA_FALSE
-ALPHA_TRUE
-X86_DARWIN_FALSE
-X86_DARWIN_TRUE
-X86_WIN64_FALSE
-X86_WIN64_TRUE
-X86_WIN32_FALSE
-X86_WIN32_TRUE
-X86_FREEBSD_FALSE
-X86_FREEBSD_TRUE
-X86_FALSE
-X86_TRUE
-SPARC_FALSE
-SPARC_TRUE
-BFIN_FALSE
-BFIN_TRUE
-MIPS_FALSE
-MIPS_TRUE
 AM_LTLDFLAGS
 AM_RUNTESTFLAGS
 TESTSUBDIR_FALSE
@@ -681,6 +624,7 @@
 MAINT
 MAINTAINER_MODE_FALSE
 MAINTAINER_MODE_TRUE
+CXXCPP
 CPP
 OTOOL64
 OTOOL
@@ -705,6 +649,12 @@
 CCASDEPMODE
 CCASFLAGS
 CCAS
+am__fastdepCXX_FALSE
+am__fastdepCXX_TRUE
+CXXDEPMODE
+ac_ct_CXX
+CXXFLAGS
+CXX
 am__fastdepCC_FALSE
 am__fastdepCC_TRUE
 CCDEPMODE
@@ -824,7 +774,8 @@
 CCAS
 CCASFLAGS
 CPP
-CPPFLAGS'
+CPPFLAGS
+CXXCPP'
 
 
 # Initialize some variables set by options.
@@ -1366,7 +1317,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures libffi 3.0.11 to adapt to many kinds of systems.
+\`configure' configures libffi 3.99999 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1437,7 +1388,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of libffi 3.0.11:";;
+     short | recursive ) echo "Configuration of libffi 3.99999:";;
    esac
   cat <<\_ACEOF
 
@@ -1480,14 +1431,17 @@
   LIBS        libraries to pass to the linker, e.g. -l<library>
   CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
               you have headers in a nonstandard directory <include dir>
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
   CCAS        assembler compiler command (defaults to CC)
   CCASFLAGS   assembler compiler flags (defaults to CFLAGS)
   CPP         C preprocessor
+  CXXCPP      C++ preprocessor
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
 
-Report bugs to <http://gcc.gnu.org/bugs.html>.
+Report bugs to <http://github.com/atgreen/libffi/issues>.
 _ACEOF
 ac_status=$?
 fi
@@ -1550,7 +1504,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-libffi configure 3.0.11
+libffi configure 3.99999
 generated by GNU Autoconf 2.64
 
 Copyright (C) 2009 Free Software Foundation, Inc.
@@ -1602,6 +1556,44 @@
 
 } # ac_fn_c_try_compile
 
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_cxx_try_compile
+
 # ac_fn_c_try_link LINENO
 # -----------------------
 # Try to link conftest.$ac_ext, and return whether this succeeded.
@@ -1825,98 +1817,88 @@
 
 } # ac_fn_c_check_func
 
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
+# ac_fn_cxx_try_cpp LINENO
+# ------------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_cpp ()
 {
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
-  $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
-	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
-  # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_header_compiler=yes
-else
-  ac_header_compiler=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-  ac_header_preproc=yes
-else
-  ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
-  yes:no: )
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
-    ;;
-  no:yes:* )
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
-( cat <<\_ASBOX
-## ------------------------------------------- ##
-## Report this to http://gcc.gnu.org/bugs.html ##
-## ------------------------------------------- ##
-_ASBOX
-     ) | sed "s/^/$as_me: WARNING:     /" >&2
-    ;;
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
 esac
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
-  $as_echo_n "(cached) " >&6
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } >/dev/null && {
+	 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
 else
-  eval "$3=\$ac_header_compiler"
-fi
-eval ac_res=\$$3
-	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
 fi
   eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
 
-} # ac_fn_c_check_header_mongrel
+} # ac_fn_cxx_try_cpp
+
+# ac_fn_cxx_try_link LINENO
+# -------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  return $ac_retval
+
+} # ac_fn_cxx_try_link
 
 # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
 # --------------------------------------------
@@ -2095,11 +2077,104 @@
   return $ac_retval
 
 } # ac_fn_c_compute_int
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( cat <<\_ASBOX
+## ------------------------------------------------------ ##
+## Report this to http://github.com/atgreen/libffi/issues ##
+## ------------------------------------------------------ ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_mongrel
 cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by libffi $as_me 3.0.11, which was
+It was created by libffi $as_me 3.99999, which was
 generated by GNU Autoconf 2.64.  Invocation command line was
 
   $ $0 $@
@@ -2626,8 +2701,6 @@
 
 target_alias=${target_alias-$host_alias}
 
-. ${srcdir}/configure.host
-
 am__api_version='1.11'
 
 # Find a good install program.  We prefer a C program (faster),
@@ -3066,7 +3139,7 @@
 
 # Define the identity of the package.
  PACKAGE='libffi'
- VERSION='3.0.11'
+ VERSION='3.99999'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -3215,9 +3288,12 @@
 # We must force CC to /not/ be precious variables; otherwise
 # the wrong, non-multilib-adjusted value will be used in multilibs.
 # As a side effect, we have to subst CFLAGS ourselves.
+# Also save and restore CFLAGS, since AC_PROG_CC will come up with
+# defaults of its own if none are provided.
 
 
 
+save_CFLAGS=$CFLAGS
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -4172,6 +4248,392 @@
 fi
 
 
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    rm -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+else
+  CXXFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CXX"  am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CXX_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvisualcpp | msvcmsys)
+      # This compiler won't grok `-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CXX_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+  am__fastdepCXX_TRUE=
+  am__fastdepCXX_FALSE='#'
+else
+  am__fastdepCXX_TRUE='#'
+  am__fastdepCXX_FALSE=
+fi
+
+
+CFLAGS=$save_CFLAGS
+
 
 
 
@@ -7125,7 +7587,7 @@
       case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
 	10.0,*86*-darwin8*|10.0,*-darwin[91]*)
 	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
-	10.[012]*)
+	10.[012][,.]*)
 	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
 	10.*)
 	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
@@ -7433,6 +7895,7 @@
 
 
 
+
 # Set options
 
 
@@ -8697,7 +9160,7 @@
       if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
 	 && test "$tmp_diet" = no
       then
-	tmp_addflag=
+	tmp_addflag=' $pic_flag'
 	tmp_sharedflag='-shared'
 	case $cc_basename,$host_cpu in
         pgcc*)				# Portland Group C compiler
@@ -10907,7 +11370,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 10910 "configure"
+#line 11373 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11013,7 +11476,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11016 "configure"
+#line 11479 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11230,6 +11693,3022 @@
 
 CC="$lt_save_CC"
 
+      if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+    (test "X$CXX" != "Xg++"))) ; then
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
+$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+if test -z "$CXXCPP"; then
+  if test "${ac_cv_prog_CXXCPP+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CXXCPP needs to be expanded
+    for CXXCPP in "$CXX -E" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+  CXXCPP=$ac_cv_prog_CXXCPP
+else
+  ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
+$as_echo "$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+else
+  _lt_caught_CXX_error=yes
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+archive_cmds_need_lc_CXX=no
+allow_undefined_flag_CXX=
+always_export_symbols_CXX=no
+archive_expsym_cmds_CXX=
+compiler_needs_object_CXX=no
+export_dynamic_flag_spec_CXX=
+hardcode_direct_CXX=no
+hardcode_direct_absolute_CXX=no
+hardcode_libdir_flag_spec_CXX=
+hardcode_libdir_flag_spec_ld_CXX=
+hardcode_libdir_separator_CXX=
+hardcode_minus_L_CXX=no
+hardcode_shlibpath_var_CXX=unsupported
+hardcode_automatic_CXX=no
+inherit_rpath_CXX=no
+module_cmds_CXX=
+module_expsym_cmds_CXX=
+link_all_deplibs_CXX=unknown
+old_archive_cmds_CXX=$old_archive_cmds
+reload_flag_CXX=$reload_flag
+reload_cmds_CXX=$reload_cmds
+no_undefined_flag_CXX=
+whole_archive_flag_spec_CXX=
+enable_shared_with_static_runtimes_CXX=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+objext_CXX=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_caught_CXX_error" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="int some_variable = 0;"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code='int main(int, char *[]) { return(0); }'
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+  # save warnings/boilerplate of simple test code
+  ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+  ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_LD=$LD
+  lt_save_GCC=$GCC
+  GCC=$GXX
+  lt_save_with_gnu_ld=$with_gnu_ld
+  lt_save_path_LD=$lt_cv_path_LD
+  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+  else
+    $as_unset lt_cv_prog_gnu_ld
+  fi
+  if test -n "${lt_cv_path_LDCXX+set}"; then
+    lt_cv_path_LD=$lt_cv_path_LDCXX
+  else
+    $as_unset lt_cv_path_LD
+  fi
+  test -z "${LDCXX+set}" || LD=$LDCXX
+  CC=${CXX-"c++"}
+  compiler=$CC
+  compiler_CXX=$CC
+  for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+
+
+  if test -n "$compiler"; then
+    # We don't want -fno-exception when compiling C++ code, so set the
+    # no_builtin_flag separately
+    if test "$GXX" = yes; then
+      lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+    else
+      lt_prog_compiler_no_builtin_flag_CXX=
+    fi
+
+    if test "$GXX" = yes; then
+      # Set up default GNU C++ configuration
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break
+	;;
+      *)
+	test "$with_gnu_ld" != yes && break
+	;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+      # Check if GNU C++ uses GNU ld as the underlying linker, since the
+      # archiving commands below assume that GNU ld is being used.
+      if test "$with_gnu_ld" = yes; then
+        archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+        hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+        export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+        # If archive_cmds runs LD, not CC, wlarc should be empty
+        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+        #     investigate it a little bit more. (MM)
+        wlarc='${wl}'
+
+        # ancient GNU ld didn't support --whole-archive et. al.
+        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+	  $GREP 'no-whole-archive' > /dev/null; then
+          whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+        else
+          whole_archive_flag_spec_CXX=
+        fi
+      else
+        with_gnu_ld=no
+        wlarc=
+
+        # A generic and very simple default shared library creation
+        # command for GNU C++ for the case where it uses the native
+        # linker, instead of GNU ld.  If possible, this setting should
+        # overridden to take advantage of the native linker features on
+        # the platform it is being used on.
+        archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+      fi
+
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+    else
+      GXX=no
+      with_gnu_ld=no
+      wlarc=
+    fi
+
+    # PORTME: fill in a description of your system's C++ link characteristics
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+    ld_shlibs_CXX=yes
+    case $host_os in
+      aix3*)
+        # FIXME: insert proper C++ library support
+        ld_shlibs_CXX=no
+        ;;
+      aix[4-9]*)
+        if test "$host_cpu" = ia64; then
+          # On IA64, the linker does run time linking by default, so we don't
+          # have to do anything special.
+          aix_use_runtimelinking=no
+          exp_sym_flag='-Bexport'
+          no_entry_flag=""
+        else
+          aix_use_runtimelinking=no
+
+          # Test if we are trying to use run time linking or normal
+          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+          # need to do runtime linking.
+          case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+	    for ld_flag in $LDFLAGS; do
+	      case $ld_flag in
+	      *-brtl*)
+	        aix_use_runtimelinking=yes
+	        break
+	        ;;
+	      esac
+	    done
+	    ;;
+          esac
+
+          exp_sym_flag='-bexport'
+          no_entry_flag='-bnoentry'
+        fi
+
+        # When large executables or shared objects are built, AIX ld can
+        # have problems creating the table of contents.  If linking a library
+        # or program results in "error TOC overflow" add -mminimal-toc to
+        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+        archive_cmds_CXX=''
+        hardcode_direct_CXX=yes
+        hardcode_direct_absolute_CXX=yes
+        hardcode_libdir_separator_CXX=':'
+        link_all_deplibs_CXX=yes
+        file_list_spec_CXX='${wl}-f,'
+
+        if test "$GXX" = yes; then
+          case $host_os in aix4.[012]|aix4.[012].*)
+          # We only want to do this on AIX 4.2 and lower, the check
+          # below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	     strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	    # We have reworked collect2
+	    :
+	  else
+	    # We have old collect2
+	    hardcode_direct_CXX=unsupported
+	    # It fails to find uninstalled libraries when the uninstalled
+	    # path is not listed in the libpath.  Setting hardcode_minus_L
+	    # to unsupported forces relinking
+	    hardcode_minus_L_CXX=yes
+	    hardcode_libdir_flag_spec_CXX='-L$libdir'
+	    hardcode_libdir_separator_CXX=
+	  fi
+          esac
+          shared_flag='-shared'
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag="$shared_flag "'${wl}-G'
+	  fi
+        else
+          # not using gcc
+          if test "$host_cpu" = ia64; then
+	  # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	  # chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+          else
+	    if test "$aix_use_runtimelinking" = yes; then
+	      shared_flag='${wl}-G'
+	    else
+	      shared_flag='${wl}-bM:SRE'
+	    fi
+          fi
+        fi
+
+        export_dynamic_flag_spec_CXX='${wl}-bexpall'
+        # It seems that -bexpall does not export symbols beginning with
+        # underscore (_), so it is better to generate a list of symbols to
+	# export.
+        always_export_symbols_CXX=yes
+        if test "$aix_use_runtimelinking" = yes; then
+          # Warning - without using the other runtime loading flags (-brtl),
+          # -berok will link without error, but may produce a broken library.
+          allow_undefined_flag_CXX='-berok'
+          # Determine the default libpath from the value encoded in an empty
+          # executable.
+          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+          hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+          archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+        else
+          if test "$host_cpu" = ia64; then
+	    hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib'
+	    allow_undefined_flag_CXX="-z nodefs"
+	    archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+          else
+	    # Determine the default libpath from the value encoded in an
+	    # empty executable.
+	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+	    hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+	    # Warning - without using the other run time loading flags,
+	    # -berok will link without error, but may produce a broken library.
+	    no_undefined_flag_CXX=' ${wl}-bernotok'
+	    allow_undefined_flag_CXX=' ${wl}-berok'
+	    if test "$with_gnu_ld" = yes; then
+	      # We only use this code for GNU lds that support --whole-archive.
+	      whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	    else
+	      # Exported symbols can be pulled into shared objects from archives
+	      whole_archive_flag_spec_CXX='$convenience'
+	    fi
+	    archive_cmds_need_lc_CXX=yes
+	    # This is similar to how AIX traditionally builds its shared
+	    # libraries.
+	    archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+          fi
+        fi
+        ;;
+
+      beos*)
+	if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	  allow_undefined_flag_CXX=unsupported
+	  # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	  # support --undefined.  This deserves some investigation.  FIXME
+	  archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	else
+	  ld_shlibs_CXX=no
+	fi
+	;;
+
+      chorus*)
+        case $cc_basename in
+          *)
+	  # FIXME: insert proper C++ library support
+	  ld_shlibs_CXX=no
+	  ;;
+        esac
+        ;;
+
+      cygwin* | mingw* | pw32* | cegcc*)
+        # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
+        # as there is no search path for DLLs.
+        hardcode_libdir_flag_spec_CXX='-L$libdir'
+        export_dynamic_flag_spec_CXX='${wl}--export-all-symbols'
+        allow_undefined_flag_CXX=unsupported
+        always_export_symbols_CXX=no
+        enable_shared_with_static_runtimes_CXX=yes
+
+        if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+          archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+          # If the export-symbols file already is a .def file (1st line
+          # is EXPORTS), use it as is; otherwise, prepend...
+          archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	    cp $export_symbols $output_objdir/$soname.def;
+          else
+	    echo EXPORTS > $output_objdir/$soname.def;
+	    cat $export_symbols >> $output_objdir/$soname.def;
+          fi~
+          $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+        else
+          ld_shlibs_CXX=no
+        fi
+        ;;
+      darwin* | rhapsody*)
+
+
+  archive_cmds_need_lc_CXX=no
+  hardcode_direct_CXX=no
+  hardcode_automatic_CXX=yes
+  hardcode_shlibpath_var_CXX=unsupported
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+  else
+    whole_archive_flag_spec_CXX=''
+  fi
+  link_all_deplibs_CXX=yes
+  allow_undefined_flag_CXX="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=func_echo_all
+    archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+       if test "$lt_cv_apple_cc_single_mod" != "yes"; then
+      archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
+      archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+    fi
+
+  else
+  ld_shlibs_CXX=no
+  fi
+
+	;;
+
+      dgux*)
+        case $cc_basename in
+          ec++*)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          ghcx*)
+	    # Green Hills C++ Compiler
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+        esac
+        ;;
+
+      freebsd2.*)
+        # C++ shared libraries reported to be fairly broken before
+	# switch to ELF
+        ld_shlibs_CXX=no
+        ;;
+
+      freebsd-elf*)
+        archive_cmds_need_lc_CXX=no
+        ;;
+
+      freebsd* | dragonfly*)
+        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+        # conventions
+        ld_shlibs_CXX=yes
+        ;;
+
+      gnu*)
+        ;;
+
+      haiku*)
+        archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        link_all_deplibs_CXX=yes
+        ;;
+
+      hpux9*)
+        hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+        hardcode_libdir_separator_CXX=:
+        export_dynamic_flag_spec_CXX='${wl}-E'
+        hardcode_direct_CXX=yes
+        hardcode_minus_L_CXX=yes # Not in the search PATH,
+				             # but as the default
+				             # location of the library.
+
+        case $cc_basename in
+          CC*)
+            # FIXME: insert proper C++ library support
+            ld_shlibs_CXX=no
+            ;;
+          aCC*)
+            archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            # Commands to make compiler produce verbose output that lists
+            # what "hidden" libraries, object files and flags are used when
+            # linking a shared library.
+            #
+            # There doesn't appear to be a way to prevent this compiler from
+            # explicitly linking system object files so we need to strip them
+            # from the output so that they don't get included in the library
+            # dependencies.
+            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+            ;;
+          *)
+            if test "$GXX" = yes; then
+              archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            else
+              # FIXME: insert proper C++ library support
+              ld_shlibs_CXX=no
+            fi
+            ;;
+        esac
+        ;;
+
+      hpux10*|hpux11*)
+        if test $with_gnu_ld = no; then
+	  hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+	  hardcode_libdir_separator_CXX=:
+
+          case $host_cpu in
+            hppa*64*|ia64*)
+              ;;
+            *)
+	      export_dynamic_flag_spec_CXX='${wl}-E'
+              ;;
+          esac
+        fi
+        case $host_cpu in
+          hppa*64*|ia64*)
+            hardcode_direct_CXX=no
+            hardcode_shlibpath_var_CXX=no
+            ;;
+          *)
+            hardcode_direct_CXX=yes
+            hardcode_direct_absolute_CXX=yes
+            hardcode_minus_L_CXX=yes # Not in the search PATH,
+					         # but as the default
+					         # location of the library.
+            ;;
+        esac
+
+        case $cc_basename in
+          CC*)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          aCC*)
+	    case $host_cpu in
+	      hppa*64*)
+	        archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      ia64*)
+	        archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      *)
+	        archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	    esac
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+	    ;;
+          *)
+	    if test "$GXX" = yes; then
+	      if test $with_gnu_ld = no; then
+	        case $host_cpu in
+	          hppa*64*)
+	            archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          ia64*)
+	            archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          *)
+	            archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	        esac
+	      fi
+	    else
+	      # FIXME: insert proper C++ library support
+	      ld_shlibs_CXX=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      interix[3-9]*)
+	hardcode_direct_CXX=no
+	hardcode_shlibpath_var_CXX=no
+	hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+	export_dynamic_flag_spec_CXX='${wl}-E'
+	# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+	# Instead, shared libraries are loaded at an image base (0x10000000 by
+	# default) and relocated if they conflict, which is a slow very memory
+	# consuming and fragmenting process.  To avoid this, we pick a random,
+	# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+	# time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+	archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	;;
+      irix5* | irix6*)
+        case $cc_basename in
+          CC*)
+	    # SGI C++
+	    archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    if test "$GXX" = yes; then
+	      if test "$with_gnu_ld" = no; then
+	        archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	      else
+	        archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib'
+	      fi
+	    fi
+	    link_all_deplibs_CXX=yes
+	    ;;
+        esac
+        hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+        hardcode_libdir_separator_CXX=:
+        inherit_rpath_CXX=yes
+        ;;
+
+      linux* | k*bsd*-gnu | kopensolaris*-gnu)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+	    archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+
+	    hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+	    export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+	    old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+	    ;;
+	  icpc* | ecpc* )
+	    # Intel C++
+	    with_gnu_ld=yes
+	    # version 8.0 and above of icpc choke on multiply defined symbols
+	    # if we add $predep_objects and $postdep_objects, however 7.1 and
+	    # earlier do not add the objects themselves.
+	    case `$CC -V 2>&1` in
+	      *"Version 7."*)
+	        archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+		archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	      *)  # Version 8.0 or newer
+	        tmp_idyn=
+	        case $host_cpu in
+		  ia64*) tmp_idyn=' -i_dynamic';;
+		esac
+	        archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+		archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	    esac
+	    archive_cmds_need_lc_CXX=no
+	    hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+	    export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+	    whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	    ;;
+          pgCC* | pgcpp*)
+            # Portland Group C++ compiler
+	    case `$CC -V` in
+	    *pgCC\ [1-5].* | *pgcpp\ [1-5].*)
+	      prelink_cmds_CXX='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+		compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
+	      old_archive_cmds_CXX='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+		$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
+		$RANLIB $oldlib'
+	      archive_cmds_CXX='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+	      archive_expsym_cmds_CXX='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+	      ;;
+	    *) # Version 6 and above use weak symbols
+	      archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+	      archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+	      ;;
+	    esac
+
+	    hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+	    export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+	    whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+            ;;
+	  cxx*)
+	    # Compaq C++
+	    archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+	    runpath_var=LD_RUN_PATH
+	    hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+	    hardcode_libdir_separator_CXX=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
+	    ;;
+	  xl* | mpixl* | bgxl*)
+	    # IBM XL 8.0 on PPC, with GNU ld
+	    hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+	    export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+	    archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    if test "x$supports_anon_versioning" = xyes; then
+	      archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~
+		cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+		echo "local: *; };" >> $output_objdir/$libname.ver~
+		$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+	    fi
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | sed 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      no_undefined_flag_CXX=' -zdefs'
+	      archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	      archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+	      hardcode_libdir_flag_spec_CXX='-R$libdir'
+	      whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	      compiler_needs_object_CXX=yes
+
+	      # Not sure whether something based on
+	      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+	      # would be better.
+	      output_verbose_link_cmd='func_echo_all'
+
+	      # Archives containing C++ object files must be created using
+	      # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	      # necessary to make sure instantiated templates are included
+	      # in the archive.
+	      old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+
+      lynxos*)
+        # FIXME: insert proper C++ library support
+	ld_shlibs_CXX=no
+	;;
+
+      m88k*)
+        # FIXME: insert proper C++ library support
+        ld_shlibs_CXX=no
+	;;
+
+      mvs*)
+        case $cc_basename in
+          cxx*)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+	  *)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+	esac
+	;;
+
+      netbsd*)
+        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	  archive_cmds_CXX='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+	  wlarc=
+	  hardcode_libdir_flag_spec_CXX='-R$libdir'
+	  hardcode_direct_CXX=yes
+	  hardcode_shlibpath_var_CXX=no
+	fi
+	# Workaround some broken pre-1.5 toolchains
+	output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+	;;
+
+      *nto* | *qnx*)
+        ld_shlibs_CXX=yes
+	;;
+
+      openbsd2*)
+        # C++ shared libraries are fairly broken
+	ld_shlibs_CXX=no
+	;;
+
+      openbsd*)
+	if test -f /usr/libexec/ld.so; then
+	  hardcode_direct_CXX=yes
+	  hardcode_shlibpath_var_CXX=no
+	  hardcode_direct_absolute_CXX=yes
+	  archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+	  hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+	  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	    archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+	    export_dynamic_flag_spec_CXX='${wl}-E'
+	    whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+	  fi
+	  output_verbose_link_cmd=func_echo_all
+	else
+	  ld_shlibs_CXX=no
+	fi
+	;;
+
+      osf3* | osf4* | osf5*)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+	    hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+	    hardcode_libdir_separator_CXX=:
+
+	    # Archives containing C++ object files must be created using
+	    # the KAI C++ compiler.
+	    case $host in
+	      osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;;
+	      *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;;
+	    esac
+	    ;;
+          RCC*)
+	    # Rational C++ 2.4.1
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          cxx*)
+	    case $host in
+	      osf3*)
+	        allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+	        archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	        hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+		;;
+	      *)
+	        allow_undefined_flag_CXX=' -expect_unresolved \*'
+	        archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	        archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+	          echo "-hidden">> $lib.exp~
+	          $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~
+	          $RM $lib.exp'
+	        hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+		;;
+	    esac
+
+	    hardcode_libdir_separator_CXX=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+	    ;;
+	  *)
+	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+	      allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+	      case $host in
+	        osf3*)
+	          archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+		  ;;
+	        *)
+	          archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+		  ;;
+	      esac
+
+	      hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+	      hardcode_libdir_separator_CXX=:
+
+	      # Commands to make compiler produce verbose output that lists
+	      # what "hidden" libraries, object files and flags are used when
+	      # linking a shared library.
+	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+	    else
+	      # FIXME: insert proper C++ library support
+	      ld_shlibs_CXX=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      psos*)
+        # FIXME: insert proper C++ library support
+        ld_shlibs_CXX=no
+        ;;
+
+      sunos4*)
+        case $cc_basename in
+          CC*)
+	    # Sun C++ 4.x
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          lcc*)
+	    # Lucid
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+        esac
+        ;;
+
+      solaris*)
+        case $cc_basename in
+          CC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+            archive_cmds_need_lc_CXX=yes
+	    no_undefined_flag_CXX=' -zdefs'
+	    archive_cmds_CXX='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	    archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	      $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	    hardcode_libdir_flag_spec_CXX='-R$libdir'
+	    hardcode_shlibpath_var_CXX=no
+	    case $host_os in
+	      solaris2.[0-5] | solaris2.[0-5].*) ;;
+	      *)
+		# The compiler driver will combine and reorder linker options,
+		# but understands `-z linker_flag'.
+	        # Supported since Solaris 2.6 (maybe 2.5.1?)
+		whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract'
+	        ;;
+	    esac
+	    link_all_deplibs_CXX=yes
+
+	    output_verbose_link_cmd='func_echo_all'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+	    ;;
+          gcx*)
+	    # Green Hills C++ Compiler
+	    archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+	    # The C++ compiler must be used to create the archive.
+	    old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    # GNU C++ compiler with Solaris linker
+	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+	      no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
+	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+	        archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	        archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+		  $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+	      else
+	        # g++ 2.7 appears to require `-G' NOT `-shared' on this
+	        # platform.
+	        archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	        archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+		  $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+	      fi
+
+	      hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir'
+	      case $host_os in
+		solaris2.[0-5] | solaris2.[0-5].*) ;;
+		*)
+		  whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+		  ;;
+	      esac
+	    fi
+	    ;;
+        esac
+        ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag_CXX='${wl}-z,text'
+      archive_cmds_need_lc_CXX=no
+      hardcode_shlibpath_var_CXX=no
+      runpath_var='LD_RUN_PATH'
+
+      case $cc_basename in
+        CC*)
+	  archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+      esac
+      ;;
+
+      sysv5* | sco3.2v5* | sco5v6*)
+	# Note: We can NOT use -z defs as we might desire, because we do not
+	# link with -lc, and that would cause any symbols used from libc to
+	# always be unresolved, which means just about no library would
+	# ever link correctly.  If we're not using GNU ld we use -z text
+	# though, which does catch some bad symbols but isn't as heavy-handed
+	# as -z defs.
+	no_undefined_flag_CXX='${wl}-z,text'
+	allow_undefined_flag_CXX='${wl}-z,nodefs'
+	archive_cmds_need_lc_CXX=no
+	hardcode_shlibpath_var_CXX=no
+	hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir'
+	hardcode_libdir_separator_CXX=':'
+	link_all_deplibs_CXX=yes
+	export_dynamic_flag_spec_CXX='${wl}-Bexport'
+	runpath_var='LD_RUN_PATH'
+
+	case $cc_basename in
+          CC*)
+	    archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~
+	      '"$old_archive_cmds_CXX"
+	    reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~
+	      '"$reload_cmds_CXX"
+	    ;;
+	  *)
+	    archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    ;;
+	esac
+      ;;
+
+      tandem*)
+        case $cc_basename in
+          NCC*)
+	    # NonStop-UX NCC 3.20
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    ld_shlibs_CXX=no
+	    ;;
+        esac
+        ;;
+
+      vxworks*)
+        # FIXME: insert proper C++ library support
+        ld_shlibs_CXX=no
+        ;;
+
+      *)
+        # FIXME: insert proper C++ library support
+        ld_shlibs_CXX=no
+        ;;
+    esac
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
+$as_echo "$ld_shlibs_CXX" >&6; }
+    test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+    GCC_CXX="$GXX"
+    LD_CXX="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    # Dependencies to place before and after the object being linked:
+predep_objects_CXX=
+postdep_objects_CXX=
+predeps_CXX=
+postdeps_CXX=
+compiler_lib_search_path_CXX=
+
+cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+_LT_EOF
+
+if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  for p in `eval "$output_verbose_link_cmd"`; do
+    case $p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test $p = "-L" ||
+          test $p = "-R"; then
+	 prev=$p
+	 continue
+       else
+	 prev=
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+	 case $p in
+	 -L* | -R*)
+	   # Internal compiler library paths should come after those
+	   # provided the user.  The postdeps already come after the
+	   # user supplied libs so there is no need to process them.
+	   if test -z "$compiler_lib_search_path_CXX"; then
+	     compiler_lib_search_path_CXX="${prev}${p}"
+	   else
+	     compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}"
+	   fi
+	   ;;
+	 # The "-l" case would never come before the object being
+	 # linked, so don't bother handling this case.
+	 esac
+       else
+	 if test -z "$postdeps_CXX"; then
+	   postdeps_CXX="${prev}${p}"
+	 else
+	   postdeps_CXX="${postdeps_CXX} ${prev}${p}"
+	 fi
+       fi
+       ;;
+
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+	 pre_test_object_deps_done=yes
+	 continue
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+	 if test -z "$predep_objects_CXX"; then
+	   predep_objects_CXX="$p"
+	 else
+	   predep_objects_CXX="$predep_objects_CXX $p"
+	 fi
+       else
+	 if test -z "$postdep_objects_CXX"; then
+	   postdep_objects_CXX="$p"
+	 else
+	   postdep_objects_CXX="$postdep_objects_CXX $p"
+	 fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling CXX test program"
+fi
+
+$RM -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+case $host_os in
+interix[3-9]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  predep_objects_CXX=
+  postdep_objects_CXX=
+  postdeps_CXX=
+  ;;
+
+linux*)
+  case `$CC -V 2>&1 | sed 5q` in
+  *Sun\ C*)
+    # Sun C++ 5.9
+
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    if test "$solaris_use_stlport4" != yes; then
+      postdeps_CXX='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+
+solaris*)
+  case $cc_basename in
+  CC*)
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    if test "$solaris_use_stlport4" != yes; then
+      postdeps_CXX='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+esac
+
+
+case " $postdeps_CXX " in
+*" -lc "*) archive_cmds_need_lc_CXX=no ;;
+esac
+ compiler_lib_search_dirs_CXX=
+if test -n "${compiler_lib_search_path_CXX}"; then
+ compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    lt_prog_compiler_wl_CXX=
+lt_prog_compiler_pic_CXX=
+lt_prog_compiler_static_CXX=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+
+  # C++ specific cases for pic, static, wl, etc.
+  if test "$GXX" = yes; then
+    lt_prog_compiler_wl_CXX='-Wl,'
+    lt_prog_compiler_static_CXX='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static_CXX='-Bstatic'
+      fi
+      lt_prog_compiler_pic_CXX='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            lt_prog_compiler_pic_CXX='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic_CXX='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      lt_prog_compiler_pic_CXX=
+      ;;
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      lt_prog_compiler_static_CXX=
+      ;;
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	lt_prog_compiler_pic_CXX=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	;;
+      *)
+	lt_prog_compiler_pic_CXX='-fPIC'
+	;;
+      esac
+      ;;
+    *qnx* | *nto*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic_CXX='-fPIC -shared'
+      ;;
+    *)
+      lt_prog_compiler_pic_CXX='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix[4-9]*)
+	# All AIX code is PIC.
+	if test "$host_cpu" = ia64; then
+	  # AIX 5 now supports IA64 processor
+	  lt_prog_compiler_static_CXX='-Bstatic'
+	else
+	  lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
+	fi
+	;;
+      chorus*)
+	case $cc_basename in
+	cxch68*)
+	  # Green Hills C++ Compiler
+	  # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+	  ;;
+	esac
+	;;
+      dgux*)
+	case $cc_basename in
+	  ec++*)
+	    lt_prog_compiler_pic_CXX='-KPIC'
+	    ;;
+	  ghcx*)
+	    # Green Hills C++ Compiler
+	    lt_prog_compiler_pic_CXX='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      freebsd* | dragonfly*)
+	# FreeBSD uses GNU C++
+	;;
+      hpux9* | hpux10* | hpux11*)
+	case $cc_basename in
+	  CC*)
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+	    if test "$host_cpu" != ia64; then
+	      lt_prog_compiler_pic_CXX='+Z'
+	    fi
+	    ;;
+	  aCC*)
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+	    case $host_cpu in
+	    hppa*64*|ia64*)
+	      # +Z the default
+	      ;;
+	    *)
+	      lt_prog_compiler_pic_CXX='+Z'
+	      ;;
+	    esac
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      interix*)
+	# This is c89, which is MS Visual C++ (no shared libs)
+	# Anyone wants to do a port?
+	;;
+      irix5* | irix6* | nonstopux*)
+	case $cc_basename in
+	  CC*)
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_static_CXX='-non_shared'
+	    # CC pic flag -KPIC is the default.
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      linux* | k*bsd*-gnu | kopensolaris*-gnu)
+	case $cc_basename in
+	  KCC*)
+	    # KAI C++ Compiler
+	    lt_prog_compiler_wl_CXX='--backend -Wl,'
+	    lt_prog_compiler_pic_CXX='-fPIC'
+	    ;;
+	  ecpc* )
+	    # old Intel C++ for x86_64 which still supported -KPIC.
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_pic_CXX='-KPIC'
+	    lt_prog_compiler_static_CXX='-static'
+	    ;;
+	  icpc* )
+	    # Intel C++, used to be incompatible with GCC.
+	    # ICC 10 doesn't accept -KPIC any more.
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_pic_CXX='-fPIC'
+	    lt_prog_compiler_static_CXX='-static'
+	    ;;
+	  pgCC* | pgcpp*)
+	    # Portland Group C++ compiler
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_pic_CXX='-fpic'
+	    lt_prog_compiler_static_CXX='-Bstatic'
+	    ;;
+	  cxx*)
+	    # Compaq C++
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    lt_prog_compiler_pic_CXX=
+	    lt_prog_compiler_static_CXX='-non_shared'
+	    ;;
+	  xlc* | xlC* | bgxl[cC]* | mpixl[cC]*)
+	    # IBM XL 8.0, 9.0 on PPC and BlueGene
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_pic_CXX='-qpic'
+	    lt_prog_compiler_static_CXX='-qstaticlink'
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | sed 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      lt_prog_compiler_pic_CXX='-KPIC'
+	      lt_prog_compiler_static_CXX='-Bstatic'
+	      lt_prog_compiler_wl_CXX='-Qoption ld '
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+      lynxos*)
+	;;
+      m88k*)
+	;;
+      mvs*)
+	case $cc_basename in
+	  cxx*)
+	    lt_prog_compiler_pic_CXX='-W c,exportall'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      netbsd*)
+	;;
+      *qnx* | *nto*)
+        # QNX uses GNU C++, but need to define -shared option too, otherwise
+        # it will coredump.
+        lt_prog_compiler_pic_CXX='-fPIC -shared'
+        ;;
+      osf3* | osf4* | osf5*)
+	case $cc_basename in
+	  KCC*)
+	    lt_prog_compiler_wl_CXX='--backend -Wl,'
+	    ;;
+	  RCC*)
+	    # Rational C++ 2.4.1
+	    lt_prog_compiler_pic_CXX='-pic'
+	    ;;
+	  cxx*)
+	    # Digital/Compaq C++
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    lt_prog_compiler_pic_CXX=
+	    lt_prog_compiler_static_CXX='-non_shared'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      psos*)
+	;;
+      solaris*)
+	case $cc_basename in
+	  CC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+	    lt_prog_compiler_pic_CXX='-KPIC'
+	    lt_prog_compiler_static_CXX='-Bstatic'
+	    lt_prog_compiler_wl_CXX='-Qoption ld '
+	    ;;
+	  gcx*)
+	    # Green Hills C++ Compiler
+	    lt_prog_compiler_pic_CXX='-PIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sunos4*)
+	case $cc_basename in
+	  CC*)
+	    # Sun C++ 4.x
+	    lt_prog_compiler_pic_CXX='-pic'
+	    lt_prog_compiler_static_CXX='-Bstatic'
+	    ;;
+	  lcc*)
+	    # Lucid
+	    lt_prog_compiler_pic_CXX='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+	case $cc_basename in
+	  CC*)
+	    lt_prog_compiler_wl_CXX='-Wl,'
+	    lt_prog_compiler_pic_CXX='-KPIC'
+	    lt_prog_compiler_static_CXX='-Bstatic'
+	    ;;
+	esac
+	;;
+      tandem*)
+	case $cc_basename in
+	  NCC*)
+	    # NonStop-UX NCC 3.20
+	    lt_prog_compiler_pic_CXX='-KPIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      vxworks*)
+	;;
+      *)
+	lt_prog_compiler_can_build_shared_CXX=no
+	;;
+    esac
+  fi
+
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic_CXX=
+    ;;
+  *)
+    lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
+    ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_CXX" >&5
+$as_echo "$lt_prog_compiler_pic_CXX" >&6; }
+
+
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; }
+if test "${lt_cv_prog_compiler_pic_works_CXX+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_works_CXX=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_pic_works_CXX=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then
+    case $lt_prog_compiler_pic_CXX in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
+     esac
+else
+    lt_prog_compiler_pic_CXX=
+     lt_prog_compiler_can_build_shared_CXX=no
+fi
+
+fi
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if test "${lt_cv_prog_compiler_static_works_CXX+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_static_works_CXX=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler_static_works_CXX=yes
+       fi
+     else
+       lt_cv_prog_compiler_static_works_CXX=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then
+    :
+else
+    lt_prog_compiler_static_CXX=
+fi
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o_CXX=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o_CXX=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; }
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o_CXX=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o_CXX=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+  export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  case $host_os in
+  aix[4-9]*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    # Also, AIX nm treats weak defined symbols like other global defined
+    # symbols, whereas GNU nm marks them as "W".
+    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+      export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    else
+      export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    export_symbols_cmds_CXX="$ltdll_cmds"
+  ;;
+  cygwin* | mingw* | cegcc*)
+    export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  *)
+    export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  esac
+  exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
+$as_echo "$ld_shlibs_CXX" >&6; }
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+with_gnu_ld_CXX=$with_gnu_ld
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_CXX" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc_CXX=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds_CXX in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if test "${lt_cv_archive_cmds_need_lc_CXX+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  $RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } 2>conftest.err; then
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$lt_prog_compiler_wl_CXX
+	  pic_flag=$lt_prog_compiler_pic_CXX
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
+	  allow_undefined_flag_CXX=
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+  (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+	  then
+	    lt_cv_archive_cmds_need_lc_CXX=no
+	  else
+	    lt_cv_archive_cmds_need_lc_CXX=yes
+	  fi
+	  allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; }
+      archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[4-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[23].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+haiku*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[3-9]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test "$lt_cv_prog_gnu_ld" = yes; then
+		version_type=linux
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  if test "${lt_cv_shlibpath_overrides_runpath+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \
+	 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\""
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+  lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+
+fi
+
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*)	need_version=yes ;;
+    *)				need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+	shlibpath_overrides_runpath=no
+	;;
+      *)
+	shlibpath_overrides_runpath=yes
+	;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action_CXX=
+if test -n "$hardcode_libdir_flag_spec_CXX" ||
+   test -n "$runpath_var_CXX" ||
+   test "X$hardcode_automatic_CXX" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$hardcode_direct_CXX" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no &&
+     test "$hardcode_minus_L_CXX" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action_CXX=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action_CXX=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action_CXX=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5
+$as_echo "$hardcode_action_CXX" >&6; }
+
+if test "$hardcode_action_CXX" = relink ||
+   test "$inherit_rpath_CXX" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+
+
+
+
+
+  fi # test -n "$compiler"
+
+  CC=$lt_save_CC
+  LDCXX=$LD
+  LD=$lt_save_LD
+  GCC=$lt_save_GCC
+  with_gnu_ld=$lt_save_with_gnu_ld
+  lt_cv_path_LDCXX=$lt_cv_path_LD
+  lt_cv_path_LD=$lt_save_path_LD
+  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test "$_lt_caught_CXX_error" != yes
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
 
 
 
@@ -11251,6 +14730,42 @@
 
 
 
+# Test for 64-bit build.
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of size_t" >&5
+$as_echo_n "checking size of size_t... " >&6; }
+if test "${ac_cv_sizeof_size_t+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (size_t))" "ac_cv_sizeof_size_t"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_size_t" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "cannot compute sizeof (size_t)
+See \`config.log' for more details." "$LINENO" 5; }; }
+   else
+     ac_cv_sizeof_size_t=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_size_t" >&5
+$as_echo "$ac_cv_sizeof_size_t" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_SIZE_T $ac_cv_sizeof_size_t
+_ACEOF
+
+
+
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
@@ -11287,12 +14802,14 @@
 
 done
 
-for ac_func in mmap
+for ac_func in mmap mkostemp
 do :
-  ac_fn_c_check_func "$LINENO" "mmap" "ac_cv_func_mmap"
-if test "x$ac_cv_func_mmap" = x""yes; then :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
   cat >>confdefs.h <<_ACEOF
-#define HAVE_MMAP 1
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
 _ACEOF
 
 fi
@@ -11451,407 +14968,14 @@
 
 TARGETDIR="unknown"
 HAVE_LONG_DOUBLE_VARIANT=0
-case "$host" in
-  aarch64*-*-*)
-	TARGET=AARCH64; TARGETDIR=aarch64
-	;;
 
-  alpha*-*-*)
-	TARGET=ALPHA; TARGETDIR=alpha;
-	# Support 128-bit long double, changeable via command-line switch.
-	HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
-	;;
+. ${srcdir}/configure.host
 
-  arm*-*-*)
-	TARGET=ARM; TARGETDIR=arm
-	;;
-
-  amd64-*-freebsd* | amd64-*-openbsd*)
-	TARGET=X86_64; TARGETDIR=x86
-  	;;
-
-  amd64-*-freebsd*)
-	TARGET=X86_64; TARGETDIR=x86
-	;;
-
-  avr32*-*-*)
-	TARGET=AVR32; TARGETDIR=avr32
-	;;
-
-  bfin*)
-  	TARGET=BFIN; TARGETDIR=bfin
-  	;;
-
-  cris-*-*)
-	TARGET=LIBFFI_CRIS; TARGETDIR=cris
-	;;
-
-  frv-*-*)
-	TARGET=FRV; TARGETDIR=frv
-	;;
-
-  hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
-	TARGET=PA_LINUX; TARGETDIR=pa
-	;;
-  hppa*64-*-hpux*)
-	TARGET=PA64_HPUX; TARGETDIR=pa
-	;;
-  hppa*-*-hpux*)
-	TARGET=PA_HPUX; TARGETDIR=pa
-	;;
-
-  i?86-*-freebsd* | i?86-*-openbsd*)
-	TARGET=X86_FREEBSD; TARGETDIR=x86
-	;;
-  i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix*)
-	TARGET=X86_WIN32; TARGETDIR=x86
-	# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
-	# We must also check with_cross_host to decide if this is a native
-	# or cross-build and select where to install dlls appropriately.
-	if test -n "$with_cross_host" &&
-	   test x"$with_cross_host" != x"no"; then
-	  AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
-	else
-	  AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
-	fi
-	;;
-  i?86-*-darwin*)
-	TARGET=X86_DARWIN; TARGETDIR=x86
-	;;
-  i?86-*-solaris2.1[0-9]*)
-	TARGET=X86_64; TARGETDIR=x86
-	;;
-  i?86-*-*)
-	TARGET=X86_64; TARGETDIR=x86
-	;;
-
-  ia64*-*-*)
-	TARGET=IA64; TARGETDIR=ia64
-	;;
-
-  m32r*-*-*)
-	TARGET=M32R; TARGETDIR=m32r
-	;;
-
-  m68k-*-*)
-	TARGET=M68K; TARGETDIR=m68k
-	;;
-
-  mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
-	TARGET=MIPS; TARGETDIR=mips
-	;;
-  mips*-*-linux* | mips*-*-openbsd*)
-	# Support 128-bit long double for NewABI.
-	HAVE_LONG_DOUBLE='defined(__mips64)'
-	TARGET=MIPS; TARGETDIR=mips
-	;;
-
-  powerpc*-*-linux* | powerpc-*-sysv*)
-	TARGET=POWERPC; TARGETDIR=powerpc
-	HAVE_LONG_DOUBLE_VARIANT=1
-	;;
-  powerpc-*-amigaos*)
-	TARGET=POWERPC; TARGETDIR=powerpc
-	;;
-  powerpc-*-beos*)
-	TARGET=POWERPC; TARGETDIR=powerpc
-	;;
-  powerpc-*-darwin* | powerpc64-*-darwin*)
-	TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
-	;;
-  powerpc-*-aix* | rs6000-*-aix*)
-	TARGET=POWERPC_AIX; TARGETDIR=powerpc
-	;;
-  powerpc-*-freebsd* | powerpc-*-openbsd*)
-	TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
-	HAVE_LONG_DOUBLE_VARIANT=1
-	;;
-  powerpc64-*-freebsd*)
-	TARGET=POWERPC; TARGETDIR=powerpc
-	;;
-  powerpc*-*-rtems*)
-	TARGET=POWERPC; TARGETDIR=powerpc
-	;;
-
-  s390-*-* | s390x-*-*)
-	TARGET=S390; TARGETDIR=s390
-	;;
-
-  sh-*-* | sh[34]*-*-*)
-	TARGET=SH; TARGETDIR=sh
-	;;
-  sh64-*-* | sh5*-*-*)
-	TARGET=SH64; TARGETDIR=sh64
-	;;
-
-  sparc*-*-*)
-	TARGET=SPARC; TARGETDIR=sparc
-	;;
-
-  tile*-*)
-        TARGET=TILE; TARGETDIR=tile
-        ;;
-
-  x86_64-*-darwin*)
-	TARGET=X86_DARWIN; TARGETDIR=x86
-	;;
-
-  x86_64-*-cygwin* | x86_64-*-mingw*)
-	TARGET=X86_WIN64; TARGETDIR=x86
-	# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
-	# We must also check with_cross_host to decide if this is a native
-	# or cross-build and select where to install dlls appropriately.
-	if test -n "$with_cross_host" &&
-	   test x"$with_cross_host" != x"no"; then
-	  AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
-	else
-	  AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
-	fi
-	;;
-
-  x86_64-*-*)
-	TARGET=X86_64; TARGETDIR=x86
-	;;
-esac
-
-
-
-
-if test $TARGETDIR = unknown; then
+if test -n "${UNSUPPORTED}"; then
   as_fn_error "\"libffi has not been ported to $host.\"" "$LINENO" 5
 fi
 
- if test x$TARGET = xMIPS; then
-  MIPS_TRUE=
-  MIPS_FALSE='#'
-else
-  MIPS_TRUE='#'
-  MIPS_FALSE=
-fi
 
- if test x$TARGET = xBFIN; then
-  BFIN_TRUE=
-  BFIN_FALSE='#'
-else
-  BFIN_TRUE='#'
-  BFIN_FALSE=
-fi
-
- if test x$TARGET = xSPARC; then
-  SPARC_TRUE=
-  SPARC_FALSE='#'
-else
-  SPARC_TRUE='#'
-  SPARC_FALSE=
-fi
-
- if test x$TARGET = xX86; then
-  X86_TRUE=
-  X86_FALSE='#'
-else
-  X86_TRUE='#'
-  X86_FALSE=
-fi
-
- if test x$TARGET = xX86_FREEBSD; then
-  X86_FREEBSD_TRUE=
-  X86_FREEBSD_FALSE='#'
-else
-  X86_FREEBSD_TRUE='#'
-  X86_FREEBSD_FALSE=
-fi
-
- if test x$TARGET = xX86_WIN32; then
-  X86_WIN32_TRUE=
-  X86_WIN32_FALSE='#'
-else
-  X86_WIN32_TRUE='#'
-  X86_WIN32_FALSE=
-fi
-
- if test x$TARGET = xX86_WIN64; then
-  X86_WIN64_TRUE=
-  X86_WIN64_FALSE='#'
-else
-  X86_WIN64_TRUE='#'
-  X86_WIN64_FALSE=
-fi
-
- if test x$TARGET = xX86_DARWIN; then
-  X86_DARWIN_TRUE=
-  X86_DARWIN_FALSE='#'
-else
-  X86_DARWIN_TRUE='#'
-  X86_DARWIN_FALSE=
-fi
-
- if test x$TARGET = xALPHA; then
-  ALPHA_TRUE=
-  ALPHA_FALSE='#'
-else
-  ALPHA_TRUE='#'
-  ALPHA_FALSE=
-fi
-
- if test x$TARGET = xIA64; then
-  IA64_TRUE=
-  IA64_FALSE='#'
-else
-  IA64_TRUE='#'
-  IA64_FALSE=
-fi
-
- if test x$TARGET = xM32R; then
-  M32R_TRUE=
-  M32R_FALSE='#'
-else
-  M32R_TRUE='#'
-  M32R_FALSE=
-fi
-
- if test x$TARGET = xM68K; then
-  M68K_TRUE=
-  M68K_FALSE='#'
-else
-  M68K_TRUE='#'
-  M68K_FALSE=
-fi
-
- if test x$TARGET = xPOWERPC; then
-  POWERPC_TRUE=
-  POWERPC_FALSE='#'
-else
-  POWERPC_TRUE='#'
-  POWERPC_FALSE=
-fi
-
- if test x$TARGET = xPOWERPC_AIX; then
-  POWERPC_AIX_TRUE=
-  POWERPC_AIX_FALSE='#'
-else
-  POWERPC_AIX_TRUE='#'
-  POWERPC_AIX_FALSE=
-fi
-
- if test x$TARGET = xPOWERPC_DARWIN; then
-  POWERPC_DARWIN_TRUE=
-  POWERPC_DARWIN_FALSE='#'
-else
-  POWERPC_DARWIN_TRUE='#'
-  POWERPC_DARWIN_FALSE=
-fi
-
- if test x$TARGET = xPOWERPC_FREEBSD; then
-  POWERPC_FREEBSD_TRUE=
-  POWERPC_FREEBSD_FALSE='#'
-else
-  POWERPC_FREEBSD_TRUE='#'
-  POWERPC_FREEBSD_FALSE=
-fi
-
- if test x$TARGET = xAARCH64; then
-  AARCH64_TRUE=
-  AARCH64_FALSE='#'
-else
-  AARCH64_TRUE='#'
-  AARCH64_FALSE=
-fi
-
- if test x$TARGET = xARM; then
-  ARM_TRUE=
-  ARM_FALSE='#'
-else
-  ARM_TRUE='#'
-  ARM_FALSE=
-fi
-
- if test x$TARGET = xAVR32; then
-  AVR32_TRUE=
-  AVR32_FALSE='#'
-else
-  AVR32_TRUE='#'
-  AVR32_FALSE=
-fi
-
- if test x$TARGET = xLIBFFI_CRIS; then
-  LIBFFI_CRIS_TRUE=
-  LIBFFI_CRIS_FALSE='#'
-else
-  LIBFFI_CRIS_TRUE='#'
-  LIBFFI_CRIS_FALSE=
-fi
-
- if test x$TARGET = xFRV; then
-  FRV_TRUE=
-  FRV_FALSE='#'
-else
-  FRV_TRUE='#'
-  FRV_FALSE=
-fi
-
- if test x$TARGET = xS390; then
-  S390_TRUE=
-  S390_FALSE='#'
-else
-  S390_TRUE='#'
-  S390_FALSE=
-fi
-
- if test x$TARGET = xX86_64; then
-  X86_64_TRUE=
-  X86_64_FALSE='#'
-else
-  X86_64_TRUE='#'
-  X86_64_FALSE=
-fi
-
- if test x$TARGET = xSH; then
-  SH_TRUE=
-  SH_FALSE='#'
-else
-  SH_TRUE='#'
-  SH_FALSE=
-fi
-
- if test x$TARGET = xSH64; then
-  SH64_TRUE=
-  SH64_FALSE='#'
-else
-  SH64_TRUE='#'
-  SH64_FALSE=
-fi
-
- if test x$TARGET = xPA_LINUX; then
-  PA_LINUX_TRUE=
-  PA_LINUX_FALSE='#'
-else
-  PA_LINUX_TRUE='#'
-  PA_LINUX_FALSE=
-fi
-
- if test x$TARGET = xPA_HPUX; then
-  PA_HPUX_TRUE=
-  PA_HPUX_FALSE='#'
-else
-  PA_HPUX_TRUE='#'
-  PA_HPUX_FALSE=
-fi
-
- if test x$TARGET = xPA64_HPUX; then
-  PA64_HPUX_TRUE=
-  PA64_HPUX_FALSE='#'
-else
-  PA64_HPUX_TRUE='#'
-  PA64_HPUX_FALSE=
-fi
-
- if test x$TARGET = xTILE; then
-  TILE_TRUE=
-  TILE_FALSE='#'
-else
-  TILE_TRUE='#'
-  TILE_FALSE=
-fi
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
@@ -12519,28 +15643,6 @@
  fi
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -Qunused-arguments" >&5
-$as_echo_n "checking if compiler supports -Qunused-arguments... " >&6; }
-if test "${libffi_cv_c_unused_arguments+set}" = set; then :
-  $as_echo_n "(cached) " >&6
-else
-  CFLAGS_hold=$CFLAGS
-CFLAGS="$CFLAGS -Qunused-arguments"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-int i;
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  libffi_cv_c_unused_arguments=yes
-else
-  libffi_cv_c_unused_arguments=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-CFLAGS=$CFLAGS_hold
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_c_unused_arguments" >&5
-$as_echo "$libffi_cv_c_unused_arguments" >&6; }
-
 if test x$TARGET = xSPARC; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler and linker support unaligned pc related relocs" >&5
 $as_echo_n "checking assembler and linker support unaligned pc related relocs... " >&6; }
@@ -12591,11 +15693,11 @@
        # Check if we have .register
        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-asm (".register %g2, #scratch");
+
 int
 main ()
 {
-
+asm (".register %g2, #scratch");
   ;
   return 0;
 }
@@ -12624,16 +15726,11 @@
   $as_echo_n "(cached) " >&6
 else
 
-	libffi_cv_as_x86_pcrel=yes
+	libffi_cv_as_x86_pcrel=no
 	echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
-	CFLAGS_hold=$CFLAGS
-	if test "$libffi_cv_c_unused_arguments" = yes; then
-	    CFLAGS="$CFLAGS -Qunused-arguments"
+	if $CC $CFLAGS -c conftest.s > /dev/null 2>&1; then
+	    libffi_cv_as_x86_pcrel=yes
 	fi
-	if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
-	    libffi_cv_as_x86_pcrel=no
-	fi
-	CFLAGS=$CFLAGS_hold
 
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_x86_pcrel" >&5
@@ -12654,11 +15751,11 @@
        # Check if we have .ascii
        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-asm (".ascii \\"string\\"");
+
 int
 main ()
 {
-
+asm (".ascii \\"string\\"");
   ;
   return 0;
 }
@@ -12689,11 +15786,11 @@
        # Check if we have .string
        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-asm (".string \\"string\\"");
+
 int
 main ()
 {
-
+asm (".string \\"string\\"");
   ;
   return 0;
 }
@@ -12715,6 +15812,31 @@
     fi
 fi
 
+if test x$TARGET = xS390; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking compiler uses zarch features" >&5
+$as_echo_n "checking compiler uses zarch features... " >&6; }
+if test "${libffi_cv_as_s390_zarch+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+	libffi_cv_as_s390_zarch=no
+	echo 'void foo(void) { bar(); bar(); }' > conftest.c
+	if $CC $CFLAGS -S conftest.c > /dev/null 2>&1; then
+	    if grep -q brasl conftest.s; then
+	        libffi_cv_as_s390_zarch=yes
+	    fi
+	fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_s390_zarch" >&5
+$as_echo "$libffi_cv_as_s390_zarch" >&6; }
+    if test "x$libffi_cv_as_s390_zarch" = xyes; then
+
+$as_echo "#define HAVE_AS_S390_ZARCH 1" >>confdefs.h
+
+    fi
+fi
+
 # On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC.
 # Check whether --enable-pax_emutramp was given.
 if test "${enable_pax_emutramp+set}" = set; then :
@@ -12751,22 +15873,33 @@
 
 
 if test x$TARGET = xX86_64; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler supports unwind section type" >&5
-$as_echo_n "checking assembler supports unwind section type... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking toolchain supports unwind section type" >&5
+$as_echo_n "checking toolchain supports unwind section type... " >&6; }
 if test "${libffi_cv_as_x86_64_unwind_section_type+set}" = set; then :
   $as_echo_n "(cached) " >&6
 else
 
-	libffi_cv_as_x86_64_unwind_section_type=yes
-	echo '.section .eh_frame,"a",@unwind' > conftest.s
-	CFLAGS_hold=$CFLAGS
-	if test "$libffi_cv_c_unused_arguments" = yes; then
-	    CFLAGS="$CFLAGS -Qunused-arguments"
+        cat  > conftest1.s << EOF
+.text
+.globl foo
+foo:
+jmp bar
+.section .eh_frame,"a",@unwind
+bar:
+EOF
+
+        cat > conftest2.c  << EOF
+extern void foo();
+int main(){foo();}
+EOF
+
+	libffi_cv_as_x86_64_unwind_section_type=no
+	# we ensure that we can compile _and_ link an assembly file containing an @unwind section
+	# since the compiler can support it and not the linker (ie old binutils)
+	if $CC -Wa,--fatal-warnings $CFLAGS -c conftest1.s > /dev/null 2>&1 && \
+           $CC conftest2.c conftest1.o > /dev/null 2>&1 ; then
+	    libffi_cv_as_x86_64_unwind_section_type=yes
 	fi
-	if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
-	    libffi_cv_as_x86_64_unwind_section_type=no
-	fi
-	CFLAGS=$CFLAGS_hold
 
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_x86_64_unwind_section_type" >&5
@@ -12787,13 +15920,16 @@
 
   	libffi_cv_ro_eh_frame=no
   	echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
-  	if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
-  	    if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
-  		libffi_cv_ro_eh_frame=yes
-  	    elif grep '.section.*eh_frame.*#alloc' conftest.c \
-  		 | grep -v '#write' > /dev/null; then
-  		libffi_cv_ro_eh_frame=yes
-  	    fi
+  	if $CC $CFLAGS -c -fpic -fexceptions -o conftest.o conftest.c > /dev/null 2>&1; then
+	    objdump -h conftest.o > conftest.dump 2>&1
+	    libffi_eh_frame_line=`grep -n eh_frame conftest.dump | cut -d: -f 1`
+	    if test "x$libffi_eh_frame_line" != "x"; then
+	        libffi_test_line=`expr $libffi_eh_frame_line + 1`p
+	        sed -n $libffi_test_line conftest.dump > conftest.line
+	        if grep READONLY conftest.line > /dev/null; then
+	            libffi_cv_ro_eh_frame=yes
+	        fi
+	    fi
   	fi
   	rm -f conftest.*
 
@@ -12849,6 +15985,14 @@
 
 
 
+TARGET_OBJ=
+for i in $SOURCES; do
+  TARGET_OBJ="${TARGET_OBJ} src/${TARGETDIR}/"`echo $i | sed 's/[cS]$/lo/'`
+done
+
+
+
+
 
 # Check whether --enable-debug was given.
 if test "${enable_debug+set}" = set; then :
@@ -12877,6 +16021,14 @@
   fi
 fi
 
+ if test "$enable_debug" = "yes"; then
+  FFI_DEBUG_TRUE=
+  FFI_DEBUG_FALSE='#'
+else
+  FFI_DEBUG_TRUE='#'
+  FFI_DEBUG_FALSE=
+fi
+
 
 # Check whether --enable-raw-api was given.
 if test "${enable_raw_api+set}" = set; then :
@@ -12928,7 +16080,7 @@
 ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETDIR/ffitarget.h"
 
 
-ac_config_files="$ac_config_files include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile"
+ac_config_files="$ac_config_files include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc"
 
 
 cat >confcache <<\_ACEOF
@@ -13052,6 +16204,10 @@
   as_fn_error "conditional \"am__fastdepCC\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+  as_fn_error "conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then
   as_fn_error "conditional \"am__fastdepCCAS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -13064,122 +16220,6 @@
   as_fn_error "conditional \"TESTSUBDIR\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${MIPS_TRUE}" && test -z "${MIPS_FALSE}"; then
-  as_fn_error "conditional \"MIPS\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${BFIN_TRUE}" && test -z "${BFIN_FALSE}"; then
-  as_fn_error "conditional \"BFIN\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${SPARC_TRUE}" && test -z "${SPARC_FALSE}"; then
-  as_fn_error "conditional \"SPARC\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${X86_TRUE}" && test -z "${X86_FALSE}"; then
-  as_fn_error "conditional \"X86\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${X86_FREEBSD_TRUE}" && test -z "${X86_FREEBSD_FALSE}"; then
-  as_fn_error "conditional \"X86_FREEBSD\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${X86_WIN32_TRUE}" && test -z "${X86_WIN32_FALSE}"; then
-  as_fn_error "conditional \"X86_WIN32\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${X86_WIN64_TRUE}" && test -z "${X86_WIN64_FALSE}"; then
-  as_fn_error "conditional \"X86_WIN64\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${X86_DARWIN_TRUE}" && test -z "${X86_DARWIN_FALSE}"; then
-  as_fn_error "conditional \"X86_DARWIN\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${ALPHA_TRUE}" && test -z "${ALPHA_FALSE}"; then
-  as_fn_error "conditional \"ALPHA\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${IA64_TRUE}" && test -z "${IA64_FALSE}"; then
-  as_fn_error "conditional \"IA64\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${M32R_TRUE}" && test -z "${M32R_FALSE}"; then
-  as_fn_error "conditional \"M32R\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${M68K_TRUE}" && test -z "${M68K_FALSE}"; then
-  as_fn_error "conditional \"M68K\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${POWERPC_TRUE}" && test -z "${POWERPC_FALSE}"; then
-  as_fn_error "conditional \"POWERPC\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${POWERPC_AIX_TRUE}" && test -z "${POWERPC_AIX_FALSE}"; then
-  as_fn_error "conditional \"POWERPC_AIX\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${POWERPC_DARWIN_TRUE}" && test -z "${POWERPC_DARWIN_FALSE}"; then
-  as_fn_error "conditional \"POWERPC_DARWIN\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${POWERPC_FREEBSD_TRUE}" && test -z "${POWERPC_FREEBSD_FALSE}"; then
-  as_fn_error "conditional \"POWERPC_FREEBSD\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${AARCH64_TRUE}" && test -z "${AARCH64_FALSE}"; then
-  as_fn_error "conditional \"AARCH64\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${ARM_TRUE}" && test -z "${ARM_FALSE}"; then
-  as_fn_error "conditional \"ARM\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${AVR32_TRUE}" && test -z "${AVR32_FALSE}"; then
-  as_fn_error "conditional \"AVR32\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${LIBFFI_CRIS_TRUE}" && test -z "${LIBFFI_CRIS_FALSE}"; then
-  as_fn_error "conditional \"LIBFFI_CRIS\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${FRV_TRUE}" && test -z "${FRV_FALSE}"; then
-  as_fn_error "conditional \"FRV\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${S390_TRUE}" && test -z "${S390_FALSE}"; then
-  as_fn_error "conditional \"S390\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${X86_64_TRUE}" && test -z "${X86_64_FALSE}"; then
-  as_fn_error "conditional \"X86_64\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${SH_TRUE}" && test -z "${SH_FALSE}"; then
-  as_fn_error "conditional \"SH\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${SH64_TRUE}" && test -z "${SH64_FALSE}"; then
-  as_fn_error "conditional \"SH64\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${PA_LINUX_TRUE}" && test -z "${PA_LINUX_FALSE}"; then
-  as_fn_error "conditional \"PA_LINUX\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${PA_HPUX_TRUE}" && test -z "${PA_HPUX_FALSE}"; then
-  as_fn_error "conditional \"PA_HPUX\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${PA64_HPUX_TRUE}" && test -z "${PA64_HPUX_FALSE}"; then
-  as_fn_error "conditional \"PA64_HPUX\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${TILE_TRUE}" && test -z "${TILE_FALSE}"; then
-  as_fn_error "conditional \"TILE\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
 
 if test -z "${FFI_EXEC_TRAMPOLINE_TABLE_TRUE}" && test -z "${FFI_EXEC_TRAMPOLINE_TABLE_FALSE}"; then
   as_fn_error "conditional \"FFI_EXEC_TRAMPOLINE_TABLE\" was never defined.
@@ -13189,6 +16229,10 @@
   as_fn_error "conditional \"FFI_DEBUG\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${FFI_DEBUG_TRUE}" && test -z "${FFI_DEBUG_FALSE}"; then
+  as_fn_error "conditional \"FFI_DEBUG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 
 : ${CONFIG_STATUS=./config.status}
 ac_write_fail=0
@@ -13597,7 +16641,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by libffi $as_me 3.0.11, which was
+This file was extended by libffi $as_me 3.99999, which was
 generated by GNU Autoconf 2.64.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -13660,12 +16704,12 @@
 Configuration commands:
 $config_commands
 
-Report bugs to <http://gcc.gnu.org/bugs.html>."
+Report bugs to <http://github.com/atgreen/libffi/issues>."
 
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_version="\\
-libffi config.status 3.0.11
+libffi config.status 3.99999
 configured by $0, generated by GNU Autoconf 2.64,
   with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
@@ -13920,6 +16964,61 @@
 enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
 old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
 striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`'
+predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`'
+postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`'
+predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`'
+postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`'
+LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`'
+reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`'
+reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`'
+GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld_CXX='`$ECHO "$hardcode_libdir_flag_spec_ld_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`'
+inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`'
+fix_srcfile_path_CXX='`$ECHO "$fix_srcfile_path_CXX" | $SED "$delay_single_quote_subst"`'
+always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
+include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
+prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`'
+predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`'
+postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`'
+predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`'
+postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`'
 
 LTCC='$LTCC'
 LTCFLAGS='$LTCFLAGS'
@@ -13992,7 +17091,40 @@
 install_override_mode \
 finish_eval \
 old_striplib \
-striplib; do
+striplib \
+compiler_lib_search_dirs \
+predep_objects \
+postdep_objects \
+predeps \
+postdeps \
+compiler_lib_search_path \
+LD_CXX \
+reload_flag_CXX \
+compiler_CXX \
+lt_prog_compiler_no_builtin_flag_CXX \
+lt_prog_compiler_wl_CXX \
+lt_prog_compiler_pic_CXX \
+lt_prog_compiler_static_CXX \
+lt_cv_prog_compiler_c_o_CXX \
+export_dynamic_flag_spec_CXX \
+whole_archive_flag_spec_CXX \
+compiler_needs_object_CXX \
+with_gnu_ld_CXX \
+allow_undefined_flag_CXX \
+no_undefined_flag_CXX \
+hardcode_libdir_flag_spec_CXX \
+hardcode_libdir_flag_spec_ld_CXX \
+hardcode_libdir_separator_CXX \
+fix_srcfile_path_CXX \
+exclude_expsyms_CXX \
+include_expsyms_CXX \
+file_list_spec_CXX \
+compiler_lib_search_dirs_CXX \
+predep_objects_CXX \
+postdep_objects_CXX \
+predeps_CXX \
+postdeps_CXX \
+compiler_lib_search_path_CXX; do
     case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
     *[\\\\\\\`\\"\\\$]*)
       eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
@@ -14021,7 +17153,17 @@
 postuninstall_cmds \
 finish_cmds \
 sys_lib_search_path_spec \
-sys_lib_dlsearch_path_spec; do
+sys_lib_dlsearch_path_spec \
+reload_cmds_CXX \
+old_archive_cmds_CXX \
+old_archive_from_new_cmds_CXX \
+old_archive_from_expsyms_cmds_CXX \
+archive_cmds_CXX \
+archive_expsym_cmds_CXX \
+module_cmds_CXX \
+module_expsym_cmds_CXX \
+export_symbols_cmds_CXX \
+prelink_cmds_CXX; do
     case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
     *[\\\\\\\`\\"\\\$]*)
       eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
@@ -14051,6 +17193,8 @@
 
 
 
+
+
 TARGETDIR="$TARGETDIR"
 
 _ACEOF
@@ -14073,6 +17217,7 @@
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     "testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;;
     "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
+    "libffi.pc") CONFIG_FILES="$CONFIG_FILES libffi.pc" ;;
 
   *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
@@ -14841,7 +17986,7 @@
 
 
 # The names of the tagged configurations supported by this script.
-available_tags=""
+available_tags="CXX "
 
 # ### BEGIN LIBTOOL CONFIG
 
@@ -15197,6 +18342,20 @@
 # How to hardcode a shared library path into an executable.
 hardcode_action=$hardcode_action
 
+# The directories searched by this compiler when creating a shared library.
+compiler_lib_search_dirs=$lt_compiler_lib_search_dirs
+
+# Dependencies to place before and after the objects being linked to
+# create a shared library.
+predep_objects=$lt_predep_objects
+postdep_objects=$lt_postdep_objects
+predeps=$lt_predeps
+postdeps=$lt_postdeps
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path
+
 # ### END LIBTOOL CONFIG
 
 _LT_EOF
@@ -15430,6 +18589,163 @@
     (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
   chmod +x "$ofile"
 
+
+    cat <<_LT_EOF >> "$ofile"
+
+# ### BEGIN LIBTOOL TAG CONFIG: CXX
+
+# The linker used to build libraries.
+LD=$lt_LD_CXX
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag_CXX
+reload_cmds=$lt_reload_cmds_CXX
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds_CXX
+
+# A language specific compiler.
+CC=$lt_compiler_CXX
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC_CXX
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_CXX
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_CXX
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_CXX
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object_CXX
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds_CXX
+archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds_CXX
+module_expsym_cmds=$lt_module_expsym_cmds_CXX
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld_CXX
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_CXX
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_CXX
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking.  This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct_CXX
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute_CXX
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L_CXX
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic_CXX
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath_CXX
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_CXX
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path_CXX
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols_CXX
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_CXX
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_CXX
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_CXX
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds_CXX
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec_CXX
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_CXX
+
+# The directories searched by this compiler when creating a shared library.
+compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX
+
+# Dependencies to place before and after the objects being linked to
+# create a shared library.
+predep_objects=$lt_predep_objects_CXX
+postdep_objects=$lt_postdep_objects_CXX
+predeps=$lt_predeps_CXX
+postdeps=$lt_postdeps_CXX
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
+
+# ### END LIBTOOL TAG CONFIG: CXX
+_LT_EOF
+
  ;;
     "include":C) test -d include || mkdir include ;;
     "src":C)
diff --git a/third_party/gofrontend/libffi/configure.ac b/third_party/gofrontend/libffi/configure.ac
index 97d2641..07ec10d 100644
--- a/third_party/gofrontend/libffi/configure.ac
+++ b/third_party/gofrontend/libffi/configure.ac
@@ -2,7 +2,7 @@
 
 AC_PREREQ(2.64)
 
-AC_INIT([libffi], [3.0.11], [http://gcc.gnu.org/bugs.html])
+AC_INIT([libffi], [3.99999], [http://github.com/atgreen/libffi/issues])
 AC_CONFIG_HEADERS([fficonfig.h])
 
 AM_ENABLE_MULTILIB(, ..)
@@ -10,8 +10,6 @@
 AC_CANONICAL_SYSTEM
 target_alias=${target_alias-$host_alias}
 
-. ${srcdir}/configure.host
-
 AM_INIT_AUTOMAKE([no-dist])
 
 # See if makeinfo has been installed and is modern enough
@@ -43,10 +41,16 @@
 # We must force CC to /not/ be precious variables; otherwise
 # the wrong, non-multilib-adjusted value will be used in multilibs.
 # As a side effect, we have to subst CFLAGS ourselves.
+# Also save and restore CFLAGS, since AC_PROG_CC will come up with
+# defaults of its own if none are provided.
 
 m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
 m4_define([_AC_ARG_VAR_PRECIOUS],[])
+save_CFLAGS=$CFLAGS
 AC_PROG_CC
+AC_PROG_CXX
+CFLAGS=$save_CFLAGS
+m4_undefine([_AC_ARG_VAR_PRECIOUS])
 m4_rename_force([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
 
 AC_SUBST(CFLAGS)
@@ -55,10 +59,13 @@
 AM_PROG_CC_C_O
 AC_PROG_LIBTOOL
 
+# Test for 64-bit build.
+AC_CHECK_SIZEOF([size_t])
+
 AM_MAINTAINER_MODE
 
 AC_CHECK_HEADERS(sys/mman.h)
-AC_CHECK_FUNCS(mmap)
+AC_CHECK_FUNCS([mmap mkostemp])
 AC_FUNC_MMAP_BLACKLIST
 
 dnl The -no-testsuite modules omit the test subdir.
@@ -66,205 +73,15 @@
 
 TARGETDIR="unknown"
 HAVE_LONG_DOUBLE_VARIANT=0
-case "$host" in
-  aarch64*-*-*)
-	TARGET=AARCH64; TARGETDIR=aarch64
-	;;
 
-  alpha*-*-*)
-	TARGET=ALPHA; TARGETDIR=alpha;
-	# Support 128-bit long double, changeable via command-line switch.
-	HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
-	;;
+. ${srcdir}/configure.host
 
-  arm*-*-*)
-	TARGET=ARM; TARGETDIR=arm
-	;;
-
-  amd64-*-freebsd* | amd64-*-openbsd*)
-	TARGET=X86_64; TARGETDIR=x86
-  	;;
-
-  amd64-*-freebsd*)
-	TARGET=X86_64; TARGETDIR=x86
-	;;
-
-  avr32*-*-*)
-	TARGET=AVR32; TARGETDIR=avr32
-	;;
-
-  bfin*)
-  	TARGET=BFIN; TARGETDIR=bfin
-  	;;
-
-  cris-*-*)
-	TARGET=LIBFFI_CRIS; TARGETDIR=cris
-	;;
-
-  frv-*-*)
-	TARGET=FRV; TARGETDIR=frv
-	;;
-
-  hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
-	TARGET=PA_LINUX; TARGETDIR=pa
-	;;
-  hppa*64-*-hpux*)
-	TARGET=PA64_HPUX; TARGETDIR=pa
-	;;
-  hppa*-*-hpux*)
-	TARGET=PA_HPUX; TARGETDIR=pa
-	;;
-
-  i?86-*-freebsd* | i?86-*-openbsd*)
-	TARGET=X86_FREEBSD; TARGETDIR=x86
-	;;
-  i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix*)
-	TARGET=X86_WIN32; TARGETDIR=x86
-	# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
-	# We must also check with_cross_host to decide if this is a native
-	# or cross-build and select where to install dlls appropriately.
-	if test -n "$with_cross_host" &&
-	   test x"$with_cross_host" != x"no"; then
-	  AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
-	else
-	  AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
-	fi
-	;;
-  i?86-*-darwin*)
-	TARGET=X86_DARWIN; TARGETDIR=x86
-	;;
-  i?86-*-solaris2.1[[0-9]]*)
-	TARGET=X86_64; TARGETDIR=x86
-	;;
-  i?86-*-*)
-	TARGET=X86_64; TARGETDIR=x86
-	;;
-
-  ia64*-*-*)
-	TARGET=IA64; TARGETDIR=ia64
-	;;
-
-  m32r*-*-*)
-	TARGET=M32R; TARGETDIR=m32r
-	;;
-
-  m68k-*-*)
-	TARGET=M68K; TARGETDIR=m68k
-	;;
-
-  mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
-	TARGET=MIPS; TARGETDIR=mips
-	;;
-  mips*-*-linux* | mips*-*-openbsd*)
-	# Support 128-bit long double for NewABI.
-	HAVE_LONG_DOUBLE='defined(__mips64)'
-	TARGET=MIPS; TARGETDIR=mips
-	;;
-
-  powerpc*-*-linux* | powerpc-*-sysv*)
-	TARGET=POWERPC; TARGETDIR=powerpc
-	HAVE_LONG_DOUBLE_VARIANT=1
-	;;
-  powerpc-*-amigaos*)
-	TARGET=POWERPC; TARGETDIR=powerpc
-	;;
-  powerpc-*-beos*)
-	TARGET=POWERPC; TARGETDIR=powerpc
-	;;
-  powerpc-*-darwin* | powerpc64-*-darwin*)
-	TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
-	;;
-  powerpc-*-aix* | rs6000-*-aix*)
-	TARGET=POWERPC_AIX; TARGETDIR=powerpc
-	;;
-  powerpc-*-freebsd* | powerpc-*-openbsd*)
-	TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
-	HAVE_LONG_DOUBLE_VARIANT=1
-	;;
-  powerpc64-*-freebsd*)
-	TARGET=POWERPC; TARGETDIR=powerpc
-	;;
-  powerpc*-*-rtems*)
-	TARGET=POWERPC; TARGETDIR=powerpc
-	;;
-
-  s390-*-* | s390x-*-*)
-	TARGET=S390; TARGETDIR=s390
-	;;
-
-  sh-*-* | sh[[34]]*-*-*)
-	TARGET=SH; TARGETDIR=sh
-	;;
-  sh64-*-* | sh5*-*-*)
-	TARGET=SH64; TARGETDIR=sh64
-	;;
-
-  sparc*-*-*)
-	TARGET=SPARC; TARGETDIR=sparc
-	;;
-
-  tile*-*)
-        TARGET=TILE; TARGETDIR=tile
-        ;;
-
-  x86_64-*-darwin*)
-	TARGET=X86_DARWIN; TARGETDIR=x86
-	;;
-
-  x86_64-*-cygwin* | x86_64-*-mingw*)
-	TARGET=X86_WIN64; TARGETDIR=x86
-	# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
-	# We must also check with_cross_host to decide if this is a native
-	# or cross-build and select where to install dlls appropriately.
-	if test -n "$with_cross_host" &&
-	   test x"$with_cross_host" != x"no"; then
-	  AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
-	else
-	  AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
-	fi
-	;;
-
-  x86_64-*-*)
-	TARGET=X86_64; TARGETDIR=x86
-	;;
-esac
-
-AC_SUBST(AM_RUNTESTFLAGS)
-AC_SUBST(AM_LTLDFLAGS)
-
-if test $TARGETDIR = unknown; then
+if test -n "${UNSUPPORTED}"; then
   AC_MSG_ERROR(["libffi has not been ported to $host."])
 fi
 
-AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS)
-AM_CONDITIONAL(BFIN, test x$TARGET = xBFIN)
-AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
-AM_CONDITIONAL(X86, test x$TARGET = xX86)
-AM_CONDITIONAL(X86_FREEBSD, test x$TARGET = xX86_FREEBSD)
-AM_CONDITIONAL(X86_WIN32, test x$TARGET = xX86_WIN32)
-AM_CONDITIONAL(X86_WIN64, test x$TARGET = xX86_WIN64)
-AM_CONDITIONAL(X86_DARWIN, test x$TARGET = xX86_DARWIN)
-AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
-AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
-AM_CONDITIONAL(M32R, test x$TARGET = xM32R)
-AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
-AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
-AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
-AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
-AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD)
-AM_CONDITIONAL(AARCH64, test x$TARGET = xAARCH64)
-AM_CONDITIONAL(ARM, test x$TARGET = xARM)
-AM_CONDITIONAL(AVR32, test x$TARGET = xAVR32)
-AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS)
-AM_CONDITIONAL(FRV, test x$TARGET = xFRV)
-AM_CONDITIONAL(S390, test x$TARGET = xS390)
-AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
-AM_CONDITIONAL(SH, test x$TARGET = xSH)
-AM_CONDITIONAL(SH64, test x$TARGET = xSH64)
-AM_CONDITIONAL(PA_LINUX, test x$TARGET = xPA_LINUX)
-AM_CONDITIONAL(PA_HPUX, test x$TARGET = xPA_HPUX)
-AM_CONDITIONAL(PA64_HPUX, test x$TARGET = xPA64_HPUX)
-AM_CONDITIONAL(TILE, test x$TARGET = xTILE)
+AC_SUBST(AM_RUNTESTFLAGS)
+AC_SUBST(AM_LTLDFLAGS)
 
 AC_HEADER_STDC
 AC_CHECK_FUNCS(memcpy)
@@ -295,15 +112,6 @@
 
 GCC_AS_CFI_PSEUDO_OP
 
-AC_CACHE_CHECK([if compiler supports -Qunused-arguments],
-[libffi_cv_c_unused_arguments],
-[CFLAGS_hold=$CFLAGS
-CFLAGS="$CFLAGS -Qunused-arguments"
-AC_COMPILE_IFELSE([[int i;]],
-[libffi_cv_c_unused_arguments=yes],
-[libffi_cv_c_unused_arguments=no])
-CFLAGS=$CFLAGS_hold])
-
 if test x$TARGET = xSPARC; then
     AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
 	libffi_cv_as_sparc_ua_pcrel, [
@@ -325,7 +133,7 @@
        libffi_cv_as_register_pseudo_op, [
        libffi_cv_as_register_pseudo_op=unknown
        # Check if we have .register
-       AC_TRY_COMPILE([asm (".register %g2, #scratch");],,
+       AC_TRY_COMPILE(,[asm (".register %g2, #scratch");],
 		       [libffi_cv_as_register_pseudo_op=yes],
 		       [libffi_cv_as_register_pseudo_op=no])
     ])
@@ -338,16 +146,11 @@
 if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64; then
     AC_CACHE_CHECK([assembler supports pc related relocs],
 	libffi_cv_as_x86_pcrel, [
-	libffi_cv_as_x86_pcrel=yes
+	libffi_cv_as_x86_pcrel=no
 	echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
-	CFLAGS_hold=$CFLAGS
-	if test "$libffi_cv_c_unused_arguments" = yes; then
-	    CFLAGS="$CFLAGS -Qunused-arguments"
+	if $CC $CFLAGS -c conftest.s > /dev/null 2>&1; then
+	    libffi_cv_as_x86_pcrel=yes
 	fi
-	if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
-	    libffi_cv_as_x86_pcrel=no
-	fi
-	CFLAGS=$CFLAGS_hold
 	])
     if test "x$libffi_cv_as_x86_pcrel" = xyes; then
 	AC_DEFINE(HAVE_AS_X86_PCREL, 1,
@@ -358,7 +161,7 @@
        libffi_cv_as_ascii_pseudo_op, [
        libffi_cv_as_ascii_pseudo_op=unknown
        # Check if we have .ascii
-       AC_TRY_COMPILE([asm (".ascii \\"string\\"");],,
+       AC_TRY_COMPILE(,[asm (".ascii \\"string\\"");],
 		       [libffi_cv_as_ascii_pseudo_op=yes],
 		       [libffi_cv_as_ascii_pseudo_op=no])
     ])
@@ -371,7 +174,7 @@
        libffi_cv_as_string_pseudo_op, [
        libffi_cv_as_string_pseudo_op=unknown
        # Check if we have .string
-       AC_TRY_COMPILE([asm (".string \\"string\\"");],,
+       AC_TRY_COMPILE(,[asm (".string \\"string\\"");],
 		       [libffi_cv_as_string_pseudo_op=yes],
 		       [libffi_cv_as_string_pseudo_op=no])
     ])
@@ -381,6 +184,23 @@
     fi
 fi
 
+if test x$TARGET = xS390; then
+    AC_CACHE_CHECK([compiler uses zarch features],
+	libffi_cv_as_s390_zarch, [
+	libffi_cv_as_s390_zarch=no
+	echo 'void foo(void) { bar(); bar(); }' > conftest.c
+	if $CC $CFLAGS -S conftest.c > /dev/null 2>&1; then
+	    if grep -q brasl conftest.s; then
+	        libffi_cv_as_s390_zarch=yes
+	    fi
+	fi
+	])
+    if test "x$libffi_cv_as_s390_zarch" = xyes; then
+	AC_DEFINE(HAVE_AS_S390_ZARCH, 1,
+		  [Define if the compiler uses zarch features.])
+    fi
+fi
+
 # On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC.
 AC_ARG_ENABLE(pax_emutramp,
   [  --enable-pax_emutramp       enable pax emulated trampolines, for we can't use PROT_EXEC],
@@ -407,18 +227,29 @@
 AC_SUBST(FFI_EXEC_TRAMPOLINE_TABLE)
 
 if test x$TARGET = xX86_64; then
-    AC_CACHE_CHECK([assembler supports unwind section type],
+    AC_CACHE_CHECK([toolchain supports unwind section type],
 	libffi_cv_as_x86_64_unwind_section_type, [
-	libffi_cv_as_x86_64_unwind_section_type=yes
-	echo '.section .eh_frame,"a",@unwind' > conftest.s
-	CFLAGS_hold=$CFLAGS
-	if test "$libffi_cv_c_unused_arguments" = yes; then
-	    CFLAGS="$CFLAGS -Qunused-arguments"
+        cat  > conftest1.s << EOF
+.text
+.globl foo
+foo:
+jmp bar
+.section .eh_frame,"a",@unwind
+bar:
+EOF
+
+        cat > conftest2.c  << EOF
+extern void foo();
+int main(){foo();}
+EOF
+
+	libffi_cv_as_x86_64_unwind_section_type=no
+	# we ensure that we can compile _and_ link an assembly file containing an @unwind section
+	# since the compiler can support it and not the linker (ie old binutils)
+	if $CC -Wa,--fatal-warnings $CFLAGS -c conftest1.s > /dev/null 2>&1 && \
+           $CC conftest2.c conftest1.o > /dev/null 2>&1 ; then
+	    libffi_cv_as_x86_64_unwind_section_type=yes
 	fi
-	if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
-	    libffi_cv_as_x86_64_unwind_section_type=no
-	fi
-	CFLAGS=$CFLAGS_hold
 	])
     if test "x$libffi_cv_as_x86_64_unwind_section_type" = xyes; then
 	AC_DEFINE(HAVE_AS_X86_64_UNWIND_SECTION_TYPE, 1,
@@ -431,13 +262,16 @@
       libffi_cv_ro_eh_frame, [
   	libffi_cv_ro_eh_frame=no
   	echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
-  	if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
-  	    if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
-  		libffi_cv_ro_eh_frame=yes
-  	    elif grep '.section.*eh_frame.*#alloc' conftest.c \
-  		 | grep -v '#write' > /dev/null; then
-  		libffi_cv_ro_eh_frame=yes
-  	    fi
+  	if $CC $CFLAGS -c -fpic -fexceptions -o conftest.o conftest.c > /dev/null 2>&1; then
+	    objdump -h conftest.o > conftest.dump 2>&1
+	    libffi_eh_frame_line=`grep -n eh_frame conftest.dump | cut -d: -f 1`
+	    if test "x$libffi_eh_frame_line" != "x"; then
+	        libffi_test_line=`expr $libffi_eh_frame_line + 1`p
+	        sed -n $libffi_test_line conftest.dump > conftest.line
+	        if grep READONLY conftest.line > /dev/null; then
+	            libffi_cv_ro_eh_frame=yes
+	        fi
+	    fi
   	fi
   	rm -f conftest.*
       ])
@@ -487,6 +321,14 @@
 AC_SUBST(TARGET)
 AC_SUBST(TARGETDIR)
 
+changequote(<,>)
+TARGET_OBJ=
+for i in $SOURCES; do
+  TARGET_OBJ="${TARGET_OBJ} src/${TARGETDIR}/"`echo $i | sed 's/[cS]$/lo/'`
+done
+changequote([,])
+AC_SUBST(TARGET_OBJ)
+
 AC_SUBST(SHELL)
 
 AC_ARG_ENABLE(debug,
@@ -499,13 +341,14 @@
 AC_ARG_ENABLE(structs,
 [  --disable-structs       omit code for struct support],
   if test "$enable_structs" = "no"; then
-    AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this is you do not want support for aggregate types.])
+    AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this if you do not want support for aggregate types.])
   fi)
+AM_CONDITIONAL(FFI_DEBUG, test "$enable_debug" = "yes")
 
 AC_ARG_ENABLE(raw-api,
 [  --disable-raw-api       make the raw api unavailable],
   if test "$enable_raw_api" = "no"; then
-    AC_DEFINE(FFI_NO_RAW_API, 1, [Define this is you do not want support for the raw API.])
+    AC_DEFINE(FFI_NO_RAW_API, 1, [Define this if you do not want support for the raw API.])
   fi)
 
 AC_ARG_ENABLE(purify-safety,
@@ -544,6 +387,6 @@
 
 AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
 
-AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile)
+AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc)
 
 AC_OUTPUT
diff --git a/third_party/gofrontend/libffi/configure.host b/third_party/gofrontend/libffi/configure.host
index f52457b..90de638 100644
--- a/third_party/gofrontend/libffi/configure.host
+++ b/third_party/gofrontend/libffi/configure.host
@@ -1,11 +1,265 @@
 # configure.host
 #
 # This shell script handles all host based configuration for libffi.
-# 
+#
 
 # THIS TABLE IS SORTED.  KEEP IT THAT WAY.
+# Most of the time we can define all the variables all at once...
 case "${host}" in
-  frv*-elf)
-    LDFLAGS=`echo $LDFLAGS | sed "s/\-B[^ ]*libgloss\/frv\///"`\ -B`pwd`/../libgloss/frv/
-    ;;
+  aarch64*-*-*)
+	TARGET=AARCH64; TARGETDIR=aarch64
+	SOURCES="ffi.c sysv.S"
+	;;
+
+  alpha*-*-*)
+	TARGET=ALPHA; TARGETDIR=alpha;
+	# Support 128-bit long double, changeable via command-line switch.
+	HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
+	SOURCES="ffi.c osf.S"
+	;;
+
+  arc*-*-*)
+	TARGET=ARC; TARGETDIR=arc
+	SOURCES="ffi.c arcompact.S"
+	;;
+
+  arm*-*-*)
+	TARGET=ARM; TARGETDIR=arm
+	SOURCES="ffi.c sysv.S"
+	;;
+
+  avr32*-*-*)
+	TARGET=AVR32; TARGETDIR=avr32
+	SOURCES="ffi.c sysv.S"
+	;;
+
+  bfin*)
+	TARGET=BFIN; TARGETDIR=bfin
+	SOURCES="ffi.c sysv.S"
+	;;
+
+  cris-*-*)
+	TARGET=LIBFFI_CRIS; TARGETDIR=cris
+	SOURCES="ffi.c sysv.S"
+	;;
+
+  frv-*-*)
+	TARGET=FRV; TARGETDIR=frv
+	SOURCES="ffi.c eabi.S"
+	;;
+
+  hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
+	TARGET=PA_LINUX; TARGETDIR=pa
+	SOURCES="ffi.c linux.S"
+	;;
+  hppa*64-*-hpux*)
+	TARGET=PA64_HPUX; TARGETDIR=pa
+	;;
+  hppa*-*-hpux*)
+	TARGET=PA_HPUX; TARGETDIR=pa
+	SOURCES="ffi.c hpux32.S"
+	;;
+
+  i?86-*-freebsd* | i?86-*-openbsd*)
+	TARGET=X86_FREEBSD; TARGETDIR=x86
+	;;
+
+  i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix* \
+  | x86_64-*-cygwin* | x86_64-*-mingw*)
+	TARGETDIR=x86
+	if test $ac_cv_sizeof_size_t = 4; then
+	  TARGET=X86_WIN32
+	else
+	  TARGET=X86_WIN64
+	fi
+	# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
+	# We must also check with_cross_host to decide if this is a native
+	# or cross-build and select where to install dlls appropriately.
+	if test -n "$with_cross_host" &&
+	   test x"$with_cross_host" != x"no"; then
+	  AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
+	else
+	  AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
+	fi
+	;;
+
+  i?86-*-darwin* | x86_64-*-darwin*)
+	TARGETDIR=x86
+	if test $ac_cv_sizeof_size_t = 4; then
+	  TARGET=X86_DARWIN
+	else
+	  TARGET=X86_64_DARWIN
+	fi
+	;;
+
+  i?86-*-* | x86_64-*-* | amd64-*)
+	TARGETDIR=x86
+	if test $ac_cv_sizeof_size_t = 4; then
+	  case "$host" in
+	    *-gnux32)
+	      TARGET=X86_64
+	      ;;
+	    *)
+	      TARGET=X86
+	      ;;
+          esac
+	else
+	  TARGET=X86_64;
+	fi
+	;;
+
+  ia64*-*-*)
+	TARGET=IA64; TARGETDIR=ia64
+	SOURCES="ffi.c unix.S"
+	;;
+
+  m32r*-*-*)
+	TARGET=M32R; TARGETDIR=m32r
+	SOURCES="ffi.c sysv.S"
+	;;
+
+  m68k-*-*)
+	TARGET=M68K; TARGETDIR=m68k
+	SOURCES="ffi.c sysv.S"
+	;;
+
+  m88k-*-*)
+	TARGET=M88K; TARGETDIR=m88k
+	SOURCES="ffi.c obsd.S"
+	;;
+
+  microblaze*-*-*)
+	TARGET=MICROBLAZE; TARGETDIR=microblaze
+	SOURCES="ffi.c sysv.S"
+	;;
+
+  moxie-*-*)
+	TARGET=MOXIE; TARGETDIR=moxie
+	SOURCES="ffi.c eabi.S"
+	;;
+
+  metag-*-*)
+	TARGET=METAG; TARGETDIR=metag
+	SOURCES="ffi.c sysv.S"
+	;;
+
+  mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
+	TARGET=MIPS; TARGETDIR=mips
+	;;
+  mips*-*linux* | mips*-*-openbsd*)
+	# Support 128-bit long double for NewABI.
+	HAVE_LONG_DOUBLE='defined(__mips64)'
+	TARGET=MIPS; TARGETDIR=mips
+	;;
+
+  nios2*-linux*)
+	TARGET=NIOS2; TARGETDIR=nios2
+	SOURCES="ffi.c sysv.S"
+	;;
+
+  or1k*-linux*)
+	TARGET=OR1K; TARGETDIR=or1k
+	SOURCES="ffi.c sysv.S"
+	;;
+
+  powerpc*-*-linux* | powerpc-*-sysv*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	HAVE_LONG_DOUBLE_VARIANT=1
+	;;
+  powerpc-*-amigaos*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	;;
+  powerpc-*-beos*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	;;
+  powerpc-*-darwin* | powerpc64-*-darwin*)
+	TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
+	;;
+  powerpc-*-aix* | rs6000-*-aix*)
+	TARGET=POWERPC_AIX; TARGETDIR=powerpc
+	;;
+  powerpc-*-freebsd* | powerpc-*-openbsd*)
+	TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
+	HAVE_LONG_DOUBLE_VARIANT=1
+	;;
+  powerpc64-*-freebsd*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	;;
+  powerpc*-*-rtems*)
+	TARGET=POWERPC; TARGETDIR=powerpc
+	;;
+
+  s390-*-* | s390x-*-*)
+	TARGET=S390; TARGETDIR=s390
+	SOURCES="ffi.c sysv.S"
+	;;
+
+  sh-*-* | sh[[34]]*-*-*)
+	TARGET=SH; TARGETDIR=sh
+	SOURCES="ffi.c sysv.S"
+	;;
+  sh64-*-* | sh5*-*-*)
+	TARGET=SH64; TARGETDIR=sh64
+	SOURCES="ffi.c sysv.S"
+	;;
+
+  sparc*-*-*)
+	TARGET=SPARC; TARGETDIR=sparc
+	SOURCES="ffi.c ffi64.c v8.S v9.S"
+	;;
+
+  tile*-*)
+        TARGET=TILE; TARGETDIR=tile
+	SOURCES="ffi.c tile.S"
+        ;;
+
+  vax-*-*)
+	TARGET=VAX; TARGETDIR=vax
+	SOURCES="ffi.c elfbsd.S"
+	;;
+
+  xtensa*-*)
+	TARGET=XTENSA; TARGETDIR=xtensa
+	SOURCES="ffi.c sysv.S"
+	;;
 esac
+
+# ... but some of the cases above share configury.
+case "${TARGET}" in
+  MIPS)
+	SOURCES="ffi.c o32.S n32.S"
+	;;
+  POWERPC)
+	SOURCES="ffi.c ffi_sysv.c ffi_linux64.c sysv.S ppc_closure.S"
+	SOURCES="${SOURCES} linux64.S linux64_closure.S"
+	;;
+  POWERPC_AIX)
+	SOURCES="ffi_darwin.c aix.S aix_closure.S"
+	;;
+  POWERPC_DARWIN)
+	SOURCES="ffi_darwin.c darwin.S darwin_closure.S"
+	;;
+  POWERPC_FREEBSD)
+	SOURCES="ffi.c ffi_sysv.c sysv.S ppc_closure.S"
+	;;
+  X86 | X86_FREEBSD | X86_WIN32)
+	SOURCES="ffi.c sysv.S"
+	;;
+  X86_64)
+	SOURCES="ffi64.c unix64.S"
+	;;
+  X86_WIN64)
+	SOURCES="ffiw64.c win64.S"
+	;;
+  X86_DARWIN)
+	SOURCES="darwin_c.c darwin.S"
+	;;
+  X86_64_DARWIN)
+	SOURCES="darwin64_c.c darwin64.S"
+	;;
+esac
+
+# If we failed to configure SOURCES, we can't do anything.
+if test -z "${SOURCES}"; then
+  UNSUPPORTED=1
+fi
diff --git a/third_party/gofrontend/libffi/doc/stamp-vti b/third_party/gofrontend/libffi/doc/stamp-vti
deleted file mode 100644
index b9b2131..0000000
--- a/third_party/gofrontend/libffi/doc/stamp-vti
+++ /dev/null
@@ -1,4 +0,0 @@
-@set UPDATED 6 March 2012
-@set UPDATED-MONTH March 2012
-@set EDITION 3.0.11
-@set VERSION 3.0.11
diff --git a/third_party/gofrontend/libffi/doc/version.texi b/third_party/gofrontend/libffi/doc/version.texi
index b9b2131..ccef70f 100644
--- a/third_party/gofrontend/libffi/doc/version.texi
+++ b/third_party/gofrontend/libffi/doc/version.texi
@@ -1,4 +1,4 @@
-@set UPDATED 6 March 2012
-@set UPDATED-MONTH March 2012
-@set EDITION 3.0.11
-@set VERSION 3.0.11
+@set UPDATED 8 November 2014
+@set UPDATED-MONTH November 2014
+@set EDITION 3.2.1
+@set VERSION 3.2.1
diff --git a/third_party/gofrontend/libffi/fficonfig.h.in b/third_party/gofrontend/libffi/fficonfig.h.in
index 19d66d0..f245ce0 100644
--- a/third_party/gofrontend/libffi/fficonfig.h.in
+++ b/third_party/gofrontend/libffi/fficonfig.h.in
@@ -26,10 +26,10 @@
 /* Cannot use malloc on this target, so, we revert to alternative means */
 #undef FFI_MMAP_EXEC_WRIT
 
-/* Define this is you do not want support for the raw API. */
+/* Define this if you do not want support for the raw API. */
 #undef FFI_NO_RAW_API
 
-/* Define this is you do not want support for aggregate types. */
+/* Define this if you do not want support for aggregate types. */
 #undef FFI_NO_STRUCTS
 
 /* Define to 1 if you have `alloca', as a function or macro. */
@@ -48,6 +48,9 @@
 /* Define if your assembler supports .register. */
 #undef HAVE_AS_REGISTER_PSEUDO_OP
 
+/* Define if the compiler uses zarch features. */
+#undef HAVE_AS_S390_ZARCH
+
 /* Define if your assembler and linker support unaligned PC relative relocs.
    */
 #undef HAVE_AS_SPARC_UA_PCREL
@@ -82,6 +85,9 @@
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
+/* Define to 1 if you have the `mkostemp' function. */
+#undef HAVE_MKOSTEMP
+
 /* Define to 1 if you have the `mmap' function. */
 #undef HAVE_MMAP
 
@@ -155,6 +161,9 @@
 /* The size of `long double', as computed by sizeof. */
 #undef SIZEOF_LONG_DOUBLE
 
+/* The size of `size_t', as computed by sizeof. */
+#undef SIZEOF_SIZE_T
+
 /* If using the C implementation of alloca, define if you know the
    direction of stack growth for your system; otherwise it will be
    automatically deduced at runtime.
diff --git a/third_party/gofrontend/libffi/generate-darwin-source-and-headers.py b/third_party/gofrontend/libffi/generate-darwin-source-and-headers.py
new file mode 100644
index 0000000..306136f
--- /dev/null
+++ b/third_party/gofrontend/libffi/generate-darwin-source-and-headers.py
@@ -0,0 +1,209 @@
+#!/usr/bin/env python
+import subprocess
+import os
+import errno
+import collections
+import glob
+import argparse
+
+class Platform(object):
+    pass
+
+class simulator_platform(Platform):
+    directory = 'darwin_ios'
+    sdk = 'iphonesimulator'
+    arch = 'i386'
+    triple = 'i386-apple-darwin11'
+    version_min = '-miphoneos-version-min=7.0'
+
+    prefix = "#ifdef __i386__\n\n"
+    suffix = "\n\n#endif"
+    src_dir = 'x86'
+    src_files = ['darwin.S', 'win32.S', 'ffi.c']
+
+
+class simulator64_platform(Platform):
+    directory = 'darwin_ios'
+    sdk = 'iphonesimulator'
+    arch = 'x86_64'
+    triple = 'x86_64-apple-darwin13'
+    version_min = '-miphoneos-version-min=7.0'
+
+    prefix = "#ifdef __x86_64__\n\n"
+    suffix = "\n\n#endif"
+    src_dir = 'x86'
+    src_files = ['darwin64.S', 'ffi64.c']
+
+
+class device_platform(Platform):
+    directory = 'darwin_ios'
+    sdk = 'iphoneos'
+    arch = 'armv7'
+    triple = 'arm-apple-darwin11'
+    version_min = '-miphoneos-version-min=7.0'
+
+    prefix = "#ifdef __arm__\n\n"
+    suffix = "\n\n#endif"
+    src_dir = 'arm'
+    src_files = ['sysv.S', 'trampoline.S', 'ffi.c']
+
+
+class device64_platform(Platform):
+    directory = 'darwin_ios'
+    sdk = 'iphoneos'
+    arch = 'arm64'
+    triple = 'aarch64-apple-darwin13'
+    version_min = '-miphoneos-version-min=7.0'
+
+    prefix = "#ifdef __arm64__\n\n"
+    suffix = "\n\n#endif"
+    src_dir = 'aarch64'
+    src_files = ['sysv.S', 'ffi.c']
+
+
+class desktop32_platform(Platform):
+    directory = 'darwin_osx'
+    sdk = 'macosx'
+    arch = 'i386'
+    triple = 'i386-apple-darwin10'
+    version_min = '-mmacosx-version-min=10.6'
+    src_dir = 'x86'
+    src_files = ['darwin.S', 'win32.S', 'ffi.c']
+
+    prefix = "#ifdef __i386__\n\n"
+    suffix = "\n\n#endif"
+
+
+class desktop64_platform(Platform):
+    directory = 'darwin_osx'
+    sdk = 'macosx'
+    arch = 'x86_64'
+    triple = 'x86_64-apple-darwin10'
+    version_min = '-mmacosx-version-min=10.6'
+
+    prefix = "#ifdef __x86_64__\n\n"
+    suffix = "\n\n#endif"
+    src_dir = 'x86'
+    src_files = ['darwin64.S', 'ffi64.c']
+
+
+def mkdir_p(path):
+    try:
+        os.makedirs(path)
+    except OSError as exc:  # Python >2.5
+        if exc.errno == errno.EEXIST:
+            pass
+        else:
+            raise
+
+
+def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
+    mkdir_p(dst_dir)
+    out_filename = filename
+
+    if file_suffix:
+        split_name = os.path.splitext(filename)
+        out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
+
+    with open(os.path.join(src_dir, filename)) as in_file:
+        with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
+            if prefix:
+                out_file.write(prefix)
+
+            out_file.write(in_file.read())
+
+            if suffix:
+                out_file.write(suffix)
+
+
+def list_files(src_dir, pattern=None, filelist=None):
+    if pattern: filelist = glob.iglob(os.path.join(src_dir, pattern))
+    for file in filelist:
+        yield os.path.basename(file)
+
+
+def copy_files(src_dir, dst_dir, pattern=None, filelist=None, file_suffix=None, prefix=None, suffix=None):
+    for filename in list_files(src_dir, pattern=pattern, filelist=filelist):
+        move_file(src_dir, dst_dir, filename, file_suffix=file_suffix, prefix=prefix, suffix=suffix)
+
+
+def copy_src_platform_files(platform):
+    src_dir = os.path.join('src', platform.src_dir)
+    dst_dir = os.path.join(platform.directory, 'src', platform.src_dir)
+    copy_files(src_dir, dst_dir, filelist=platform.src_files, file_suffix=platform.arch, prefix=platform.prefix, suffix=platform.suffix)
+
+
+def build_target(platform, platform_headers):
+    def xcrun_cmd(cmd):
+        return 'xcrun -sdk %s %s -arch %s' % (platform.sdk, cmd, platform.arch)
+
+    tag='%s-%s' % (platform.sdk, platform.arch)
+    build_dir = 'build_%s' % tag
+    mkdir_p(build_dir)
+    env = dict(CC=xcrun_cmd('clang'),
+               LD=xcrun_cmd('ld'),
+               CFLAGS='%s' % (platform.version_min))
+    working_dir = os.getcwd()
+    try:
+        os.chdir(build_dir)
+        subprocess.check_call(['../configure', '-host', platform.triple], env=env)
+    finally:
+        os.chdir(working_dir)
+
+    for src_dir in [build_dir, os.path.join(build_dir, 'include')]:
+        copy_files(src_dir,
+                   os.path.join(platform.directory, 'include'),
+                   pattern='*.h',
+                   file_suffix=platform.arch,
+                   prefix=platform.prefix,
+                   suffix=platform.suffix)
+
+        for filename in list_files(src_dir, pattern='*.h'):
+            platform_headers[filename].add((platform.prefix, platform.arch, platform.suffix))
+
+
+def make_tramp():
+    with open('src/arm/trampoline.S', 'w') as tramp_out:
+        p = subprocess.Popen(['bash', 'src/arm/gentramp.sh'], stdout=tramp_out)
+        p.wait()
+
+
+def generate_source_and_headers(generate_osx=True, generate_ios=True):
+    copy_files('src', 'darwin_common/src', pattern='*.c')
+    copy_files('include', 'darwin_common/include', pattern='*.h')
+
+    if generate_ios:
+        make_tramp()
+        copy_src_platform_files(simulator_platform)
+        copy_src_platform_files(simulator64_platform)
+        copy_src_platform_files(device_platform)
+        copy_src_platform_files(device64_platform)
+    if generate_osx:
+        copy_src_platform_files(desktop32_platform)
+        copy_src_platform_files(desktop64_platform)
+
+    platform_headers = collections.defaultdict(set)
+
+    if generate_ios:
+        build_target(simulator_platform, platform_headers)
+        build_target(simulator64_platform, platform_headers)
+        build_target(device_platform, platform_headers)
+        build_target(device64_platform, platform_headers)
+    if generate_osx:
+        build_target(desktop32_platform, platform_headers)
+        build_target(desktop64_platform, platform_headers)
+
+    mkdir_p('darwin_common/include')
+    for header_name, tag_tuples in platform_headers.iteritems():
+        basename, suffix = os.path.splitext(header_name)
+        with open(os.path.join('darwin_common/include', header_name), 'w') as header:
+            for tag_tuple in tag_tuples:
+                header.write('%s#include <%s_%s%s>\n%s\n' % (tag_tuple[0], basename, tag_tuple[1], suffix, tag_tuple[2]))
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--only-ios', action='store_true', default=False)
+    parser.add_argument('--only-osx', action='store_true', default=False)
+    args = parser.parse_args()
+
+    generate_source_and_headers(generate_osx=not args.only_ios, generate_ios=not args.only_osx)
diff --git a/third_party/gofrontend/libffi/generate-ios-source-and-headers.py b/third_party/gofrontend/libffi/generate-ios-source-and-headers.py
deleted file mode 100644
index c2bca73..0000000
--- a/third_party/gofrontend/libffi/generate-ios-source-and-headers.py
+++ /dev/null
@@ -1,160 +0,0 @@
-#!/usr/bin/env python
-
-import subprocess
-import re
-import os
-import errno
-import collections
-import sys
-
-class Platform(object):
-    pass
-
-sdk_re = re.compile(r'.*-sdk ([a-zA-Z0-9.]*)')
-
-def sdkinfo(sdkname):
-    ret = {}
-    for line in subprocess.Popen(['xcodebuild', '-sdk', sdkname, '-version'], stdout=subprocess.PIPE).stdout:
-        kv = line.strip().split(': ', 1)
-        if len(kv) == 2:
-            k,v = kv
-            ret[k] = v
-    return ret
-
-sim_sdk_info = sdkinfo('iphonesimulator')
-device_sdk_info = sdkinfo('iphoneos')
-
-def latest_sdks():
-    latest_sim = None
-    latest_device = None
-    for line in subprocess.Popen(['xcodebuild', '-showsdks'], stdout=subprocess.PIPE).stdout:
-        match = sdk_re.match(line)
-        if match:
-            if 'Simulator' in line:
-                latest_sim = match.group(1)
-            elif 'iOS' in line:
-                latest_device = match.group(1)
-
-    return latest_sim, latest_device
-
-sim_sdk, device_sdk = latest_sdks()
-
-class simulator_platform(Platform):
-    sdk='iphonesimulator'
-    arch = 'i386'
-    name = 'simulator'
-    triple = 'i386-apple-darwin10'
-    sdkroot = sim_sdk_info['Path']
-
-    prefix = "#if !defined(__arm__) && defined(__i386__)\n\n"
-    suffix = "\n\n#endif"
-
-class device_platform(Platform):
-    sdk='iphoneos'
-    name = 'ios'
-    arch = 'armv7'
-    triple = 'arm-apple-darwin10'
-    sdkroot = device_sdk_info['Path']
-
-    prefix = "#ifdef __arm__\n\n"
-    suffix = "\n\n#endif"
-
-
-def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
-    if not os.path.exists(dst_dir):
-        os.makedirs(dst_dir)
-
-    out_filename = filename
-
-    if file_suffix:
-        split_name = os.path.splitext(filename)
-        out_filename =  "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
-
-    with open(os.path.join(src_dir, filename)) as in_file:
-        with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
-            if prefix:
-                out_file.write(prefix)
-
-            out_file.write(in_file.read())
-
-            if suffix:
-                out_file.write(suffix)
-
-headers_seen = collections.defaultdict(set)
-
-def move_source_tree(src_dir, dest_dir, dest_include_dir, arch=None, prefix=None, suffix=None):
-    for root, dirs, files in os.walk(src_dir, followlinks=True):
-        relroot = os.path.relpath(root,src_dir)
-
-        def move_dir(arch, prefix='', suffix='', files=[]):
-            for file in files:
-                file_suffix = None
-                if file.endswith('.h'):
-                    if dest_include_dir:
-                        file_suffix = arch
-                        if arch:
-                            headers_seen[file].add(arch)
-                        move_file(root, dest_include_dir, file, arch, prefix=prefix, suffix=suffix)
-
-                elif dest_dir:
-                    outroot = os.path.join(dest_dir, relroot)
-                    move_file(root, outroot, file, prefix=prefix, suffix=suffix)
-
-        if relroot == '.':
-            move_dir(arch=arch,
-                     files=files,
-                     prefix=prefix,
-                     suffix=suffix)
-        elif relroot == 'arm':
-            move_dir(arch='arm',
-                     prefix="#ifdef __arm__\n\n",
-                     suffix="\n\n#endif",
-                     files=files)
-        elif relroot == 'x86':
-            move_dir(arch='i386',
-                     prefix="#if !defined(__arm__) && defined(__i386__)\n\n",
-                     suffix="\n\n#endif",
-                     files=files)
-
-def build_target(platform):
-    def xcrun_cmd(cmd):
-        return subprocess.check_output(['xcrun', '-sdk', platform.sdkroot, '-find', cmd]).strip()
-
-    build_dir = 'build_' + platform.name
-    if not os.path.exists(build_dir):
-        os.makedirs(build_dir)
-        env = dict(CC=xcrun_cmd('clang'),
-                   LD=xcrun_cmd('ld'),
-                   CFLAGS='-arch %s -isysroot %s -miphoneos-version-min=4.0' % (platform.arch, platform.sdkroot))
-        working_dir=os.getcwd()
-        try:
-            os.chdir(build_dir)
-            subprocess.check_call(['../configure', '-host', platform.triple], env=env)
-            move_source_tree('.', None, '../ios/include',
-                             arch=platform.arch,
-                             prefix=platform.prefix,
-                             suffix=platform.suffix)
-            move_source_tree('./include', None, '../ios/include',
-                            arch=platform.arch,
-                            prefix=platform.prefix,
-                            suffix=platform.suffix)
-        finally:
-            os.chdir(working_dir)
-
-        for header_name, archs in headers_seen.iteritems():
-            basename, suffix = os.path.splitext(header_name)
-
-def main():
-    move_source_tree('src', 'ios/src', 'ios/include')
-    move_source_tree('include', None, 'ios/include')
-    build_target(simulator_platform)
-    build_target(device_platform)
-
-    for header_name, archs in headers_seen.iteritems():
-        basename, suffix = os.path.splitext(header_name)
-        with open(os.path.join('ios/include', header_name), 'w') as header:
-            for arch in archs:
-                header.write('#include <%s_%s%s>\n' % (basename, arch, suffix))
-
-if __name__ == '__main__':
-    main()
diff --git a/third_party/gofrontend/libffi/generate-osx-source-and-headers.py b/third_party/gofrontend/libffi/generate-osx-source-and-headers.py
deleted file mode 100644
index 64313c1..0000000
--- a/third_party/gofrontend/libffi/generate-osx-source-and-headers.py
+++ /dev/null
@@ -1,153 +0,0 @@
-#!/usr/bin/env python
-import subprocess
-import re
-import os
-import errno
-import collections
-import sys
-
-class Platform(object):
-    pass
-
-sdk_re = re.compile(r'.*-sdk ([a-zA-Z0-9.]*)')
-
-def sdkinfo(sdkname):
-    ret = {}
-    for line in subprocess.Popen(['xcodebuild', '-sdk', sdkname, '-version'], stdout=subprocess.PIPE).stdout:
-        kv = line.strip().split(': ', 1)
-        if len(kv) == 2:
-            k,v = kv
-            ret[k] = v
-    return ret
-
-desktop_sdk_info = sdkinfo('macosx')
-
-def latest_sdks():
-    latest_desktop = None
-    for line in subprocess.Popen(['xcodebuild', '-showsdks'], stdout=subprocess.PIPE).stdout:
-        match = sdk_re.match(line)
-        if match:
-            if 'OS X' in line:
-                latest_desktop = match.group(1)
-
-    return latest_desktop
-
-desktop_sdk = latest_sdks()
-
-class desktop_platform_32(Platform):
-    sdk='macosx'
-    arch = 'i386'
-    name = 'mac32'
-    triple = 'i386-apple-darwin10'
-    sdkroot = desktop_sdk_info['Path']
-
-    prefix = "#if defined(__i386__) && !defined(__x86_64__)\n\n"
-    suffix = "\n\n#endif"
-
-class desktop_platform_64(Platform):
-    sdk='macosx'
-    arch = 'x86_64'
-    name = 'mac'
-    triple = 'x86_64-apple-darwin10'
-    sdkroot = desktop_sdk_info['Path']
-
-    prefix = "#if !defined(__i386__) && defined(__x86_64__)\n\n"
-    suffix = "\n\n#endif"
-
-def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
-    if not os.path.exists(dst_dir):
-        os.makedirs(dst_dir)
-
-    out_filename = filename
-
-    if file_suffix:
-        split_name = os.path.splitext(filename)
-        out_filename =  "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
-
-    with open(os.path.join(src_dir, filename)) as in_file:
-        with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
-            if prefix:
-                out_file.write(prefix)
-
-            out_file.write(in_file.read())
-
-            if suffix:
-                out_file.write(suffix)
-
-headers_seen = collections.defaultdict(set)
-
-def move_source_tree(src_dir, dest_dir, dest_include_dir, arch=None, prefix=None, suffix=None):
-    for root, dirs, files in os.walk(src_dir, followlinks=True):
-        relroot = os.path.relpath(root,src_dir)
-
-        def move_dir(arch, prefix='', suffix='', files=[]):
-            for file in files:
-                file_suffix = None
-                if file.endswith('.h'):
-                    if dest_include_dir:
-                        file_suffix = arch
-                        if arch:
-                            headers_seen[file].add(arch)
-                        move_file(root, dest_include_dir, file, arch, prefix=prefix, suffix=suffix)
-
-                elif dest_dir:
-                    outroot = os.path.join(dest_dir, relroot)
-                    move_file(root, outroot, file, prefix=prefix, suffix=suffix)
-
-        if relroot == '.':
-            move_dir(arch=arch,
-                     files=files,
-                     prefix=prefix,
-                     suffix=suffix)
-        elif relroot == 'x86':
-            move_dir(arch='i386',
-                     prefix="#if defined(__i386__) && !defined(__x86_64__)\n\n",
-                     suffix="\n\n#endif",
-                     files=files)
-            move_dir(arch='x86_64',
-                     prefix="#if !defined(__i386__) && defined(__x86_64__)\n\n",
-                     suffix="\n\n#endif",
-                     files=files)
-
-def build_target(platform):
-    def xcrun_cmd(cmd):
-        return subprocess.check_output(['xcrun', '-sdk', platform.sdkroot, '-find', cmd]).strip()
-
-    build_dir = 'build_' + platform.name
-    if not os.path.exists(build_dir):
-        os.makedirs(build_dir)
-        env = dict(CC=xcrun_cmd('clang'),
-                   LD=xcrun_cmd('ld'),
-                   CFLAGS='-arch %s -isysroot %s -mmacosx-version-min=10.6' % (platform.arch, platform.sdkroot))
-        working_dir=os.getcwd()
-        try:
-            os.chdir(build_dir)
-            subprocess.check_call(['../configure', '-host', platform.triple], env=env)
-            move_source_tree('.', None, '../osx/include',
-                             arch=platform.arch,
-                             prefix=platform.prefix,
-                             suffix=platform.suffix)
-            move_source_tree('./include', None, '../osx/include',
-                             arch=platform.arch,
-                             prefix=platform.prefix,
-                             suffix=platform.suffix)
-        finally:
-            os.chdir(working_dir)
-
-        for header_name, archs in headers_seen.iteritems():
-            basename, suffix = os.path.splitext(header_name)
-
-def main():
-    move_source_tree('src', 'osx/src', 'osx/include')
-    move_source_tree('include', None, 'osx/include')
-    build_target(desktop_platform_32)
-    build_target(desktop_platform_64)
-
-    for header_name, archs in headers_seen.iteritems():
-        basename, suffix = os.path.splitext(header_name)
-        with open(os.path.join('osx/include', header_name), 'w') as header:
-            for arch in archs:
-                header.write('#include <%s_%s%s>\n' % (basename, arch, suffix))
-
-if __name__ == '__main__':
-    main()
diff --git a/third_party/gofrontend/libffi/include/Makefile.am b/third_party/gofrontend/libffi/include/Makefile.am
index f11151e..79f222c 100644
--- a/third_party/gofrontend/libffi/include/Makefile.am
+++ b/third_party/gofrontend/libffi/include/Makefile.am
@@ -3,7 +3,8 @@
 AUTOMAKE_OPTIONS=foreign
 
 DISTCLEANFILES=ffitarget.h
-EXTRA_DIST=ffi.h.in ffi_common.h
+noinst_HEADERS=ffi_common.h ffi_cfi.h
+EXTRA_DIST=ffi.h.in
 
 # Where generated headers like ffitarget.h get installed.
 gcc_version   := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
diff --git a/third_party/gofrontend/libffi/include/Makefile.in b/third_party/gofrontend/libffi/include/Makefile.in
index c923bf2..d8d17f1 100644
--- a/third_party/gofrontend/libffi/include/Makefile.in
+++ b/third_party/gofrontend/libffi/include/Makefile.in
@@ -37,7 +37,7 @@
 target_triplet = @target@
 subdir = include
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-	$(srcdir)/ffi.h.in $(toollibffi_HEADERS)
+	$(srcdir)/ffi.h.in $(noinst_HEADERS) $(toollibffi_HEADERS)
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
 	$(top_srcdir)/../config/asmcfi.m4 \
@@ -78,7 +78,7 @@
   sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
 am__installdirs = "$(DESTDIR)$(toollibffidir)"
-HEADERS = $(toollibffi_HEADERS)
+HEADERS = $(noinst_HEADERS) $(toollibffi_HEADERS)
 ETAGS = etags
 CTAGS = ctags
 ACLOCAL = @ACLOCAL@
@@ -99,6 +99,10 @@
 CFLAGS = @CFLAGS@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -151,12 +155,14 @@
 STRIP = @STRIP@
 TARGET = @TARGET@
 TARGETDIR = @TARGETDIR@
+TARGET_OBJ = @TARGET_OBJ@
 VERSION = @VERSION@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
 abs_top_srcdir = @abs_top_srcdir@
 ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
 am__include = @am__include@
 am__leading_dot = @am__leading_dot@
@@ -212,7 +218,8 @@
 top_srcdir = @top_srcdir@
 AUTOMAKE_OPTIONS = foreign
 DISTCLEANFILES = ffitarget.h
-EXTRA_DIST = ffi.h.in ffi_common.h
+noinst_HEADERS = ffi_common.h ffi_cfi.h
+EXTRA_DIST = ffi.h.in
 
 # Where generated headers like ffitarget.h get installed.
 gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
diff --git a/third_party/gofrontend/libffi/include/ffi.h.in b/third_party/gofrontend/libffi/include/ffi.h.in
index 380673b..c43d52f 100644
--- a/third_party/gofrontend/libffi/include/ffi.h.in
+++ b/third_party/gofrontend/libffi/include/ffi.h.in
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------*-C-*-
-   libffi @VERSION@ - Copyright (c) 2011 Anthony Green
+   libffi @VERSION@ - Copyright (c) 2011, 2014 Anthony Green
                     - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
 
    Permission is hereby granted, free of charge, to any person
@@ -68,7 +68,7 @@
 
 #ifndef LIBFFI_ASM
 
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(__clang__)
 #define __attribute__(X)
 #endif
 
@@ -166,25 +166,49 @@
  #error "long size not supported"
 #endif
 
+/* Need minimal decorations for DLLs to works on Windows. */
+/* GCC has autoimport and autoexport.  Rely on Libtool to */
+/* help MSVC export from a DLL, but always declare data   */
+/* to be imported for MSVC clients.  This costs an extra  */
+/* indirection for MSVC clients using the static version  */
+/* of the library, but don't worry about that.  Besides,  */
+/* as a workaround, they can define FFI_BUILDING if they  */
+/* *know* they are going to link with the static library. */
+#if defined _MSC_VER && !defined FFI_BUILDING
+#define FFI_EXTERN extern __declspec(dllimport)
+#else
+#define FFI_EXTERN extern
+#endif
+
 /* These are defined in types.c */
-extern ffi_type ffi_type_void;
-extern ffi_type ffi_type_uint8;
-extern ffi_type ffi_type_sint8;
-extern ffi_type ffi_type_uint16;
-extern ffi_type ffi_type_sint16;
-extern ffi_type ffi_type_uint32;
-extern ffi_type ffi_type_sint32;
-extern ffi_type ffi_type_uint64;
-extern ffi_type ffi_type_sint64;
-extern ffi_type ffi_type_float;
-extern ffi_type ffi_type_double;
-extern ffi_type ffi_type_pointer;
+FFI_EXTERN ffi_type ffi_type_void;
+FFI_EXTERN ffi_type ffi_type_uint8;
+FFI_EXTERN ffi_type ffi_type_sint8;
+FFI_EXTERN ffi_type ffi_type_uint16;
+FFI_EXTERN ffi_type ffi_type_sint16;
+FFI_EXTERN ffi_type ffi_type_uint32;
+FFI_EXTERN ffi_type ffi_type_sint32;
+FFI_EXTERN ffi_type ffi_type_uint64;
+FFI_EXTERN ffi_type ffi_type_sint64;
+FFI_EXTERN ffi_type ffi_type_float;
+FFI_EXTERN ffi_type ffi_type_double;
+FFI_EXTERN ffi_type ffi_type_pointer;
 
 #if @HAVE_LONG_DOUBLE@
-extern ffi_type ffi_type_longdouble;
+FFI_EXTERN ffi_type ffi_type_longdouble;
 #else
 #define ffi_type_longdouble ffi_type_double
 #endif
+
+#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
+FFI_EXTERN ffi_type ffi_type_complex_float;
+FFI_EXTERN ffi_type ffi_type_complex_double;
+#if @HAVE_LONG_DOUBLE@
+FFI_EXTERN ffi_type ffi_type_complex_longdouble;
+#else
+#define ffi_type_complex_longdouble ffi_type_complex_double
+#endif
+#endif
 #endif /* LIBFFI_HIDE_BASIC_TYPES */
 
 typedef enum {
@@ -207,10 +231,10 @@
 #endif
 } ffi_cif;
 
-#if HAVE_LONG_DOUBLE_VARIANT
+#if @HAVE_LONG_DOUBLE_VARIANT@
 /* Used to adjust size/alignment of ffi types.  */
 void ffi_prep_types (ffi_abi abi);
-# endif
+#endif
 
 /* Used internally, but overridden by some architectures */
 ffi_status ffi_prep_cif_core(ffi_cif *cif,
@@ -288,7 +312,12 @@
 __declspec(align(8))
 #endif
 typedef struct {
+#if @FFI_EXEC_TRAMPOLINE_TABLE@
+  void *trampoline_table;
+  void *trampoline_table_entry;
+#else
   char tramp[FFI_TRAMPOLINE_SIZE];
+#endif
   ffi_cif   *cif;
   void     (*fun)(ffi_cif*,void*,void**,void*);
   void      *user_data;
@@ -321,8 +350,12 @@
 # pragma pack 8
 #endif
 typedef struct {
+#if @FFI_EXEC_TRAMPOLINE_TABLE@
+  void *trampoline_table;
+  void *trampoline_table_entry;
+#else
   char tramp[FFI_TRAMPOLINE_SIZE];
-
+#endif
   ffi_cif   *cif;
 
 #if !FFI_NATIVE_RAW_API
@@ -342,7 +375,12 @@
 } ffi_raw_closure;
 
 typedef struct {
+#if @FFI_EXEC_TRAMPOLINE_TABLE@
+  void *trampoline_table;
+  void *trampoline_table_entry;
+#else
   char tramp[FFI_TRAMPOLINE_SIZE];
+#endif
 
   ffi_cif   *cif;
 
@@ -390,6 +428,22 @@
 
 #endif /* FFI_CLOSURES */
 
+#if FFI_GO_CLOSURES
+
+typedef struct {
+  void      *tramp;
+  ffi_cif   *cif;
+  void     (*fun)(ffi_cif*,void*,void**,void*);
+} ffi_go_closure;
+
+ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
+				void (*fun)(ffi_cif*,void*,void**,void*));
+
+void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
+		  void **avalue, void *closure);
+
+#endif /* FFI_GO_CLOSURES */
+
 /* ---- Public interface definition -------------------------------------- */
 
 ffi_status ffi_prep_cif(ffi_cif *cif,
@@ -437,9 +491,10 @@
 #define FFI_TYPE_SINT64     12
 #define FFI_TYPE_STRUCT     13
 #define FFI_TYPE_POINTER    14
+#define FFI_TYPE_COMPLEX    15
 
 /* This should always refer to the last type code (for sanity checks) */
-#define FFI_TYPE_LAST       FFI_TYPE_POINTER
+#define FFI_TYPE_LAST       FFI_TYPE_COMPLEX
 
 #ifdef __cplusplus
 }
diff --git a/third_party/gofrontend/libffi/include/ffi_cfi.h b/third_party/gofrontend/libffi/include/ffi_cfi.h
new file mode 100644
index 0000000..244ce57
--- /dev/null
+++ b/third_party/gofrontend/libffi/include/ffi_cfi.h
@@ -0,0 +1,55 @@
+/* -----------------------------------------------------------------------
+   ffi_cfi.h - Copyright (c) 2014  Red Hat, Inc.
+
+   Conditionally assemble cfi directives. Only necessary for building libffi.
+   ----------------------------------------------------------------------- */
+
+#ifndef FFI_CFI_H
+#define FFI_CFI_H
+
+#ifdef HAVE_AS_CFI_PSEUDO_OP
+
+# define cfi_startproc			.cfi_startproc
+# define cfi_endproc			.cfi_endproc
+# define cfi_def_cfa(reg, off)		.cfi_def_cfa reg, off
+# define cfi_def_cfa_register(reg)	.cfi_def_cfa_register reg
+# define cfi_def_cfa_offset(off)	.cfi_def_cfa_offset off
+# define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
+# define cfi_offset(reg, off)		.cfi_offset reg, off
+# define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
+# define cfi_register(r1, r2)		.cfi_register r1, r2
+# define cfi_return_column(reg)		.cfi_return_column reg
+# define cfi_restore(reg)		.cfi_restore reg
+# define cfi_same_value(reg)		.cfi_same_value reg
+# define cfi_undefined(reg)		.cfi_undefined reg
+# define cfi_remember_state		.cfi_remember_state
+# define cfi_restore_state		.cfi_restore_state
+# define cfi_window_save		.cfi_window_save
+# define cfi_personality(enc, exp)	.cfi_personality enc, exp
+# define cfi_lsda(enc, exp)		.cfi_lsda enc, exp
+# define cfi_escape(...)		.cfi_escape __VA_ARGS__
+
+#else
+
+# define cfi_startproc
+# define cfi_endproc
+# define cfi_def_cfa(reg, off)
+# define cfi_def_cfa_register(reg)
+# define cfi_def_cfa_offset(off)
+# define cfi_adjust_cfa_offset(off)
+# define cfi_offset(reg, off)
+# define cfi_rel_offset(reg, off)
+# define cfi_register(r1, r2)
+# define cfi_return_column(reg)
+# define cfi_restore(reg)
+# define cfi_same_value(reg)
+# define cfi_undefined(reg)
+# define cfi_remember_state
+# define cfi_restore_state
+# define cfi_window_save
+# define cfi_personality(enc, exp)
+# define cfi_lsda(enc, exp)
+# define cfi_escape(...)
+
+#endif /* HAVE_AS_CFI_PSEUDO_OP */
+#endif /* FFI_CFI_H */
diff --git a/third_party/gofrontend/libffi/include/ffi_common.h b/third_party/gofrontend/libffi/include/ffi_common.h
index c179d68..37f5a9e 100644
--- a/third_party/gofrontend/libffi/include/ffi_common.h
+++ b/third_party/gofrontend/libffi/include/ffi_common.h
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   ffi_common.h - Copyright (C) 2011, 2012  Anthony Green
+   ffi_common.h - Copyright (C) 2011, 2012, 2013  Anthony Green
                   Copyright (C) 2007  Free Software Foundation, Inc
                   Copyright (c) 1996  Red Hat, Inc.
                   
@@ -19,10 +19,14 @@
 /* Do not move this. Some versions of AIX are very picky about where
    this is positioned. */
 #ifdef __GNUC__
-/* mingw64 defines this already in malloc.h. */
-#ifndef alloca
-# define alloca __builtin_alloca
-#endif
+# if HAVE_ALLOCA_H
+#  include <alloca.h>
+# else
+  /* mingw64 defines this already in malloc.h. */
+#  ifndef alloca
+#    define alloca __builtin_alloca
+#  endif
+# endif
 # define MAYBE_UNUSED __attribute__((__unused__))
 #else
 # define MAYBE_UNUSED
@@ -30,17 +34,17 @@
 #  include <alloca.h>
 # else
 #  ifdef _AIX
- #pragma alloca
+#   pragma alloca
 #  else
 #   ifndef alloca /* predefined by HP cc +Olibcalls */
 #    ifdef _MSC_VER
 #     define alloca _alloca
 #    else
 char *alloca ();
-#    endif
 #   endif
 #  endif
 # endif
+# endif
 #endif
 
 /* Check for the existence of memcpy. */
@@ -87,7 +91,7 @@
 } extended_cif;
 
 /* Terse sized type definitions.  */
-#if defined(_MSC_VER) || defined(__sgi)
+#if defined(_MSC_VER) || defined(__sgi) || defined(__SUNPRO_C)
 typedef unsigned char UINT8;
 typedef signed char   SINT8;
 typedef unsigned short UINT16;
diff --git a/third_party/gofrontend/libffi/libffi.pc.in b/third_party/gofrontend/libffi/libffi.pc.in
new file mode 100644
index 0000000..edf6fde
--- /dev/null
+++ b/third_party/gofrontend/libffi/libffi.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+toolexeclibdir=@toolexeclibdir@
+includedir=${libdir}/@PACKAGE_NAME@-@PACKAGE_VERSION@/include
+
+Name: @PACKAGE_NAME@
+Description: Library supporting Foreign Function Interfaces
+Version: @PACKAGE_VERSION@
+Libs: -L${toolexeclibdir} -lffi
+Cflags: -I${includedir}
diff --git a/third_party/gofrontend/libffi/libffi.xcodeproj/project.pbxproj b/third_party/gofrontend/libffi/libffi.xcodeproj/project.pbxproj
index 14c39a2..1cf396f 100644
--- a/third_party/gofrontend/libffi/libffi.xcodeproj/project.pbxproj
+++ b/third_party/gofrontend/libffi/libffi.xcodeproj/project.pbxproj
@@ -7,473 +7,448 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		6C43CBDC1534F76F00162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBBD1534F76F00162364 /* ffi.c */; };
-		6C43CBDD1534F76F00162364 /* sysv.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBBF1534F76F00162364 /* sysv.S */; };
-		6C43CBDE1534F76F00162364 /* trampoline.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBC01534F76F00162364 /* trampoline.S */; };
-		6C43CBE61534F76F00162364 /* darwin.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBC91534F76F00162364 /* darwin.S */; };
-		6C43CBE81534F76F00162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBCB1534F76F00162364 /* ffi.c */; };
-		6C43CC1F1534F77800162364 /* darwin.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC051534F77800162364 /* darwin.S */; };
-		6C43CC201534F77800162364 /* darwin64.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC061534F77800162364 /* darwin64.S */; };
-		6C43CC211534F77800162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC071534F77800162364 /* ffi.c */; };
-		6C43CC221534F77800162364 /* ffi64.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC081534F77800162364 /* ffi64.c */; };
-		6C43CC2F1534F7BE00162364 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC281534F7BE00162364 /* closures.c */; };
-		6C43CC301534F7BE00162364 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC281534F7BE00162364 /* closures.c */; };
-		6C43CC351534F7BE00162364 /* java_raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2B1534F7BE00162364 /* java_raw_api.c */; };
-		6C43CC361534F7BE00162364 /* java_raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2B1534F7BE00162364 /* java_raw_api.c */; };
-		6C43CC371534F7BE00162364 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2C1534F7BE00162364 /* prep_cif.c */; };
-		6C43CC381534F7BE00162364 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2C1534F7BE00162364 /* prep_cif.c */; };
-		6C43CC391534F7BE00162364 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2D1534F7BE00162364 /* raw_api.c */; };
-		6C43CC3A1534F7BE00162364 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2D1534F7BE00162364 /* raw_api.c */; };
-		6C43CC3B1534F7BE00162364 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2E1534F7BE00162364 /* types.c */; };
-		6C43CC3C1534F7BE00162364 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2E1534F7BE00162364 /* types.c */; };
-		6C43CC971535032600162364 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8D1535032600162364 /* ffi.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CC981535032600162364 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8E1535032600162364 /* ffi_common.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CC991535032600162364 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8F1535032600162364 /* ffi_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CC9A1535032600162364 /* ffi_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC901535032600162364 /* ffi_x86_64.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CC9B1535032600162364 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC911535032600162364 /* fficonfig.h */; };
-		6C43CC9C1535032600162364 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC921535032600162364 /* fficonfig_i386.h */; };
-		6C43CC9D1535032600162364 /* fficonfig_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC931535032600162364 /* fficonfig_x86_64.h */; };
-		6C43CC9E1535032600162364 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC941535032600162364 /* ffitarget.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CC9F1535032600162364 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC951535032600162364 /* ffitarget_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CCA01535032600162364 /* ffitarget_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC961535032600162364 /* ffitarget_x86_64.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CCAD1535039600162364 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA21535039600162364 /* ffi.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CCAE1535039600162364 /* ffi_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA31535039600162364 /* ffi_armv7.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CCAF1535039600162364 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA41535039600162364 /* ffi_common.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CCB01535039600162364 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA51535039600162364 /* ffi_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CCB11535039600162364 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA61535039600162364 /* fficonfig.h */; };
-		6C43CCB21535039600162364 /* fficonfig_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA71535039600162364 /* fficonfig_armv7.h */; };
-		6C43CCB31535039600162364 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA81535039600162364 /* fficonfig_i386.h */; };
-		6C43CCB41535039600162364 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA91535039600162364 /* ffitarget.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CCB51535039600162364 /* ffitarget_arm.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAA1535039600162364 /* ffitarget_arm.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CCB61535039600162364 /* ffitarget_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAB1535039600162364 /* ffitarget_armv7.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6C43CCB71535039600162364 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAC1535039600162364 /* ffitarget_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		DBFA714A187F1D8600A76262 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; };
+		DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713F187F1D8600A76262 /* ffi_common.h */; };
+		DBFA714C187F1D8600A76262 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7140187F1D8600A76262 /* fficonfig.h */; };
+		DBFA714D187F1D8600A76262 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7141187F1D8600A76262 /* ffitarget.h */; };
+		DBFA714E187F1D8600A76262 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7143187F1D8600A76262 /* closures.c */; };
+		DBFA714F187F1D8600A76262 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7143187F1D8600A76262 /* closures.c */; };
+		DBFA7156187F1D8600A76262 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; };
+		DBFA7157187F1D8600A76262 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; };
+		DBFA7158187F1D8600A76262 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; };
+		DBFA7159187F1D8600A76262 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; };
+		DBFA715A187F1D8600A76262 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; };
+		DBFA715B187F1D8600A76262 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; };
+		DBFA7177187F1D9B00A76262 /* ffi_arm64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716C187F1D9B00A76262 /* ffi_arm64.c */; };
+		DBFA7178187F1D9B00A76262 /* sysv_arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716D187F1D9B00A76262 /* sysv_arm64.S */; };
+		DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716F187F1D9B00A76262 /* ffi_armv7.c */; };
+		DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7170187F1D9B00A76262 /* sysv_armv7.S */; };
+		DBFA717B187F1D9B00A76262 /* trampoline_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */; };
+		DBFA717C187F1D9B00A76262 /* darwin64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */; };
+		DBFA717D187F1D9B00A76262 /* darwin_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7174187F1D9B00A76262 /* darwin_i386.S */; };
+		DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */; };
+		DBFA717F187F1D9B00A76262 /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7176187F1D9B00A76262 /* ffi_i386.c */; };
+		DBFA718E187F1DA100A76262 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7182187F1DA100A76262 /* ffi_i386.h */; };
+		DBFA718F187F1DA100A76262 /* ffi_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7183187F1DA100A76262 /* ffi_x86_64.h */; };
+		DBFA7190187F1DA100A76262 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7184187F1DA100A76262 /* fficonfig_i386.h */; };
+		DBFA7191187F1DA100A76262 /* fficonfig_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */; };
+		DBFA7192187F1DA100A76262 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7186187F1DA100A76262 /* ffitarget_i386.h */; };
+		DBFA7193187F1DA100A76262 /* ffitarget_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */; };
+		DBFA7194187F1DA100A76262 /* darwin64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */; };
+		DBFA7195187F1DA100A76262 /* darwin_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718B187F1DA100A76262 /* darwin_i386.S */; };
+		DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */; };
+		DBFA7197187F1DA100A76262 /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718D187F1DA100A76262 /* ffi_i386.c */; };
 /* End PBXBuildFile section */
 
+/* Begin PBXCopyFilesBuildPhase section */
+		DB13B1641849DF1E0010F42D /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 8;
+			dstPath = "include/$(PRODUCT_NAME)";
+			dstSubfolderSpec = 16;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
 /* Begin PBXFileReference section */
-		6C43CB3D1534E9D100162364 /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
-		6C43CBBD1534F76F00162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
-		6C43CBBF1534F76F00162364 /* sysv.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv.S; sourceTree = "<group>"; };
-		6C43CBC01534F76F00162364 /* trampoline.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = trampoline.S; sourceTree = "<group>"; };
-		6C43CBC91534F76F00162364 /* darwin.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin.S; sourceTree = "<group>"; };
-		6C43CBCB1534F76F00162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
-		6C43CC051534F77800162364 /* darwin.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin.S; sourceTree = "<group>"; };
-		6C43CC061534F77800162364 /* darwin64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64.S; sourceTree = "<group>"; };
-		6C43CC071534F77800162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
-		6C43CC081534F77800162364 /* ffi64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64.c; sourceTree = "<group>"; };
-		6C43CC281534F7BE00162364 /* closures.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = closures.c; path = src/closures.c; sourceTree = SOURCE_ROOT; };
-		6C43CC2B1534F7BE00162364 /* java_raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = java_raw_api.c; path = src/java_raw_api.c; sourceTree = SOURCE_ROOT; };
-		6C43CC2C1534F7BE00162364 /* prep_cif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = prep_cif.c; path = src/prep_cif.c; sourceTree = SOURCE_ROOT; };
-		6C43CC2D1534F7BE00162364 /* raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = raw_api.c; path = src/raw_api.c; sourceTree = SOURCE_ROOT; };
-		6C43CC2E1534F7BE00162364 /* types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = types.c; path = src/types.c; sourceTree = SOURCE_ROOT; };
-		6C43CC8D1535032600162364 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; };
-		6C43CC8E1535032600162364 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = "<group>"; };
-		6C43CC8F1535032600162364 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
-		6C43CC901535032600162364 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = "<group>"; };
-		6C43CC911535032600162364 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = "<group>"; };
-		6C43CC921535032600162364 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
-		6C43CC931535032600162364 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = "<group>"; };
-		6C43CC941535032600162364 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = "<group>"; };
-		6C43CC951535032600162364 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
-		6C43CC961535032600162364 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = "<group>"; };
-		6C43CCA21535039600162364 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; };
-		6C43CCA31535039600162364 /* ffi_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_armv7.h; sourceTree = "<group>"; };
-		6C43CCA41535039600162364 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = "<group>"; };
-		6C43CCA51535039600162364 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
-		6C43CCA61535039600162364 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = "<group>"; };
-		6C43CCA71535039600162364 /* fficonfig_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_armv7.h; sourceTree = "<group>"; };
-		6C43CCA81535039600162364 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
-		6C43CCA91535039600162364 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = "<group>"; };
-		6C43CCAA1535039600162364 /* ffitarget_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm.h; sourceTree = "<group>"; };
-		6C43CCAB1535039600162364 /* ffitarget_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_armv7.h; sourceTree = "<group>"; };
-		6C43CCAC1535039600162364 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
-		F6F980BA147386130008F121 /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		DB13B1661849DF1E0010F42D /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		DB13B1911849DF510010F42D /* ffi.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = ffi.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		DBFA713E187F1D8600A76262 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; };
+		DBFA713F187F1D8600A76262 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = "<group>"; };
+		DBFA7140187F1D8600A76262 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = "<group>"; };
+		DBFA7141187F1D8600A76262 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = "<group>"; };
+		DBFA7143187F1D8600A76262 /* closures.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = closures.c; sourceTree = "<group>"; };
+		DBFA7145187F1D8600A76262 /* dlmalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dlmalloc.c; sourceTree = "<group>"; };
+		DBFA7147187F1D8600A76262 /* prep_cif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = prep_cif.c; sourceTree = "<group>"; };
+		DBFA7148187F1D8600A76262 /* raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = raw_api.c; sourceTree = "<group>"; };
+		DBFA7149187F1D8600A76262 /* types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = types.c; sourceTree = "<group>"; };
+		DBFA715E187F1D9B00A76262 /* ffi_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_arm64.h; sourceTree = "<group>"; };
+		DBFA715F187F1D9B00A76262 /* ffi_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_armv7.h; sourceTree = "<group>"; };
+		DBFA7160187F1D9B00A76262 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
+		DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = "<group>"; };
+		DBFA7162187F1D9B00A76262 /* fficonfig_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_arm64.h; sourceTree = "<group>"; };
+		DBFA7163187F1D9B00A76262 /* fficonfig_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_armv7.h; sourceTree = "<group>"; };
+		DBFA7164187F1D9B00A76262 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
+		DBFA7165187F1D9B00A76262 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = "<group>"; };
+		DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm64.h; sourceTree = "<group>"; };
+		DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_armv7.h; sourceTree = "<group>"; };
+		DBFA7168187F1D9B00A76262 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
+		DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = "<group>"; };
+		DBFA716C187F1D9B00A76262 /* ffi_arm64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_arm64.c; sourceTree = "<group>"; };
+		DBFA716D187F1D9B00A76262 /* sysv_arm64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_arm64.S; sourceTree = "<group>"; };
+		DBFA716F187F1D9B00A76262 /* ffi_armv7.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_armv7.c; sourceTree = "<group>"; };
+		DBFA7170187F1D9B00A76262 /* sysv_armv7.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_armv7.S; sourceTree = "<group>"; };
+		DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = trampoline_armv7.S; sourceTree = "<group>"; };
+		DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64_x86_64.S; sourceTree = "<group>"; };
+		DBFA7174187F1D9B00A76262 /* darwin_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin_i386.S; sourceTree = "<group>"; };
+		DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = "<group>"; };
+		DBFA7176187F1D9B00A76262 /* ffi_i386.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_i386.c; sourceTree = "<group>"; };
+		DBFA7182187F1DA100A76262 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
+		DBFA7183187F1DA100A76262 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = "<group>"; };
+		DBFA7184187F1DA100A76262 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
+		DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = "<group>"; };
+		DBFA7186187F1DA100A76262 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
+		DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = "<group>"; };
+		DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64_x86_64.S; sourceTree = "<group>"; };
+		DBFA718B187F1DA100A76262 /* darwin_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin_i386.S; sourceTree = "<group>"; };
+		DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = "<group>"; };
+		DBFA718D187F1DA100A76262 /* ffi_i386.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_i386.c; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
-/* Begin PBXFrameworksBuildPhase section */
-		6C43CB3A1534E9D100162364 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		F6F980B7147386130008F121 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXFrameworksBuildPhase section */
-
 /* Begin PBXGroup section */
-		6C43CBAF1534F76F00162364 /* iOS */ = {
+		DB13B15B1849DEB70010F42D = {
 			isa = PBXGroup;
 			children = (
-				6C43CCA11535039600162364 /* include */,
-				6C43CBBB1534F76F00162364 /* src */,
+				DBFA713C187F1D8600A76262 /* darwin_common */,
+				DBFA715C187F1D9B00A76262 /* darwin_ios */,
+				DBFA7180187F1DA100A76262 /* darwin_osx */,
+				DB13B1671849DF1E0010F42D /* Products */,
 			);
-			name = iOS;
-			path = ios;
 			sourceTree = "<group>";
 		};
-		6C43CBBB1534F76F00162364 /* src */ = {
+		DB13B1671849DF1E0010F42D /* Products */ = {
 			isa = PBXGroup;
 			children = (
-				6C43CBC81534F76F00162364 /* x86 */,
-				6C43CBBC1534F76F00162364 /* arm */,
+				DB13B1661849DF1E0010F42D /* libffi.a */,
+				DB13B1911849DF510010F42D /* ffi.dylib */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		DBFA713C187F1D8600A76262 /* darwin_common */ = {
+			isa = PBXGroup;
+			children = (
+				DBFA713D187F1D8600A76262 /* include */,
+				DBFA7142187F1D8600A76262 /* src */,
+			);
+			path = "darwin_common";
+			sourceTree = "<group>";
+		};
+		DBFA713D187F1D8600A76262 /* include */ = {
+			isa = PBXGroup;
+			children = (
+				DBFA713E187F1D8600A76262 /* ffi.h */,
+				DBFA713F187F1D8600A76262 /* ffi_common.h */,
+				DBFA7140187F1D8600A76262 /* fficonfig.h */,
+				DBFA7141187F1D8600A76262 /* ffitarget.h */,
+			);
+			path = include;
+			sourceTree = "<group>";
+		};
+		DBFA7142187F1D8600A76262 /* src */ = {
+			isa = PBXGroup;
+			children = (
+				DBFA7143187F1D8600A76262 /* closures.c */,
+				DBFA7145187F1D8600A76262 /* dlmalloc.c */,
+				DBFA7147187F1D8600A76262 /* prep_cif.c */,
+				DBFA7148187F1D8600A76262 /* raw_api.c */,
+				DBFA7149187F1D8600A76262 /* types.c */,
 			);
 			path = src;
 			sourceTree = "<group>";
 		};
-		6C43CBBC1534F76F00162364 /* arm */ = {
+		DBFA715C187F1D9B00A76262 /* darwin_ios */ = {
 			isa = PBXGroup;
 			children = (
-				6C43CBBD1534F76F00162364 /* ffi.c */,
-				6C43CBBF1534F76F00162364 /* sysv.S */,
-				6C43CBC01534F76F00162364 /* trampoline.S */,
+				DBFA715D187F1D9B00A76262 /* include */,
+				DBFA716A187F1D9B00A76262 /* src */,
+			);
+			path = "darwin_ios";
+			sourceTree = "<group>";
+		};
+		DBFA715D187F1D9B00A76262 /* include */ = {
+			isa = PBXGroup;
+			children = (
+				DBFA715E187F1D9B00A76262 /* ffi_arm64.h */,
+				DBFA715F187F1D9B00A76262 /* ffi_armv7.h */,
+				DBFA7160187F1D9B00A76262 /* ffi_i386.h */,
+				DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */,
+				DBFA7162187F1D9B00A76262 /* fficonfig_arm64.h */,
+				DBFA7163187F1D9B00A76262 /* fficonfig_armv7.h */,
+				DBFA7164187F1D9B00A76262 /* fficonfig_i386.h */,
+				DBFA7165187F1D9B00A76262 /* fficonfig_x86_64.h */,
+				DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */,
+				DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */,
+				DBFA7168187F1D9B00A76262 /* ffitarget_i386.h */,
+				DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */,
+			);
+			path = include;
+			sourceTree = "<group>";
+		};
+		DBFA716A187F1D9B00A76262 /* src */ = {
+			isa = PBXGroup;
+			children = (
+				DBFA716B187F1D9B00A76262 /* aarch64 */,
+				DBFA716E187F1D9B00A76262 /* arm */,
+				DBFA7172187F1D9B00A76262 /* x86 */,
+			);
+			path = src;
+			sourceTree = "<group>";
+		};
+		DBFA716B187F1D9B00A76262 /* aarch64 */ = {
+			isa = PBXGroup;
+			children = (
+				DBFA716C187F1D9B00A76262 /* ffi_arm64.c */,
+				DBFA716D187F1D9B00A76262 /* sysv_arm64.S */,
+			);
+			path = aarch64;
+			sourceTree = "<group>";
+		};
+		DBFA716E187F1D9B00A76262 /* arm */ = {
+			isa = PBXGroup;
+			children = (
+				DBFA716F187F1D9B00A76262 /* ffi_armv7.c */,
+				DBFA7170187F1D9B00A76262 /* sysv_armv7.S */,
+				DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */,
 			);
 			path = arm;
 			sourceTree = "<group>";
 		};
-		6C43CBC81534F76F00162364 /* x86 */ = {
+		DBFA7172187F1D9B00A76262 /* x86 */ = {
 			isa = PBXGroup;
 			children = (
-				6C43CBC91534F76F00162364 /* darwin.S */,
-				6C43CBCB1534F76F00162364 /* ffi.c */,
+				DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */,
+				DBFA7174187F1D9B00A76262 /* darwin_i386.S */,
+				DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */,
+				DBFA7176187F1D9B00A76262 /* ffi_i386.c */,
 			);
 			path = x86;
 			sourceTree = "<group>";
 		};
-		6C43CBF01534F77800162364 /* OS X */ = {
+		DBFA7180187F1DA100A76262 /* darwin_osx */ = {
 			isa = PBXGroup;
 			children = (
-				6C43CC8C1535032600162364 /* include */,
-				6C43CBFC1534F77800162364 /* src */,
+				DBFA7181187F1DA100A76262 /* include */,
+				DBFA7188187F1DA100A76262 /* src */,
 			);
-			name = "OS X";
-			path = osx;
+			path = "darwin_osx";
 			sourceTree = "<group>";
 		};
-		6C43CBFC1534F77800162364 /* src */ = {
+		DBFA7181187F1DA100A76262 /* include */ = {
 			isa = PBXGroup;
 			children = (
-				6C43CC041534F77800162364 /* x86 */,
+				DBFA7182187F1DA100A76262 /* ffi_i386.h */,
+				DBFA7183187F1DA100A76262 /* ffi_x86_64.h */,
+				DBFA7184187F1DA100A76262 /* fficonfig_i386.h */,
+				DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */,
+				DBFA7186187F1DA100A76262 /* ffitarget_i386.h */,
+				DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */,
+			);
+			path = include;
+			sourceTree = "<group>";
+		};
+		DBFA7188187F1DA100A76262 /* src */ = {
+			isa = PBXGroup;
+			children = (
+				DBFA7189187F1DA100A76262 /* x86 */,
 			);
 			path = src;
 			sourceTree = "<group>";
 		};
-		6C43CC041534F77800162364 /* x86 */ = {
+		DBFA7189187F1DA100A76262 /* x86 */ = {
 			isa = PBXGroup;
 			children = (
-				6C43CC051534F77800162364 /* darwin.S */,
-				6C43CC061534F77800162364 /* darwin64.S */,
-				6C43CC071534F77800162364 /* ffi.c */,
-				6C43CC081534F77800162364 /* ffi64.c */,
+				DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */,
+				DBFA718B187F1DA100A76262 /* darwin_i386.S */,
+				DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */,
+				DBFA718D187F1DA100A76262 /* ffi_i386.c */,
 			);
 			path = x86;
 			sourceTree = "<group>";
 		};
-		6C43CC3D1534F7C400162364 /* src */ = {
-			isa = PBXGroup;
-			children = (
-				6C43CC281534F7BE00162364 /* closures.c */,
-				6C43CC2B1534F7BE00162364 /* java_raw_api.c */,
-				6C43CC2C1534F7BE00162364 /* prep_cif.c */,
-				6C43CC2D1534F7BE00162364 /* raw_api.c */,
-				6C43CC2E1534F7BE00162364 /* types.c */,
-			);
-			name = src;
-			path = ios;
-			sourceTree = "<group>";
-		};
-		6C43CC8C1535032600162364 /* include */ = {
-			isa = PBXGroup;
-			children = (
-				6C43CC8D1535032600162364 /* ffi.h */,
-				6C43CC8E1535032600162364 /* ffi_common.h */,
-				6C43CC8F1535032600162364 /* ffi_i386.h */,
-				6C43CC901535032600162364 /* ffi_x86_64.h */,
-				6C43CC911535032600162364 /* fficonfig.h */,
-				6C43CC921535032600162364 /* fficonfig_i386.h */,
-				6C43CC931535032600162364 /* fficonfig_x86_64.h */,
-				6C43CC941535032600162364 /* ffitarget.h */,
-				6C43CC951535032600162364 /* ffitarget_i386.h */,
-				6C43CC961535032600162364 /* ffitarget_x86_64.h */,
-			);
-			path = include;
-			sourceTree = "<group>";
-		};
-		6C43CCA11535039600162364 /* include */ = {
-			isa = PBXGroup;
-			children = (
-				6C43CCA21535039600162364 /* ffi.h */,
-				6C43CCA31535039600162364 /* ffi_armv7.h */,
-				6C43CCA41535039600162364 /* ffi_common.h */,
-				6C43CCA51535039600162364 /* ffi_i386.h */,
-				6C43CCA61535039600162364 /* fficonfig.h */,
-				6C43CCA71535039600162364 /* fficonfig_armv7.h */,
-				6C43CCA81535039600162364 /* fficonfig_i386.h */,
-				6C43CCA91535039600162364 /* ffitarget.h */,
-				6C43CCAA1535039600162364 /* ffitarget_arm.h */,
-				6C43CCAB1535039600162364 /* ffitarget_armv7.h */,
-				6C43CCAC1535039600162364 /* ffitarget_i386.h */,
-			);
-			path = include;
-			sourceTree = "<group>";
-		};
-		F6B0839514721EE50031D8A1 = {
-			isa = PBXGroup;
-			children = (
-				6C43CC3D1534F7C400162364 /* src */,
-				6C43CBAF1534F76F00162364 /* iOS */,
-				6C43CBF01534F77800162364 /* OS X */,
-				F6F980C6147386260008F121 /* Products */,
-			);
-			sourceTree = "<group>";
-		};
-		F6F980C6147386260008F121 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				F6F980BA147386130008F121 /* libffi.a */,
-				6C43CB3D1534E9D100162364 /* libffi.a */,
-			);
-			name = Products;
-			path = ../..;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
 /* End PBXGroup section */
 
 /* Begin PBXHeadersBuildPhase section */
-		6C43CB3B1534E9D100162364 /* Headers */ = {
+		DB13B18F1849DF510010F42D /* Headers */ = {
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				6C43CC971535032600162364 /* ffi.h in Headers */,
-				6C43CC981535032600162364 /* ffi_common.h in Headers */,
-				6C43CC991535032600162364 /* ffi_i386.h in Headers */,
-				6C43CC9A1535032600162364 /* ffi_x86_64.h in Headers */,
-				6C43CC9E1535032600162364 /* ffitarget.h in Headers */,
-				6C43CC9F1535032600162364 /* ffitarget_i386.h in Headers */,
-				6C43CCA01535032600162364 /* ffitarget_x86_64.h in Headers */,
-				6C43CC9B1535032600162364 /* fficonfig.h in Headers */,
-				6C43CC9C1535032600162364 /* fficonfig_i386.h in Headers */,
-				6C43CC9D1535032600162364 /* fficonfig_x86_64.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		F6F980B8147386130008F121 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				6C43CCAD1535039600162364 /* ffi.h in Headers */,
-				6C43CCAE1535039600162364 /* ffi_armv7.h in Headers */,
-				6C43CCAF1535039600162364 /* ffi_common.h in Headers */,
-				6C43CCB01535039600162364 /* ffi_i386.h in Headers */,
-				6C43CCB41535039600162364 /* ffitarget.h in Headers */,
-				6C43CCB51535039600162364 /* ffitarget_arm.h in Headers */,
-				6C43CCB61535039600162364 /* ffitarget_armv7.h in Headers */,
-				6C43CCB71535039600162364 /* ffitarget_i386.h in Headers */,
-				6C43CCB11535039600162364 /* fficonfig.h in Headers */,
-				6C43CCB21535039600162364 /* fficonfig_armv7.h in Headers */,
-				6C43CCB31535039600162364 /* fficonfig_i386.h in Headers */,
+				DBFA714C187F1D8600A76262 /* fficonfig.h in Headers */,
+				DBFA714D187F1D8600A76262 /* ffitarget.h in Headers */,
+				DBFA714A187F1D8600A76262 /* ffi.h in Headers */,
+				DBFA718F187F1DA100A76262 /* ffi_x86_64.h in Headers */,
+				DBFA7191187F1DA100A76262 /* fficonfig_x86_64.h in Headers */,
+				DBFA718E187F1DA100A76262 /* ffi_i386.h in Headers */,
+				DBFA7190187F1DA100A76262 /* fficonfig_i386.h in Headers */,
+				DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */,
+				DBFA7193187F1DA100A76262 /* ffitarget_x86_64.h in Headers */,
+				DBFA7192187F1DA100A76262 /* ffitarget_i386.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXHeadersBuildPhase section */
 
 /* Begin PBXNativeTarget section */
-		6C43CB3C1534E9D100162364 /* libffi OS X */ = {
+		DB13B1651849DF1E0010F42D /* libffi-iOS */ = {
 			isa = PBXNativeTarget;
-			buildConfigurationList = 6C43CB4A1534E9D100162364 /* Build configuration list for PBXNativeTarget "libffi OS X" */;
+			buildConfigurationList = DB13B18B1849DF1E0010F42D /* Build configuration list for PBXNativeTarget "libffi-iOS" */;
 			buildPhases = (
-				6C43CC401534FF3B00162364 /* Generate Source and Headers */,
-				6C43CB391534E9D100162364 /* Sources */,
-				6C43CB3A1534E9D100162364 /* Frameworks */,
-				6C43CB3B1534E9D100162364 /* Headers */,
+				DB13B3051849E01C0010F42D /* ShellScript */,
+				DB13B1621849DF1E0010F42D /* Sources */,
+				DB13B1641849DF1E0010F42D /* CopyFiles */,
 			);
 			buildRules = (
 			);
 			dependencies = (
 			);
-			name = "libffi OS X";
-			productName = "ffi OS X";
-			productReference = 6C43CB3D1534E9D100162364 /* libffi.a */;
+			name = "libffi-iOS";
+			productName = ffi;
+			productReference = DB13B1661849DF1E0010F42D /* libffi.a */;
 			productType = "com.apple.product-type.library.static";
 		};
-		F6F980B9147386130008F121 /* libffi iOS */ = {
+		DB13B1901849DF510010F42D /* libffi-Mac */ = {
 			isa = PBXNativeTarget;
-			buildConfigurationList = F6F980C4147386130008F121 /* Build configuration list for PBXNativeTarget "libffi iOS" */;
+			buildConfigurationList = DB13B1B01849DF520010F42D /* Build configuration list for PBXNativeTarget "libffi-Mac" */;
 			buildPhases = (
-				6C43CC3E1534F8E200162364 /* Generate Trampoline */,
-				6C43CC3F1534FF1B00162364 /* Generate Source and Headers */,
-				F6F980B6147386130008F121 /* Sources */,
-				F6F980B7147386130008F121 /* Frameworks */,
-				F6F980B8147386130008F121 /* Headers */,
+				DB13B3061849E0490010F42D /* ShellScript */,
+				DB13B18D1849DF510010F42D /* Sources */,
+				DB13B18F1849DF510010F42D /* Headers */,
 			);
 			buildRules = (
 			);
 			dependencies = (
 			);
-			name = "libffi iOS";
+			name = "libffi-Mac";
 			productName = ffi;
-			productReference = F6F980BA147386130008F121 /* libffi.a */;
-			productType = "com.apple.product-type.library.static";
+			productReference = DB13B1911849DF510010F42D /* ffi.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
 		};
 /* End PBXNativeTarget section */
 
 /* Begin PBXProject section */
-		F6B0839714721EE50031D8A1 /* Project object */ = {
+		DB13B15C1849DEB70010F42D /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
-				LastUpgradeCheck = 0430;
+				LastUpgradeCheck = 0510;
 			};
-			buildConfigurationList = F6B0839A14721EE50031D8A1 /* Build configuration list for PBXProject "libffi" */;
+			buildConfigurationList = DB13B15F1849DEB70010F42D /* Build configuration list for PBXProject "libffi" */;
 			compatibilityVersion = "Xcode 3.2";
 			developmentRegion = English;
 			hasScannedForEncodings = 0;
 			knownRegions = (
 				en,
 			);
-			mainGroup = F6B0839514721EE50031D8A1;
-			productRefGroup = F6B0839514721EE50031D8A1;
+			mainGroup = DB13B15B1849DEB70010F42D;
+			productRefGroup = DB13B1671849DF1E0010F42D /* Products */;
 			projectDirPath = "";
 			projectRoot = "";
 			targets = (
-				F6F980B9147386130008F121 /* libffi iOS */,
-				6C43CB3C1534E9D100162364 /* libffi OS X */,
+				DB13B1651849DF1E0010F42D /* libffi-iOS */,
+				DB13B1901849DF510010F42D /* libffi-Mac */,
 			);
 		};
 /* End PBXProject section */
 
 /* Begin PBXShellScriptBuildPhase section */
-		6C43CC3E1534F8E200162364 /* Generate Trampoline */ = {
+		DB13B3051849E01C0010F42D /* ShellScript */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Generate Trampoline";
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /usr/bin/python;
-			shellScript = "import subprocess\nimport re\nimport os\nimport errno\nimport sys\n\ndef main():\n    with open('src/arm/trampoline.S', 'w') as tramp_out:\n        p = subprocess.Popen(['bash', 'src/arm/gentramp.sh'], stdout=tramp_out)\n        p.wait()\n\nif __name__ == '__main__':\n    main()";
-		};
-		6C43CC3F1534FF1B00162364 /* Generate Source and Headers */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-			);
-			name = "Generate Source and Headers";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "/usr/bin/python generate-ios-source-and-headers.py";
+			shellScript = "/usr/bin/python generate-darwin-source-and-headers.py --only-ios";
 		};
-		6C43CC401534FF3B00162364 /* Generate Source and Headers */ = {
+		DB13B3061849E0490010F42D /* ShellScript */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputPaths = (
 			);
-			name = "Generate Source and Headers";
 			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "/usr/bin/python generate-osx-source-and-headers.py";
+			shellScript = "/usr/bin/python generate-darwin-source-and-headers.py --only-osx";
 		};
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
-		6C43CB391534E9D100162364 /* Sources */ = {
+		DB13B1621849DF1E0010F42D /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				6C43CC1F1534F77800162364 /* darwin.S in Sources */,
-				6C43CC201534F77800162364 /* darwin64.S in Sources */,
-				6C43CC211534F77800162364 /* ffi.c in Sources */,
-				6C43CC221534F77800162364 /* ffi64.c in Sources */,
-				6C43CC301534F7BE00162364 /* closures.c in Sources */,
-				6C43CC361534F7BE00162364 /* java_raw_api.c in Sources */,
-				6C43CC381534F7BE00162364 /* prep_cif.c in Sources */,
-				6C43CC3A1534F7BE00162364 /* raw_api.c in Sources */,
-				6C43CC3C1534F7BE00162364 /* types.c in Sources */,
+				DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */,
+				DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */,
+				DBFA717B187F1D9B00A76262 /* trampoline_armv7.S in Sources */,
+				DBFA714E187F1D8600A76262 /* closures.c in Sources */,
+				DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */,
+				DBFA717D187F1D9B00A76262 /* darwin_i386.S in Sources */,
+				DBFA7156187F1D8600A76262 /* prep_cif.c in Sources */,
+				DBFA717F187F1D9B00A76262 /* ffi_i386.c in Sources */,
+				DBFA7158187F1D8600A76262 /* raw_api.c in Sources */,
+				DBFA7178187F1D9B00A76262 /* sysv_arm64.S in Sources */,
+				DBFA717C187F1D9B00A76262 /* darwin64_x86_64.S in Sources */,
+				DBFA715A187F1D8600A76262 /* types.c in Sources */,
+				DBFA7177187F1D9B00A76262 /* ffi_arm64.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		F6F980B6147386130008F121 /* Sources */ = {
+		DB13B18D1849DF510010F42D /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				6C43CBDC1534F76F00162364 /* ffi.c in Sources */,
-				6C43CBDD1534F76F00162364 /* sysv.S in Sources */,
-				6C43CBDE1534F76F00162364 /* trampoline.S in Sources */,
-				6C43CBE61534F76F00162364 /* darwin.S in Sources */,
-				6C43CBE81534F76F00162364 /* ffi.c in Sources */,
-				6C43CC2F1534F7BE00162364 /* closures.c in Sources */,
-				6C43CC351534F7BE00162364 /* java_raw_api.c in Sources */,
-				6C43CC371534F7BE00162364 /* prep_cif.c in Sources */,
-				6C43CC391534F7BE00162364 /* raw_api.c in Sources */,
-				6C43CC3B1534F7BE00162364 /* types.c in Sources */,
+				DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */,
+				DBFA7195187F1DA100A76262 /* darwin_i386.S in Sources */,
+				DBFA7157187F1D8600A76262 /* prep_cif.c in Sources */,
+				DBFA7197187F1DA100A76262 /* ffi_i386.c in Sources */,
+				DBFA715B187F1D8600A76262 /* types.c in Sources */,
+				DBFA7159187F1D8600A76262 /* raw_api.c in Sources */,
+				DBFA714F187F1D8600A76262 /* closures.c in Sources */,
+				DBFA7194187F1DA100A76262 /* darwin64_x86_64.S in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXSourcesBuildPhase section */
 
 /* Begin XCBuildConfiguration section */
-		6C43CB4B1534E9D100162364 /* Debug */ = {
+		DB13B1601849DEB70010F42D /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
-				DSTROOT = /tmp/ffi.dst;
-				FRAMEWORK_SEARCH_PATHS = (
+				HEADER_SEARCH_PATHS = (
 					"$(inherited)",
-					"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
+					"darwin_common/include",
 				);
-				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
-				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
-				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = YES;
-				MACOSX_DEPLOYMENT_TARGET = 10.6;
 				ONLY_ACTIVE_ARCH = YES;
-				PRODUCT_NAME = ffi;
-				SDKROOT = macosx;
 			};
 			name = Debug;
 		};
-		6C43CB4C1534E9D100162364 /* Release */ = {
+		DB13B1611849DEB70010F42D /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
-				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-				DSTROOT = /tmp/ffi.dst;
-				FRAMEWORK_SEARCH_PATHS = (
+				HEADER_SEARCH_PATHS = (
 					"$(inherited)",
-					"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
+					"darwin_common/include",
 				);
-				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
-				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
-				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = YES;
-				MACOSX_DEPLOYMENT_TARGET = 10.6;
-				PRODUCT_NAME = ffi;
-				SDKROOT = macosx;
 			};
 			name = Release;
 		};
-		F6B083AB14721EE50031D8A1 /* Debug */ = {
+		DB13B1871849DF1E0010F42D /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
-				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
+				DSTROOT = /tmp/ffi.dst;
 				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_DYNAMIC_NO_PIC = NO;
 				GCC_OPTIMIZATION_LEVEL = 0;
@@ -482,98 +457,181 @@
 					"$(inherited)",
 				);
 				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
-				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
-				GCC_WARN_ABOUT_RETURN_TYPE = YES;
-				GCC_WARN_UNUSED_VALUE = NO;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				HEADER_SEARCH_PATHS = ios/include;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"darwin_ios/include",
+				);
+				IPHONEOS_DEPLOYMENT_TARGET = 5.0;
+				"IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 7.0;
+				OTHER_LDFLAGS = "-ObjC";
+				PRODUCT_NAME = ffi;
 				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
 			};
 			name = Debug;
 		};
-		F6B083AC14721EE50031D8A1 /* Release */ = {
+		DB13B1881849DF1E0010F42D /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
-				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = YES;
+				DSTROOT = /tmp/ffi.dst;
+				ENABLE_NS_ASSERTIONS = NO;
 				GCC_C_LANGUAGE_STANDARD = gnu99;
-				GCC_PREPROCESSOR_DEFINITIONS = "";
-				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
-				GCC_WARN_ABOUT_RETURN_TYPE = YES;
-				GCC_WARN_UNUSED_VALUE = NO;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				HEADER_SEARCH_PATHS = ios/include;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"darwin_ios/include",
+				);
+				IPHONEOS_DEPLOYMENT_TARGET = 5.0;
+				"IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 7.0;
+				OTHER_LDFLAGS = "-ObjC";
+				PRODUCT_NAME = ffi;
 				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
 				VALIDATE_PRODUCT = YES;
 			};
 			name = Release;
 		};
-		F6F980C2147386130008F121 /* Debug */ = {
+		DB13B1B11849DF520010F42D /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				ARCHS = (
-					armv6,
-					armv7,
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
 				);
-				DSTROOT = /tmp/ffi.dst;
-				GCC_PRECOMPILE_PREFIX_HEADER = YES;
-				GCC_THUMB_SUPPORT = NO;
-				IPHONEOS_DEPLOYMENT_TARGET = 4.0;
-				OTHER_LDFLAGS = "-ObjC";
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"darwin_osx/include",
+				);
+				MACOSX_DEPLOYMENT_TARGET = 10.6;
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_LDFLAGS = "-Wl,-no_compact_unwind";
 				PRODUCT_NAME = ffi;
-				SKIP_INSTALL = YES;
+				SDKROOT = macosx;
 			};
 			name = Debug;
 		};
-		F6F980C3147386130008F121 /* Release */ = {
+		DB13B1B21849DF520010F42D /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				ARCHS = (
-					armv6,
-					armv7,
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				ENABLE_NS_ASSERTIONS = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"darwin_osx/include",
 				);
-				DSTROOT = /tmp/ffi.dst;
-				GCC_PRECOMPILE_PREFIX_HEADER = YES;
-				GCC_THUMB_SUPPORT = NO;
-				IPHONEOS_DEPLOYMENT_TARGET = 4.0;
-				OTHER_LDFLAGS = "-ObjC";
+				MACOSX_DEPLOYMENT_TARGET = 10.6;
+				OTHER_LDFLAGS = "-Wl,-no_compact_unwind";
 				PRODUCT_NAME = ffi;
-				SKIP_INSTALL = YES;
+				SDKROOT = macosx;
 			};
 			name = Release;
 		};
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
-		6C43CB4A1534E9D100162364 /* Build configuration list for PBXNativeTarget "libffi OS X" */ = {
+		DB13B15F1849DEB70010F42D /* Build configuration list for PBXProject "libffi" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
-				6C43CB4B1534E9D100162364 /* Debug */,
-				6C43CB4C1534E9D100162364 /* Release */,
+				DB13B1601849DEB70010F42D /* Debug */,
+				DB13B1611849DEB70010F42D /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
-		F6B0839A14721EE50031D8A1 /* Build configuration list for PBXProject "libffi" */ = {
+		DB13B18B1849DF1E0010F42D /* Build configuration list for PBXNativeTarget "libffi-iOS" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
-				F6B083AB14721EE50031D8A1 /* Debug */,
-				F6B083AC14721EE50031D8A1 /* Release */,
+				DB13B1871849DF1E0010F42D /* Debug */,
+				DB13B1881849DF1E0010F42D /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
-		F6F980C4147386130008F121 /* Build configuration list for PBXNativeTarget "libffi iOS" */ = {
+		DB13B1B01849DF520010F42D /* Build configuration list for PBXNativeTarget "libffi-Mac" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
-				F6F980C2147386130008F121 /* Debug */,
-				F6F980C3147386130008F121 /* Release */,
+				DB13B1B11849DF520010F42D /* Debug */,
+				DB13B1B21849DF520010F42D /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
 /* End XCConfigurationList section */
 	};
-	rootObject = F6B0839714721EE50031D8A1 /* Project object */;
+	rootObject = DB13B15C1849DEB70010F42D /* Project object */;
 }
diff --git a/third_party/gofrontend/libffi/man/Makefile.in b/third_party/gofrontend/libffi/man/Makefile.in
index 743e67b..39f6cbf 100644
--- a/third_party/gofrontend/libffi/man/Makefile.in
+++ b/third_party/gofrontend/libffi/man/Makefile.in
@@ -97,6 +97,10 @@
 CFLAGS = @CFLAGS@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -149,12 +153,14 @@
 STRIP = @STRIP@
 TARGET = @TARGET@
 TARGETDIR = @TARGETDIR@
+TARGET_OBJ = @TARGET_OBJ@
 VERSION = @VERSION@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
 abs_top_srcdir = @abs_top_srcdir@
 ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
 am__include = @am__include@
 am__leading_dot = @am__leading_dot@
diff --git a/third_party/gofrontend/libffi/man/ffi_prep_cif.3 b/third_party/gofrontend/libffi/man/ffi_prep_cif.3
index e1bdbd7..ab2be8a 100644
--- a/third_party/gofrontend/libffi/man/ffi_prep_cif.3
+++ b/third_party/gofrontend/libffi/man/ffi_prep_cif.3
@@ -61,10 +61,8 @@
 .Nm FFI_BAD_ABI
 will be returned. Available ABIs are
 defined in
-.Nm <ffitarget.h>
-.
+.Nm <ffitarget.h> .
 .Sh SEE ALSO
 .Xr ffi 3 ,
 .Xr ffi_call 3 ,
 .Xr ffi_prep_cif_var 3
-
diff --git a/third_party/gofrontend/libffi/src/aarch64/ffi.c b/third_party/gofrontend/libffi/src/aarch64/ffi.c
index 1405665..0cace9d 100644
--- a/third_party/gofrontend/libffi/src/aarch64/ffi.c
+++ b/third_party/gofrontend/libffi/src/aarch64/ffi.c
@@ -20,19 +20,22 @@
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 
 #include <stdio.h>
-
+#include <stdlib.h>
+#include <stdint.h>
 #include <ffi.h>
 #include <ffi_common.h>
+#include "internal.h"
 
-#include <stdlib.h>
-
-/* Stack alignment requirement in bytes */
-#define AARCH64_STACK_ALIGN 16
-
-#define N_X_ARG_REG 8
-#define N_V_ARG_REG 8
-
-#define AARCH64_FFI_WITH_V (1 << AARCH64_FFI_WITH_V_BIT)
+/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
+   all further uses in this file will refer to the 128-bit type.  */
+#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
+# if FFI_TYPE_LONGDOUBLE != 4
+#  error FFI_TYPE_LONGDOUBLE out of date
+# endif
+#else
+# undef FFI_TYPE_LONGDOUBLE
+# define FFI_TYPE_LONGDOUBLE 4
+#endif
 
 union _d
 {
@@ -40,321 +43,184 @@
   UINT32 s[2];
 };
 
-struct call_context
+struct _v
 {
-  UINT64 x [AARCH64_N_XREG];
-  struct
-  {
-    union _d d[2];
-  } v [AARCH64_N_VREG];
+  union _d d[2] __attribute__((aligned(16)));
 };
 
-static void *
-get_x_addr (struct call_context *context, unsigned n)
+struct call_context
 {
-  return &context->x[n];
-}
+  struct _v v[N_V_ARG_REG];
+  UINT64 x[N_X_ARG_REG];
+};
 
-static void *
-get_s_addr (struct call_context *context, unsigned n)
+#if defined (__clang__) && defined (__APPLE__)
+extern void sys_icache_invalidate (void *start, size_t len);
+#endif
+
+static inline void
+ffi_clear_cache (void *start, void *end)
 {
-#if defined __AARCH64EB__
-  return &context->v[n].d[1].s[1];
+#if defined (__clang__) && defined (__APPLE__)
+  sys_icache_invalidate (start, (char *)end - (char *)start);
+#elif defined (__GNUC__)
+  __builtin___clear_cache (start, end);
 #else
-  return &context->v[n].d[0].s[0];
+#error "Missing builtin to flush instruction cache"
 #endif
 }
 
-static void *
-get_d_addr (struct call_context *context, unsigned n)
-{
-#if defined __AARCH64EB__
-  return &context->v[n].d[1];
-#else
-  return &context->v[n].d[0];
-#endif
-}
-
-static void *
-get_v_addr (struct call_context *context, unsigned n)
-{
-  return &context->v[n];
-}
-
-/* Return the memory location at which a basic type would reside
-   were it to have been stored in register n.  */
-
-static void *
-get_basic_type_addr (unsigned short type, struct call_context *context,
-		     unsigned n)
-{
-  switch (type)
-    {
-    case FFI_TYPE_FLOAT:
-      return get_s_addr (context, n);
-    case FFI_TYPE_DOUBLE:
-      return get_d_addr (context, n);
-    case FFI_TYPE_LONGDOUBLE:
-      return get_v_addr (context, n);
-    case FFI_TYPE_UINT8:
-    case FFI_TYPE_SINT8:
-    case FFI_TYPE_UINT16:
-    case FFI_TYPE_SINT16:
-    case FFI_TYPE_UINT32:
-    case FFI_TYPE_SINT32:
-    case FFI_TYPE_INT:
-    case FFI_TYPE_POINTER:
-    case FFI_TYPE_UINT64:
-    case FFI_TYPE_SINT64:
-      return get_x_addr (context, n);
-    default:
-      FFI_ASSERT (0);
-      return NULL;
-    }
-}
-
-/* Return the alignment width for each of the basic types.  */
-
-static size_t
-get_basic_type_alignment (unsigned short type)
-{
-  switch (type)
-    {
-    case FFI_TYPE_FLOAT:
-    case FFI_TYPE_DOUBLE:
-      return sizeof (UINT64);
-    case FFI_TYPE_LONGDOUBLE:
-      return sizeof (long double);
-    case FFI_TYPE_UINT8:
-    case FFI_TYPE_SINT8:
-    case FFI_TYPE_UINT16:
-    case FFI_TYPE_SINT16:
-    case FFI_TYPE_UINT32:
-    case FFI_TYPE_INT:
-    case FFI_TYPE_SINT32:
-    case FFI_TYPE_POINTER:
-    case FFI_TYPE_UINT64:
-    case FFI_TYPE_SINT64:
-      return sizeof (UINT64);
-
-    default:
-      FFI_ASSERT (0);
-      return 0;
-    }
-}
-
-/* Return the size in bytes for each of the basic types.  */
-
-static size_t
-get_basic_type_size (unsigned short type)
-{
-  switch (type)
-    {
-    case FFI_TYPE_FLOAT:
-      return sizeof (UINT32);
-    case FFI_TYPE_DOUBLE:
-      return sizeof (UINT64);
-    case FFI_TYPE_LONGDOUBLE:
-      return sizeof (long double);
-    case FFI_TYPE_UINT8:
-      return sizeof (UINT8);
-    case FFI_TYPE_SINT8:
-      return sizeof (SINT8);
-    case FFI_TYPE_UINT16:
-      return sizeof (UINT16);
-    case FFI_TYPE_SINT16:
-      return sizeof (SINT16);
-    case FFI_TYPE_UINT32:
-      return sizeof (UINT32);
-    case FFI_TYPE_INT:
-    case FFI_TYPE_SINT32:
-      return sizeof (SINT32);
-    case FFI_TYPE_POINTER:
-    case FFI_TYPE_UINT64:
-      return sizeof (UINT64);
-    case FFI_TYPE_SINT64:
-      return sizeof (SINT64);
-
-    default:
-      FFI_ASSERT (0);
-      return 0;
-    }
-}
-
-extern void
-ffi_call_SYSV (unsigned (*)(struct call_context *context, unsigned char *,
-			    extended_cif *),
-               struct call_context *context,
-               extended_cif *,
-               unsigned,
-               void (*fn)(void));
-
-extern void
-ffi_closure_SYSV (ffi_closure *);
-
-/* Test for an FFI floating point representation.  */
-
-static unsigned
-is_floating_type (unsigned short type)
-{
-  return (type == FFI_TYPE_FLOAT || type == FFI_TYPE_DOUBLE
-	  || type == FFI_TYPE_LONGDOUBLE);
-}
-
-/* Test for a homogeneous structure.  */
-
-static unsigned short
-get_homogeneous_type (ffi_type *ty)
-{
-  if (ty->type == FFI_TYPE_STRUCT && ty->elements)
-    {
-      unsigned i;
-      unsigned short candidate_type
-	= get_homogeneous_type (ty->elements[0]);
-      for (i =1; ty->elements[i]; i++)
-	{
-	  unsigned short iteration_type = 0;
-	  /* If we have a nested struct, we must find its homogeneous type.
-	     If that fits with our candidate type, we are still
-	     homogeneous.  */
-	  if (ty->elements[i]->type == FFI_TYPE_STRUCT
-	      && ty->elements[i]->elements)
-	    {
-	      iteration_type = get_homogeneous_type (ty->elements[i]);
-	    }
-	  else
-	    {
-	      iteration_type = ty->elements[i]->type;
-	    }
-
-	  /* If we are not homogeneous, return FFI_TYPE_STRUCT.  */
-	  if (candidate_type != iteration_type)
-	    return FFI_TYPE_STRUCT;
-	}
-      return candidate_type;
-    }
-
-  /* Base case, we have no more levels of nesting, so we
-     are a basic type, and so, trivially homogeneous in that type.  */
-  return ty->type;
-}
-
-/* Determine the number of elements within a STRUCT.
-
-   Note, we must handle nested structs.
-
-   If ty is not a STRUCT this function will return 0.  */
-
-static unsigned
-element_count (ffi_type *ty)
-{
-  if (ty->type == FFI_TYPE_STRUCT && ty->elements)
-    {
-      unsigned n;
-      unsigned elems = 0;
-      for (n = 0; ty->elements[n]; n++)
-	{
-	  if (ty->elements[n]->type == FFI_TYPE_STRUCT
-	      && ty->elements[n]->elements)
-	    elems += element_count (ty->elements[n]);
-	  else
-	    elems++;
-	}
-      return elems;
-    }
-  return 0;
-}
-
-/* Test for a homogeneous floating point aggregate.
-
-   A homogeneous floating point aggregate is a homogeneous aggregate of
-   a half- single- or double- precision floating point type with one
-   to four elements.  Note that this includes nested structs of the
-   basic type.  */
+/* A subroutine of is_vfp_type.  Given a structure type, return the type code
+   of the first non-structure element.  Recurse for structure elements.
+   Return -1 if the structure is in fact empty, i.e. no nested elements.  */
 
 static int
-is_hfa (ffi_type *ty)
+is_hfa0 (const ffi_type *ty)
 {
-  if (ty->type == FFI_TYPE_STRUCT
-      && ty->elements[0]
-      && is_floating_type (get_homogeneous_type (ty)))
-    {
-      unsigned n = element_count (ty);
-      return n >= 1 && n <= 4;
-    }
-  return 0;
+  ffi_type **elements = ty->elements;
+  int i, ret = -1;
+
+  if (elements != NULL)
+    for (i = 0; elements[i]; ++i)
+      {
+        ret = elements[i]->type;
+        if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX)
+          {
+            ret = is_hfa0 (elements[i]);
+            if (ret < 0)
+              continue;
+          }
+        break;
+      }
+
+  return ret;
 }
 
-/* Test if an ffi_type is a candidate for passing in a register.
-
-   This test does not check that sufficient registers of the
-   appropriate class are actually available, merely that IFF
-   sufficient registers are available then the argument will be passed
-   in register(s).
-
-   Note that an ffi_type that is deemed to be a register candidate
-   will always be returned in registers.
-
-   Returns 1 if a register candidate else 0.  */
+/* A subroutine of is_vfp_type.  Given a structure type, return true if all
+   of the non-structure elements are the same as CANDIDATE.  */
 
 static int
-is_register_candidate (ffi_type *ty)
+is_hfa1 (const ffi_type *ty, int candidate)
 {
-  switch (ty->type)
-    {
-    case FFI_TYPE_VOID:
-    case FFI_TYPE_FLOAT:
-    case FFI_TYPE_DOUBLE:
-    case FFI_TYPE_LONGDOUBLE:
-    case FFI_TYPE_UINT8:
-    case FFI_TYPE_UINT16:
-    case FFI_TYPE_UINT32:
-    case FFI_TYPE_UINT64:
-    case FFI_TYPE_POINTER:
-    case FFI_TYPE_SINT8:
-    case FFI_TYPE_SINT16:
-    case FFI_TYPE_SINT32:
-    case FFI_TYPE_INT:
-    case FFI_TYPE_SINT64:
-      return 1;
+  ffi_type **elements = ty->elements;
+  int i;
 
-    case FFI_TYPE_STRUCT:
-      if (is_hfa (ty))
-        {
-          return 1;
-        }
-      else if (ty->size > 16)
-        {
-          /* Too large. Will be replaced with a pointer to memory. The
-             pointer MAY be passed in a register, but the value will
-             not. This test specifically fails since the argument will
-             never be passed by value in registers. */
+  if (elements != NULL)
+    for (i = 0; elements[i]; ++i)
+      {
+        int t = elements[i]->type;
+        if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
+          {
+            if (!is_hfa1 (elements[i], candidate))
+              return 0;
+          }
+        else if (t != candidate)
           return 0;
-        }
-      else
-        {
-          /* Might be passed in registers depending on the number of
-             registers required. */
-          return (ty->size + 7) / 8 < N_X_ARG_REG;
-        }
-      break;
+      }
 
+  return 1;
+}
+
+/* Determine if TY may be allocated to the FP registers.  This is both an
+   fp scalar type as well as an homogenous floating point aggregate (HFA).
+   That is, a structure consisting of 1 to 4 members of all the same type,
+   where that type is an fp scalar.
+
+   Returns non-zero iff TY is an HFA.  The result is the AARCH64_RET_*
+   constant for the type.  */
+
+static int
+is_vfp_type (const ffi_type *ty)
+{
+  ffi_type **elements;
+  int candidate, i;
+  size_t size, ele_count;
+
+  /* Quickest tests first.  */
+  candidate = ty->type;
+  switch (candidate)
+    {
     default:
-      FFI_ASSERT (0);
+      return 0;
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_LONGDOUBLE:
+      ele_count = 1;
+      goto done;
+    case FFI_TYPE_COMPLEX:
+      candidate = ty->elements[0]->type;
+      switch (candidate)
+	{
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_LONGDOUBLE:
+	  ele_count = 2;
+	  goto done;
+	}
+      return 0;
+    case FFI_TYPE_STRUCT:
       break;
     }
 
-  return 0;
-}
+  /* No HFA types are smaller than 4 bytes, or larger than 64 bytes.  */
+  size = ty->size;
+  if (size < 4 || size > 64)
+    return 0;
 
-/* Test if an ffi_type argument or result is a candidate for a vector
-   register.  */
+  /* Find the type of the first non-structure member.  */
+  elements = ty->elements;
+  candidate = elements[0]->type;
+  if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX)
+    {
+      for (i = 0; ; ++i)
+        {
+          candidate = is_hfa0 (elements[i]);
+          if (candidate >= 0)
+            break;
+        }
+    }
 
-static int
-is_v_register_candidate (ffi_type *ty)
-{
-  return is_floating_type (ty->type)
-	   || (ty->type == FFI_TYPE_STRUCT && is_hfa (ty));
+  /* If the first member is not a floating point type, it's not an HFA.
+     Also quickly re-check the size of the structure.  */
+  switch (candidate)
+    {
+    case FFI_TYPE_FLOAT:
+      ele_count = size / sizeof(float);
+      if (size != ele_count * sizeof(float))
+        return 0;
+      break;
+    case FFI_TYPE_DOUBLE:
+      ele_count = size / sizeof(double);
+      if (size != ele_count * sizeof(double))
+        return 0;
+      break;
+    case FFI_TYPE_LONGDOUBLE:
+      ele_count = size / sizeof(long double);
+      if (size != ele_count * sizeof(long double))
+        return 0;
+      break;
+    default:
+      return 0;
+    }
+  if (ele_count > 4)
+    return 0;
+
+  /* Finally, make sure that all scalar elements are the same type.  */
+  for (i = 0; elements[i]; ++i)
+    {
+      int t = elements[i]->type;
+      if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
+        {
+          if (!is_hfa1 (elements[i], candidate))
+            return 0;
+        }
+      else if (t != candidate)
+        return 0;
+    }
+
+  /* All tests succeeded.  Encode the result.  */
+ done:
+  return candidate * 4 + (4 - ele_count);
 }
 
 /* Representation of the procedure call argument marshalling
@@ -367,161 +233,198 @@
 {
   unsigned ngrn;                /* Next general-purpose register number. */
   unsigned nsrn;                /* Next vector register number. */
-  unsigned nsaa;                /* Next stack offset. */
+  size_t nsaa;                  /* Next stack offset. */
+
+#if defined (__APPLE__)
+  unsigned allocating_variadic;
+#endif
 };
 
 /* Initialize a procedure call argument marshalling state.  */
 static void
-arg_init (struct arg_state *state, unsigned call_frame_size)
+arg_init (struct arg_state *state)
 {
   state->ngrn = 0;
   state->nsrn = 0;
   state->nsaa = 0;
-}
-
-/* Return the number of available consecutive core argument
-   registers.  */
-
-static unsigned
-available_x (struct arg_state *state)
-{
-  return N_X_ARG_REG - state->ngrn;
-}
-
-/* Return the number of available consecutive vector argument
-   registers.  */
-
-static unsigned
-available_v (struct arg_state *state)
-{
-  return N_V_ARG_REG - state->nsrn;
-}
-
-static void *
-allocate_to_x (struct call_context *context, struct arg_state *state)
-{
-  FFI_ASSERT (state->ngrn < N_X_ARG_REG)
-  return get_x_addr (context, (state->ngrn)++);
-}
-
-static void *
-allocate_to_s (struct call_context *context, struct arg_state *state)
-{
-  FFI_ASSERT (state->nsrn < N_V_ARG_REG)
-  return get_s_addr (context, (state->nsrn)++);
-}
-
-static void *
-allocate_to_d (struct call_context *context, struct arg_state *state)
-{
-  FFI_ASSERT (state->nsrn < N_V_ARG_REG)
-  return get_d_addr (context, (state->nsrn)++);
-}
-
-static void *
-allocate_to_v (struct call_context *context, struct arg_state *state)
-{
-  FFI_ASSERT (state->nsrn < N_V_ARG_REG)
-  return get_v_addr (context, (state->nsrn)++);
+#if defined (__APPLE__)
+  state->allocating_variadic = 0;
+#endif
 }
 
 /* Allocate an aligned slot on the stack and return a pointer to it.  */
 static void *
-allocate_to_stack (struct arg_state *state, void *stack, unsigned alignment,
-		   unsigned size)
+allocate_to_stack (struct arg_state *state, void *stack,
+		   size_t alignment, size_t size)
 {
-  void *allocation;
+  size_t nsaa = state->nsaa;
 
   /* Round up the NSAA to the larger of 8 or the natural
      alignment of the argument's type.  */
-  state->nsaa = ALIGN (state->nsaa, alignment);
-  state->nsaa = ALIGN (state->nsaa, alignment);
-  state->nsaa = ALIGN (state->nsaa, 8);
+#if defined (__APPLE__)
+  if (state->allocating_variadic && alignment < 8)
+    alignment = 8;
+#else
+  if (alignment < 8)
+    alignment = 8;
+#endif
+    
+  nsaa = ALIGN (nsaa, alignment);
+  state->nsaa = nsaa + size;
 
-  allocation = stack + state->nsaa;
+  return (char *)stack + nsaa;
+}
 
-  state->nsaa += size;
-  return allocation;
+static ffi_arg
+extend_integer_type (void *source, int type)
+{
+  switch (type)
+    {
+    case FFI_TYPE_UINT8:
+      return *(UINT8 *) source;
+    case FFI_TYPE_SINT8:
+      return *(SINT8 *) source;
+    case FFI_TYPE_UINT16:
+      return *(UINT16 *) source;
+    case FFI_TYPE_SINT16:
+      return *(SINT16 *) source;
+    case FFI_TYPE_UINT32:
+      return *(UINT32 *) source;
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+      return *(SINT32 *) source;
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      return *(UINT64 *) source;
+      break;
+    case FFI_TYPE_POINTER:
+      return *(uintptr_t *) source;
+    default:
+      abort();
+    }
 }
 
 static void
-copy_basic_type (void *dest, void *source, unsigned short type)
+extend_hfa_type (void *dest, void *src, int h)
 {
-  /* This is neccessary to ensure that basic types are copied
-     sign extended to 64-bits as libffi expects.  */
-  switch (type)
+  int f = h - AARCH64_RET_S4;
+  void *x0;
+
+  asm volatile (
+	"adr	%0, 0f\n"
+"	add	%0, %0, %1\n"
+"	br	%0\n"
+"0:	ldp	s16, s17, [%3]\n"	/* S4 */
+"	ldp	s18, s19, [%3, #8]\n"
+"	b	4f\n"
+"	ldp	s16, s17, [%3]\n"	/* S3 */
+"	ldr	s18, [%3, #8]\n"
+"	b	3f\n"
+"	ldp	s16, s17, [%3]\n"	/* S2 */
+"	b	2f\n"
+"	nop\n"
+"	ldr	s16, [%3]\n"		/* S1 */
+"	b	1f\n"
+"	nop\n"
+"	ldp	d16, d17, [%3]\n"	/* D4 */
+"	ldp	d18, d19, [%3, #16]\n"
+"	b	4f\n"
+"	ldp	d16, d17, [%3]\n"	/* D3 */
+"	ldr	d18, [%3, #16]\n"
+"	b	3f\n"
+"	ldp	d16, d17, [%3]\n"	/* D2 */
+"	b	2f\n"
+"	nop\n"
+"	ldr	d16, [%3]\n"		/* D1 */
+"	b	1f\n"
+"	nop\n"
+"	ldp	q16, q17, [%3]\n"	/* Q4 */
+"	ldp	q18, q19, [%3, #16]\n"
+"	b	4f\n"
+"	ldp	q16, q17, [%3]\n"	/* Q3 */
+"	ldr	q18, [%3, #16]\n"
+"	b	3f\n"
+"	ldp	q16, q17, [%3]\n"	/* Q2 */
+"	b	2f\n"
+"	nop\n"
+"	ldr	q16, [%3]\n"		/* Q1 */
+"	b	1f\n"
+"4:	str	q19, [%2, #48]\n"
+"3:	str	q18, [%2, #32]\n"
+"2:	str	q17, [%2, #16]\n"
+"1:	str	q16, [%2]"
+    : "=&r"(x0)
+    : "r"(f * 12), "r"(dest), "r"(src)
+    : "memory", "v16", "v17", "v18", "v19");
+}
+
+static void *
+compress_hfa_type (void *dest, void *reg, int h)
+{
+  switch (h)
     {
-    case FFI_TYPE_FLOAT:
-      *(float *) dest = *(float *) source;
+    case AARCH64_RET_S1:
+      if (dest == reg)
+	{
+#ifdef __AARCH64EB__
+	  dest += 12;
+#endif
+	}
+      else
+	*(float *)dest = *(float *)reg;
       break;
-    case FFI_TYPE_DOUBLE:
-      *(double *) dest = *(double *) source;
+    case AARCH64_RET_S2:
+      asm ("ldp q16, q17, [%1]\n\t"
+	   "st2 { v16.s, v17.s }[0], [%0]"
+	   : : "r"(dest), "r"(reg) : "memory", "v16", "v17");
       break;
-    case FFI_TYPE_LONGDOUBLE:
-      *(long double *) dest = *(long double *) source;
+    case AARCH64_RET_S3:
+      asm ("ldp q16, q17, [%1]\n\t"
+	   "ldr q18, [%1, #32]\n\t"
+	   "st3 { v16.s, v17.s, v18.s }[0], [%0]"
+	   : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18");
       break;
-    case FFI_TYPE_UINT8:
-      *(ffi_arg *) dest = *(UINT8 *) source;
+    case AARCH64_RET_S4:
+      asm ("ldp q16, q17, [%1]\n\t"
+	   "ldp q18, q19, [%1, #32]\n\t"
+	   "st4 { v16.s, v17.s, v18.s, v19.s }[0], [%0]"
+	   : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18", "v19");
       break;
-    case FFI_TYPE_SINT8:
-      *(ffi_sarg *) dest = *(SINT8 *) source;
+
+    case AARCH64_RET_D1:
+      if (dest == reg)
+	{
+#ifdef __AARCH64EB__
+	  dest += 8;
+#endif
+	}
+      else
+	*(double *)dest = *(double *)reg;
       break;
-    case FFI_TYPE_UINT16:
-      *(ffi_arg *) dest = *(UINT16 *) source;
+    case AARCH64_RET_D2:
+      asm ("ldp q16, q17, [%1]\n\t"
+	   "st2 { v16.d, v17.d }[0], [%0]"
+	   : : "r"(dest), "r"(reg) : "memory", "v16", "v17");
       break;
-    case FFI_TYPE_SINT16:
-      *(ffi_sarg *) dest = *(SINT16 *) source;
+    case AARCH64_RET_D3:
+      asm ("ldp q16, q17, [%1]\n\t"
+	   "ldr q18, [%1, #32]\n\t"
+	   "st3 { v16.d, v17.d, v18.d }[0], [%0]"
+	   : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18");
       break;
-    case FFI_TYPE_UINT32:
-      *(ffi_arg *) dest = *(UINT32 *) source;
-      break;
-    case FFI_TYPE_INT:
-    case FFI_TYPE_SINT32:
-      *(ffi_sarg *) dest = *(SINT32 *) source;
-      break;
-    case FFI_TYPE_POINTER:
-    case FFI_TYPE_UINT64:
-      *(ffi_arg *) dest = *(UINT64 *) source;
-      break;
-    case FFI_TYPE_SINT64:
-      *(ffi_sarg *) dest = *(SINT64 *) source;
+    case AARCH64_RET_D4:
+      asm ("ldp q16, q17, [%1]\n\t"
+	   "ldp q18, q19, [%1, #32]\n\t"
+	   "st4 { v16.d, v17.d, v18.d, v19.d }[0], [%0]"
+	   : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18", "v19");
       break;
 
     default:
-      FFI_ASSERT (0);
+      if (dest != reg)
+	return memcpy (dest, reg, 16 * (4 - (h & 3)));
+      break;
     }
-}
-
-static void
-copy_hfa_to_reg_or_stack (void *memory,
-			  ffi_type *ty,
-			  struct call_context *context,
-			  unsigned char *stack,
-			  struct arg_state *state)
-{
-  unsigned elems = element_count (ty);
-  if (available_v (state) < elems)
-    {
-      /* There are insufficient V registers. Further V register allocations
-	 are prevented, the NSAA is adjusted (by allocate_to_stack ())
-	 and the argument is copied to memory at the adjusted NSAA.  */
-      state->nsrn = N_V_ARG_REG;
-      memcpy (allocate_to_stack (state, stack, ty->alignment, ty->size),
-	      memory,
-	      ty->size);
-    }
-  else
-    {
-      int i;
-      unsigned short type = get_homogeneous_type (ty);
-      unsigned elems = element_count (ty);
-      for (i = 0; i < elems; i++)
-	{
-	  void *reg = allocate_to_v (context, state);
-	  copy_basic_type (reg, memory, type);
-	  memory += get_basic_type_size (type);
-	}
-    }
+  return dest;
 }
 
 /* Either allocate an appropriate register for the argument type, or if
@@ -529,83 +432,164 @@
    to the allocated space.  */
 
 static void *
-allocate_to_register_or_stack (struct call_context *context,
-			       unsigned char *stack,
-			       struct arg_state *state,
-			       unsigned short type)
+allocate_int_to_reg_or_stack (struct call_context *context,
+			      struct arg_state *state,
+			      void *stack, size_t size)
 {
-  size_t alignment = get_basic_type_alignment (type);
-  size_t size = alignment;
-  switch (type)
+  if (state->ngrn < N_X_ARG_REG)
+    return &context->x[state->ngrn++];
+
+  state->ngrn = N_X_ARG_REG;
+  return allocate_to_stack (state, stack, size, size);
+}
+
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  ffi_type *rtype = cif->rtype;
+  size_t bytes = cif->bytes;
+  int flags, i, n;
+
+  switch (rtype->type)
     {
-    case FFI_TYPE_FLOAT:
-      /* This is the only case for which the allocated stack size
-	 should not match the alignment of the type.  */
-      size = sizeof (UINT32);
-      /* Fall through.  */
-    case FFI_TYPE_DOUBLE:
-      if (state->nsrn < N_V_ARG_REG)
-	return allocate_to_d (context, state);
-      state->nsrn = N_V_ARG_REG;
-      break;
-    case FFI_TYPE_LONGDOUBLE:
-      if (state->nsrn < N_V_ARG_REG)
-	return allocate_to_v (context, state);
-      state->nsrn = N_V_ARG_REG;
+    case FFI_TYPE_VOID:
+      flags = AARCH64_RET_VOID;
       break;
     case FFI_TYPE_UINT8:
-    case FFI_TYPE_SINT8:
-    case FFI_TYPE_UINT16:
-    case FFI_TYPE_SINT16:
-    case FFI_TYPE_UINT32:
-    case FFI_TYPE_SINT32:
-    case FFI_TYPE_INT:
-    case FFI_TYPE_POINTER:
-    case FFI_TYPE_UINT64:
-    case FFI_TYPE_SINT64:
-      if (state->ngrn < N_X_ARG_REG)
-	return allocate_to_x (context, state);
-      state->ngrn = N_X_ARG_REG;
+      flags = AARCH64_RET_UINT8;
       break;
+    case FFI_TYPE_UINT16:
+      flags = AARCH64_RET_UINT16;
+      break;
+    case FFI_TYPE_UINT32:
+      flags = AARCH64_RET_UINT32;
+      break;
+    case FFI_TYPE_SINT8:
+      flags = AARCH64_RET_SINT8;
+      break;
+    case FFI_TYPE_SINT16:
+      flags = AARCH64_RET_SINT16;
+      break;
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+      flags = AARCH64_RET_SINT32;
+      break;
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      flags = AARCH64_RET_INT64;
+      break;
+    case FFI_TYPE_POINTER:
+      flags = (sizeof(void *) == 4 ? AARCH64_RET_UINT32 : AARCH64_RET_INT64);
+      break;
+
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_LONGDOUBLE:
+    case FFI_TYPE_STRUCT:
+    case FFI_TYPE_COMPLEX:
+      flags = is_vfp_type (rtype);
+      if (flags == 0)
+	{
+	  size_t s = rtype->size;
+	  if (s > 16)
+	    {
+	      flags = AARCH64_RET_VOID | AARCH64_RET_IN_MEM;
+	      bytes += 8;
+	    }
+	  else if (s == 16)
+	    flags = AARCH64_RET_INT128;
+	  else if (s == 8)
+	    flags = AARCH64_RET_INT64;
+	  else
+	    flags = AARCH64_RET_INT128 | AARCH64_RET_NEED_COPY;
+	}
+      break;
+
     default:
-      FFI_ASSERT (0);
+      abort();
     }
 
-    return allocate_to_stack (state, stack, alignment, size);
+  for (i = 0, n = cif->nargs; i < n; i++)
+    if (is_vfp_type (cif->arg_types[i]))
+      {
+	flags |= AARCH64_FLAG_ARG_V;
+	break;
+      }
+
+  /* Round the stack up to a multiple of the stack alignment requirement. */
+  cif->bytes = ALIGN(bytes, 16);
+  cif->flags = flags;
+#if defined (__APPLE__)
+  cif->aarch64_nfixedargs = 0;
+#endif
+
+  return FFI_OK;
 }
 
-/* Copy a value to an appropriate register, or if none are
-   available, to the stack.  */
+#if defined (__APPLE__)
+/* Perform Apple-specific cif processing for variadic calls */
+ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
+				    unsigned int nfixedargs,
+				    unsigned int ntotalargs)
+{
+  ffi_status status = ffi_prep_cif_machdep (cif);
+  cif->aarch64_nfixedargs = nfixedargs;
+  return status;
+}
+#endif /* __APPLE__ */
 
+extern void ffi_call_SYSV (struct call_context *context, void *frame,
+			   void (*fn)(void), void *rvalue, int flags,
+			   void *closure) FFI_HIDDEN;
+
+/* Call a function with the provided arguments and capture the return
+   value.  */
 static void
-copy_to_register_or_stack (struct call_context *context,
-			   unsigned char *stack,
-			   struct arg_state *state,
-			   void *value,
-			   unsigned short type)
+ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
+	      void **avalue, void *closure)
 {
-  copy_basic_type (
-	  allocate_to_register_or_stack (context, stack, state, type),
-	  value,
-	  type);
-}
-
-/* Marshall the arguments from FFI representation to procedure call
-   context and stack.  */
-
-static unsigned
-aarch64_prep_args (struct call_context *context, unsigned char *stack,
-		   extended_cif *ecif)
-{
-  int i;
+  struct call_context *context;
+  void *stack, *frame, *rvalue;
   struct arg_state state;
+  size_t stack_bytes, rtype_size, rsize;
+  int i, nargs, flags;
+  ffi_type *rtype;
 
-  arg_init (&state, ALIGN(ecif->cif->bytes, 16));
+  flags = cif->flags;
+  rtype = cif->rtype;
+  rtype_size = rtype->size;
+  stack_bytes = cif->bytes;
 
-  for (i = 0; i < ecif->cif->nargs; i++)
+  /* If the target function returns a structure via hidden pointer,
+     then we cannot allow a null rvalue.  Otherwise, mash a null
+     rvalue to void return type.  */
+  rsize = 0;
+  if (flags & AARCH64_RET_IN_MEM)
     {
-      ffi_type *ty = ecif->cif->arg_types[i];
-      switch (ty->type)
+      if (orig_rvalue == NULL)
+	rsize = rtype_size;
+    }
+  else if (orig_rvalue == NULL)
+    flags &= AARCH64_FLAG_ARG_V;
+  else if (flags & AARCH64_RET_NEED_COPY)
+    rsize = 16;
+
+  /* Allocate consectutive stack for everything we'll need.  */
+  context = alloca (sizeof(struct call_context) + stack_bytes + 32 + rsize);
+  stack = context + 1;
+  frame = stack + stack_bytes;
+  rvalue = (rsize ? frame + 32 : orig_rvalue);
+
+  arg_init (&state);
+  for (i = 0, nargs = cif->nargs; i < nargs; i++)
+    {
+      ffi_type *ty = cif->arg_types[i];
+      size_t s = ty->size;
+      void *a = avalue[i];
+      int h, t;
+
+      t = ty->type;
+      switch (t)
 	{
 	case FFI_TYPE_VOID:
 	  FFI_ASSERT (0);
@@ -613,240 +597,195 @@
 
 	/* If the argument is a basic type the argument is allocated to an
 	   appropriate register, or if none are available, to the stack.  */
-	case FFI_TYPE_FLOAT:
-	case FFI_TYPE_DOUBLE:
-	case FFI_TYPE_LONGDOUBLE:
+	case FFI_TYPE_INT:
 	case FFI_TYPE_UINT8:
 	case FFI_TYPE_SINT8:
 	case FFI_TYPE_UINT16:
 	case FFI_TYPE_SINT16:
 	case FFI_TYPE_UINT32:
-	case FFI_TYPE_INT:
 	case FFI_TYPE_SINT32:
-	case FFI_TYPE_POINTER:
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_SINT64:
-	  copy_to_register_or_stack (context, stack, &state,
-				     ecif->avalue[i], ty->type);
+	case FFI_TYPE_POINTER:
+	do_pointer:
+	  {
+	    ffi_arg ext = extend_integer_type (a, t);
+	    if (state.ngrn < N_X_ARG_REG)
+	      context->x[state.ngrn++] = ext;
+	    else
+	      {
+		void *d = allocate_to_stack (&state, stack, ty->alignment, s);
+		state.ngrn = N_X_ARG_REG;
+		/* Note that the default abi extends each argument
+		   to a full 64-bit slot, while the iOS abi allocates
+		   only enough space. */
+#ifdef __APPLE__
+		memcpy(d, a, s);
+#else
+		*(ffi_arg *)d = ext;
+#endif
+	      }
+	  }
 	  break;
 
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_LONGDOUBLE:
 	case FFI_TYPE_STRUCT:
-	  if (is_hfa (ty))
-	    {
-	      copy_hfa_to_reg_or_stack (ecif->avalue[i], ty, context,
-					stack, &state);
-	    }
-	  else if (ty->size > 16)
-	    {
-	      /* If the argument is a composite type that is larger than 16
-		 bytes, then the argument has been copied to memory, and
-		 the argument is replaced by a pointer to the copy.  */
+	case FFI_TYPE_COMPLEX:
+	  {
+	    void *dest;
 
-	      copy_to_register_or_stack (context, stack, &state,
-					 &(ecif->avalue[i]), FFI_TYPE_POINTER);
-	    }
-	  else if (available_x (&state) >= (ty->size + 7) / 8)
-	    {
-	      /* If the argument is a composite type and the size in
-		 double-words is not more than the number of available
-		 X registers, then the argument is copied into consecutive
-		 X registers.  */
-	      int j;
-	      for (j = 0; j < (ty->size + 7) / 8; j++)
-		{
-		  memcpy (allocate_to_x (context, &state),
-			  &(((UINT64 *) ecif->avalue[i])[j]),
-			  sizeof (UINT64));
+	    h = is_vfp_type (ty);
+	    if (h)
+	      {
+		int elems = 4 - (h & 3);
+	        if (state.nsrn + elems <= N_V_ARG_REG)
+		  {
+		    dest = &context->v[state.nsrn];
+		    state.nsrn += elems;
+		    extend_hfa_type (dest, a, h);
+		    break;
+		  }
+		state.nsrn = N_V_ARG_REG;
+		dest = allocate_to_stack (&state, stack, ty->alignment, s);
+	      }
+	    else if (s > 16)
+	      {
+		/* If the argument is a composite type that is larger than 16
+		   bytes, then the argument has been copied to memory, and
+		   the argument is replaced by a pointer to the copy.  */
+		a = &avalue[i];
+		t = FFI_TYPE_POINTER;
+		goto do_pointer;
+	      }
+	    else
+	      {
+		size_t n = (s + 7) / 8;
+		if (state.ngrn + n <= N_X_ARG_REG)
+		  {
+		    /* If the argument is a composite type and the size in
+		       double-words is not more than the number of available
+		       X registers, then the argument is copied into
+		       consecutive X registers.  */
+		    dest = &context->x[state.ngrn];
+		    state.ngrn += n;
+		  }
+		else
+		  {
+		    /* Otherwise, there are insufficient X registers. Further
+		       X register allocations are prevented, the NSAA is
+		       adjusted and the argument is copied to memory at the
+		       adjusted NSAA.  */
+		    state.ngrn = N_X_ARG_REG;
+		    dest = allocate_to_stack (&state, stack, ty->alignment, s);
+		  }
 		}
-	    }
-	  else
-	    {
-	      /* Otherwise, there are insufficient X registers. Further X
-		 register allocations are prevented, the NSAA is adjusted
-		 (by allocate_to_stack ()) and the argument is copied to
-		 memory at the adjusted NSAA.  */
-	      state.ngrn = N_X_ARG_REG;
-
-	      memcpy (allocate_to_stack (&state, stack, ty->alignment,
-					 ty->size), ecif->avalue + i, ty->size);
+	      memcpy (dest, a, s);
 	    }
 	  break;
 
 	default:
-	  FFI_ASSERT (0);
-	  break;
+	  abort();
 	}
+
+#if defined (__APPLE__)
+      if (i + 1 == cif->aarch64_nfixedargs)
+	{
+	  state.ngrn = N_X_ARG_REG;
+	  state.nsrn = N_V_ARG_REG;
+	  state.allocating_variadic = 1;
+	}
+#endif
     }
 
-  return ecif->cif->aarch64_flags;
+  ffi_call_SYSV (context, frame, fn, rvalue, flags, closure);
+
+  if (flags & AARCH64_RET_NEED_COPY)
+    memcpy (orig_rvalue, rvalue, rtype_size);
 }
 
-ffi_status
-ffi_prep_cif_machdep (ffi_cif *cif)
-{
-  /* Round the stack up to a multiple of the stack alignment requirement. */
-  cif->bytes =
-    (cif->bytes + (AARCH64_STACK_ALIGN - 1)) & ~ (AARCH64_STACK_ALIGN - 1);
-
-  /* Initialize our flags. We are interested if this CIF will touch a
-     vector register, if so we will enable context save and load to
-     those registers, otherwise not. This is intended to be friendly
-     to lazy float context switching in the kernel.  */
-  cif->aarch64_flags = 0;
-
-  if (is_v_register_candidate (cif->rtype))
-    {
-      cif->aarch64_flags |= AARCH64_FFI_WITH_V;
-    }
-  else
-    {
-      int i;
-      for (i = 0; i < cif->nargs; i++)
-        if (is_v_register_candidate (cif->arg_types[i]))
-          {
-            cif->aarch64_flags |= AARCH64_FFI_WITH_V;
-            break;
-          }
-    }
-
-  return FFI_OK;
-}
-
-/* Call a function with the provided arguments and capture the return
-   value.  */
 void
-ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
 {
-  extended_cif ecif;
-
-  ecif.cif = cif;
-  ecif.avalue = avalue;
-  ecif.rvalue = rvalue;
-
-  switch (cif->abi)
-    {
-    case FFI_SYSV:
-      {
-        struct call_context context;
-	unsigned stack_bytes;
-
-	/* Figure out the total amount of stack space we need, the
-	   above call frame space needs to be 16 bytes aligned to
-	   ensure correct alignment of the first object inserted in
-	   that space hence the ALIGN applied to cif->bytes.*/
-	stack_bytes = ALIGN(cif->bytes, 16);
-
-	memset (&context, 0, sizeof (context));
-        if (is_register_candidate (cif->rtype))
-          {
-            ffi_call_SYSV (aarch64_prep_args, &context, &ecif, stack_bytes, fn);
-            switch (cif->rtype->type)
-              {
-              case FFI_TYPE_VOID:
-              case FFI_TYPE_FLOAT:
-              case FFI_TYPE_DOUBLE:
-              case FFI_TYPE_LONGDOUBLE:
-              case FFI_TYPE_UINT8:
-              case FFI_TYPE_SINT8:
-              case FFI_TYPE_UINT16:
-              case FFI_TYPE_SINT16:
-              case FFI_TYPE_UINT32:
-              case FFI_TYPE_SINT32:
-              case FFI_TYPE_POINTER:
-              case FFI_TYPE_UINT64:
-              case FFI_TYPE_INT:
-              case FFI_TYPE_SINT64:
-		{
-		  void *addr = get_basic_type_addr (cif->rtype->type,
-						    &context, 0);
-		  copy_basic_type (rvalue, addr, cif->rtype->type);
-		  break;
-		}
-
-              case FFI_TYPE_STRUCT:
-                if (is_hfa (cif->rtype))
-		  {
-		    int j;
-		    unsigned short type = get_homogeneous_type (cif->rtype);
-		    unsigned elems = element_count (cif->rtype);
-		    for (j = 0; j < elems; j++)
-		      {
-			void *reg = get_basic_type_addr (type, &context, j);
-			copy_basic_type (rvalue, reg, type);
-			rvalue += get_basic_type_size (type);
-		      }
-		  }
-                else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG)
-                  {
-                    unsigned size = ALIGN (cif->rtype->size, sizeof (UINT64));
-                    memcpy (rvalue, get_x_addr (&context, 0), size);
-                  }
-                else
-                  {
-                    FFI_ASSERT (0);
-                  }
-                break;
-
-              default:
-                FFI_ASSERT (0);
-                break;
-              }
-          }
-        else
-          {
-            memcpy (get_x_addr (&context, 8), &rvalue, sizeof (UINT64));
-            ffi_call_SYSV (aarch64_prep_args, &context, &ecif,
-			   stack_bytes, fn);
-          }
-        break;
-      }
-
-    default:
-      FFI_ASSERT (0);
-      break;
-    }
+  ffi_call_int (cif, fn, rvalue, avalue, NULL);
 }
 
-static unsigned char trampoline [] =
-{ 0x70, 0x00, 0x00, 0x58,	/* ldr	x16, 1f	*/
-  0x91, 0x00, 0x00, 0x10,	/* adr	x17, 2f	*/
-  0x00, 0x02, 0x1f, 0xd6	/* br	x16	*/
-};
+#ifdef FFI_GO_CLOSURES
+void
+ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
+	     void **avalue, void *closure)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, closure);
+}
+#endif /* FFI_GO_CLOSURES */
 
 /* Build a trampoline.  */
 
-#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,FLAGS)			\
-  ({unsigned char *__tramp = (unsigned char*)(TRAMP);			\
-    UINT64  __fun = (UINT64)(FUN);					\
-    UINT64  __ctx = (UINT64)(CTX);					\
-    UINT64  __flags = (UINT64)(FLAGS);					\
-    memcpy (__tramp, trampoline, sizeof (trampoline));			\
-    memcpy (__tramp + 12, &__fun, sizeof (__fun));			\
-    memcpy (__tramp + 20, &__ctx, sizeof (__ctx));			\
-    memcpy (__tramp + 28, &__flags, sizeof (__flags));			\
-    __clear_cache(__tramp, __tramp + FFI_TRAMPOLINE_SIZE);		\
-  })
+extern void ffi_closure_SYSV (void) FFI_HIDDEN;
+extern void ffi_closure_SYSV_V (void) FFI_HIDDEN;
 
 ffi_status
-ffi_prep_closure_loc (ffi_closure* closure,
+ffi_prep_closure_loc (ffi_closure *closure,
                       ffi_cif* cif,
                       void (*fun)(ffi_cif*,void*,void**,void*),
                       void *user_data,
                       void *codeloc)
 {
+  static const unsigned char trampoline[16] = {
+    0x90, 0x00, 0x00, 0x58,	/* ldr	x16, tramp+16	*/
+    0xf1, 0xff, 0xff, 0x10,	/* adr	x17, tramp+0	*/
+    0x00, 0x02, 0x1f, 0xd6	/* br	x16		*/
+  };
+  char *tramp = closure->tramp;
+  void (*start)(void);
+
   if (cif->abi != FFI_SYSV)
     return FFI_BAD_ABI;
 
-  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_SYSV, codeloc,
-		       cif->aarch64_flags);
-
-  closure->cif  = cif;
+  closure->cif = cif;
+  closure->fun = fun;
   closure->user_data = user_data;
-  closure->fun  = fun;
+
+  memcpy (tramp, trampoline, sizeof(trampoline));
+
+  if (cif->flags & AARCH64_FLAG_ARG_V)
+    start = ffi_closure_SYSV_V;
+  else
+    start = ffi_closure_SYSV;
+  *(UINT64 *)(tramp + 16) = (uintptr_t)start;
+
+  ffi_clear_cache(tramp, tramp + FFI_TRAMPOLINE_SIZE);
 
   return FFI_OK;
 }
 
+#ifdef FFI_GO_CLOSURES
+extern void ffi_go_closure_SYSV (void) FFI_HIDDEN;
+extern void ffi_go_closure_SYSV_V (void) FFI_HIDDEN;
+
+ffi_status
+ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif* cif,
+                     void (*fun)(ffi_cif*,void*,void**,void*))
+{
+  void (*start)(void);
+
+  if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+  if (cif->flags & AARCH64_FLAG_ARG_V)
+    start = ffi_go_closure_SYSV_V;
+  else
+    start = ffi_go_closure_SYSV;
+
+  closure->tramp = start;
+  closure->cif = cif;
+  closure->fun = fun;
+
+  return FFI_OK;
+}
+#endif /* FFI_GO_CLOSURES */
+
 /* Primary handler to setup and invoke a function within a closure.
 
    A closure when invoked enters via the assembler wrapper
@@ -857,220 +796,115 @@
    the stack at the point ffi_closure_SYSV() was invoked.
 
    On the return path the assembler wrapper will reload call context
-   regsiters.
+   registers.
 
    ffi_closure_SYSV_inner() marshalls the call context into ffi value
-   desriptors, invokes the wrapped function, then marshalls the return
+   descriptors, invokes the wrapped function, then marshalls the return
    value back into the call context.  */
 
-void
-ffi_closure_SYSV_inner (ffi_closure *closure, struct call_context *context,
-			void *stack)
+int FFI_HIDDEN
+ffi_closure_SYSV_inner (ffi_cif *cif,
+			void (*fun)(ffi_cif*,void*,void**,void*),
+			void *user_data,
+			struct call_context *context,
+			void *stack, void *rvalue, void *struct_rvalue)
 {
-  ffi_cif *cif = closure->cif;
   void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
-  void *rvalue = NULL;
-  int i;
+  int i, h, nargs, flags;
   struct arg_state state;
 
-  arg_init (&state, ALIGN(cif->bytes, 16));
+  arg_init (&state);
 
-  for (i = 0; i < cif->nargs; i++)
+  for (i = 0, nargs = cif->nargs; i < nargs; i++)
     {
       ffi_type *ty = cif->arg_types[i];
+      int t = ty->type;
+      size_t n, s = ty->size;
 
-      switch (ty->type)
+      switch (t)
 	{
 	case FFI_TYPE_VOID:
 	  FFI_ASSERT (0);
 	  break;
 
+	case FFI_TYPE_INT:
 	case FFI_TYPE_UINT8:
 	case FFI_TYPE_SINT8:
 	case FFI_TYPE_UINT16:
 	case FFI_TYPE_SINT16:
 	case FFI_TYPE_UINT32:
 	case FFI_TYPE_SINT32:
-	case FFI_TYPE_INT:
-	case FFI_TYPE_POINTER:
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_SINT64:
-	case  FFI_TYPE_FLOAT:
-	case  FFI_TYPE_DOUBLE:
-	case  FFI_TYPE_LONGDOUBLE:
-	  avalue[i] = allocate_to_register_or_stack (context, stack,
-						     &state, ty->type);
+	case FFI_TYPE_POINTER:
+	  avalue[i] = allocate_int_to_reg_or_stack (context, &state, stack, s);
 	  break;
 
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_LONGDOUBLE:
 	case FFI_TYPE_STRUCT:
-	  if (is_hfa (ty))
+	case FFI_TYPE_COMPLEX:
+	  h = is_vfp_type (ty);
+	  if (h)
 	    {
-	      unsigned n = element_count (ty);
-	      if (available_v (&state) < n)
+	      n = 4 - (h & 3);
+	      if (state.nsrn + n <= N_V_ARG_REG)
 		{
-		  state.nsrn = N_V_ARG_REG;
-		  avalue[i] = allocate_to_stack (&state, stack, ty->alignment,
-						 ty->size);
+		  void *reg = &context->v[state.nsrn];
+		  state.nsrn += n;
+
+		  /* Eeek! We need a pointer to the structure, however the
+		     homogeneous float elements are being passed in individual
+		     registers, therefore for float and double the structure
+		     is not represented as a contiguous sequence of bytes in
+		     our saved register context.  We don't need the original
+		     contents of the register storage, so we reformat the
+		     structure into the same memory.  */
+		  avalue[i] = compress_hfa_type (reg, reg, h);
 		}
 	      else
 		{
-		  switch (get_homogeneous_type (ty))
-		    {
-		    case FFI_TYPE_FLOAT:
-		      {
-			/* Eeek! We need a pointer to the structure,
-			   however the homogeneous float elements are
-			   being passed in individual S registers,
-			   therefore the structure is not represented as
-			   a contiguous sequence of bytes in our saved
-			   register context. We need to fake up a copy
-			   of the structure layed out in memory
-			   correctly. The fake can be tossed once the
-			   closure function has returned hence alloca()
-			   is sufficient. */
-			int j;
-			UINT32 *p = avalue[i] = alloca (ty->size);
-			for (j = 0; j < element_count (ty); j++)
-			  memcpy (&p[j],
-				  allocate_to_s (context, &state),
-				  sizeof (*p));
-			break;
-		      }
-
-		    case FFI_TYPE_DOUBLE:
-		      {
-			/* Eeek! We need a pointer to the structure,
-			   however the homogeneous float elements are
-			   being passed in individual S registers,
-			   therefore the structure is not represented as
-			   a contiguous sequence of bytes in our saved
-			   register context. We need to fake up a copy
-			   of the structure layed out in memory
-			   correctly. The fake can be tossed once the
-			   closure function has returned hence alloca()
-			   is sufficient. */
-			int j;
-			UINT64 *p = avalue[i] = alloca (ty->size);
-			for (j = 0; j < element_count (ty); j++)
-			  memcpy (&p[j],
-				  allocate_to_d (context, &state),
-				  sizeof (*p));
-			break;
-		      }
-
-		    case FFI_TYPE_LONGDOUBLE:
-			  memcpy (&avalue[i],
-				  allocate_to_v (context, &state),
-				  sizeof (*avalue));
-		      break;
-
-		    default:
-		      FFI_ASSERT (0);
-		      break;
-		    }
+		  state.nsrn = N_V_ARG_REG;
+		  avalue[i] = allocate_to_stack (&state, stack,
+						 ty->alignment, s);
 		}
 	    }
-	  else if (ty->size > 16)
+	  else if (s > 16)
 	    {
 	      /* Replace Composite type of size greater than 16 with a
 		 pointer.  */
-	      memcpy (&avalue[i],
-		      allocate_to_register_or_stack (context, stack,
-						     &state, FFI_TYPE_POINTER),
-		      sizeof (avalue[i]));
-	    }
-	  else if (available_x (&state) >= (ty->size + 7) / 8)
-	    {
-	      avalue[i] = get_x_addr (context, state.ngrn);
-	      state.ngrn += (ty->size + 7) / 8;
+	      avalue[i] = *(void **)
+		allocate_int_to_reg_or_stack (context, &state, stack,
+					      sizeof (void *));
 	    }
 	  else
 	    {
-	      state.ngrn = N_X_ARG_REG;
-
-	      avalue[i] = allocate_to_stack (&state, stack, ty->alignment,
-					     ty->size);
+	      n = (s + 7) / 8;
+	      if (state.ngrn + n <= N_X_ARG_REG)
+		{
+		  avalue[i] = &context->x[state.ngrn];
+		  state.ngrn += n;
+		}
+	      else
+		{
+		  state.ngrn = N_X_ARG_REG;
+		  avalue[i] = allocate_to_stack (&state, stack,
+						 ty->alignment, s);
+		}
 	    }
 	  break;
 
 	default:
-	  FFI_ASSERT (0);
-	  break;
+	  abort();
 	}
     }
 
-  /* Figure out where the return value will be passed, either in
-     registers or in a memory block allocated by the caller and passed
-     in x8.  */
+  flags = cif->flags;
+  if (flags & AARCH64_RET_IN_MEM)
+    rvalue = struct_rvalue;
 
-  if (is_register_candidate (cif->rtype))
-    {
-      /* Register candidates are *always* returned in registers. */
+  fun (cif, rvalue, avalue, user_data);
 
-      /* Allocate a scratchpad for the return value, we will let the
-         callee scrible the result into the scratch pad then move the
-         contents into the appropriate return value location for the
-         call convention.  */
-      rvalue = alloca (cif->rtype->size);
-      (closure->fun) (cif, rvalue, avalue, closure->user_data);
-
-      /* Copy the return value into the call context so that it is returned
-         as expected to our caller.  */
-      switch (cif->rtype->type)
-        {
-        case FFI_TYPE_VOID:
-          break;
-
-        case FFI_TYPE_UINT8:
-        case FFI_TYPE_UINT16:
-        case FFI_TYPE_UINT32:
-        case FFI_TYPE_POINTER:
-        case FFI_TYPE_UINT64:
-        case FFI_TYPE_SINT8:
-        case FFI_TYPE_SINT16:
-        case FFI_TYPE_INT:
-        case FFI_TYPE_SINT32:
-        case FFI_TYPE_SINT64:
-        case FFI_TYPE_FLOAT:
-        case FFI_TYPE_DOUBLE:
-        case FFI_TYPE_LONGDOUBLE:
-	  {
-	    void *addr = get_basic_type_addr (cif->rtype->type, context, 0);
-	    copy_basic_type (addr, rvalue, cif->rtype->type);
-            break;
-	  }
-        case FFI_TYPE_STRUCT:
-          if (is_hfa (cif->rtype))
-	    {
-	      int i;
-	      unsigned short type = get_homogeneous_type (cif->rtype);
-	      unsigned elems = element_count (cif->rtype);
-	      for (i = 0; i < elems; i++)
-		{
-		  void *reg = get_basic_type_addr (type, context, i);
-		  copy_basic_type (reg, rvalue, type);
-		  rvalue += get_basic_type_size (type);
-		}
-	    }
-          else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG)
-            {
-              unsigned size = ALIGN (cif->rtype->size, sizeof (UINT64)) ;
-              memcpy (get_x_addr (context, 0), rvalue, size);
-            }
-          else
-            {
-              FFI_ASSERT (0);
-            }
-          break;
-        default:
-          FFI_ASSERT (0);
-          break;
-        }
-    }
-  else
-    {
-      memcpy (&rvalue, get_x_addr (context, 8), sizeof (UINT64));
-      (closure->fun) (cif, rvalue, avalue, closure->user_data);
-    }
+  return flags;
 }
-
diff --git a/third_party/gofrontend/libffi/src/aarch64/ffitarget.h b/third_party/gofrontend/libffi/src/aarch64/ffitarget.h
index 6f1a348..80d09af 100644
--- a/third_party/gofrontend/libffi/src/aarch64/ffitarget.h
+++ b/third_party/gofrontend/libffi/src/aarch64/ffitarget.h
@@ -42,18 +42,20 @@
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
-#define FFI_TRAMPOLINE_SIZE 36
+#define FFI_TRAMPOLINE_SIZE 24
 #define FFI_NATIVE_RAW_API 0
 
 /* ---- Internal ---- */
 
+#if defined (__APPLE__)
+#define FFI_TARGET_SPECIFIC_VARIADIC
+#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs
+#else
+/* iOS reserves x18 for the system.  Disable Go closures until
+   a new static chain is chosen.  */
+#define FFI_GO_CLOSURES 1
+#endif
 
-#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags
-
-#define AARCH64_FFI_WITH_V_BIT 0
-
-#define AARCH64_N_XREG 32
-#define AARCH64_N_VREG 32
-#define AARCH64_CALL_CONTEXT_SIZE (AARCH64_N_XREG * 8 + AARCH64_N_VREG * 16)
+#define FFI_TARGET_HAS_COMPLEX_TYPE
 
 #endif
diff --git a/third_party/gofrontend/libffi/src/aarch64/internal.h b/third_party/gofrontend/libffi/src/aarch64/internal.h
new file mode 100644
index 0000000..9c3e077
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/aarch64/internal.h
@@ -0,0 +1,67 @@
+/* 
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+``Software''), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+#define AARCH64_RET_VOID	0
+#define AARCH64_RET_INT64	1
+#define AARCH64_RET_INT128	2
+
+#define AARCH64_RET_UNUSED3	3
+#define AARCH64_RET_UNUSED4	4
+#define AARCH64_RET_UNUSED5	5
+#define AARCH64_RET_UNUSED6	6
+#define AARCH64_RET_UNUSED7	7
+
+/* Note that FFI_TYPE_FLOAT == 2, _DOUBLE == 3, _LONGDOUBLE == 4,
+   so _S4 through _Q1 are layed out as (TYPE * 4) + (4 - COUNT).  */
+#define AARCH64_RET_S4		8
+#define AARCH64_RET_S3		9
+#define AARCH64_RET_S2		10
+#define AARCH64_RET_S1		11
+
+#define AARCH64_RET_D4		12
+#define AARCH64_RET_D3		13
+#define AARCH64_RET_D2		14
+#define AARCH64_RET_D1		15
+
+#define AARCH64_RET_Q4		16
+#define AARCH64_RET_Q3		17
+#define AARCH64_RET_Q2		18
+#define AARCH64_RET_Q1		19
+
+/* Note that each of the sub-64-bit integers gets two entries.  */
+#define AARCH64_RET_UINT8	20
+#define AARCH64_RET_UINT16	22
+#define AARCH64_RET_UINT32	24
+
+#define AARCH64_RET_SINT8	26
+#define AARCH64_RET_SINT16	28
+#define AARCH64_RET_SINT32	30
+
+#define AARCH64_RET_MASK	31
+
+#define AARCH64_RET_IN_MEM	(1 << 5)
+#define AARCH64_RET_NEED_COPY	(1 << 6)
+
+#define AARCH64_FLAG_ARG_V_BIT	7
+#define AARCH64_FLAG_ARG_V	(1 << AARCH64_FLAG_ARG_V_BIT)
+
+#define N_X_ARG_REG		8
+#define N_V_ARG_REG		8
+#define CALL_CONTEXT_SIZE	(N_V_ARG_REG * 16 + N_X_ARG_REG * 8)
diff --git a/third_party/gofrontend/libffi/src/aarch64/sysv.S b/third_party/gofrontend/libffi/src/aarch64/sysv.S
index ffb16f8..5c9cdda 100644
--- a/third_party/gofrontend/libffi/src/aarch64/sysv.S
+++ b/third_party/gofrontend/libffi/src/aarch64/sysv.S
@@ -22,286 +22,382 @@
 #define LIBFFI_ASM
 #include <fficonfig.h>
 #include <ffi.h>
+#include <ffi_cfi.h>
+#include "internal.h"
 
-#define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
-#define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
-#define cfi_restore(reg)		.cfi_restore reg
-#define cfi_def_cfa_register(reg)	.cfi_def_cfa_register reg
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+#ifdef __USER_LABEL_PREFIX__
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
 
-        .text
-        .globl ffi_call_SYSV
-        .type ffi_call_SYSV, #function
+/* Use the right prefix for global labels.  */
+#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+#else
+#define CNAME(x) x
+#endif
+#endif
 
-/* ffi_call_SYSV()
+#ifdef __AARCH64EB__
+# define BE(X)	X
+#else
+# define BE(X)	0
+#endif
 
-   Create a stack frame, setup an argument context, call the callee
-   and extract the result.
+	.text
+	.align 4
 
-   The maximum required argument stack size is provided,
-   ffi_call_SYSV() allocates that stack space then calls the
-   prepare_fn to populate register context and stack.  The
-   argument passing registers are loaded from the register
-   context and the callee called, on return the register passing
-   register are saved back to the context.  Our caller will
-   extract the return value from the final state of the saved
-   register context.
-
-   Prototype:
-
-   extern unsigned
-   ffi_call_SYSV (void (*)(struct call_context *context, unsigned char *,
-			   extended_cif *),
-                  struct call_context *context,
-                  extended_cif *,
-                  unsigned required_stack_size,
-                  void (*fn)(void));
+/* ffi_call_SYSV
+   extern void ffi_call_SYSV (void *stack, void *frame,
+			      void (*fn)(void), void *rvalue,
+			      int flags, void *closure);
 
    Therefore on entry we have:
 
-   x0 prepare_fn
-   x1 &context
-   x2 &ecif
-   x3 bytes
-   x4 fn
+   x0 stack
+   x1 frame
+   x2 fn
+   x3 rvalue
+   x4 flags
+   x5 closure
+*/
 
-   This function uses the following stack frame layout:
+	cfi_startproc
+CNAME(ffi_call_SYSV):
+	/* Use a stack frame allocated by our caller.  */
+	cfi_def_cfa(x1, 32);
+	stp	x29, x30, [x1]
+	mov	x29, x1
+	mov	sp, x0
+	cfi_def_cfa_register(x29)
+	cfi_rel_offset (x29, 0)
+	cfi_rel_offset (x30, 8)
 
-   ==
-                saved x30(lr)
-   x29(fp)->    saved x29(fp)
-                saved x24
-                saved x23
-                saved x22
-   sp'    ->    saved x21
-                ...
-   sp     ->    (constructed callee stack arguments)
-   ==
+	mov	x9, x2			/* save fn */
+	mov	x8, x3			/* install structure return */
+#ifdef FFI_GO_CLOSURES
+	mov	x18, x5			/* install static chain */
+#endif
+	stp	x3, x4, [x29, #16]	/* save rvalue and flags */
 
-   Voila! */
-
-#define ffi_call_SYSV_FS (8 * 4)
-
-        .cfi_startproc
-ffi_call_SYSV:
-        stp     x29, x30, [sp, #-16]!
-	cfi_adjust_cfa_offset (16)
-        cfi_rel_offset (x29, 0)
-        cfi_rel_offset (x30, 8)
-
-        mov     x29, sp
-	cfi_def_cfa_register (x29)
-        sub     sp, sp, #ffi_call_SYSV_FS
-
-        stp     x21, x22, [sp, 0]
-        cfi_rel_offset (x21, 0 - ffi_call_SYSV_FS)
-        cfi_rel_offset (x22, 8 - ffi_call_SYSV_FS)
-
-        stp     x23, x24, [sp, 16]
-        cfi_rel_offset (x23, 16 - ffi_call_SYSV_FS)
-        cfi_rel_offset (x24, 24 - ffi_call_SYSV_FS)
-
-        mov     x21, x1
-        mov     x22, x2
-        mov     x24, x4
-
-        /* Allocate the stack space for the actual arguments, many
-           arguments will be passed in registers, but we assume
-           worst case and allocate sufficient stack for ALL of
-           the arguments.  */
-        sub     sp, sp, x3
-
-        /* unsigned (*prepare_fn) (struct call_context *context,
-				   unsigned char *stack, extended_cif *ecif);
-	 */
-        mov     x23, x0
-        mov     x0, x1
-        mov     x1, sp
-        /* x2 already in place */
-        blr     x23
-
-        /* Preserve the flags returned.  */
-        mov     x23, x0
-
-        /* Figure out if we should touch the vector registers.  */
-        tbz     x23, #AARCH64_FFI_WITH_V_BIT, 1f
-
-        /* Load the vector argument passing registers.  */
-        ldp     q0, q1, [x21, #8*32 +  0]
-        ldp     q2, q3, [x21, #8*32 + 32]
-        ldp     q4, q5, [x21, #8*32 + 64]
-        ldp     q6, q7, [x21, #8*32 + 96]
+	/* Load the vector argument passing registers, if necessary.  */
+	tbz	w4, #AARCH64_FLAG_ARG_V_BIT, 1f
+	ldp     q0, q1, [sp, #0]
+	ldp     q2, q3, [sp, #32]
+	ldp     q4, q5, [sp, #64]
+	ldp     q6, q7, [sp, #96]
 1:
-        /* Load the core argument passing registers.  */
-        ldp     x0, x1, [x21,  #0]
-        ldp     x2, x3, [x21, #16]
-        ldp     x4, x5, [x21, #32]
-        ldp     x6, x7, [x21, #48]
+	/* Load the core argument passing registers, including
+	   the structure return pointer.  */
+	ldp     x0, x1, [sp, #16*N_V_ARG_REG + 0]
+	ldp     x2, x3, [sp, #16*N_V_ARG_REG + 16]
+	ldp     x4, x5, [sp, #16*N_V_ARG_REG + 32]
+	ldp     x6, x7, [sp, #16*N_V_ARG_REG + 48]
 
-        /* Don't forget x8 which may be holding the address of a return buffer.
-	 */
-        ldr     x8,     [x21, #8*8]
+	/* Deallocate the context, leaving the stacked arguments.  */
+	add	sp, sp, #CALL_CONTEXT_SIZE
 
-        blr     x24
+	blr     x9			/* call fn */
 
-        /* Save the core argument passing registers.  */
-        stp     x0, x1, [x21,  #0]
-        stp     x2, x3, [x21, #16]
-        stp     x4, x5, [x21, #32]
-        stp     x6, x7, [x21, #48]
+	ldp	x3, x4, [x29, #16]	/* reload rvalue and flags */
 
-        /* Note nothing useful ever comes back in x8!  */
-
-        /* Figure out if we should touch the vector registers.  */
-        tbz     x23, #AARCH64_FFI_WITH_V_BIT, 1f
-
-        /* Save the vector argument passing registers.  */
-        stp     q0, q1, [x21, #8*32 + 0]
-        stp     q2, q3, [x21, #8*32 + 32]
-        stp     q4, q5, [x21, #8*32 + 64]
-        stp     q6, q7, [x21, #8*32 + 96]
-1:
-        /* All done, unwind our stack frame.  */
-        ldp     x21, x22, [x29,  # - ffi_call_SYSV_FS]
-        cfi_restore (x21)
-        cfi_restore (x22)
-
-        ldp     x23, x24, [x29,  # - ffi_call_SYSV_FS + 16]
-        cfi_restore (x23)
-        cfi_restore (x24)
-
-        mov     sp, x29
+	/* Partially deconstruct the stack frame.  */
+	mov     sp, x29
 	cfi_def_cfa_register (sp)
+	ldp     x29, x30, [x29]
 
-        ldp     x29, x30, [sp], #16
-	cfi_adjust_cfa_offset (-16)
-        cfi_restore (x29)
-        cfi_restore (x30)
+	/* Save the return value as directed.  */
+	adr	x5, 0f
+	and	w4, w4, #AARCH64_RET_MASK
+	add	x5, x5, x4, lsl #3
+	br	x5
 
-        ret
+	/* Note that each table entry is 2 insns, and thus 8 bytes.
+	   For integer data, note that we're storing into ffi_arg
+	   and therefore we want to extend to 64 bits; these types
+	   have two consecutive entries allocated for them.  */
+	.align	4
+0:	ret				/* VOID */
+	nop
+1:	str	x0, [x3]		/* INT64 */
+	ret
+2:	stp	x0, x1, [x3]		/* INT128 */
+	ret
+3:	brk	#1000			/* UNUSED */
+	ret
+4:	brk	#1000			/* UNUSED */
+	ret
+5:	brk	#1000			/* UNUSED */
+	ret
+6:	brk	#1000			/* UNUSED */
+	ret
+7:	brk	#1000			/* UNUSED */
+	ret
+8:	st4	{ v0.s-v3.s }[0], [x3]	/* S4 */
+	ret
+9:	st3	{ v0.s-v2.s }[0], [x3]	/* S3 */
+	ret
+10:	stp	s0, s1, [x3]		/* S2 */
+	ret
+11:	str	s0, [x3]		/* S1 */
+	ret
+12:	st4	{ v0.d-v3.d }[0], [x3]	/* D4 */
+	ret
+13:	st3	{ v0.d-v2.d }[0], [x3]	/* D3 */
+	ret
+14:	stp	d0, d1, [x3]		/* D2 */
+	ret
+15:	str	d0, [x3]		/* D1 */
+	ret
+16:	str	q3, [x3, #48]		/* Q4 */
+	nop
+17:	str	q2, [x3, #32]		/* Q3 */
+	nop
+18:	stp	q0, q1, [x3]		/* Q2 */
+	ret
+19:	str	q0, [x3]		/* Q1 */
+	ret
+20:	uxtb	w0, w0			/* UINT8 */
+	str	x0, [x3]
+21:	ret				/* reserved */
+	nop
+22:	uxth	w0, w0			/* UINT16 */
+	str	x0, [x3]
+23:	ret				/* reserved */
+	nop
+24:	mov	w0, w0			/* UINT32 */
+	str	x0, [x3]
+25:	ret				/* reserved */
+	nop
+26:	sxtb	x0, w0			/* SINT8 */
+	str	x0, [x3]
+27:	ret				/* reserved */
+	nop
+28:	sxth	x0, w0			/* SINT16 */
+	str	x0, [x3]
+29:	ret				/* reserved */
+	nop
+30:	sxtw	x0, w0			/* SINT32 */
+	str	x0, [x3]
+31:	ret				/* reserved */
+	nop
 
-        .cfi_endproc
-        .size ffi_call_SYSV, .-ffi_call_SYSV
+	cfi_endproc
 
-#define ffi_closure_SYSV_FS (8 * 2 + AARCH64_CALL_CONTEXT_SIZE)
+	.globl	CNAME(ffi_call_SYSV)
+#ifdef __ELF__
+	.type	CNAME(ffi_call_SYSV), #function
+	.hidden	CNAME(ffi_call_SYSV)
+	.size CNAME(ffi_call_SYSV), .-CNAME(ffi_call_SYSV)
+#endif
 
 /* ffi_closure_SYSV
 
    Closure invocation glue. This is the low level code invoked directly by
    the closure trampoline to setup and call a closure.
 
-   On entry x17 points to a struct trampoline_data, x16 has been clobbered
+   On entry x17 points to a struct ffi_closure, x16 has been clobbered
    all other registers are preserved.
 
    We allocate a call context and save the argument passing registers,
    then invoked the generic C ffi_closure_SYSV_inner() function to do all
    the real work, on return we load the result passing registers back from
    the call context.
+*/
 
-   On entry
+#define ffi_closure_SYSV_FS (8*2 + CALL_CONTEXT_SIZE + 64)
 
-   extern void
-   ffi_closure_SYSV (struct trampoline_data *);
+	.align 4
+CNAME(ffi_closure_SYSV_V):
+	cfi_startproc
+	stp     x29, x30, [sp, #-ffi_closure_SYSV_FS]!
+	cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
+	cfi_rel_offset (x29, 0)
+	cfi_rel_offset (x30, 8)
 
-   struct trampoline_data
-   {
-        UINT64 *ffi_closure;
-        UINT64 flags;
-   };
+	/* Save the argument passing vector registers.  */
+	stp     q0, q1, [sp, #16 + 0]
+	stp     q2, q3, [sp, #16 + 32]
+	stp     q4, q5, [sp, #16 + 64]
+	stp     q6, q7, [sp, #16 + 96]
+	b	0f
+	cfi_endproc
 
-   This function uses the following stack frame layout:
+	.globl	CNAME(ffi_closure_SYSV_V)
+#ifdef __ELF__
+	.type	CNAME(ffi_closure_SYSV_V), #function
+	.hidden	CNAME(ffi_closure_SYSV_V)
+	.size	CNAME(ffi_closure_SYSV_V), . - CNAME(ffi_closure_SYSV_V)
+#endif
 
-   ==
-                saved x30(lr)
-   x29(fp)->    saved x29(fp)
-                saved x22
-                saved x21
-                ...
-   sp     ->    call_context
-   ==
+	.align	4
+	cfi_startproc
+CNAME(ffi_closure_SYSV):
+	stp     x29, x30, [sp, #-ffi_closure_SYSV_FS]!
+	cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
+	cfi_rel_offset (x29, 0)
+	cfi_rel_offset (x30, 8)
+0:
+	mov     x29, sp
 
-   Voila!  */
+	/* Save the argument passing core registers.  */
+	stp     x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0]
+	stp     x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16]
+	stp     x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32]
+	stp     x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48]
 
-        .text
-        .globl ffi_closure_SYSV
-        .cfi_startproc
-ffi_closure_SYSV:
-        stp     x29, x30, [sp, #-16]!
-	cfi_adjust_cfa_offset (16)
-        cfi_rel_offset (x29, 0)
-        cfi_rel_offset (x30, 8)
+	/* Load ffi_closure_inner arguments.  */
+	ldp	x0, x1, [x17, #FFI_TRAMPOLINE_SIZE]	/* load cif, fn */
+	ldr	x2, [x17, #FFI_TRAMPOLINE_SIZE+16]	/* load user_data */
+.Ldo_closure:
+	add	x3, sp, #16				/* load context */
+	add	x4, sp, #ffi_closure_SYSV_FS		/* load stack */
+	add	x5, sp, #16+CALL_CONTEXT_SIZE		/* load rvalue */
+	mov	x6, x8					/* load struct_rval */
+	bl      CNAME(ffi_closure_SYSV_inner)
 
-        mov     x29, sp
-        cfi_def_cfa_register (x29)
+	/* Load the return value as directed.  */
+	adr	x1, 0f
+	and	w0, w0, #AARCH64_RET_MASK
+	add	x1, x1, x0, lsl #3
+	add	x3, sp, #16+CALL_CONTEXT_SIZE
+	br	x1
 
-        sub     sp, sp, #ffi_closure_SYSV_FS
+	/* Note that each table entry is 2 insns, and thus 8 bytes.  */
+	.align	4
+0:	b	99f			/* VOID */
+	nop
+1:	ldr	x0, [x3]		/* INT64 */
+	b	99f
+2:	ldp	x0, x1, [x3]		/* INT128 */
+	b	99f
+3:	brk	#1000			/* UNUSED */
+	nop
+4:	brk	#1000			/* UNUSED */
+	nop
+5:	brk	#1000			/* UNUSED */
+	nop
+6:	brk	#1000			/* UNUSED */
+	nop
+7:	brk	#1000			/* UNUSED */
+	nop
+8:	ldr	s3, [x3, #12]		/* S4 */
+	nop
+9:	ldr	s2, [x2, #8]		/* S3 */
+	nop
+10:	ldp	s0, s1, [x3]		/* S2 */
+	b	99f
+11:	ldr	s0, [x3]		/* S1 */
+	b	99f
+12:	ldr	d3, [x3, #24]		/* D4 */
+	nop
+13:	ldr	d2, [x3, #16]		/* D3 */
+	nop
+14:	ldp	d0, d1, [x3]		/* D2 */
+	b	99f
+15:	ldr	d0, [x3]		/* D1 */
+	b	99f
+16:	ldr	q3, [x3, #48]		/* Q4 */
+	nop
+17:	ldr	q2, [x3, #32]		/* Q3 */
+	nop
+18:	ldp	q0, q1, [x3]		/* Q2 */
+	b	99f
+19:	ldr	q0, [x3]		/* Q1 */
+	b	99f
+20:	ldrb	w0, [x3, #BE(7)]	/* UINT8 */
+	b	99f
+21:	brk	#1000			/* reserved */
+	nop
+22:	ldrh	w0, [x3, #BE(6)]	/* UINT16 */
+	b	99f
+23:	brk	#1000			/* reserved */
+	nop
+24:	ldr	w0, [x3, #BE(4)]	/* UINT32 */
+	b	99f
+25:	brk	#1000			/* reserved */
+	nop
+26:	ldrsb	x0, [x3, #BE(7)]	/* SINT8 */
+	b	99f
+27:	brk	#1000			/* reserved */
+	nop
+28:	ldrsh	x0, [x3, #BE(6)]	/* SINT16 */
+	b	99f
+29:	brk	#1000			/* reserved */
+	nop
+30:	ldrsw	x0, [x3, #BE(4)]	/* SINT32 */
+	nop
+31:					/* reserved */
+99:	ldp     x29, x30, [sp], #ffi_closure_SYSV_FS
+	cfi_adjust_cfa_offset (-ffi_closure_SYSV_FS)
+	cfi_restore (x29)
+	cfi_restore (x30)
+	ret
+	cfi_endproc
 
-        stp     x21, x22, [x29, #-16]
-        cfi_rel_offset (x21, -16)
-        cfi_rel_offset (x22, -8)
+	.globl	CNAME(ffi_closure_SYSV)
+#ifdef __ELF__
+	.type	CNAME(ffi_closure_SYSV), #function
+	.hidden	CNAME(ffi_closure_SYSV)
+	.size	CNAME(ffi_closure_SYSV), . - CNAME(ffi_closure_SYSV)
+#endif
 
-        /* Load x21 with &call_context.  */
-        mov     x21, sp
-        /* Preserve our struct trampoline_data *  */
-        mov     x22, x17
+#ifdef FFI_GO_CLOSURES
+	.align 4
+CNAME(ffi_go_closure_SYSV_V):
+	cfi_startproc
+	stp     x29, x30, [sp, #-ffi_closure_SYSV_FS]!
+	cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
+	cfi_rel_offset (x29, 0)
+	cfi_rel_offset (x30, 8)
 
-        /* Save the rest of the argument passing registers.  */
-        stp     x0, x1, [x21, #0]
-        stp     x2, x3, [x21, #16]
-        stp     x4, x5, [x21, #32]
-        stp     x6, x7, [x21, #48]
-        /* Don't forget we may have been given a result scratch pad address.
-	 */
-        str     x8,     [x21, #64]
+	/* Save the argument passing vector registers.  */
+	stp     q0, q1, [sp, #16 + 0]
+	stp     q2, q3, [sp, #16 + 32]
+	stp     q4, q5, [sp, #16 + 64]
+	stp     q6, q7, [sp, #16 + 96]
+	b	0f
+	cfi_endproc
 
-        /* Figure out if we should touch the vector registers.  */
-        ldr     x0, [x22, #8]
-        tbz     x0, #AARCH64_FFI_WITH_V_BIT, 1f
+	.globl	CNAME(ffi_go_closure_SYSV_V)
+#ifdef __ELF__
+	.type	CNAME(ffi_go_closure_SYSV_V), #function
+	.hidden	CNAME(ffi_go_closure_SYSV_V)
+	.size	CNAME(ffi_go_closure_SYSV_V), . - CNAME(ffi_go_closure_SYSV_V)
+#endif
 
-        /* Save the argument passing vector registers.  */
-        stp     q0, q1, [x21, #8*32 + 0]
-        stp     q2, q3, [x21, #8*32 + 32]
-        stp     q4, q5, [x21, #8*32 + 64]
-        stp     q6, q7, [x21, #8*32 + 96]
-1:
-        /* Load &ffi_closure..  */
-        ldr     x0, [x22, #0]
-        mov     x1, x21
-        /* Compute the location of the stack at the point that the
-           trampoline was called.  */
-        add     x2, x29, #16
+	.align	4
+	cfi_startproc
+CNAME(ffi_go_closure_SYSV):
+	stp     x29, x30, [sp, #-ffi_closure_SYSV_FS]!
+	cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
+	cfi_rel_offset (x29, 0)
+	cfi_rel_offset (x30, 8)
+0:
+	mov     x29, sp
 
-        bl      ffi_closure_SYSV_inner
+	/* Save the argument passing core registers.  */
+	stp     x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0]
+	stp     x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16]
+	stp     x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32]
+	stp     x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48]
 
-        /* Figure out if we should touch the vector registers.  */
-        ldr     x0, [x22, #8]
-        tbz     x0, #AARCH64_FFI_WITH_V_BIT, 1f
+	/* Load ffi_closure_inner arguments.  */
+	ldp	x0, x1, [x18, #8]			/* load cif, fn */
+	mov	x2, x18					/* load user_data */
+	b	.Ldo_closure
+	cfi_endproc
 
-        /* Load the result passing vector registers.  */
-        ldp     q0, q1, [x21, #8*32 + 0]
-        ldp     q2, q3, [x21, #8*32 + 32]
-        ldp     q4, q5, [x21, #8*32 + 64]
-        ldp     q6, q7, [x21, #8*32 + 96]
-1:
-        /* Load the result passing core registers.  */
-        ldp     x0, x1, [x21,  #0]
-        ldp     x2, x3, [x21, #16]
-        ldp     x4, x5, [x21, #32]
-        ldp     x6, x7, [x21, #48]
-        /* Note nothing usefull is returned in x8.  */
+	.globl	CNAME(ffi_go_closure_SYSV)
+#ifdef __ELF__
+	.type	CNAME(ffi_go_closure_SYSV), #function
+	.hidden	CNAME(ffi_go_closure_SYSV)
+	.size	CNAME(ffi_go_closure_SYSV), . - CNAME(ffi_go_closure_SYSV)
+#endif
+#endif /* FFI_GO_CLOSURES */
 
-        /* We are done, unwind our frame.  */
-        ldp     x21, x22, [x29,  #-16]
-        cfi_restore (x21)
-        cfi_restore (x22)
+#if defined __ELF__ && defined __linux__
+	.section .note.GNU-stack,"",%progbits
+#endif
 
-        mov     sp, x29
-        cfi_def_cfa_register (sp)
-
-        ldp     x29, x30, [sp], #16
-	cfi_adjust_cfa_offset (-16)
-        cfi_restore (x29)
-        cfi_restore (x30)
-
-        ret
-        .cfi_endproc
-        .size ffi_closure_SYSV, .-ffi_closure_SYSV
diff --git a/third_party/gofrontend/libffi/src/alpha/ffi.c b/third_party/gofrontend/libffi/src/alpha/ffi.c
index cf0a730..efae4cc 100644
--- a/third_party/gofrontend/libffi/src/alpha/ffi.c
+++ b/third_party/gofrontend/libffi/src/alpha/ffi.c
@@ -1,8 +1,8 @@
 /* -----------------------------------------------------------------------
    ffi.c - Copyright (c) 2012  Anthony Green
-           Copyright (c) 1998, 2001, 2007, 2008  Red Hat, Inc.
-   
-   Alpha Foreign Function Interface 
+	   Copyright (c) 1998, 2001, 2007, 2008  Red Hat, Inc.
+
+   Alpha Foreign Function Interface
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -27,6 +27,8 @@
 
 #include <ffi.h>
 #include <ffi_common.h>
+#include <stdlib.h>
+#include "internal.h"
 
 /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
    all further uses in this file will refer to the 128-bit type.  */
@@ -39,135 +41,286 @@
 # define FFI_TYPE_LONGDOUBLE 4
 #endif
 
-extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)(void))
-  FFI_HIDDEN;
+extern void ffi_call_osf(void *stack, void *frame, unsigned flags,
+			 void *raddr, void (*fn)(void), void *closure)
+	FFI_HIDDEN;
 extern void ffi_closure_osf(void) FFI_HIDDEN;
+extern void ffi_go_closure_osf(void) FFI_HIDDEN;
 
+/* Promote a float value to its in-register double representation.
+   Unlike actually casting to double, this does not trap on NaN.  */
+static inline UINT64 lds(void *ptr)
+{
+  UINT64 ret;
+  asm("lds %0,%1" : "=f"(ret) : "m"(*(UINT32 *)ptr));
+  return ret;
+}
 
-ffi_status
+/* And the reverse.  */
+static inline void sts(void *ptr, UINT64 val)
+{
+  asm("sts %1,%0" : "=m"(*(UINT32 *)ptr) : "f"(val));
+}
+
+ffi_status FFI_HIDDEN
 ffi_prep_cif_machdep(ffi_cif *cif)
 {
-  /* Adjust cif->bytes to represent a minimum 6 words for the temporary
-     register argument loading area.  */
-  if (cif->bytes < 6*FFI_SIZEOF_ARG)
-    cif->bytes = 6*FFI_SIZEOF_ARG;
+  size_t bytes = 0;
+  int flags, i, avn;
+  ffi_type *rtype, *itype;
+
+  if (cif->abi != FFI_OSF)
+    return FFI_BAD_ABI;
+
+  /* Compute the size of the argument area.  */
+  for (i = 0, avn = cif->nargs; i < avn; i++)
+    {
+      itype = cif->arg_types[i];
+      switch (itype->type)
+	{
+	case FFI_TYPE_INT:
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT8:
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_POINTER:
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_LONGDOUBLE:
+	  /* All take one 8 byte slot.  */
+	  bytes += 8;
+	  break;
+
+	case FFI_TYPE_VOID:
+	case FFI_TYPE_STRUCT:
+	  /* Passed by value in N slots.  */
+	  bytes += ALIGN(itype->size, FFI_SIZEOF_ARG);
+	  break;
+
+	case FFI_TYPE_COMPLEX:
+	  /* _Complex long double passed by reference; others in 2 slots.  */
+	  if (itype->elements[0]->type == FFI_TYPE_LONGDOUBLE)
+	    bytes += 8;
+	  else
+	    bytes += 16;
+	  break;
+
+	default:
+	  abort();
+	}
+    }
 
   /* Set the return type flag */
-  switch (cif->rtype->type)
+  rtype = cif->rtype;
+  switch (rtype->type)
     {
-    case FFI_TYPE_STRUCT:
+    case FFI_TYPE_VOID:
+      flags = ALPHA_FLAGS(ALPHA_ST_VOID, ALPHA_LD_VOID);
+      break;
+    case FFI_TYPE_INT:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_SINT32:
+      flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT32);
+      break;
     case FFI_TYPE_FLOAT:
+      flags = ALPHA_FLAGS(ALPHA_ST_FLOAT, ALPHA_LD_FLOAT);
+      break;
     case FFI_TYPE_DOUBLE:
-      cif->flags = cif->rtype->type;
+      flags = ALPHA_FLAGS(ALPHA_ST_DOUBLE, ALPHA_LD_DOUBLE);
       break;
-
+    case FFI_TYPE_UINT8:
+      flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_UINT8);
+      break;
+    case FFI_TYPE_SINT8:
+      flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_SINT8);
+      break;
+    case FFI_TYPE_UINT16:
+      flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_UINT16);
+      break;
+    case FFI_TYPE_SINT16:
+      flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_SINT16);
+      break;
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_POINTER:
+      flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT64);
+      break;
     case FFI_TYPE_LONGDOUBLE:
-      /* 128-bit long double is returned in memory, like a struct.  */
-      cif->flags = FFI_TYPE_STRUCT;
+    case FFI_TYPE_STRUCT:
+      /* Passed in memory, with a hidden pointer.  */
+      flags = ALPHA_RET_IN_MEM;
       break;
-
+    case FFI_TYPE_COMPLEX:
+      itype = rtype->elements[0];
+      switch (itype->type)
+	{
+	case FFI_TYPE_FLOAT:
+	  flags = ALPHA_FLAGS(ALPHA_ST_CPLXF, ALPHA_LD_CPLXF);
+	  break;
+	case FFI_TYPE_DOUBLE:
+	  flags = ALPHA_FLAGS(ALPHA_ST_CPLXD, ALPHA_LD_CPLXD);
+	  break;
+	default:
+	  if (rtype->size <= 8)
+	    flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT64);
+	  else
+	    flags = ALPHA_RET_IN_MEM;
+	  break;
+	}
+      break;
     default:
-      cif->flags = FFI_TYPE_INT;
-      break;
+      abort();
     }
-  
+  cif->flags = flags;
+
+  /* Include the hidden structure pointer in args requirement.  */
+  if (flags == ALPHA_RET_IN_MEM)
+    bytes += 8;
+  /* Minimum size is 6 slots, so that ffi_call_osf can pop them.  */
+  if (bytes < 6*8)
+    bytes = 6*8;
+  cif->bytes = bytes;
+
   return FFI_OK;
 }
 
-
-void
-ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+static unsigned long
+extend_basic_type(void *valp, int type, int argn)
 {
-  unsigned long *stack, *argp;
-  long i, avn;
+  switch (type)
+    {
+    case FFI_TYPE_SINT8:
+      return *(SINT8 *)valp;
+    case FFI_TYPE_UINT8:
+      return *(UINT8 *)valp;
+    case FFI_TYPE_SINT16:
+      return *(SINT16 *)valp;
+    case FFI_TYPE_UINT16:
+      return *(UINT16 *)valp;
+
+    case FFI_TYPE_FLOAT:
+      if (argn < 6)
+	return lds(valp);
+      /* FALLTHRU */
+
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT32:
+      /* Note that unsigned 32-bit quantities are sign extended.  */
+      return *(SINT32 *)valp;
+
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_DOUBLE:
+      return *(UINT64 *)valp;
+
+    default:
+      abort();
+    }
+}
+
+static void
+ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
+	      void **avalue, void *closure)
+{
+  unsigned long *argp;
+  long i, avn, argn, flags = cif->flags;
   ffi_type **arg_types;
-  
+  void *frame;
+
   /* If the return value is a struct and we don't have a return
      value address then we need to make one.  */
-  if (rvalue == NULL && cif->flags == FFI_TYPE_STRUCT)
+  if (rvalue == NULL && flags == ALPHA_RET_IN_MEM)
     rvalue = alloca(cif->rtype->size);
 
   /* Allocate the space for the arguments, plus 4 words of temp
      space for ffi_call_osf.  */
-  argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
+  argp = frame = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
+  frame += cif->bytes;
 
-  if (cif->flags == FFI_TYPE_STRUCT)
-    *(void **) argp++ = rvalue;
+  argn = 0;
+  if (flags == ALPHA_RET_IN_MEM)
+    argp[argn++] = (unsigned long)rvalue;
 
-  i = 0;
   avn = cif->nargs;
   arg_types = cif->arg_types;
 
-  while (i < avn)
+  for (i = 0, avn = cif->nargs; i < avn; i++)
     {
-      size_t size = (*arg_types)->size;
+      ffi_type *ty = arg_types[i];
+      void *valp = avalue[i];
+      int type = ty->type;
+      size_t size;
 
-      switch ((*arg_types)->type)
+      switch (type)
 	{
+	case FFI_TYPE_INT:
 	case FFI_TYPE_SINT8:
-	  *(SINT64 *) argp = *(SINT8 *)(* avalue);
-	  break;
-		  
 	case FFI_TYPE_UINT8:
-	  *(SINT64 *) argp = *(UINT8 *)(* avalue);
-	  break;
-		  
 	case FFI_TYPE_SINT16:
-	  *(SINT64 *) argp = *(SINT16 *)(* avalue);
-	  break;
-		  
 	case FFI_TYPE_UINT16:
-	  *(SINT64 *) argp = *(UINT16 *)(* avalue);
-	  break;
-		  
 	case FFI_TYPE_SINT32:
 	case FFI_TYPE_UINT32:
-	  /* Note that unsigned 32-bit quantities are sign extended.  */
-	  *(SINT64 *) argp = *(SINT32 *)(* avalue);
-	  break;
-		  
 	case FFI_TYPE_SINT64:
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_POINTER:
-	  *(UINT64 *) argp = *(UINT64 *)(* avalue);
-	  break;
-
 	case FFI_TYPE_FLOAT:
-	  if (argp - stack < 6)
-	    {
-	      /* Note the conversion -- all the fp regs are loaded as
-		 doubles.  The in-register format is the same.  */
-	      *(double *) argp = *(float *)(* avalue);
-	    }
-	  else
-	    *(float *) argp = *(float *)(* avalue);
-	  break;
-
 	case FFI_TYPE_DOUBLE:
-	  *(double *) argp = *(double *)(* avalue);
+	  argp[argn] = extend_basic_type(valp, type, argn);
+	  argn++;
 	  break;
 
 	case FFI_TYPE_LONGDOUBLE:
-	  /* 128-bit long double is passed by reference.  */
-	  *(long double **) argp = (long double *)(* avalue);
-	  size = sizeof (long double *);
+	by_reference:
+	  /* Note that 128-bit long double is passed by reference.  */
+	  argp[argn++] = (unsigned long)valp;
 	  break;
 
+	case FFI_TYPE_VOID:
 	case FFI_TYPE_STRUCT:
-	  memcpy(argp, *avalue, (*arg_types)->size);
+	  size = ty->size;
+	  memcpy(argp + argn, valp, size);
+	  argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+	  break;
+
+	case FFI_TYPE_COMPLEX:
+	  type = ty->elements[0]->type;
+	  if (type == FFI_TYPE_LONGDOUBLE)
+	    goto by_reference;
+
+	  /* Most complex types passed as two separate arguments.  */
+	  size = ty->elements[0]->size;
+	  argp[argn] = extend_basic_type(valp, type, argn);
+	  argp[argn + 1] = extend_basic_type(valp + size, type, argn + 1);
+	  argn += 2;
 	  break;
 
 	default:
-	  FFI_ASSERT(0);
+	  abort();
 	}
-
-      argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
-      i++, arg_types++, avalue++;
     }
 
-  ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn);
+  flags = (flags >> ALPHA_ST_SHIFT) & 0xff;
+  ffi_call_osf(argp, frame, flags, rvalue, fn, closure);
 }
 
+void
+ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  ffi_call_int(cif, fn, rvalue, avalue, NULL);
+}
+
+void
+ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
+	     void **avalue, void *closure)
+{
+  ffi_call_int(cif, fn, rvalue, avalue, closure);
+}
 
 ffi_status
 ffi_prep_closure_loc (ffi_closure* closure,
@@ -203,39 +356,56 @@
   return FFI_OK;
 }
 
+ffi_status
+ffi_prep_go_closure (ffi_go_closure* closure,
+		     ffi_cif* cif,
+		     void (*fun)(ffi_cif*, void*, void**, void*))
+{
+  if (cif->abi != FFI_OSF)
+    return FFI_BAD_ABI;
+
+  closure->tramp = (void *)ffi_go_closure_osf;
+  closure->cif = cif;
+  closure->fun = fun;
+
+  return FFI_OK;
+}
 
 long FFI_HIDDEN
-ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
+ffi_closure_osf_inner (ffi_cif *cif,
+		       void (*fun)(ffi_cif*, void*, void**, void*),
+		       void *user_data,
+		       void *rvalue, unsigned long *argp)
 {
-  ffi_cif *cif;
   void **avalue;
   ffi_type **arg_types;
-  long i, avn, argn;
+  long i, avn, argn, flags;
 
-  cif = closure->cif;
   avalue = alloca(cif->nargs * sizeof(void *));
-
+  flags = cif->flags;
   argn = 0;
 
   /* Copy the caller's structure return address to that the closure
      returns the data directly to the caller.  */
-  if (cif->flags == FFI_TYPE_STRUCT)
+  if (flags == ALPHA_RET_IN_MEM)
     {
       rvalue = (void *) argp[0];
       argn = 1;
     }
 
-  i = 0;
-  avn = cif->nargs;
   arg_types = cif->arg_types;
-  
-  /* Grab the addresses of the arguments from the stack frame.  */
-  while (i < avn)
-    {
-      size_t size = arg_types[i]->size;
 
-      switch (arg_types[i]->type)
+  /* Grab the addresses of the arguments from the stack frame.  */
+  for (i = 0, avn = cif->nargs; i < avn; i++)
+    {
+      ffi_type *ty = arg_types[i];
+      int type = ty->type;
+      void *valp = &argp[argn];
+      size_t size;
+
+      switch (type)
 	{
+	case FFI_TYPE_INT:
 	case FFI_TYPE_SINT8:
 	case FFI_TYPE_UINT8:
 	case FFI_TYPE_SINT16:
@@ -245,43 +415,107 @@
 	case FFI_TYPE_SINT64:
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_POINTER:
+	  argn += 1;
+	  break;
+
+	case FFI_TYPE_VOID:
 	case FFI_TYPE_STRUCT:
-	  avalue[i] = &argp[argn];
+	  size = ty->size;
+	  argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
 	  break;
 
 	case FFI_TYPE_FLOAT:
+	  /* Floats coming from registers need conversion from double
+	     back to float format.  */
 	  if (argn < 6)
 	    {
-	      /* Floats coming from registers need conversion from double
-	         back to float format.  */
-	      *(float *)&argp[argn - 6] = *(double *)&argp[argn - 6];
-	      avalue[i] = &argp[argn - 6];
+	      valp = &argp[argn - 6];
+	      sts(valp, argp[argn - 6]);
 	    }
-	  else
-	    avalue[i] = &argp[argn];
+	  argn += 1;
 	  break;
 
 	case FFI_TYPE_DOUBLE:
-	  avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)];
+	  if (argn < 6)
+	    valp = &argp[argn - 6];
+	  argn += 1;
 	  break;
 
 	case FFI_TYPE_LONGDOUBLE:
+	by_reference:
 	  /* 128-bit long double is passed by reference.  */
-	  avalue[i] = (long double *) argp[argn];
-	  size = sizeof (long double *);
+	  valp = (void *)argp[argn];
+	  argn += 1;
+	  break;
+
+	case FFI_TYPE_COMPLEX:
+	  type = ty->elements[0]->type;
+	  switch (type)
+	    {
+	    case FFI_TYPE_SINT64:
+	    case FFI_TYPE_UINT64:
+	      /* Passed as separate arguments, but they wind up sequential.  */
+	      break;
+
+	    case FFI_TYPE_INT:
+	    case FFI_TYPE_SINT8:
+	    case FFI_TYPE_UINT8:
+	    case FFI_TYPE_SINT16:
+	    case FFI_TYPE_UINT16:
+	    case FFI_TYPE_SINT32:
+	    case FFI_TYPE_UINT32:
+	      /* Passed as separate arguments.  Disjoint, but there's room
+		 enough in one slot to hold the pair.  */
+	      size = ty->elements[0]->size;
+	      memcpy(valp + size, valp + 8, size);
+	      break;
+
+	    case FFI_TYPE_FLOAT:
+	      /* Passed as separate arguments.  Disjoint, and each piece
+		 may need conversion back to float.  */
+	      if (argn < 6)
+		{
+		  valp = &argp[argn - 6];
+		  sts(valp, argp[argn - 6]);
+		}
+	      if (argn + 1 < 6)
+		sts(valp + 4, argp[argn + 1 - 6]);
+	      else
+		*(UINT32 *)(valp + 4) = argp[argn + 1];
+	      break;
+
+	    case FFI_TYPE_DOUBLE:
+	      /* Passed as separate arguments.  Only disjoint if one part
+		 is in fp regs and the other is on the stack.  */
+	      if (argn < 5)
+		valp = &argp[argn - 6];
+	      else if (argn == 5)
+		{
+		  valp = alloca(16);
+		  ((UINT64 *)valp)[0] = argp[5 - 6];
+		  ((UINT64 *)valp)[1] = argp[6];
+		}
+	      break;
+
+	    case FFI_TYPE_LONGDOUBLE:
+	      goto by_reference;
+
+	    default:
+	      abort();
+	    }
+	  argn += 2;
 	  break;
 
 	default:
-	  FFI_ASSERT (0);
+	  abort ();
 	}
 
-      argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
-      i++;
+      avalue[i] = valp;
     }
 
   /* Invoke the closure.  */
-  closure->fun (cif, rvalue, avalue, closure->user_data);
+  fun (cif, rvalue, avalue, user_data);
 
   /* Tell ffi_closure_osf how to perform return type promotions.  */
-  return cif->rtype->type;
+  return (flags >> ALPHA_LD_SHIFT) & 0xff;
 }
diff --git a/third_party/gofrontend/libffi/src/alpha/ffitarget.h b/third_party/gofrontend/libffi/src/alpha/ffitarget.h
index af145bc..a02dbd0 100644
--- a/third_party/gofrontend/libffi/src/alpha/ffitarget.h
+++ b/third_party/gofrontend/libffi/src/alpha/ffitarget.h
@@ -44,9 +44,13 @@
 } ffi_abi;
 #endif
 
+#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
+#define FFI_TARGET_HAS_COMPLEX_TYPE
+
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
+#define FFI_GO_CLOSURES 1
 #define FFI_TRAMPOLINE_SIZE 24
 #define FFI_NATIVE_RAW_API 0
 
diff --git a/third_party/gofrontend/libffi/src/alpha/internal.h b/third_party/gofrontend/libffi/src/alpha/internal.h
new file mode 100644
index 0000000..44da192
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/alpha/internal.h
@@ -0,0 +1,23 @@
+#define ALPHA_ST_VOID	0
+#define ALPHA_ST_INT	1
+#define ALPHA_ST_FLOAT	2
+#define ALPHA_ST_DOUBLE	3
+#define ALPHA_ST_CPLXF	4
+#define ALPHA_ST_CPLXD	5
+
+#define ALPHA_LD_VOID	0
+#define ALPHA_LD_INT64	1
+#define ALPHA_LD_INT32	2
+#define ALPHA_LD_UINT16	3
+#define ALPHA_LD_SINT16	4
+#define ALPHA_LD_UINT8	5
+#define ALPHA_LD_SINT8	6
+#define ALPHA_LD_FLOAT	7
+#define ALPHA_LD_DOUBLE	8
+#define ALPHA_LD_CPLXF	9
+#define ALPHA_LD_CPLXD	10
+
+#define ALPHA_ST_SHIFT		0
+#define ALPHA_LD_SHIFT		8
+#define ALPHA_RET_IN_MEM	0x10000
+#define ALPHA_FLAGS(S, L)	(((L) << ALPHA_LD_SHIFT) | (S))
diff --git a/third_party/gofrontend/libffi/src/alpha/osf.S b/third_party/gofrontend/libffi/src/alpha/osf.S
index 6b9f4df..b031828 100644
--- a/third_party/gofrontend/libffi/src/alpha/osf.S
+++ b/third_party/gofrontend/libffi/src/alpha/osf.S
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------
-   osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011 Red Hat
-   
-   Alpha/OSF Foreign Function Interface 
+   osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011, 2014 Red Hat
+
+   Alpha/OSF Foreign Function Interface
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -24,40 +24,49 @@
    DEALINGS IN THE SOFTWARE.
    ----------------------------------------------------------------------- */
 
-#define LIBFFI_ASM	
+#define LIBFFI_ASM
 #include <fficonfig.h>
 #include <ffi.h>
+#include <ffi_cfi.h>
+#include "internal.h"
 
 	.arch ev6
 	.text
 
-/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
-		 void *raddr, void (*fnaddr)(void));
+/* Aid in building a direct addressed jump table, 4 insns per entry.  */
+.macro E index
+	.align	4
+	.org	99b + \index * 16
+.endm
 
-   Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
+/* ffi_call_osf (void *stack, void *frame, unsigned flags,
+		 void *raddr, void (*fnaddr)(void), void *closure)
+
+   Bit o trickiness here -- FRAME is the base of the stack frame
    for this function.  This has been allocated by ffi_call.  We also
    deallocate some of the stack that has been alloca'd.  */
 
-	.align	3
+	.align	4
 	.globl	ffi_call_osf
 	.ent	ffi_call_osf
 	FFI_HIDDEN(ffi_call_osf)
 
 ffi_call_osf:
-	.frame	$15, 32, $26, 0
-	.mask   0x4008000, -32
-$LFB1:
-	addq	$16,$17,$1
+	cfi_startproc
+	cfi_def_cfa($17, 32)
 	mov	$16, $30
-	stq	$26, 0($1)
-	stq	$15, 8($1)
-	stq	$18, 16($1)
-	mov	$1, $15
-$LCFI1:
+	stq	$26, 0($17)
+	stq	$15, 8($17)
+	mov	$17, $15
 	.prologue 0
+	cfi_def_cfa_register($15)
+	cfi_rel_offset($26, 0)
+	cfi_rel_offset($15, 8)
 
-	stq	$19, 24($1)
-	mov	$20, $27
+	stq	$18, 16($17)		# save flags into frame
+	stq	$19, 24($17)		# save rvalue into frame
+	mov	$20, $27		# fn into place for call
+	mov	$21, $1			# closure into static chain
 
 	# Load up all of the (potential) argument registers.
 	ldq	$16, 0($30)
@@ -77,310 +86,196 @@
 	lda	$30, 48($30)
 
 	jsr	$26, ($27), 0
-	ldgp	$29, 0($26)
-
-	# If the return value pointer is NULL, assume no return value.
-	ldq	$19, 24($15)
-	ldq	$18, 16($15)
+0:
+	ldah	$29, 0($26)		!gpdisp!1
+	ldq	$2, 24($15)		# reload rvalue
+	lda	$29, 0($29)		!gpdisp!1
+	ldq	$3, 16($15)		# reload flags
+	lda	$1, 99f-0b($26)
 	ldq	$26, 0($15)
-$LCFI2:
-	beq	$19, $noretval
-
-	# Store the return value out in the proper type.
-	cmpeq	$18, FFI_TYPE_INT, $1
-	bne	$1, $retint
-	cmpeq	$18, FFI_TYPE_FLOAT, $2
-	bne	$2, $retfloat
-	cmpeq	$18, FFI_TYPE_DOUBLE, $3
-	bne	$3, $retdouble
-
-	.align	3
-$noretval:
 	ldq	$15, 8($15)
-	ret
+	cfi_restore($26)
+	cfi_restore($15)
+	cfi_def_cfa($sp, 0)
+	cmoveq	$2, ALPHA_ST_VOID, $3	# mash null rvalue to void
+	addq	$3, $3, $3
+	s8addq	$3, $1, $1		# 99f + stcode * 16
+	jmp	$31, ($1), $st_int
 
 	.align	4
-$retint:
-	stq	$0, 0($19)
-	nop
-	ldq	$15, 8($15)
+99:
+E ALPHA_ST_VOID
+	ret
+E ALPHA_ST_INT
+$st_int:
+	stq	$0, 0($2)
+	ret
+E ALPHA_ST_FLOAT
+	sts	$f0, 0($2)
+	ret
+E ALPHA_ST_DOUBLE
+	stt	$f0, 0($2)
+	ret
+E ALPHA_ST_CPLXF
+	sts	$f0, 0($2)
+	sts	$f1, 4($2)
+	ret
+E ALPHA_ST_CPLXD
+	stt	$f0, 0($2)
+	stt	$f1, 8($2)
 	ret
 
-	.align	4
-$retfloat:
-	sts	$f0, 0($19)
-	nop
-	ldq	$15, 8($15)
-	ret
-
-	.align	4
-$retdouble:
-	stt	$f0, 0($19)
-	nop
-	ldq	$15, 8($15)
-	ret
-$LFE1:
-
+	cfi_endproc
 	.end	ffi_call_osf
 
 /* ffi_closure_osf(...)
 
    Receives the closure argument in $1.   */
 
-	.align	3
+#define CLOSURE_FS	(16*8)
+
+	.align	4
+	.globl	ffi_go_closure_osf
+	.ent	ffi_go_closure_osf
+	FFI_HIDDEN(ffi_go_closure_osf)
+
+ffi_go_closure_osf:
+	cfi_startproc
+	ldgp	$29, 0($27)
+	subq	$30, CLOSURE_FS, $30
+	cfi_adjust_cfa_offset(CLOSURE_FS)
+	stq	$26, 0($30)
+	.prologue 1
+	cfi_rel_offset($26, 0)
+
+	stq	$16, 10*8($30)
+	stq	$17, 11*8($30)
+	stq	$18, 12*8($30)
+
+	ldq	$16, 8($1)			# load cif
+	ldq	$17, 16($1)			# load fun
+	mov	$1, $18				# closure is user_data
+	br	$do_closure
+
+	cfi_endproc
+	.end	ffi_go_closure_osf
+
+	.align	4
 	.globl	ffi_closure_osf
 	.ent	ffi_closure_osf
 	FFI_HIDDEN(ffi_closure_osf)
 
 ffi_closure_osf:
-	.frame	$30, 16*8, $26, 0
-	.mask	0x4000000, -16*8
-$LFB2:
+	cfi_startproc
 	ldgp	$29, 0($27)
-	subq	$30, 16*8, $30
-$LCFI5:
+	subq	$30, CLOSURE_FS, $30
+	cfi_adjust_cfa_offset(CLOSURE_FS)
 	stq	$26, 0($30)
-$LCFI6:
 	.prologue 1
+	cfi_rel_offset($26, 0)
 
 	# Store all of the potential argument registers in va_list format.
+	stq	$16, 10*8($30)
+	stq	$17, 11*8($30)
+	stq	$18, 12*8($30)
+
+	ldq	$16, 24($1)			# load cif
+	ldq	$17, 32($1)			# load fun
+	ldq	$18, 40($1)			# load user_data
+
+$do_closure:
+	stq	$19, 13*8($30)
+	stq	$20, 14*8($30)
+	stq	$21, 15*8($30)
 	stt	$f16, 4*8($30)
 	stt	$f17, 5*8($30)
 	stt	$f18, 6*8($30)
 	stt	$f19, 7*8($30)
 	stt	$f20, 8*8($30)
 	stt	$f21, 9*8($30)
-	stq	$16, 10*8($30)
-	stq	$17, 11*8($30)
-	stq	$18, 12*8($30)
-	stq	$19, 13*8($30)
-	stq	$20, 14*8($30)
-	stq	$21, 15*8($30)
 
 	# Call ffi_closure_osf_inner to do the bulk of the work.
-	mov	$1, $16
-	lda	$17, 2*8($30)
-	lda	$18, 10*8($30)
+	lda	$19, 2*8($30)
+	lda	$20, 10*8($30)
 	jsr	$26, ffi_closure_osf_inner
-	ldgp	$29, 0($26)
+0:
+	ldah	$29, 0($26)			!gpdisp!2
+	lda	$2, 99f-0b($26)
+	s4addq	$0, 0, $1			# ldcode * 4
+	ldq	$0, 16($30)			# preload return value
+	s4addq	$1, $2, $1			# 99f + ldcode * 16
+	lda	$29, 0($29)			!gpdisp!2
 	ldq	$26, 0($30)
-
-	# Load up the return value in the proper type.
-	lda	$1, $load_table
-	s4addq	$0, $1, $1
-	ldl	$1, 0($1)
-	addq	$1, $29, $1
+	cfi_restore($26)
 	jmp	$31, ($1), $load_32
 
-	.align 4
-$load_none:
-	addq	$30, 16*8, $30
+.macro epilogue
+	addq	$30, CLOSURE_FS, $30
+	cfi_adjust_cfa_offset(-CLOSURE_FS)
 	ret
+	.align	4
+	cfi_adjust_cfa_offset(CLOSURE_FS)
+.endm
 
 	.align 4
-$load_float:
-	lds	$f0, 16($30)
-	nop
-	addq	$30, 16*8, $30
-	ret
+99:
+E ALPHA_LD_VOID
+	epilogue
 
-	.align 4
-$load_double:
-	ldt	$f0, 16($30)
-	nop
-	addq	$30, 16*8, $30
-	ret
+E ALPHA_LD_INT64
+	epilogue
 
-	.align 4
-$load_u8:
-#ifdef __alpha_bwx__
-	ldbu	$0, 16($30)
-	nop
-#else
-	ldq	$0, 16($30)
-	and	$0, 255, $0
-#endif
-	addq	$30, 16*8, $30
-	ret
+E ALPHA_LD_INT32
+$load_32:
+	sextl	$0, $0
+	epilogue
 
-	.align 4
-$load_s8:
-#ifdef __alpha_bwx__
-	ldbu	$0, 16($30)
-	sextb	$0, $0
-#else
-	ldq	$0, 16($30)
-	sll	$0, 56, $0
-	sra	$0, 56, $0
-#endif
-	addq	$30, 16*8, $30
-	ret
-
-	.align 4
-$load_u16:
-#ifdef __alpha_bwx__
-	ldwu	$0, 16($30)
-	nop
-#else
-	ldq	$0, 16($30)
+E ALPHA_LD_UINT16
 	zapnot	$0, 3, $0
-#endif
-	addq	$30, 16*8, $30
-	ret
+	epilogue
 
-	.align 4
-$load_s16:
+E ALPHA_LD_SINT16
 #ifdef __alpha_bwx__
-	ldwu	$0, 16($30)
 	sextw	$0, $0
 #else
-	ldq	$0, 16($30)
 	sll	$0, 48, $0
 	sra	$0, 48, $0
 #endif
-	addq	$30, 16*8, $30
-	ret
+	epilogue
 
-	.align 4
-$load_32:
-	ldl	$0, 16($30)
-	nop
-	addq	$30, 16*8, $30
-	ret
+E ALPHA_LD_UINT8
+	and	$0, 0xff, $0
+	epilogue
 
-	.align 4
-$load_64:
-	ldq	$0, 16($30)
-	nop
-	addq	$30, 16*8, $30
-	ret
-$LFE2:
-
-	.end	ffi_closure_osf
-
-#ifdef __ELF__
-.section .rodata
+E ALPHA_LD_SINT8
+#ifdef __alpha_bwx__
+	sextb	$0, $0
 #else
-.rdata
+	sll	$0, 56, $0
+	sra	$0, 56, $0
 #endif
-$load_table:
-	.gprel32 $load_none	# FFI_TYPE_VOID
-	.gprel32 $load_32	# FFI_TYPE_INT
-	.gprel32 $load_float	# FFI_TYPE_FLOAT
-	.gprel32 $load_double	# FFI_TYPE_DOUBLE
-	.gprel32 $load_none	# FFI_TYPE_LONGDOUBLE
-	.gprel32 $load_u8	# FFI_TYPE_UINT8
-	.gprel32 $load_s8	# FFI_TYPE_SINT8
-	.gprel32 $load_u16	# FFI_TYPE_UINT16
-	.gprel32 $load_s16	# FFI_TYPE_SINT16
-	.gprel32 $load_32	# FFI_TYPE_UINT32
-	.gprel32 $load_32	# FFI_TYPE_SINT32
-	.gprel32 $load_64	# FFI_TYPE_UINT64
-	.gprel32 $load_64	# FFI_TYPE_SINT64
-	.gprel32 $load_none	# FFI_TYPE_STRUCT
-	.gprel32 $load_64	# FFI_TYPE_POINTER
+	epilogue
 
-/* Assert that the table above is in sync with ffi.h.  */
+E ALPHA_LD_FLOAT
+	lds	$f0, 16($sp)
+	epilogue
 
-#if	   FFI_TYPE_FLOAT != 2		\
-	|| FFI_TYPE_DOUBLE != 3		\
-	|| FFI_TYPE_UINT8 != 5		\
-	|| FFI_TYPE_SINT8 != 6		\
-	|| FFI_TYPE_UINT16 != 7		\
-	|| FFI_TYPE_SINT16 != 8		\
-	|| FFI_TYPE_UINT32 != 9		\
-	|| FFI_TYPE_SINT32 != 10	\
-	|| FFI_TYPE_UINT64 != 11	\
-	|| FFI_TYPE_SINT64 != 12	\
-	|| FFI_TYPE_STRUCT != 13	\
-	|| FFI_TYPE_POINTER != 14	\
-	|| FFI_TYPE_LAST != 14
-#error "osf.S out of sync with ffi.h"
-#endif
+E ALPHA_LD_DOUBLE
+	ldt	$f0, 16($sp)
+	epilogue
 
-#ifdef __ELF__
-# define UA_SI		.4byte
-# define FDE_ENCODING	0x1b	/* pcrel sdata4 */
-# define FDE_ENCODE(X)	.4byte X-.
-# define FDE_ARANGE(X)	.4byte X
-#elif defined __osf__
-# define UA_SI		.align 0; .long
-# define FDE_ENCODING	0x50	/* aligned absolute */
-# define FDE_ENCODE(X)	.align 3; .quad X
-# define FDE_ARANGE(X)	.align 0; .quad X
-#endif
+E ALPHA_LD_CPLXF
+	lds	$f0, 16($sp)
+	lds	$f1, 20($sp)
+	epilogue
 
-#ifdef __ELF__
-	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
-#elif defined __osf__
-	.data
-	.align 3
-	.globl _GLOBAL__F_ffi_call_osf
-_GLOBAL__F_ffi_call_osf:
-#endif
-__FRAME_BEGIN__:
-	UA_SI	$LECIE1-$LSCIE1	# Length of Common Information Entry
-$LSCIE1:
-	UA_SI	0x0		# CIE Identifier Tag
-	.byte	0x1		# CIE Version
-	.ascii "zR\0"		# CIE Augmentation
-	.byte	0x1		# uleb128 0x1; CIE Code Alignment Factor
-	.byte	0x78		# sleb128 -8; CIE Data Alignment Factor
-	.byte	26		# CIE RA Column
-	.byte	0x1		# uleb128 0x1; Augmentation size
-	.byte	FDE_ENCODING	# FDE Encoding
-	.byte	0xc		# DW_CFA_def_cfa
-	.byte	30		# uleb128 column 30
-	.byte	0		# uleb128 offset 0
-	.align 3
-$LECIE1:
-$LSFDE1:
-	UA_SI	$LEFDE1-$LASFDE1		# FDE Length
-$LASFDE1:
-	UA_SI	$LASFDE1-__FRAME_BEGIN__	# FDE CIE offset
-	FDE_ENCODE($LFB1)			# FDE initial location
-	FDE_ARANGE($LFE1-$LFB1)			# FDE address range
-	.byte	0x0		# uleb128 0x0; Augmentation size
+E ALPHA_LD_CPLXD
+	ldt	$f0, 16($sp)
+	ldt	$f1, 24($sp)
+	epilogue
 
-	.byte	0x4		# DW_CFA_advance_loc4
-	UA_SI	$LCFI1-$LFB1
-	.byte	0x9a		# DW_CFA_offset, column 26
-	.byte	4		# uleb128 4*-8
-	.byte	0x8f		# DW_CFA_offset, column 15
-	.byte	0x3		# uleb128 3*-8
-	.byte	0xc		# DW_CFA_def_cfa
-	.byte	15		# uleb128 column 15
-	.byte	32		# uleb128 offset 32
-
-	.byte	0x4		# DW_CFA_advance_loc4
-	UA_SI	$LCFI2-$LCFI1
-	.byte	0xda		# DW_CFA_restore, column 26
-	.align 3
-$LEFDE1:
-
-$LSFDE3:
-	UA_SI	$LEFDE3-$LASFDE3		# FDE Length
-$LASFDE3:
-	UA_SI	$LASFDE3-__FRAME_BEGIN__	# FDE CIE offset
-	FDE_ENCODE($LFB2)			# FDE initial location
-	FDE_ARANGE($LFE2-$LFB2)			# FDE address range
-	.byte	0x0		# uleb128 0x0; Augmentation size
-
-	.byte	0x4		# DW_CFA_advance_loc4
-	UA_SI	$LCFI5-$LFB2
-	.byte	0xe		# DW_CFA_def_cfa_offset
-	.byte	0x80,0x1	# uleb128 128
-
-	.byte	0x4		# DW_CFA_advance_loc4
-	UA_SI	$LCFI6-$LCFI5
-	.byte	0x9a		# DW_CFA_offset, column 26
-	.byte	16		# uleb128 offset 16*-8
-	.align 3
-$LEFDE3:
-#if defined __osf__
-	.align 0
-	.long	0		# End of Table
-#endif
+	cfi_endproc
+	.end	ffi_closure_osf
 
 #if defined __ELF__ && defined __linux__
 	.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/gofrontend/libffi/src/arc/arcompact.S b/third_party/gofrontend/libffi/src/arc/arcompact.S
new file mode 100644
index 0000000..03715fd
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/arc/arcompact.S
@@ -0,0 +1,135 @@
+/* -----------------------------------------------------------------------
+   arcompact.S - Copyright (c) 2013 Synposys, Inc. (www.synopsys.com)
+   
+   ARCompact Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+#define CNAME(x) x
+#define ENTRY(x) .globl CNAME(x)` .type CNAME(x),%function` CNAME(x):
+#endif
+
+.text
+
+        /* R0:   ffi_prep_args */
+        /* R1:   &ecif */
+        /* R2:   cif->bytes */
+        /* R3:   fig->flags */
+        /* R4:   ecif.rvalue */
+        /* R5:   fn */
+ENTRY(ffi_call_ARCompact)
+        /* Save registers.  */
+        st.a       fp, [sp, -4]        /* fp + 20, fp */
+        push_s     blink               /* fp + 16, blink */
+        st.a       r4, [sp, -4]        /* fp + 12, ecif.rvalue */
+        push_s     r3                  /* fp +  8, fig->flags */
+        st.a       r5, [sp, -4]        /* fp +  4, fn */
+        push_s     r2                  /* fp +  0, cif->bytes */
+        mov        fp, sp
+
+        /* Make room for all of the new args.  */
+        sub        sp, sp, r2
+
+        /* Place all of the ffi_prep_args in position.  */
+        /* ffi_prep_args(char *stack, extended_cif *ecif) */
+        /* R1 already set.  */
+
+        /* And call.  */
+        jl_s.d     [r0]
+        mov_s      r0, sp
+
+        ld.ab      r12, [fp, 4]        /* cif->bytes */
+        ld.ab      r11, [fp, 4]        /* fn */
+
+        /* Move first 8 parameters in registers...  */
+        ld_s       r0, [sp]
+        ld_s       r1, [sp, 4]
+        ld_s       r2, [sp, 8]
+        ld_s       r3, [sp, 12]
+        ld         r4, [sp, 16]
+        ld         r5, [sp, 20]
+        ld         r6, [sp, 24]
+        ld         r7, [sp, 28]
+
+        /* ...and adjust the stack.  */
+        min        r12, r12, 32
+
+        /* Call the function.  */
+        jl.d       [r11]
+        add        sp, sp, r12 
+
+        mov        sp, fp        
+        pop_s      r3        /* fig->flags, return type */
+        pop_s      r2        /* ecif.rvalue, pointer for return value */
+
+        /* If the return value pointer is NULL, assume no return value.  */
+        breq.d     r2, 0, epilogue
+        pop_s      blink
+
+        /* Return INT.  */
+        brne       r3, FFI_TYPE_INT, return_double
+        b.d        epilogue
+        st_s       r0, [r2]        
+
+return_double:
+        brne       r3, FFI_TYPE_DOUBLE, epilogue
+        st_s       r0, [r2]        
+        st_s       r1, [r2,4]
+
+epilogue:
+        j_s.d      [blink]
+        ld.ab      fp, [sp, 4]
+
+ENTRY(ffi_closure_ARCompact)
+        st.a       r0, [sp, -32]
+        st_s       r1, [sp, 4]
+        st_s       r2, [sp, 8]
+        st_s       r3, [sp, 12]
+        st         r4, [sp, 16]
+        st         r5, [sp, 20]
+        st         r6, [sp, 24]
+        st         r7, [sp, 28]
+
+        /* pointer to arguments */
+        mov_s      r2, sp
+
+        /* return value goes here */
+        sub        sp, sp, 8
+        mov_s      r1, sp
+
+        push_s     blink
+        
+        bl.d       ffi_closure_inner_ARCompact
+        mov_s      r0, r8                /* codeloc, set by trampoline */
+
+        pop_s      blink
+
+        /* set return value to r1:r0 */
+        pop_s      r0
+        pop_s      r1
+        j_s.d      [blink]
+        add_s      sp, sp, 32
diff --git a/third_party/gofrontend/libffi/src/arc/ffi.c b/third_party/gofrontend/libffi/src/arc/ffi.c
new file mode 100644
index 0000000..32f82a7
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/arc/ffi.c
@@ -0,0 +1,268 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2013  Synopsys, Inc. (www.synopsys.com)
+   
+   ARC Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <sys/cachectl.h>
+
+/* for little endian ARC, the code is in fact stored as mixed endian for
+   performance reasons */
+#if __BIG_ENDIAN__
+#define CODE_ENDIAN(x) (x)
+#else
+#define CODE_ENDIAN(x) ( (((uint32_t) (x)) << 16) | (((uint32_t) (x)) >> 16))
+#endif
+
+/* ffi_prep_args is called by the assembly routine once stack
+   space has been allocated for the function's arguments.  */
+
+void
+ffi_prep_args (char *stack, extended_cif * ecif)
+{
+  unsigned int i;
+  int tmp;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+  tmp = 0;
+  argp = stack;
+
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += 4;
+    }
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0); i--, p_arg++)
+    {
+      size_t z;
+      int alignment;
+
+      /* align alignment to 4 */
+      alignment = (((*p_arg)->alignment - 1) | 3) + 1;
+
+      /* Align if necessary.  */
+      if ((alignment - 1) & (unsigned) argp)
+	argp = (char *) ALIGN (argp, alignment);
+
+      z = (*p_arg)->size;
+      if (z < sizeof (int))
+	{
+	  z = sizeof (int);
+
+	  switch ((*p_arg)->type)
+	    {
+	    case FFI_TYPE_SINT8:
+	      *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
+	      break;
+
+	    case FFI_TYPE_UINT8:
+	      *(unsigned int *) argp = (unsigned int) *(UINT8 *) (*p_argv);
+	      break;
+
+	    case FFI_TYPE_SINT16:
+	      *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
+	      break;
+
+	    case FFI_TYPE_UINT16:
+	      *(unsigned int *) argp = (unsigned int) *(UINT16 *) (*p_argv);
+	      break;
+
+	    case FFI_TYPE_STRUCT:
+	      memcpy (argp, *p_argv, (*p_arg)->size);
+	      break;
+
+	    default:
+	      FFI_ASSERT (0);
+	    }
+	}
+      else if (z == sizeof (int))
+	{
+	  *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
+	}
+      else
+	{
+	  if ((*p_arg)->type == FFI_TYPE_STRUCT)
+	    {
+	      memcpy (argp, *p_argv, z);
+	    }
+	  else
+	    {
+	      /* Double or long long 64bit.  */
+	      memcpy (argp, *p_argv, z);
+	    }
+	}
+      p_argv++;
+      argp += z;
+    }
+
+  return;
+}
+
+/* Perform machine dependent cif processing.  */
+ffi_status
+ffi_prep_cif_machdep (ffi_cif * cif)
+{
+  /* Set the return type flag.  */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_DOUBLE:
+      cif->flags = FFI_TYPE_DOUBLE;
+      break;
+
+    case FFI_TYPE_FLOAT:
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+extern void ffi_call_ARCompact (void (*)(char *, extended_cif *),
+				extended_cif *, unsigned, unsigned,
+				unsigned *, void (*fn) (void));
+
+void
+ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* If the return value is a struct and we don't have
+     a return value address then we need to make one.  */
+  if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      ecif.rvalue = alloca (cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi)
+    {
+    case FFI_ARCOMPACT:
+      ffi_call_ARCompact (ffi_prep_args, &ecif, cif->bytes,
+			  cif->flags, ecif.rvalue, fn);
+      break;
+
+    default:
+      FFI_ASSERT (0);
+      break;
+    }
+}
+
+int
+ffi_closure_inner_ARCompact (ffi_closure * closure, void *rvalue,
+			     ffi_arg * args)
+{
+  void **arg_area, **p_argv;
+  ffi_cif *cif = closure->cif;
+  char *argp = (char *) args;
+  ffi_type **p_argt;
+  int i;
+
+  arg_area = (void **) alloca (cif->nargs * sizeof (void *));
+
+  /* handle hidden argument */
+  if (cif->flags == FFI_TYPE_STRUCT)
+    {
+      rvalue = *(void **) argp;
+      argp += 4;
+    }
+
+  p_argv = arg_area;
+
+  for (i = 0, p_argt = cif->arg_types; i < cif->nargs;
+       i++, p_argt++, p_argv++)
+    {
+      size_t z;
+      int alignment;
+
+      /* align alignment to 4 */
+      alignment = (((*p_argt)->alignment - 1) | 3) + 1;
+
+      /* Align if necessary.  */
+      if ((alignment - 1) & (unsigned) argp)
+	argp = (char *) ALIGN (argp, alignment);
+
+      z = (*p_argt)->size;
+      *p_argv = (void *) argp;
+      argp += z;
+    }
+
+  (closure->fun) (cif, rvalue, arg_area, closure->user_data);
+
+  return cif->flags;
+}
+
+extern void ffi_closure_ARCompact (void);
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure * closure, ffi_cif * cif,
+		      void (*fun) (ffi_cif *, void *, void **, void *),
+		      void *user_data, void *codeloc)
+{
+  uint32_t *tramp = (uint32_t *) & (closure->tramp[0]);
+
+  switch (cif->abi)
+    {
+    case FFI_ARCOMPACT:
+      FFI_ASSERT (tramp == codeloc);
+      tramp[0] = CODE_ENDIAN (0x200a1fc0);	/* mov r8, pcl  */
+      tramp[1] = CODE_ENDIAN (0x20200f80);	/* j [long imm] */
+      tramp[2] = CODE_ENDIAN (ffi_closure_ARCompact);
+      break;
+
+    default:
+      return FFI_BAD_ABI;
+    }
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+  cacheflush (codeloc, FFI_TRAMPOLINE_SIZE, BCACHE);
+
+  return FFI_OK;
+}
diff --git a/third_party/gofrontend/libffi/src/arc/ffitarget.h b/third_party/gofrontend/libffi/src/arc/ffitarget.h
new file mode 100644
index 0000000..bf8311b
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/arc/ffitarget.h
@@ -0,0 +1,53 @@
+/* -----------------------------------------------------------------------
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (c) 2013  Synopsys, Inc. (www.synopsys.com)
+   Target configuration macros for ARC.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+/* ---- Generic type definitions ----------------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long ffi_arg;
+typedef signed long ffi_sarg;
+
+typedef enum ffi_abi
+{
+  FFI_FIRST_ABI = 0,
+  FFI_ARCOMPACT,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_ARCOMPACT
+} ffi_abi;
+#endif
+
+#define FFI_CLOSURES 		1
+#define FFI_TRAMPOLINE_SIZE	12
+#define FFI_NATIVE_RAW_API 	0
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/arm/ffi.c b/third_party/gofrontend/libffi/src/arm/ffi.c
index 3ccceb9..9c8732d 100644
--- a/third_party/gofrontend/libffi/src/arm/ffi.c
+++ b/third_party/gofrontend/libffi/src/arm/ffi.c
@@ -4,8 +4,8 @@
            Copyright (c) 2011 Anthony Green
 	   Copyright (c) 2011 Free Software Foundation
            Copyright (c) 1998, 2008, 2011  Red Hat, Inc.
-	   
-   ARM Foreign Function Interface 
+
+   ARM Foreign Function Interface
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -30,343 +30,505 @@
 
 #include <ffi.h>
 #include <ffi_common.h>
-
 #include <stdlib.h>
+#include "internal.h"
 
 /* Forward declares. */
-static int vfp_type_p (ffi_type *);
+static int vfp_type_p (const ffi_type *);
 static void layout_vfp_args (ffi_cif *);
 
-/* ffi_prep_args is called by the assembly routine once stack space
-   has been allocated for the function's arguments
-   
+static void *
+ffi_align (ffi_type *ty, void *p)
+{
+  /* Align if necessary */
+  size_t alignment;
+#ifdef _WIN32_WCE
+  alignment = 4;
+#else
+  alignment = ty->alignment;
+  if (alignment < 4)
+    alignment = 4;
+#endif
+  return (void *) ALIGN (p, alignment);
+}
+
+static size_t
+ffi_put_arg (ffi_type *ty, void *src, void *dst)
+{
+  size_t z = ty->size;
+
+  switch (ty->type)
+    {
+    case FFI_TYPE_SINT8:
+      *(UINT32 *)dst = *(SINT8 *)src;
+      break;
+    case FFI_TYPE_UINT8:
+      *(UINT32 *)dst = *(UINT8 *)src;
+      break;
+    case FFI_TYPE_SINT16:
+      *(UINT32 *)dst = *(SINT16 *)src;
+      break;
+    case FFI_TYPE_UINT16:
+      *(UINT32 *)dst = *(UINT16 *)src;
+      break;
+
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_FLOAT:
+      *(UINT32 *)dst = *(UINT32 *)src;
+      break;
+
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_DOUBLE:
+      *(UINT64 *)dst = *(UINT64 *)src;
+      break;
+
+    case FFI_TYPE_STRUCT:
+    case FFI_TYPE_COMPLEX:
+      memcpy (dst, src, z);
+      break;
+
+    default:
+      abort();
+    }
+
+  return ALIGN (z, 4);
+}
+
+/* ffi_prep_args is called once stack space has been allocated
+   for the function's arguments.
+
    The vfp_space parameter is the load area for VFP regs, the return
    value is cif->vfp_used (word bitset of VFP regs used for passing
    arguments). These are only used for the VFP hard-float ABI.
 */
-int ffi_prep_args(char *stack, extended_cif *ecif, float *vfp_space)
+static void
+ffi_prep_args_SYSV (ffi_cif *cif, int flags, void *rvalue,
+		    void **avalue, char *argp)
 {
-  register unsigned int i, vi = 0;
-  register void **p_argv;
-  register char *argp;
-  register ffi_type **p_arg;
+  ffi_type **arg_types = cif->arg_types;
+  int i, n;
 
-  argp = stack;
-
-  if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
-    *(void **) argp = ecif->rvalue;
-    argp += 4;
-  }
-
-  p_argv = ecif->avalue;
-
-  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
-       (i != 0);
-       i--, p_arg++)
+  if (flags == ARM_TYPE_STRUCT)
     {
-      size_t z;
-      size_t alignment;
-
-      /* Allocated in VFP registers. */
-      if (ecif->cif->abi == FFI_VFP
-	  && vi < ecif->cif->vfp_nargs && vfp_type_p (*p_arg))
-	{
-	  float* vfp_slot = vfp_space + ecif->cif->vfp_args[vi++];
-	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
-	    *((float*)vfp_slot) = *((float*)*p_argv);
-	  else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
-	    *((double*)vfp_slot) = *((double*)*p_argv);
-	  else
-	    memcpy(vfp_slot, *p_argv, (*p_arg)->size);
-	  p_argv++;
-	  continue;
-	}
-
-      /* Align if necessary */
-      alignment = (*p_arg)->alignment;
-#ifdef _WIN32_WCE
-      if (alignment > 4)
-	alignment = 4;
-#endif
-      if ((alignment - 1) & (unsigned) argp) {
-	argp = (char *) ALIGN(argp, alignment);
-      }
-
-      if ((*p_arg)->type == FFI_TYPE_STRUCT)
-	argp = (char *) ALIGN(argp, 4);
-
-	  z = (*p_arg)->size;
-	  if (z < sizeof(int))
-	    {
-	      z = sizeof(int);
-	      switch ((*p_arg)->type)
-		{
-		case FFI_TYPE_SINT8:
-		  *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
-		  break;
-		  
-		case FFI_TYPE_UINT8:
-		  *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
-		  break;
-		  
-		case FFI_TYPE_SINT16:
-		  *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
-		  break;
-		  
-		case FFI_TYPE_UINT16:
-		  *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
-		  break;
-		  
-		case FFI_TYPE_STRUCT:
-		  memcpy(argp, *p_argv, (*p_arg)->size);
-		  break;
-
-		default:
-		  FFI_ASSERT(0);
-		}
-	    }
-	  else if (z == sizeof(int))
-	    {
-	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
-	    }
-	  else
-	    {
-	      memcpy(argp, *p_argv, z);
-	    }
-	  p_argv++;
-	  argp += z;
+      *(void **) argp = rvalue;
+      argp += 4;
     }
 
-  /* Indicate the VFP registers used. */
-  return ecif->cif->vfp_used;
+  for (i = 0, n = cif->nargs; i < n; i++)
+    {
+      ffi_type *ty = arg_types[i];
+      argp = ffi_align (ty, argp);
+      argp += ffi_put_arg (ty, avalue[i], argp);
+    }
+}
+
+static void
+ffi_prep_args_VFP (ffi_cif *cif, int flags, void *rvalue,
+                   void **avalue, char *stack, char *vfp_space)
+{
+  ffi_type **arg_types = cif->arg_types;
+  int i, n, vi = 0;
+  char *argp, *regp, *eo_regp;
+  char stack_used = 0;
+  char done_with_regs = 0;
+
+  /* The first 4 words on the stack are used for values
+     passed in core registers.  */
+  regp = stack;
+  eo_regp = argp = regp + 16;
+
+  /* If the function returns an FFI_TYPE_STRUCT in memory,
+     that address is passed in r0 to the function.  */
+  if (flags == ARM_TYPE_STRUCT)
+    {
+      *(void **) regp = rvalue;
+      regp += 4;
+    }
+
+  for (i = 0, n = cif->nargs; i < n; i++)
+    {
+      ffi_type *ty = arg_types[i];
+      void *a = avalue[i];
+      int is_vfp_type = vfp_type_p (ty);
+
+      /* Allocated in VFP registers. */
+      if (vi < cif->vfp_nargs && is_vfp_type)
+	{
+	  char *vfp_slot = vfp_space + cif->vfp_args[vi++] * 4;
+	  ffi_put_arg (ty, a, vfp_slot);
+	  continue;
+	}
+      /* Try allocating in core registers. */
+      else if (!done_with_regs && !is_vfp_type)
+	{
+	  char *tregp = ffi_align (ty, regp);
+	  size_t size = ty->size;
+	  size = (size < 4) ? 4 : size;	// pad
+	  /* Check if there is space left in the aligned register
+	     area to place the argument.  */
+	  if (tregp + size <= eo_regp)
+	    {
+	      regp = tregp + ffi_put_arg (ty, a, tregp);
+	      done_with_regs = (regp == argp);
+	      // ensure we did not write into the stack area
+	      FFI_ASSERT (regp <= argp);
+	      continue;
+	    }
+	  /* In case there are no arguments in the stack area yet,
+	     the argument is passed in the remaining core registers
+	     and on the stack.  */
+	  else if (!stack_used)
+	    {
+	      stack_used = 1;
+	      done_with_regs = 1;
+	      argp = tregp + ffi_put_arg (ty, a, tregp);
+	      FFI_ASSERT (eo_regp < argp);
+	      continue;
+	    }
+	}
+      /* Base case, arguments are passed on the stack */
+      stack_used = 1;
+      argp = ffi_align (ty, argp);
+      argp += ffi_put_arg (ty, a, argp);
+    }
 }
 
 /* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
 {
-  int type_code;
-  /* Round the stack up to a multiple of 8 bytes.  This isn't needed 
-     everywhere, but it is on some platforms, and it doesn't harm anything
-     when it isn't needed.  */
-  cif->bytes = (cif->bytes + 7) & ~7;
+  int flags = 0, cabi = cif->abi;
+  size_t bytes = cif->bytes;
+
+  /* Map out the register placements of VFP register args.  The VFP
+     hard-float calling conventions are slightly more sophisticated
+     than the base calling conventions, so we do it here instead of
+     in ffi_prep_args(). */
+  if (cabi == FFI_VFP)
+    layout_vfp_args (cif);
 
   /* Set the return type flag */
   switch (cif->rtype->type)
     {
     case FFI_TYPE_VOID:
-    case FFI_TYPE_FLOAT:
-    case FFI_TYPE_DOUBLE:
-      cif->flags = (unsigned) cif->rtype->type;
+      flags = ARM_TYPE_VOID;
+      break;
+
+    case FFI_TYPE_INT:
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_POINTER:
+      flags = ARM_TYPE_INT;
       break;
 
     case FFI_TYPE_SINT64:
     case FFI_TYPE_UINT64:
-      cif->flags = (unsigned) FFI_TYPE_SINT64;
+      flags = ARM_TYPE_INT64;
+      break;
+
+    case FFI_TYPE_FLOAT:
+      flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_S : ARM_TYPE_INT);
+      break;
+    case FFI_TYPE_DOUBLE:
+      flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_D : ARM_TYPE_INT64);
       break;
 
     case FFI_TYPE_STRUCT:
-      if (cif->abi == FFI_VFP
-	  && (type_code = vfp_type_p (cif->rtype)) != 0)
+    case FFI_TYPE_COMPLEX:
+      if (cabi == FFI_VFP)
 	{
-	  /* A Composite Type passed in VFP registers, either
-	     FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */
-	  cif->flags = (unsigned) type_code;
+	  int h = vfp_type_p (cif->rtype);
+
+	  flags = ARM_TYPE_VFP_N;
+	  if (h == 0x100 + FFI_TYPE_FLOAT)
+	    flags = ARM_TYPE_VFP_S;
+	  if (h == 0x100 + FFI_TYPE_DOUBLE)
+	    flags = ARM_TYPE_VFP_D;
+	  if (h != 0)
+	      break;
 	}
-      else if (cif->rtype->size <= 4)
-	/* A Composite Type not larger than 4 bytes is returned in r0.  */
-	cif->flags = (unsigned)FFI_TYPE_INT;
+
+      /* A Composite Type not larger than 4 bytes is returned in r0.
+	 A Composite Type larger than 4 bytes, or whose size cannot
+	 be determined statically ... is stored in memory at an
+	 address passed [in r0].  */
+      if (cif->rtype->size <= 4)
+	flags = ARM_TYPE_INT;
       else
-	/* A Composite Type larger than 4 bytes, or whose size cannot
-	   be determined statically ... is stored in memory at an
-	   address passed [in r0].  */
-	cif->flags = (unsigned)FFI_TYPE_STRUCT;
+	{
+	  flags = ARM_TYPE_STRUCT;
+	  bytes += 4;
+	}
       break;
 
     default:
-      cif->flags = FFI_TYPE_INT;
-      break;
+      abort();
     }
 
-  /* Map out the register placements of VFP register args.
-     The VFP hard-float calling conventions are slightly more sophisticated than
-     the base calling conventions, so we do it here instead of in ffi_prep_args(). */
-  if (cif->abi == FFI_VFP)
-    layout_vfp_args (cif);
+  /* Round the stack up to a multiple of 8 bytes.  This isn't needed
+     everywhere, but it is on some platforms, and it doesn't harm anything
+     when it isn't needed.  */
+  bytes = ALIGN (bytes, 8);
+
+  /* Minimum stack space is the 4 register arguments that we pop.  */
+  if (bytes < 4*4)
+    bytes = 4*4;
+
+  cif->bytes = bytes;
+  cif->flags = flags;
 
   return FFI_OK;
 }
 
 /* Perform machine dependent cif processing for variadic calls */
-ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
-				    unsigned int nfixedargs,
-				    unsigned int ntotalargs)
+ffi_status
+ffi_prep_cif_machdep_var (ffi_cif * cif,
+			  unsigned int nfixedargs, unsigned int ntotalargs)
 {
   /* VFP variadic calls actually use the SYSV ABI */
   if (cif->abi == FFI_VFP)
-	cif->abi = FFI_SYSV;
+    cif->abi = FFI_SYSV;
 
-  return ffi_prep_cif_machdep(cif);
+  return ffi_prep_cif_machdep (cif);
 }
 
-/* Prototypes for assembly functions, in sysv.S */
-extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
-extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
+/* Prototypes for assembly functions, in sysv.S.  */
 
-void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+struct call_frame
 {
-  extended_cif ecif;
+  void *fp;
+  void *lr;
+  void *rvalue;
+  int flags;
+  void *closure;
+};
 
-  int small_struct = (cif->flags == FFI_TYPE_INT 
-		      && cif->rtype->type == FFI_TYPE_STRUCT);
-  int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT
-		    || cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE);
+extern void ffi_call_SYSV (void *stack, struct call_frame *,
+			   void (*fn) (void)) FFI_HIDDEN;
+extern void ffi_call_VFP (void *vfp_space, struct call_frame *,
+			   void (*fn) (void), unsigned vfp_used) FFI_HIDDEN;
 
-  ecif.cif = cif;
-  ecif.avalue = avalue;
+static void
+ffi_call_int (ffi_cif * cif, void (*fn) (void), void *rvalue,
+	      void **avalue, void *closure)
+{
+  int flags = cif->flags;
+  ffi_type *rtype = cif->rtype;
+  size_t bytes, rsize, vfp_size;
+  char *stack, *vfp_space, *new_rvalue;
+  struct call_frame *frame;
 
-  unsigned int temp;
-  
-  /* If the return value is a struct and we don't have a return	*/
-  /* value address then we need to make one		        */
-
-  if ((rvalue == NULL) && 
-      (cif->flags == FFI_TYPE_STRUCT))
+  rsize = 0;
+  if (rvalue == NULL)
     {
-      ecif.rvalue = alloca(cif->rtype->size);
+      /* If the return value is a struct and we don't have a return
+	 value address then we need to make one.  Otherwise the return
+	 value is in registers and we can ignore them.  */
+      if (flags == ARM_TYPE_STRUCT)
+	rsize = rtype->size;
+      else
+	flags = ARM_TYPE_VOID;
     }
-  else if (small_struct)
-    ecif.rvalue = &temp;
-  else if (vfp_struct)
+  else if (flags == ARM_TYPE_VFP_N)
     {
       /* Largest case is double x 4. */
-      ecif.rvalue = alloca(32);
+      rsize = 32;
+    }
+  else if (flags == ARM_TYPE_INT && rtype->type == FFI_TYPE_STRUCT)
+    rsize = 4;
+
+  /* Largest case.  */
+  vfp_size = (cif->abi == FFI_VFP && cif->vfp_used ? 8*8: 0);
+
+  bytes = cif->bytes;
+  stack = alloca (vfp_size + bytes + sizeof(struct call_frame) + rsize);
+
+  vfp_space = NULL;
+  if (vfp_size)
+    {
+      vfp_space = stack;
+      stack += vfp_size;
+    }
+
+  frame = (struct call_frame *)(stack + bytes);
+
+  new_rvalue = rvalue;
+  if (rsize)
+    new_rvalue = (void *)(frame + 1);
+
+  frame->rvalue = new_rvalue;
+  frame->flags = flags;
+  frame->closure = closure;
+
+  if (vfp_space)
+    {
+      ffi_prep_args_VFP (cif, flags, new_rvalue, avalue, stack, vfp_space);
+      ffi_call_VFP (vfp_space, frame, fn, cif->vfp_used);
     }
   else
-    ecif.rvalue = rvalue;
-
-  switch (cif->abi) 
     {
-    case FFI_SYSV:
-      ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
-      break;
-
-    case FFI_VFP:
-#ifdef __ARM_EABI__
-      ffi_call_VFP (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
-      break;
-#endif
-
-    default:
-      FFI_ASSERT(0);
-      break;
+      ffi_prep_args_SYSV (cif, flags, new_rvalue, avalue, stack);
+      ffi_call_SYSV (stack, frame, fn);
     }
-  if (small_struct)
-    memcpy (rvalue, &temp, cif->rtype->size);
-  else if (vfp_struct)
-    memcpy (rvalue, ecif.rvalue, cif->rtype->size);
+
+  if (rvalue && rvalue != new_rvalue)
+    memcpy (rvalue, new_rvalue, rtype->size);
 }
 
-/** private members **/
-
-static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
-					 void** args, ffi_cif* cif, float *vfp_stack);
-
-void ffi_closure_SYSV (ffi_closure *);
-
-void ffi_closure_VFP (ffi_closure *);
-
-/* This function is jumped to by the trampoline */
-
-unsigned int
-ffi_closure_SYSV_inner (closure, respp, args, vfp_args)
-     ffi_closure *closure;
-     void **respp;
-     void *args;
-     void *vfp_args;
+void
+ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
 {
-  // our various things...
-  ffi_cif       *cif;
-  void         **arg_area;
+  ffi_call_int (cif, fn, rvalue, avalue, NULL);
+}
 
-  cif         = closure->cif;
-  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
+void
+ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
+	     void **avalue, void *closure)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, closure);
+}
 
-  /* this call will initialize ARG_AREA, such that each
-   * element in that array points to the corresponding 
-   * value on the stack; and if the function returns
-   * a structure, it will re-set RESP to point to the
-   * structure return address.  */
+static void *
+ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue,
+			     char *argp, void **avalue)
+{
+  ffi_type **arg_types = cif->arg_types;
+  int i, n;
 
-  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args);
+  if (cif->flags == ARM_TYPE_STRUCT)
+    {
+      rvalue = *(void **) argp;
+      argp += 4;
+    }
 
-  (closure->fun) (cif, *respp, arg_area, closure->user_data);
+  for (i = 0, n = cif->nargs; i < n; i++)
+    {
+      ffi_type *ty = arg_types[i];
+      size_t z = ty->size;
 
+      argp = ffi_align (ty, argp);
+      avalue[i] = (void *) argp;
+      argp += z;
+    }
+
+  return rvalue;
+}
+
+static void *
+ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack,
+			    char *vfp_space, void **avalue)
+{
+  ffi_type **arg_types = cif->arg_types;
+  int i, n, vi = 0;
+  char *argp, *regp, *eo_regp;
+  char done_with_regs = 0;
+  char stack_used = 0;
+
+  regp = stack;
+  eo_regp = argp = regp + 16;
+
+  if (cif->flags == ARM_TYPE_STRUCT)
+    {
+      rvalue = *(void **) regp;
+      regp += 4;
+    }
+
+  for (i = 0, n = cif->nargs; i < n; i++)
+    {
+      ffi_type *ty = arg_types[i];
+      int is_vfp_type = vfp_type_p (ty);
+      size_t z = ty->size;
+
+      if (vi < cif->vfp_nargs && is_vfp_type)
+	{
+	  avalue[i] = vfp_space + cif->vfp_args[vi++] * 4;
+	  continue;
+	}
+      else if (!done_with_regs && !is_vfp_type)
+	{
+	  char *tregp = ffi_align (ty, regp);
+
+	  z = (z < 4) ? 4 : z;	// pad
+
+	  /* If the arguments either fits into the registers or uses registers
+	     and stack, while we haven't read other things from the stack */
+	  if (tregp + z <= eo_regp || !stack_used)
+	    {
+	      /* Because we're little endian, this is what it turns into.  */
+	      avalue[i] = (void *) tregp;
+	      regp = tregp + z;
+
+	      /* If we read past the last core register, make sure we
+		 have not read from the stack before and continue
+		 reading after regp.  */
+	      if (regp > eo_regp)
+		{
+		  FFI_ASSERT (!stack_used);
+		  argp = regp;
+		}
+	      if (regp >= eo_regp)
+		{
+		  done_with_regs = 1;
+		  stack_used = 1;
+		}
+	      continue;
+	    }
+	}
+
+      stack_used = 1;
+      argp = ffi_align (ty, argp);
+      avalue[i] = (void *) argp;
+      argp += z;
+    }
+
+  return rvalue;
+}
+
+struct closure_frame
+{
+  char vfp_space[8*8] __attribute__((aligned(8)));
+  char result[8*4];
+  char argp[];
+};
+
+int FFI_HIDDEN
+ffi_closure_inner_SYSV (ffi_cif *cif,
+		        void (*fun) (ffi_cif *, void *, void **, void *),
+		        void *user_data,
+		        struct closure_frame *frame)
+{
+  void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
+  void *rvalue = ffi_prep_incoming_args_SYSV (cif, frame->result,
+					      frame->argp, avalue);
+  fun (cif, rvalue, avalue, user_data);
   return cif->flags;
 }
 
-/*@-exportheader@*/
-static void 
-ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
-			    void **avalue, ffi_cif *cif,
-			    /* Used only under VFP hard-float ABI. */
-			    float *vfp_stack)
-/*@=exportheader@*/
+int FFI_HIDDEN
+ffi_closure_inner_VFP (ffi_cif *cif,
+		       void (*fun) (ffi_cif *, void *, void **, void *),
+		       void *user_data,
+		       struct closure_frame *frame)
 {
-  register unsigned int i, vi = 0;
-  register void **p_argv;
-  register char *argp;
-  register ffi_type **p_arg;
-
-  argp = stack;
-
-  if ( cif->flags == FFI_TYPE_STRUCT ) {
-    *rvalue = *(void **) argp;
-    argp += 4;
-  }
-
-  p_argv = avalue;
-
-  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
-    {
-      size_t z;
-      size_t alignment;
-  
-      if (cif->abi == FFI_VFP
-	  && vi < cif->vfp_nargs && vfp_type_p (*p_arg))
-	{
-	  *p_argv++ = (void*)(vfp_stack + cif->vfp_args[vi++]);
-	  continue;
-	}
-
-      alignment = (*p_arg)->alignment;
-      if (alignment < 4)
-	alignment = 4;
-#ifdef _WIN32_WCE
-      else
-	if (alignment > 4)
-	  alignment = 4;
-#endif
-      /* Align if necessary */
-      if ((alignment - 1) & (unsigned) argp) {
-	argp = (char *) ALIGN(argp, alignment);
-      }
-
-      z = (*p_arg)->size;
-
-      /* because we're little endian, this is what it turns into.   */
-
-      *p_argv = (void*) argp;
-
-      p_argv++;
-      argp += z;
-    }
-  
-  return;
+  void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
+  void *rvalue = ffi_prep_incoming_args_VFP (cif, frame->result, frame->argp,
+					     frame->vfp_space, avalue);
+  fun (cif, rvalue, avalue, user_data);
+  return cif->flags;
 }
 
-/* How to make a trampoline.  */
-
-extern unsigned int ffi_arm_trampoline[3];
+void ffi_closure_SYSV (void) FFI_HIDDEN;
+void ffi_closure_VFP (void) FFI_HIDDEN;
+void ffi_go_closure_SYSV (void) FFI_HIDDEN;
+void ffi_go_closure_VFP (void) FFI_HIDDEN;
 
 #if FFI_EXEC_TRAMPOLINE_TABLE
 
@@ -380,8 +542,9 @@
 typedef struct ffi_trampoline_table ffi_trampoline_table;
 typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
 
-struct ffi_trampoline_table {
-  /* contigious writable and executable pages */
+struct ffi_trampoline_table
+{
+  /* contiguous writable and executable pages */
   vm_address_t config_page;
   vm_address_t trampoline_page;
 
@@ -394,8 +557,9 @@
   ffi_trampoline_table *next;
 };
 
-struct ffi_trampoline_table_entry {
-  void *(*trampoline)();
+struct ffi_trampoline_table_entry
+{
+  void *(*trampoline) ();
   ffi_trampoline_table_entry *next;
 };
 
@@ -421,64 +585,81 @@
 {
   ffi_trampoline_table *table = NULL;
 
-  /* Loop until we can allocate two contigious pages */
-  while (table == NULL) {
-    vm_address_t config_page = 0x0;
-    kern_return_t kt;
+  /* Loop until we can allocate two contiguous pages */
+  while (table == NULL)
+    {
+      vm_address_t config_page = 0x0;
+      kern_return_t kt;
 
-    /* Try to allocate two pages */
-    kt = vm_allocate (mach_task_self (), &config_page, PAGE_SIZE*2, VM_FLAGS_ANYWHERE);
-    if (kt != KERN_SUCCESS) {
-      fprintf(stderr, "vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
-      break;
+      /* Try to allocate two pages */
+      kt =
+	vm_allocate (mach_task_self (), &config_page, PAGE_SIZE * 2,
+		     VM_FLAGS_ANYWHERE);
+      if (kt != KERN_SUCCESS)
+	{
+	  fprintf (stderr, "vm_allocate() failure: %d at %s:%d\n", kt,
+		   __FILE__, __LINE__);
+	  break;
+	}
+
+      /* Now drop the second half of the allocation to make room for the trampoline table */
+      vm_address_t trampoline_page = config_page + PAGE_SIZE;
+      kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE);
+      if (kt != KERN_SUCCESS)
+	{
+	  fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt,
+		   __FILE__, __LINE__);
+	  break;
+	}
+
+      /* Remap the trampoline table to directly follow the config page */
+      vm_prot_t cur_prot;
+      vm_prot_t max_prot;
+
+      kt =
+	vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE,
+		  mach_task_self (),
+		  (vm_address_t) & ffi_closure_trampoline_table_page, FALSE,
+		  &cur_prot, &max_prot, VM_INHERIT_SHARE);
+
+      /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */
+      if (kt != KERN_SUCCESS)
+	{
+	  /* Log unexpected failures */
+	  if (kt != KERN_NO_SPACE)
+	    {
+	      fprintf (stderr, "vm_remap() failure: %d at %s:%d\n", kt,
+		       __FILE__, __LINE__);
+	    }
+
+	  vm_deallocate (mach_task_self (), config_page, PAGE_SIZE);
+	  continue;
+	}
+
+      /* We have valid trampoline and config pages */
+      table = calloc (1, sizeof (ffi_trampoline_table));
+      table->free_count = FFI_TRAMPOLINE_COUNT;
+      table->config_page = config_page;
+      table->trampoline_page = trampoline_page;
+
+      /* Create and initialize the free list */
+      table->free_list_pool =
+	calloc (FFI_TRAMPOLINE_COUNT, sizeof (ffi_trampoline_table_entry));
+
+      uint16_t i;
+      for (i = 0; i < table->free_count; i++)
+	{
+	  ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
+	  entry->trampoline =
+	    (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
+
+	  if (i < table->free_count - 1)
+	    entry->next = &table->free_list_pool[i + 1];
+	}
+
+      table->free_list = table->free_list_pool;
     }
 
-    /* Now drop the second half of the allocation to make room for the trampoline table */
-    vm_address_t trampoline_page = config_page+PAGE_SIZE;
-    kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE);
-    if (kt != KERN_SUCCESS) {
-      fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
-      break;
-    }
-
-    /* Remap the trampoline table to directly follow the config page */
-    vm_prot_t cur_prot;
-    vm_prot_t max_prot;
-
-    kt = vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE, mach_task_self (), (vm_address_t) &ffi_closure_trampoline_table_page, FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE);
-
-    /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */
-    if (kt != KERN_SUCCESS) {
-      /* Log unexpected failures */
-      if (kt != KERN_NO_SPACE) {
-        fprintf(stderr, "vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
-      }
-
-      vm_deallocate (mach_task_self (), config_page, PAGE_SIZE);
-      continue;
-    }
-
-    /* We have valid trampoline and config pages */
-    table = calloc (1, sizeof(ffi_trampoline_table));
-    table->free_count = FFI_TRAMPOLINE_COUNT;
-    table->config_page = config_page;
-    table->trampoline_page = trampoline_page;
-
-    /* Create and initialize the free list */
-    table->free_list_pool = calloc(FFI_TRAMPOLINE_COUNT, sizeof(ffi_trampoline_table_entry));
-
-    uint16_t i;
-    for (i = 0; i < table->free_count; i++) {
-      ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
-      entry->trampoline = (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
-
-      if (i < table->free_count - 1)
-        entry->next = &table->free_list_pool[i+1];
-    }
-
-    table->free_list = table->free_list_pool;
-  }
-
   return table;
 }
 
@@ -486,36 +667,38 @@
 ffi_closure_alloc (size_t size, void **code)
 {
   /* Create the closure */
-  ffi_closure *closure = malloc(size);
+  ffi_closure *closure = malloc (size);
   if (closure == NULL)
     return NULL;
 
-  pthread_mutex_lock(&ffi_trampoline_lock);
+  pthread_mutex_lock (&ffi_trampoline_lock);
 
   /* Check for an active trampoline table with available entries. */
   ffi_trampoline_table *table = ffi_trampoline_tables;
-  if (table == NULL || table->free_list == NULL) {
-    table = ffi_trampoline_table_alloc ();
-    if (table == NULL) {
-      free(closure);
-      return NULL;
+  if (table == NULL || table->free_list == NULL)
+    {
+      table = ffi_trampoline_table_alloc ();
+      if (table == NULL)
+	{
+	  free (closure);
+	  return NULL;
+	}
+
+      /* Insert the new table at the top of the list */
+      table->next = ffi_trampoline_tables;
+      if (table->next != NULL)
+	table->next->prev = table;
+
+      ffi_trampoline_tables = table;
     }
 
-    /* Insert the new table at the top of the list */
-    table->next = ffi_trampoline_tables;
-    if (table->next != NULL)
-        table->next->prev = table;
-
-    ffi_trampoline_tables = table;
-  }
-
   /* Claim the free entry */
   ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list;
   ffi_trampoline_tables->free_list = entry->next;
   ffi_trampoline_tables->free_count--;
   entry->next = NULL;
 
-  pthread_mutex_unlock(&ffi_trampoline_lock);
+  pthread_mutex_unlock (&ffi_trampoline_lock);
 
   /* Initialize the return values */
   *code = entry->trampoline;
@@ -530,7 +713,7 @@
 {
   ffi_closure *closure = ptr;
 
-  pthread_mutex_lock(&ffi_trampoline_lock);
+  pthread_mutex_lock (&ffi_trampoline_lock);
 
   /* Fetch the table and entry references */
   ffi_trampoline_table *table = closure->trampoline_table;
@@ -543,36 +726,43 @@
 
   /* If all trampolines within this table are free, and at least one other table exists, deallocate
    * the table */
-  if (table->free_count == FFI_TRAMPOLINE_COUNT && ffi_trampoline_tables != table) {
-    /* Remove from the list */
-    if (table->prev != NULL)
-      table->prev->next = table->next;
+  if (table->free_count == FFI_TRAMPOLINE_COUNT
+      && ffi_trampoline_tables != table)
+    {
+      /* Remove from the list */
+      if (table->prev != NULL)
+	table->prev->next = table->next;
 
-    if (table->next != NULL)
-      table->next->prev = table->prev;
+      if (table->next != NULL)
+	table->next->prev = table->prev;
 
-    /* Deallocate pages */
-    kern_return_t kt;
-    kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE);
-    if (kt != KERN_SUCCESS)
-      fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
+      /* Deallocate pages */
+      kern_return_t kt;
+      kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE);
+      if (kt != KERN_SUCCESS)
+	fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt,
+		 __FILE__, __LINE__);
 
-    kt = vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE);
-    if (kt != KERN_SUCCESS)
-      fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
+      kt =
+	vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE);
+      if (kt != KERN_SUCCESS)
+	fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt,
+		 __FILE__, __LINE__);
 
-    /* Deallocate free list */
-    free (table->free_list_pool);
-    free (table);
-  } else if (ffi_trampoline_tables != table) {
-    /* Otherwise, bump this table to the top of the list */
-    table->prev = NULL;
-    table->next = ffi_trampoline_tables;
-    if (ffi_trampoline_tables != NULL)
-      ffi_trampoline_tables->prev = table;
+      /* Deallocate free list */
+      free (table->free_list_pool);
+      free (table);
+    }
+  else if (ffi_trampoline_tables != table)
+    {
+      /* Otherwise, bump this table to the top of the list */
+      table->prev = NULL;
+      table->next = ffi_trampoline_tables;
+      if (ffi_trampoline_tables != NULL)
+	ffi_trampoline_tables->prev = table;
 
-    ffi_trampoline_tables = table;
-  }
+      ffi_trampoline_tables = table;
+    }
 
   pthread_mutex_unlock (&ffi_trampoline_lock);
 
@@ -582,133 +772,225 @@
 
 #else
 
-#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX)				\
-({ unsigned char *__tramp = (unsigned char*)(TRAMP);			\
-   unsigned int  __fun = (unsigned int)(FUN);				\
-   unsigned int  __ctx = (unsigned int)(CTX);				\
-   unsigned char *insns = (unsigned char *)(CTX);                       \
-   memcpy (__tramp, ffi_arm_trampoline, sizeof ffi_arm_trampoline);     \
-   *(unsigned int*) &__tramp[12] = __ctx;				\
-   *(unsigned int*) &__tramp[16] = __fun;				\
-   __clear_cache((&__tramp[0]), (&__tramp[19])); /* Clear data mapping.  */ \
-   __clear_cache(insns, insns + 3 * sizeof (unsigned int));             \
-                                                 /* Clear instruction   \
-                                                    mapping.  */        \
- })
+extern unsigned int ffi_arm_trampoline[2] FFI_HIDDEN;
 
 #endif
 
 /* the cif must already be prep'ed */
 
 ffi_status
-ffi_prep_closure_loc (ffi_closure* closure,
-		      ffi_cif* cif,
-		      void (*fun)(ffi_cif*,void*,void**,void*),
-		      void *user_data,
-		      void *codeloc)
+ffi_prep_closure_loc (ffi_closure * closure,
+		      ffi_cif * cif,
+		      void (*fun) (ffi_cif *, void *, void **, void *),
+		      void *user_data, void *codeloc)
 {
-  void (*closure_func)(ffi_closure*) = NULL;
+  void (*closure_func) (void) = ffi_closure_SYSV;
 
-  if (cif->abi == FFI_SYSV)
-    closure_func = &ffi_closure_SYSV;
-#ifdef __ARM_EABI__
-  else if (cif->abi == FFI_VFP)
-    closure_func = &ffi_closure_VFP;
-#endif
-  else
+  if (cif->abi == FFI_VFP)
+    {
+      /* We only need take the vfp path if there are vfp arguments.  */
+      if (cif->vfp_used)
+	closure_func = ffi_closure_VFP;
+    }
+  else if (cif->abi != FFI_SYSV)
     return FFI_BAD_ABI;
-    
+
 #if FFI_EXEC_TRAMPOLINE_TABLE
-  void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc);
+  void **config = FFI_TRAMPOLINE_CODELOC_CONFIG (codeloc);
   config[0] = closure;
   config[1] = closure_func;
 #else
-  FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
-		       closure_func,  \
-		       codeloc);
+  memcpy (closure->tramp, ffi_arm_trampoline, 8);
+  __clear_cache(closure->tramp, closure->tramp + 8);	/* clear data map */
+  __clear_cache(codeloc, codeloc + 8);			/* clear insn map */
+  *(void (**)(void))(closure->tramp + 8) = closure_func;
 #endif
 
-  closure->cif  = cif;
+  closure->cif = cif;
+  closure->fun = fun;
   closure->user_data = user_data;
-  closure->fun  = fun;
+
+  return FFI_OK;
+}
+
+ffi_status
+ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
+		     void (*fun) (ffi_cif *, void *, void **, void *))
+{
+  void (*closure_func) (void) = ffi_go_closure_SYSV;
+
+  if (cif->abi == FFI_VFP)
+    {
+      /* We only need take the vfp path if there are vfp arguments.  */
+      if (cif->vfp_used)
+	closure_func = ffi_go_closure_VFP;
+    }
+  else if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+  closure->tramp = closure_func;
+  closure->cif = cif;
+  closure->fun = fun;
 
   return FFI_OK;
 }
 
 /* Below are routines for VFP hard-float support. */
 
-static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum)
+/* A subroutine of vfp_type_p.  Given a structure type, return the type code
+   of the first non-structure element.  Recurse for structure elements.
+   Return -1 if the structure is in fact empty, i.e. no nested elements.  */
+
+static int
+is_hfa0 (const ffi_type *ty)
 {
-  switch (t->type)
+  ffi_type **elements = ty->elements;
+  int i, ret = -1;
+
+  if (elements != NULL)
+    for (i = 0; elements[i]; ++i)
+      {
+        ret = elements[i]->type;
+        if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX)
+          {
+            ret = is_hfa0 (elements[i]);
+            if (ret < 0)
+              continue;
+          }
+        break;
+      }
+
+  return ret;
+}
+
+/* A subroutine of vfp_type_p.  Given a structure type, return true if all
+   of the non-structure elements are the same as CANDIDATE.  */
+
+static int
+is_hfa1 (const ffi_type *ty, int candidate)
+{
+  ffi_type **elements = ty->elements;
+  int i;
+
+  if (elements != NULL)
+    for (i = 0; elements[i]; ++i)
+      {
+        int t = elements[i]->type;
+        if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
+          {
+            if (!is_hfa1 (elements[i], candidate))
+              return 0;
+          }
+        else if (t != candidate)
+          return 0;
+      }
+
+  return 1;
+}
+
+/* Determine if TY is an homogenous floating point aggregate (HFA).
+   That is, a structure consisting of 1 to 4 members of all the same type,
+   where that type is a floating point scalar.
+
+   Returns non-zero iff TY is an HFA.  The result is an encoded value where
+   bits 0-7 contain the type code, and bits 8-10 contain the element count.  */
+
+static int
+vfp_type_p (const ffi_type *ty)
+{
+  ffi_type **elements;
+  int candidate, i;
+  size_t size, ele_count;
+
+  /* Quickest tests first.  */
+  candidate = ty->type;
+  switch (ty->type)
     {
+    default:
+      return 0;
     case FFI_TYPE_FLOAT:
     case FFI_TYPE_DOUBLE:
-      *elt = (int) t->type;
-      *elnum = 1;
-      return 1;
-
-    case FFI_TYPE_STRUCT_VFP_FLOAT:
-      *elt = FFI_TYPE_FLOAT;
-      *elnum = t->size / sizeof (float);
-      return 1;
-
-    case FFI_TYPE_STRUCT_VFP_DOUBLE:
-      *elt = FFI_TYPE_DOUBLE;
-      *elnum = t->size / sizeof (double);
-      return 1;
-
-    case FFI_TYPE_STRUCT:;
-      {
-	int base_elt = 0, total_elnum = 0;
-	ffi_type **el = t->elements;
-	while (*el)
-	  {
-	    int el_elt = 0, el_elnum = 0;
-	    if (! rec_vfp_type_p (*el, &el_elt, &el_elnum)
-		|| (base_elt && base_elt != el_elt)
-		|| total_elnum + el_elnum > 4)
-	      return 0;
-	    base_elt = el_elt;
-	    total_elnum += el_elnum;
-	    el++;
-	  }
-	*elnum = total_elnum;
-	*elt = base_elt;
-	return 1;
-      }
-    default: ;
+      ele_count = 1;
+      goto done;
+    case FFI_TYPE_COMPLEX:
+      candidate = ty->elements[0]->type;
+      if (candidate != FFI_TYPE_FLOAT && candidate != FFI_TYPE_DOUBLE)
+	return 0;
+      ele_count = 2;
+      goto done;
+    case FFI_TYPE_STRUCT:
+      break;
     }
-  return 0;
-}
 
-static int vfp_type_p (ffi_type *t)
-{
-  int elt, elnum;
-  if (rec_vfp_type_p (t, &elt, &elnum))
+  /* No HFA types are smaller than 4 bytes, or larger than 32 bytes.  */
+  size = ty->size;
+  if (size < 4 || size > 32)
+    return 0;
+
+  /* Find the type of the first non-structure member.  */
+  elements = ty->elements;
+  candidate = elements[0]->type;
+  if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX)
     {
-      if (t->type == FFI_TYPE_STRUCT)
-	{
-	  if (elnum == 1)
-	    t->type = elt;
-	  else
-	    t->type = (elt == FFI_TYPE_FLOAT
-		       ? FFI_TYPE_STRUCT_VFP_FLOAT
-		       : FFI_TYPE_STRUCT_VFP_DOUBLE);
-	}
-      return (int) t->type;
+      for (i = 0; ; ++i)
+        {
+          candidate = is_hfa0 (elements[i]);
+          if (candidate >= 0)
+            break;
+        }
     }
-  return 0;
+
+  /* If the first member is not a floating point type, it's not an HFA.
+     Also quickly re-check the size of the structure.  */
+  switch (candidate)
+    {
+    case FFI_TYPE_FLOAT:
+      ele_count = size / sizeof(float);
+      if (size != ele_count * sizeof(float))
+        return 0;
+      break;
+    case FFI_TYPE_DOUBLE:
+      ele_count = size / sizeof(double);
+      if (size != ele_count * sizeof(double))
+        return 0;
+      break;
+    default:
+      return 0;
+    }
+  if (ele_count > 4)
+    return 0;
+
+  /* Finally, make sure that all scalar elements are the same type.  */
+  for (i = 0; elements[i]; ++i)
+    {
+      int t = elements[i]->type;
+      if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
+        {
+          if (!is_hfa1 (elements[i], candidate))
+            return 0;
+        }
+      else if (t != candidate)
+        return 0;
+    }
+
+  /* All tests succeeded.  Encode the result.  */
+ done:
+  return (ele_count << 8) | candidate;
 }
 
-static void place_vfp_arg (ffi_cif *cif, ffi_type *t)
+static int
+place_vfp_arg (ffi_cif *cif, int h)
 {
-  int reg = cif->vfp_reg_free;
-  int nregs = t->size / sizeof (float);
-  int align = ((t->type == FFI_TYPE_STRUCT_VFP_FLOAT
-		|| t->type == FFI_TYPE_FLOAT) ? 1 : 2);
+  unsigned short reg = cif->vfp_reg_free;
+  int align = 1, nregs = h >> 8;
+
+  if ((h & 0xff) == FFI_TYPE_DOUBLE)
+    align = 2, nregs *= 2;
+
   /* Align register number. */
   if ((reg & 1) && align == 2)
     reg++;
+
   while (reg + nregs <= 16)
     {
       int s, new_used = 0;
@@ -733,24 +1015,29 @@
 	    reg += 1;
 	  cif->vfp_reg_free = reg;
 	}
-      return;
-    next_reg: ;
+      return 0;
+    next_reg:;
     }
+  // done, mark all regs as used
+  cif->vfp_reg_free = 16;
+  cif->vfp_used = 0xFFFF;
+  return 1;
 }
 
-static void layout_vfp_args (ffi_cif *cif)
+static void
+layout_vfp_args (ffi_cif * cif)
 {
   int i;
   /* Init VFP fields */
   cif->vfp_used = 0;
   cif->vfp_nargs = 0;
   cif->vfp_reg_free = 0;
-  memset (cif->vfp_args, -1, 16); /* Init to -1. */
+  memset (cif->vfp_args, -1, 16);	/* Init to -1. */
 
   for (i = 0; i < cif->nargs; i++)
     {
-      ffi_type *t = cif->arg_types[i];
-      if (vfp_type_p (t))
-	place_vfp_arg (cif, t);
+      int h = vfp_type_p (cif->arg_types[i]);
+      if (h && place_vfp_arg (cif, h) == 1)
+	break;
     }
 }
diff --git a/third_party/gofrontend/libffi/src/arm/ffitarget.h b/third_party/gofrontend/libffi/src/arm/ffitarget.h
index 26d494d..4f473f9 100644
--- a/third_party/gofrontend/libffi/src/arm/ffitarget.h
+++ b/third_party/gofrontend/libffi/src/arm/ffitarget.h
@@ -53,19 +53,17 @@
 
 #define FFI_EXTRA_CIF_FIELDS			\
   int vfp_used;					\
-  short vfp_reg_free, vfp_nargs;		\
+  unsigned short vfp_reg_free, vfp_nargs;	\
   signed char vfp_args[16]			\
 
-/* Internally used. */
-#define FFI_TYPE_STRUCT_VFP_FLOAT  (FFI_TYPE_LAST + 1)
-#define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2)
-
 #define FFI_TARGET_SPECIFIC_VARIADIC
+#define FFI_TARGET_HAS_COMPLEX_TYPE
 
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
-#define FFI_TRAMPOLINE_SIZE 20
+#define FFI_GO_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 12
 #define FFI_NATIVE_RAW_API 0
 
 #endif
diff --git a/third_party/gofrontend/libffi/src/arm/gentramp.sh b/third_party/gofrontend/libffi/src/arm/gentramp.sh
deleted file mode 100755
index 74f0b86..0000000
--- a/third_party/gofrontend/libffi/src/arm/gentramp.sh
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/bin/sh
-
-# -----------------------------------------------------------------------
-#  gentramp.sh - Copyright (c) 2010, Plausible Labs Cooperative, Inc.
-#  
-#  ARM Trampoline Page Generator
-#
-#  Permission is hereby granted, free of charge, to any person obtaining
-#  a copy of this software and associated documentation files (the
-#  ``Software''), to deal in the Software without restriction, including
-#  without limitation the rights to use, copy, modify, merge, publish,
-#  distribute, sublicense, and/or sell copies of the Software, and to
-#  permit persons to whom the Software is furnished to do so, subject to
-#  the following conditions:
-#
-#  The above copyright notice and this permission notice shall be included
-#  in all copies or substantial portions of the Software.
-#
-#  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-#  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-#  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-#  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-#  DEALINGS IN THE SOFTWARE.
-#  -----------------------------------------------------------------------
-
-PROGNAME=$0
-
-# Each trampoline is exactly 3 instructions, or 12 bytes. If any of these values change,
-# the entire arm trampoline implementation must be updated to match, too.
-
-# Size of an individual trampoline, in bytes
-TRAMPOLINE_SIZE=12
-
-# Page size, in bytes
-PAGE_SIZE=4096
-
-# Compute the size of the reachable config page; The first 16 bytes of the config page
-# are unreachable due to our maximum pc-relative ldr offset.
-PAGE_AVAIL=`expr $PAGE_SIZE - 16`
-
-# Compute the number of of available trampolines. 
-TRAMPOLINE_COUNT=`expr $PAGE_AVAIL / $TRAMPOLINE_SIZE`
-
-header () {
-    echo "# GENERATED CODE - DO NOT EDIT"
-    echo "# This file was generated by $PROGNAME"
-    echo ""
-
-    # Write out the license header
-cat << EOF
-#  Copyright (c) 2010, Plausible Labs Cooperative, Inc.
-#  
-#  Permission is hereby granted, free of charge, to any person obtaining
-#  a copy of this software and associated documentation files (the
-#  ``Software''), to deal in the Software without restriction, including
-#  without limitation the rights to use, copy, modify, merge, publish,
-#  distribute, sublicense, and/or sell copies of the Software, and to
-#  permit persons to whom the Software is furnished to do so, subject to
-#  the following conditions:
-#
-#  The above copyright notice and this permission notice shall be included
-#  in all copies or substantial portions of the Software.
-#
-#  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-#  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-#  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-#  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-#  DEALINGS IN THE SOFTWARE.
-#  -----------------------------------------------------------------------
-
-EOF
-
-    # Write out the trampoline table, aligned to the page boundary
-    echo ".text"
-    echo ".align 12"
-    echo ".globl _ffi_closure_trampoline_table_page"
-    echo "_ffi_closure_trampoline_table_page:"
-}
-
-
-# WARNING - Don't modify the trampoline code size without also updating the relevent libffi code
-trampoline () {
-    cat << END
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-END
-}
-
-main () {
-    # Write out the header
-    header
-
-    # Write out the trampolines
-    local i=0
-    while [ $i -lt ${TRAMPOLINE_COUNT} ]; do
-        trampoline
-        local i=`expr $i + 1`
-    done
-}
-
-main
diff --git a/third_party/gofrontend/libffi/src/arm/internal.h b/third_party/gofrontend/libffi/src/arm/internal.h
new file mode 100644
index 0000000..6cf0b2a
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/arm/internal.h
@@ -0,0 +1,7 @@
+#define ARM_TYPE_VFP_S	0
+#define ARM_TYPE_VFP_D	1
+#define ARM_TYPE_VFP_N	2
+#define ARM_TYPE_INT64	3
+#define ARM_TYPE_INT	4
+#define ARM_TYPE_VOID	5
+#define ARM_TYPE_STRUCT	6
diff --git a/third_party/gofrontend/libffi/src/arm/sysv.S b/third_party/gofrontend/libffi/src/arm/sysv.S
index fb38cd6..fd16589 100644
--- a/third_party/gofrontend/libffi/src/arm/sysv.S
+++ b/third_party/gofrontend/libffi/src/arm/sysv.S
@@ -1,8 +1,8 @@
 /* -----------------------------------------------------------------------
    sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
 	    Copyright (c) 2011 Plausible Labs Cooperative, Inc.
-   
-   ARM Foreign Function Interface 
+
+   ARM Foreign Function Interface
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -28,477 +28,307 @@
 #define LIBFFI_ASM	
 #include <fficonfig.h>
 #include <ffi.h>
-#ifdef HAVE_MACHINE_ASM_H
-#include <machine/asm.h>
-#else
-#ifdef __USER_LABEL_PREFIX__
-#define CONCAT1(a, b) CONCAT2(a, b)
-#define CONCAT2(a, b) a ## b
+#include <ffi_cfi.h>
+#include "internal.h"
 
-/* Use the right prefix for global labels.  */
-#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
-#else
-#define CNAME(x) x
-#endif
-#ifdef __APPLE__
-#define ENTRY(x) .globl _##x; _##x:
-#else
-#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
-#endif /* __APPLE__ */
-#endif
-
-#ifdef __ELF__
-#define LSYM(x) .x
-#else
-#define LSYM(x) x
-#endif
-
-/* Use the SOFTFP return value ABI on Mac OS X, as per the iOS ABI
-  Function Call Guide */
-#ifdef __APPLE__
-#define __SOFTFP__
-#endif
-
-/* We need a better way of testing for this, but for now, this is all 
-   we can do.  */
-@ This selects the minimum architecture level required.
-#define __ARM_ARCH__ 3
-
-#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 4
-#endif
-        
-#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
-	|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
-	|| defined(__ARM_ARCH_5TEJ__)
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 5
-#endif
-
-#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+/* GCC 4.8 provides __ARM_ARCH; construct it otherwise.  */
+#ifndef __ARM_ARCH
+# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
+     || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
+     || defined(__ARM_ARCH_7EM__)
+#  define __ARM_ARCH 7
+# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
         || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
         || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
 	|| defined(__ARM_ARCH_6M__)
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 6
-#endif
-
-#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
-        || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
-	|| defined(__ARM_ARCH_7EM__)
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 7
-#endif
-
-#if __ARM_ARCH__ >= 5
-# define call_reg(x)	blx	x
-#elif defined (__ARM_ARCH_4T__)
-# define call_reg(x)	mov	lr, pc ; bx	x
-# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
-#  define __INTERWORKING__
+#  define __ARM_ARCH 6
+# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
+	|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
+	|| defined(__ARM_ARCH_5TEJ__)
+#  define __ARM_ARCH 5
+# else
+#  define __ARM_ARCH 4
 # endif
-#else
-# define call_reg(x)	mov	lr, pc ; mov	pc, x
 #endif
 
 /* Conditionally compile unwinder directives.  */
+.macro UNWIND text:vararg
 #ifdef __ARM_EABI__
-#define UNWIND
-#else
-#define UNWIND @
+	\text
 #endif	
-
-	
-#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
-.macro	ARM_FUNC_START name
-	.text
-	.align 0
-	.thumb
-	.thumb_func
-#ifdef __APPLE__
-	ENTRY($0)
-#else
-	ENTRY(\name)
-#endif
-	bx	pc
-	nop
-	.arm
-	UNWIND .fnstart
-/* A hook to tell gdb that we've switched to ARM mode.  Also used to call
-   directly from other local arm routines.  */
-#ifdef __APPLE__
-_L__$0:
-#else
-_L__\name:
-#endif
 .endm
-#else
-.macro	ARM_FUNC_START name
-	.text
-	.align 0
-	.arm
-#ifdef __APPLE__
-	ENTRY($0)
-#else
-	ENTRY(\name)
-#endif
-	UNWIND .fnstart
-.endm
+#if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__ARM_EABI__)
+	.cfi_sections	.debug_frame
 #endif
 
-.macro	RETLDM	regs=, cond=, dirn=ia
-#if defined (__INTERWORKING__)
-	.ifc "\regs",""
-	ldr\cond	lr, [sp], #4
-	.else
-	ldm\cond\dirn	sp!, {\regs, lr}
+#define CONCAT(a, b)	CONCAT2(a, b)
+#define CONCAT2(a, b)	a ## b
+
+#ifdef __USER_LABEL_PREFIX__
+# define CNAME(X)	CONCAT (__USER_LABEL_PREFIX__, X)
+#else
+# define CNAME(X)	X
+#endif
+#ifdef __ELF__
+# define SIZE(X)	.size CNAME(X), . - CNAME(X)
+# define TYPE(X, Y)	.type CNAME(X), Y
+#else
+# define SIZE(X)
+# define TYPE(X, Y)
+#endif
+
+#define ARM_FUNC_START(name, gl) \
+	.align	3; \
+	.ifne gl; .globl CNAME(name); FFI_HIDDEN(CNAME(name)); .endif; \
+	TYPE(name, %function); \
+	CNAME(name):
+
+#define ARM_FUNC_END(name) \
+	SIZE(name)
+
+/* Aid in defining a jump table with 8 bytes between entries.  */
+.macro E index
+	.if . - 0b - 8*\index
+	.error "type table out of sync"
 	.endif
-	bx\cond	lr
-#else
-	.ifc "\regs",""
-	ldr\cond	pc, [sp], #4
-	.else
-	ldm\cond\dirn	sp!, {\regs, pc}
-	.endif
-#endif
 .endm
 
-	@ r0:   ffi_prep_args
-	@ r1:   &ecif
-	@ r2:   cif->bytes
-	@ r3:   fig->flags
-	@ sp+0: ecif.rvalue
+	.text
+	.syntax unified
+	.arm
 
-	@ This assumes we are using gas.
-ARM_FUNC_START ffi_call_SYSV
-	@ Save registers
-        stmfd	sp!, {r0-r3, fp, lr}
-	UNWIND .save	{r0-r3, fp, lr}
-	mov	fp, sp
+	/* We require interworking on LDM, which implies ARMv5T,
+	   which implies the existance of BLX.  */
+	.arch	armv5t
 
-	UNWIND .setfp	fp, sp
+	/* Note that we use STC and LDC to encode VFP instructions,
+	   so that we do not need ".fpu vfp", nor get that added to
+	   the object file attributes.  These will not be executed
+	   unless the FFI_VFP abi is used.  */
 
-	@ Make room for all of the new args.
-	sub	sp, fp, r2
+	@ r0:   stack
+	@ r1:   frame
+	@ r2:   fn
+	@ r3:	vfp_used
 
-	@ Place all of the ffi_prep_args in position
-	mov	r0, sp
-	@     r1 already set
+ARM_FUNC_START(ffi_call_VFP, 1)
+	UNWIND	.fnstart
+	cfi_startproc
 
-	@ Call ffi_prep_args(stack, &ecif)
-	bl	CNAME(ffi_prep_args)
+	cmp	r3, #3			@ load only d0 if possible
+	ldcle	p11, cr0, [r0]		@ vldrle d0, [sp]
+	ldcgt	p11, cr0, [r0], {16}	@ vldmgt sp, {d0-d7}
+	add	r0, r0, #64		@ discard the vfp register args
+	/* FALLTHRU */
+ARM_FUNC_END(ffi_call_VFP)
 
-	@ move first 4 parameters in registers
-	ldmia	sp, {r0-r3}
+ARM_FUNC_START(ffi_call_SYSV, 1)
+	stm	r1, {fp, lr}
+	mov	fp, r1
 
-	@ and adjust stack
-	sub	lr, fp, sp	@ cif->bytes == fp - sp
-	ldr	ip, [fp]	@ load fn() in advance
-	cmp	lr, #16
-	movhs	lr, #16
-	add	sp, sp, lr
+	@ This is a bit of a lie wrt the origin of the unwind info, but
+	@ now we've got the usual frame pointer and two saved registers.
+	UNWIND	.save {fp,lr}
+	UNWIND	.setfp fp, sp
+	cfi_def_cfa(fp, 8)
+	cfi_rel_offset(fp, 0)
+	cfi_rel_offset(lr, 4)
 
-	@ call (fn) (...)
-	call_reg(ip)
-	
-	@ Remove the space we pushed for the args
-	mov	sp, fp
+	mov	sp, r0		@ install the stack pointer
+	mov	lr, r2		@ move the fn pointer out of the way
+	ldr	ip, [fp, #16]	@ install the static chain
+	ldmia	sp!, {r0-r3}	@ move first 4 parameters in registers.
+	blx	lr		@ call fn
 
 	@ Load r2 with the pointer to storage for the return value
-	ldr	r2, [sp, #24]
+	@ Load r3 with the return type code
+	ldr	r2, [fp, #8]
+	ldr	r3, [fp, #12]
 
-	@ Load r3 with the return type code 
-	ldr	r3, [sp, #12]
+	@ Deallocate the stack with the arguments.
+	mov	sp, fp
+	cfi_def_cfa_register(sp)
 
-	@ If the return value pointer is NULL, assume no return value.
-	cmp	r2, #0
-	beq	LSYM(Lepilogue)
+	@ Store values stored in registers.
+	.align	3
+	add	pc, pc, r3, lsl #3
+	nop
+0:
+E ARM_TYPE_VFP_S
+	stc	p10, cr0, [r2]		@ vstr s0, [r2]
+	pop	{fp,pc}
+E ARM_TYPE_VFP_D
+	stc	p11, cr0, [r2]		@ vstr d0, [r2]
+	pop	{fp,pc}
+E ARM_TYPE_VFP_N
+	stc	p11, cr0, [r2], {8}	@ vstm r2, {d0-d3}
+	pop	{fp,pc}
+E ARM_TYPE_INT64
+	str	r1, [r2, #4]
+	nop
+E ARM_TYPE_INT
+	str	r0, [r2]
+	pop	{fp,pc}
+E ARM_TYPE_VOID
+	pop	{fp,pc}
+	nop
+E ARM_TYPE_STRUCT
+	pop	{fp,pc}
 
-@ return INT
-	cmp	r3, #FFI_TYPE_INT
-#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-	cmpne	r3, #FFI_TYPE_FLOAT
-#endif
-	streq	r0, [r2]
-	beq	LSYM(Lepilogue)
-
-	@ return INT64
-	cmp	r3, #FFI_TYPE_SINT64
-#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-	cmpne	r3, #FFI_TYPE_DOUBLE
-#endif
-	stmeqia	r2, {r0, r1}
-
-#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
-	beq	LSYM(Lepilogue)
-
-@ return FLOAT
-	cmp	r3, #FFI_TYPE_FLOAT
-	stfeqs	f0, [r2]
-	beq	LSYM(Lepilogue)
-
-@ return DOUBLE or LONGDOUBLE
-	cmp	r3, #FFI_TYPE_DOUBLE
-	stfeqd	f0, [r2]
-#endif
-
-LSYM(Lepilogue):
-#if defined (__INTERWORKING__)
-	ldmia   sp!, {r0-r3,fp, lr}
-	bx	lr
-#else
-	ldmia   sp!, {r0-r3,fp, pc}
-#endif
-
-.ffi_call_SYSV_end:
-	UNWIND .fnend
-#ifdef __ELF__
-        .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
-#endif
+	cfi_endproc
+	UNWIND	.fnend
+ARM_FUNC_END(ffi_call_SYSV)
 
 
 /*
-	unsigned int FFI_HIDDEN
-	ffi_closure_SYSV_inner (closure, respp, args)
-	     ffi_closure *closure;
-	     void **respp;
-  	     void *args;
+	int ffi_closure_inner_* (cif, fun, user_data, frame)
 */
 
-ARM_FUNC_START ffi_closure_SYSV
-	UNWIND .pad #16
+ARM_FUNC_START(ffi_go_closure_SYSV, 1)
+	cfi_startproc
+	stmdb	sp!, {r0-r3}			@ save argument regs
+	cfi_adjust_cfa_offset(16)
+	ldr	r0, [ip, #4]			@ load cif
+	ldr	r1, [ip, #8]			@ load fun
+	mov	r2, ip				@ load user_data
+	b	0f
+	cfi_endproc
+ARM_FUNC_END(ffi_go_closure_SYSV)
+
+ARM_FUNC_START(ffi_closure_SYSV, 1)
+	UNWIND	.fnstart
+	cfi_startproc
+	stmdb	sp!, {r0-r3}			@ save argument regs
+	cfi_adjust_cfa_offset(16)
+	ldr	r0, [ip, #FFI_TRAMPOLINE_SIZE]	  @ load cif
+	ldr	r1, [ip, #FFI_TRAMPOLINE_SIZE+4]  @ load fun
+	ldr	r2, [ip, #FFI_TRAMPOLINE_SIZE+8]  @ load user_data
+0:
+	add	ip, sp, #16			@ compute entry sp
+	sub	sp, sp, #64+32			@ allocate frame
+	cfi_adjust_cfa_offset(64+32)
+	stmdb	sp!, {ip,lr}
+
+	/* Remember that EABI unwind info only applies at call sites.
+	   We need do nothing except note the save of the stack pointer
+	   and the link registers.  */
+	UNWIND	.save {sp,lr}
+	cfi_adjust_cfa_offset(8)
+	cfi_rel_offset(lr, 4)
+
+	add	r3, sp, #8			@ load frame
+	bl	CNAME(ffi_closure_inner_SYSV)
+
+	@ Load values returned in registers.
+	add	r2, sp, #8+64			@ load result
+	adr	r3, CNAME(ffi_closure_ret)
+	add	pc, r3, r0, lsl #3
+	cfi_endproc
+	UNWIND	.fnend
+ARM_FUNC_END(ffi_closure_SYSV)
+
+ARM_FUNC_START(ffi_go_closure_VFP, 1)
+	cfi_startproc
+	stmdb	sp!, {r0-r3}			@ save argument regs
+	cfi_adjust_cfa_offset(16)
+	ldr	r0, [ip, #4]			@ load cif
+	ldr	r1, [ip, #8]			@ load fun
+	mov	r2, ip				@ load user_data
+	b	0f
+	cfi_endproc
+ARM_FUNC_END(ffi_go_closure_VFP)
+
+ARM_FUNC_START(ffi_closure_VFP, 1)
+	UNWIND	.fnstart
+	cfi_startproc
+	stmdb	sp!, {r0-r3}			@ save argument regs
+	cfi_adjust_cfa_offset(16)
+	ldr	r0, [ip, #FFI_TRAMPOLINE_SIZE]	  @ load cif
+	ldr	r1, [ip, #FFI_TRAMPOLINE_SIZE+4]  @ load fun
+	ldr	r2, [ip, #FFI_TRAMPOLINE_SIZE+8]  @ load user_data
+0:
 	add	ip, sp, #16
-	stmfd	sp!, {ip, lr}
-	UNWIND .save	{r0, lr}
-	add	r2, sp, #8
-	UNWIND .pad #16
-	sub	sp, sp, #16
-	str	sp, [sp, #8]
-	add	r1, sp, #8
-	bl	CNAME(ffi_closure_SYSV_inner)
-	cmp	r0, #FFI_TYPE_INT
-	beq	.Lretint
+	sub	sp, sp, #64+32			@ allocate frame
+	cfi_adjust_cfa_offset(64+32)
+	stc	p11, cr0, [sp], {16}		@ vstm sp, {d0-d7}
+	stmdb	sp!, {ip,lr}
 
-	cmp	r0, #FFI_TYPE_FLOAT
-#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-	beq	.Lretint
+	/* See above.  */
+	UNWIND	.save {sp,lr}
+	cfi_adjust_cfa_offset(8)
+	cfi_rel_offset(lr, 4)
+
+	add	r3, sp, #8			@ load frame
+	bl	CNAME(ffi_closure_inner_VFP)
+
+	@ Load values returned in registers.
+	add	r2, sp, #8+64			@ load result
+	adr	r3, CNAME(ffi_closure_ret)
+	add	pc, r3, r0, lsl #3
+	cfi_endproc
+	UNWIND	.fnend
+ARM_FUNC_END(ffi_closure_VFP)
+
+/* Load values returned in registers for both closure entry points.
+   Note that we use LDM with SP in the register set.  This is deprecated
+   by ARM, but not yet unpredictable.  */
+
+ARM_FUNC_START(ffi_closure_ret, 0)
+	cfi_startproc
+	cfi_rel_offset(sp, 0)
+	cfi_rel_offset(lr, 4)
+0:
+E ARM_TYPE_VFP_S
+	ldc	p10, cr0, [r2]			@ vldr s0, [r2]
+	ldm	sp, {sp,pc}
+E ARM_TYPE_VFP_D
+	ldc	p11, cr0, [r2]			@ vldr d0, [r2]
+	ldm	sp, {sp,pc}
+E ARM_TYPE_VFP_N
+	ldc	p11, cr0, [r2], {8}		@ vldm r2, {d0-d3}
+	ldm	sp, {sp,pc}
+E ARM_TYPE_INT64
+	ldr	r1, [r2, #4]
+	nop
+E ARM_TYPE_INT
+	ldr	r0, [r2]
+	ldm	sp, {sp,pc}
+E ARM_TYPE_VOID
+	ldm	sp, {sp,pc}
+	nop
+E ARM_TYPE_STRUCT
+	ldm	sp, {sp,pc}
+	cfi_endproc
+ARM_FUNC_END(ffi_closure_ret)
+
+#if FFI_EXEC_TRAMPOLINE_TABLE
+
+/* ??? The iOS support should be updated.  The first insn used to
+   be STMFD, but that's been moved into ffi_closure_SYSV.  If the
+   writable page is put after this one we can make use of the
+   pc+8 feature of the architecture.  We can also reduce the size
+   of the thunk to 8 and pack more of these into the page.
+
+   In the meantime, simply replace the STMFD with a NOP so as to
+   keep all the magic numbers the same within ffi.c.  */
+
+	.align	12
+ARM_FUNC_START(ffi_closure_trampoline_table_page)
+.rept	4096 / 12
+	nop
+	ldr	ip, [pc, #-4092]
+	ldr	pc, [pc, #-4092]
+.endr
+
 #else
-	beq	.Lretfloat
-#endif
 
-	cmp	r0, #FFI_TYPE_DOUBLE
-#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-	beq	.Lretlonglong
-#else
-	beq	.Lretdouble
-#endif
+ARM_FUNC_START(ffi_arm_trampoline, 1)
+0:	adr	ip, 0b
+	ldr	pc, 1f
+1:	.long	0
+ARM_FUNC_END(ffi_arm_trampoline)
 
-	cmp	r0, #FFI_TYPE_LONGDOUBLE
-#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-	beq	.Lretlonglong
-#else
-	beq	.Lretlongdouble
-#endif
-
-	cmp	r0, #FFI_TYPE_SINT64
-	beq	.Lretlonglong
-.Lclosure_epilogue:
-	add	sp, sp, #16
-	ldmfd	sp, {sp, pc}
-.Lretint:
-	ldr	r0, [sp]
-	b	.Lclosure_epilogue
-.Lretlonglong:
-	ldr	r0, [sp]
-	ldr	r1, [sp, #4]
-	b	.Lclosure_epilogue
-
-#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
-.Lretfloat:
-	ldfs	f0, [sp]
-	b	.Lclosure_epilogue
-.Lretdouble:
-	ldfd	f0, [sp]
-	b	.Lclosure_epilogue
-.Lretlongdouble:
-	ldfd	f0, [sp]
-	b	.Lclosure_epilogue
-#endif
-
-.ffi_closure_SYSV_end:
-	UNWIND .fnend
-#ifdef __ELF__
-        .size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
-#endif
-
-
-/* Below are VFP hard-float ABI call and closure implementations.
-   Add VFP FPU directive here. This is only compiled into the library
-   under EABI.  */
-#ifdef __ARM_EABI__
-	.fpu	vfp
-
-	@ r0:   fn
-	@ r1:   &ecif
-	@ r2:   cif->bytes
-	@ r3:   fig->flags
-	@ sp+0: ecif.rvalue
-
-ARM_FUNC_START ffi_call_VFP
-	@ Save registers
-        stmfd	sp!, {r0-r3, fp, lr}
-	UNWIND .save	{r0-r3, fp, lr}
-	mov	fp, sp
-	UNWIND .setfp	fp, sp
-
-	@ Make room for all of the new args.
-	sub	sp, sp, r2
-
-	@ Make room for loading VFP args
-	sub	sp, sp, #64
-
-	@ Place all of the ffi_prep_args in position
-	mov	r0, sp
-	@     r1 already set
-	sub	r2, fp, #64   @ VFP scratch space
-
-	@ Call ffi_prep_args(stack, &ecif, vfp_space)
-	bl	CNAME(ffi_prep_args)
-
-	@ Load VFP register args if needed
-	cmp	r0, #0
-	beq	LSYM(Lbase_args)
-
-	@ Load only d0 if possible
-	cmp	r0, #3
-	sub	ip, fp, #64
-	flddle	d0, [ip]
-	fldmiadgt	ip, {d0-d7}
-
-LSYM(Lbase_args):
-	@ move first 4 parameters in registers
-	ldmia	sp, {r0-r3}
-
-	@ and adjust stack
-	sub	lr, ip, sp	@ cif->bytes == (fp - 64) - sp
-	ldr	ip, [fp]	@ load fn() in advance
-        cmp	lr, #16
-	movhs	lr, #16
-        add	sp, sp, lr
-
-	@ call (fn) (...)
-	call_reg(ip)
-
-	@ Remove the space we pushed for the args
-	mov	sp, fp
-
-	@ Load r2 with the pointer to storage for
-	@ the return value
-	ldr	r2, [sp, #24]
-
-	@ Load r3 with the return type code 
-	ldr	r3, [sp, #12]
-
-	@ If the return value pointer is NULL,
-	@ assume no return value.
-	cmp	r2, #0
-	beq	LSYM(Lepilogue_vfp)
-
-	cmp	r3, #FFI_TYPE_INT
-	streq	r0, [r2]
-	beq	LSYM(Lepilogue_vfp)
-
-	cmp	r3, #FFI_TYPE_SINT64
-	stmeqia	r2, {r0, r1}
-	beq	LSYM(Lepilogue_vfp)
-
-	cmp	r3, #FFI_TYPE_FLOAT
-	fstseq	s0, [r2]
-	beq	LSYM(Lepilogue_vfp)
-	
-	cmp	r3, #FFI_TYPE_DOUBLE
-	fstdeq	d0, [r2]
-	beq	LSYM(Lepilogue_vfp)
-
-	cmp	r3, #FFI_TYPE_STRUCT_VFP_FLOAT
-	cmpne	r3, #FFI_TYPE_STRUCT_VFP_DOUBLE
-	fstmiadeq	r2, {d0-d3}
-
-LSYM(Lepilogue_vfp):
-	RETLDM	"r0-r3,fp"
-
-.ffi_call_VFP_end:
-	UNWIND .fnend
-        .size    CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP)
-
-
-ARM_FUNC_START ffi_closure_VFP
-	fstmfdd	sp!, {d0-d7}
-	@ r0-r3, then d0-d7
-	UNWIND .pad #80
-	add	ip, sp, #80
-	stmfd	sp!, {ip, lr}
-	UNWIND .save	{r0, lr}
-	add	r2, sp, #72
-	add	r3, sp, #8
-	UNWIND .pad #72
-	sub	sp, sp, #72
-	str	sp, [sp, #64]
-	add	r1, sp, #64
-	bl	CNAME(ffi_closure_SYSV_inner)
-
-	cmp	r0, #FFI_TYPE_INT
-	beq	.Lretint_vfp
-
-	cmp	r0, #FFI_TYPE_FLOAT
-	beq	.Lretfloat_vfp
-
-	cmp	r0, #FFI_TYPE_DOUBLE
-	cmpne	r0, #FFI_TYPE_LONGDOUBLE
-	beq	.Lretdouble_vfp
-
-	cmp	r0, #FFI_TYPE_SINT64
-	beq	.Lretlonglong_vfp
-
-	cmp	r0, #FFI_TYPE_STRUCT_VFP_FLOAT
-	beq	.Lretfloat_struct_vfp
-
-	cmp	r0, #FFI_TYPE_STRUCT_VFP_DOUBLE
-	beq	.Lretdouble_struct_vfp
-	
-.Lclosure_epilogue_vfp:
-	add	sp, sp, #72
-	ldmfd	sp, {sp, pc}
-
-.Lretfloat_vfp:
-	flds	s0, [sp]
-	b	.Lclosure_epilogue_vfp
-.Lretdouble_vfp:
-	fldd	d0, [sp]
-	b	.Lclosure_epilogue_vfp
-.Lretint_vfp:
-	ldr	r0, [sp]
-	b	.Lclosure_epilogue_vfp
-.Lretlonglong_vfp:
-	ldmia	sp, {r0, r1}
-	b	.Lclosure_epilogue_vfp
-.Lretfloat_struct_vfp:
-	fldmiad	sp, {d0-d1}
-	b	.Lclosure_epilogue_vfp
-.Lretdouble_struct_vfp:
-	fldmiad	sp, {d0-d3}
-	b	.Lclosure_epilogue_vfp
-
-.ffi_closure_VFP_end:
-	UNWIND .fnend
-        .size    CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP)
-#endif
-
-ENTRY(ffi_arm_trampoline)
-	stmfd sp!, {r0-r3}
-	ldr r0, [pc]
-	ldr pc, [pc]
+#endif /* FFI_EXEC_TRAMPOLINE_TABLE */
 
 #if defined __ELF__ && defined __linux__
 	.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/gofrontend/libffi/src/arm/trampoline.S b/third_party/gofrontend/libffi/src/arm/trampoline.S
deleted file mode 100644
index 935e8de..0000000
--- a/third_party/gofrontend/libffi/src/arm/trampoline.S
+++ /dev/null
@@ -1,4450 +0,0 @@
-# GENERATED CODE - DO NOT EDIT
-# This file was generated by src/arm/gentramp.sh
-
-#  Copyright (c) 2010, Plausible Labs Cooperative, Inc.
-#  
-#  Permission is hereby granted, free of charge, to any person obtaining
-#  a copy of this software and associated documentation files (the
-#  Software''), to deal in the Software without restriction, including
-#  without limitation the rights to use, copy, modify, merge, publish,
-#  distribute, sublicense, and/or sell copies of the Software, and to
-#  permit persons to whom the Software is furnished to do so, subject to
-#  the following conditions:
-#
-#  The above copyright notice and this permission notice shall be included
-#  in all copies or substantial portions of the Software.
-#
-#  THE SOFTWARE IS PROVIDED AS IS'', WITHOUT WARRANTY OF ANY KIND,
-#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-#  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-#  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-#  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-#  DEALINGS IN THE SOFTWARE.
-#  -----------------------------------------------------------------------
-
-.text
-.align 12
-.globl _ffi_closure_trampoline_table_page
-_ffi_closure_trampoline_table_page:
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
-
-    // trampoline
-    // Save to stack
-    stmfd sp!, {r0-r3}
-
-    // Load the context argument from the config page.
-    // This places the first usable config value at _ffi_closure_trampoline_table-4080
-    // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-    ldr r0, [pc, #-4092]
-
-    // Load the jump address from the config page.
-    ldr pc, [pc, #-4092]
-
diff --git a/third_party/gofrontend/libffi/src/bfin/ffi.c b/third_party/gofrontend/libffi/src/bfin/ffi.c
index 0beccc1..22a2acd 100644
--- a/third_party/gofrontend/libffi/src/bfin/ffi.c
+++ b/third_party/gofrontend/libffi/src/bfin/ffi.c
@@ -1,5 +1,6 @@
 /* -----------------------------------------------------------------------
-   ffi.c - Copyright (c) 2012  Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>
+   ffi.c - Copyright (c) 2012  Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>,
+							   Paulo Pizarro <paulo.pizarro@gmail.com>
 
    Blackfin Foreign Function Interface
 
diff --git a/third_party/gofrontend/libffi/src/bfin/sysv.S b/third_party/gofrontend/libffi/src/bfin/sysv.S
index ae7a152..f4278be 100644
--- a/third_party/gofrontend/libffi/src/bfin/sysv.S
+++ b/third_party/gofrontend/libffi/src/bfin/sysv.S
@@ -1,5 +1,6 @@
 /* -----------------------------------------------------------------------
-   sysv.S - Copyright (c) 2012  Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>
+   sysv.S - Copyright (c) 2012  Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>,
+                                Paulo Pizarro <paulo.pizarro@gmail.com>
 
    Blackfin Foreign Function Interface
 
@@ -32,7 +33,7 @@
 .align 4
 
 	/*
-	 There is a "feature" in the bfin toolchain that it puts a _ before funcion names
+	 There is a "feature" in the bfin toolchain that it puts a _ before function names
 	 that's why the function here it's called _ffi_call_SYSV and not ffi_call_SYSV
 	 */
 	.global _ffi_call_SYSV;
@@ -40,25 +41,26 @@
 	.func ffi_call_SYSV
 
 	/*
-	cif->bytes  	= R0	(fp+8)
-	&ecif			= R1	(fp+12)
-	ffi_prep_args	= R2	(fp+16)
-	ret_type		= stack (fp+20)
-	ecif.rvalue		= stack (fp+24)
-	fn				= stack	(fp+28)
-					  got	(fp+32)
-    There is room for improvement here (we can use temporary registers
-        instead of saving the values in the memory)
-	REGS:
-		P5 => Stack pointer (function arguments)
-		R5 => cif->bytes
-		R4 => ret->type
+         cif->bytes    = R0    (fp+8)
+         &ecif         = R1    (fp+12)
+         ffi_prep_args = R2    (fp+16)
+         ret_type      = stack (fp+20)
+         ecif.rvalue   = stack (fp+24)
+         fn            = stack (fp+28)
+                           got (fp+32)
 
-		FP-20 = P3
-		FP-16 = SP (parameters area)
-		FP-12 = SP (temp)
-		FP-08 = function return part 1 [R0]
-		FP-04 = function return part 2 [R1]
+        There is room for improvement here (we can use temporary registers
+        instead of saving the values in the memory)
+        REGS:
+        P5 => Stack pointer (function arguments)
+        R5 => cif->bytes
+        R4 => ret->type
+
+        FP-20 = P3
+        FP-16 = SP (parameters area)
+        FP-12 = SP (temp)
+        FP-08 = function return part 1 [R0]
+        FP-04 = function return part 2 [R1]
 	*/
 
 _ffi_call_SYSV:
diff --git a/third_party/gofrontend/libffi/src/closures.c b/third_party/gofrontend/libffi/src/closures.c
index 6298d6f..721ff00 100644
--- a/third_party/gofrontend/libffi/src/closures.c
+++ b/third_party/gofrontend/libffi/src/closures.c
@@ -34,7 +34,7 @@
 #include <ffi_common.h>
 
 #if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE
-# if __gnu_linux__
+# if __gnu_linux__ && !defined(__ANDROID__)
 /* This macro indicates it may be forbidden to map anonymous memory
    with both write and execute permission.  Code compiled when this
    option is defined will attempt to map such pages once, but if it
@@ -181,10 +181,26 @@
 static int
 emutramp_enabled_check (void)
 {
-  if (getenv ("FFI_DISABLE_EMUTRAMP") == NULL)
-    return 1;
-  else
+  char *buf = NULL;
+  size_t len = 0;
+  FILE *f;
+  int ret;
+  f = fopen ("/proc/self/status", "r");
+  if (f == NULL)
     return 0;
+  ret = 0;
+
+  while (getline (&buf, &len, f) != -1)
+    if (!strncmp (buf, "PaX:", 4))
+      {
+        char emutramp;
+        if (sscanf (buf, "%*s %*c%c", &emutramp) == 1)
+          ret = (emutramp == 'E');
+        break;
+      }
+  free (buf);
+  fclose (f);
+  return ret;
 }
 
 #define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
@@ -249,9 +265,15 @@
 
 /* Open a temporary file name, and immediately unlink it.  */
 static int
-open_temp_exec_file_name (char *name)
+open_temp_exec_file_name (char *name, int flags)
 {
-  int fd = mkstemp (name);
+  int fd;
+
+#ifdef HAVE_MKOSTEMP
+  fd = mkostemp (name, flags);
+#else
+  fd = mkstemp (name);
+#endif
 
   if (fd != -1)
     unlink (name);
@@ -264,8 +286,30 @@
 open_temp_exec_file_dir (const char *dir)
 {
   static const char suffix[] = "/ffiXXXXXX";
-  int lendir = strlen (dir);
-  char *tempname = __builtin_alloca (lendir + sizeof (suffix));
+  int lendir, flags;
+  char *tempname;
+#ifdef O_TMPFILE
+  int fd;
+#endif
+
+#ifdef O_CLOEXEC
+  flags = O_CLOEXEC;
+#else
+  flags = 0;
+#endif
+
+#ifdef O_TMPFILE
+  fd = open (dir, flags | O_RDWR | O_EXCL | O_TMPFILE, 0700);
+  /* If the running system does not support the O_TMPFILE flag then retry without it. */
+  if (fd != -1 || (errno != EINVAL && errno != EISDIR && errno != EOPNOTSUPP)) {
+    return fd;
+  } else {
+    errno = 0;
+  }
+#endif
+
+  lendir = strlen (dir);
+  tempname = __builtin_alloca (lendir + sizeof (suffix));
 
   if (!tempname)
     return -1;
@@ -273,7 +317,7 @@
   memcpy (tempname, dir, lendir);
   memcpy (tempname + lendir, suffix, sizeof (suffix));
 
-  return open_temp_exec_file_name (tempname);
+  return open_temp_exec_file_name (tempname, flags);
 }
 
 /* Open a temporary file in the directory in the named environment
@@ -382,7 +426,7 @@
 }
 
 /* Return a file descriptor of a temporary zero-sized file in a
-   writable and exexutable filesystem.  */
+   writable and executable filesystem.  */
 static int
 open_temp_exec_file (void)
 {
diff --git a/third_party/gofrontend/libffi/src/debug.c b/third_party/gofrontend/libffi/src/debug.c
index 51dcfcf..f3172b1 100644
--- a/third_party/gofrontend/libffi/src/debug.c
+++ b/third_party/gofrontend/libffi/src/debug.c
@@ -54,6 +54,11 @@
   FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line);
   FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line);
   FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line);
-  FFI_ASSERT_AT(a->type != FFI_TYPE_STRUCT || a->elements != NULL, file, line);
+  FFI_ASSERT_AT((a->type != FFI_TYPE_STRUCT && a->type != FFI_TYPE_COMPLEX)
+		|| a->elements != NULL, file, line);
+  FFI_ASSERT_AT(a->type != FFI_TYPE_COMPLEX
+		|| (a->elements != NULL
+		    && a->elements[0] != NULL && a->elements[1] == NULL),
+		file, line);
 
 }
diff --git a/third_party/gofrontend/libffi/src/dlmalloc.c b/third_party/gofrontend/libffi/src/dlmalloc.c
index 5c9f9c2..7e4ea83 100644
--- a/third_party/gofrontend/libffi/src/dlmalloc.c
+++ b/third_party/gofrontend/libffi/src/dlmalloc.c
@@ -1255,7 +1255,7 @@
 #define SIZE_T_BITSIZE      (sizeof(size_t) << 3)
 
 /* Some constants coerced to size_t */
-/* Annoying but necessary to avoid errors on some plaftorms */
+/* Annoying but necessary to avoid errors on some platforms */
 #define SIZE_T_ZERO         ((size_t)0)
 #define SIZE_T_ONE          ((size_t)1)
 #define SIZE_T_TWO          ((size_t)2)
@@ -1409,7 +1409,7 @@
 #define CALL_MORECORE(S)     MFAIL
 #endif /* HAVE_MORECORE */
 
-/* mstate bit set if continguous morecore disabled or failed */
+/* mstate bit set if contiguous morecore disabled or failed */
 #define USE_NONCONTIGUOUS_BIT (4U)
 
 /* segment bit set in create_mspace_with_base */
@@ -1661,7 +1661,7 @@
 typedef struct malloc_chunk  mchunk;
 typedef struct malloc_chunk* mchunkptr;
 typedef struct malloc_chunk* sbinptr;  /* The type of bins of chunks */
-typedef unsigned int bindex_t;         /* Described below */
+typedef size_t bindex_t;               /* Described below */
 typedef unsigned int binmap_t;         /* Described below */
 typedef unsigned int flag_t;           /* The type of various bit flag sets */
 
@@ -2291,7 +2291,7 @@
 #define treebin_at(M,i)     (&((M)->treebins[i]))
 
 /* assign tree index for size S to variable I */
-#if defined(__GNUC__) && defined(i386)
+#if defined(__GNUC__) && defined(__i386__)
 #define compute_tree_index(S, I)\
 {\
   size_t X = S >> TREEBIN_SHIFT;\
@@ -2356,7 +2356,7 @@
 
 /* index corresponding to given bit */
 
-#if defined(__GNUC__) && defined(i386)
+#if defined(__GNUC__) && defined(__i386__)
 #define compute_bit2idx(X, I)\
 {\
   unsigned int J;\
@@ -3090,8 +3090,8 @@
      and choose its bk node as its replacement.
   2. If x was the last node of its size, but not a leaf node, it must
      be replaced with a leaf node (not merely one with an open left or
-     right), to make sure that lefts and rights of descendents
-     correspond properly to bit masks.  We use the rightmost descendent
+     right), to make sure that lefts and rights of descendants
+     correspond properly to bit masks.  We use the rightmost descendant
      of x.  We could use any other leaf, but this is easy to locate and
      tends to counteract removal of leftmosts elsewhere, and so keeps
      paths shorter than minimally guaranteed.  This doesn't loop much
@@ -3388,7 +3388,7 @@
   *ss = m->seg; /* Push current record */
   m->seg.base = tbase;
   m->seg.size = tsize;
-  set_segment_flags(&m->seg, mmapped);
+  (void)set_segment_flags(&m->seg, mmapped);
   m->seg.next = ss;
 
   /* Insert trailing fenceposts */
@@ -3548,7 +3548,7 @@
     if (!is_initialized(m)) { /* first-time initialization */
       m->seg.base = m->least_addr = tbase;
       m->seg.size = tsize;
-      set_segment_flags(&m->seg, mmap_flag);
+      (void)set_segment_flags(&m->seg, mmap_flag);
       m->magic = mparams.magic;
       init_bins(m);
       if (is_global(m)) 
@@ -5091,10 +5091,10 @@
         Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
       * Use last_remainder in more cases.
       * Pack bins using idea from  colin@nyx10.cs.du.edu
-      * Use ordered bins instead of best-fit threshhold
+      * Use ordered bins instead of best-fit threshold
       * Eliminate block-local decls to simplify tracing and debugging.
       * Support another case of realloc via move into top
-      * Fix error occuring when initial sbrk_base not word-aligned.
+      * Fix error occurring when initial sbrk_base not word-aligned.
       * Rely on page size for units instead of SBRK_UNIT to
         avoid surprises about sbrk alignment conventions.
       * Add mallinfo, mallopt. Thanks to Raymond Nijssen
diff --git a/third_party/gofrontend/libffi/src/ia64/ffi.c b/third_party/gofrontend/libffi/src/ia64/ffi.c
index 9533ef6..b77a836 100644
--- a/third_party/gofrontend/libffi/src/ia64/ffi.c
+++ b/third_party/gofrontend/libffi/src/ia64/ffi.c
@@ -401,7 +401,7 @@
    the closure (in the "trampoline" area), but we replace the gp
    pointer with a pointer to the closure itself.  We also add the real
    gp pointer to the closure.  This allows the function entry code to
-   both retrieve the user data, and to restire the correct gp pointer.  */
+   both retrieve the user data, and to restore the correct gp pointer.  */
 
 extern void ffi_closure_unix ();
 
diff --git a/third_party/gofrontend/libffi/src/java_raw_api.c b/third_party/gofrontend/libffi/src/java_raw_api.c
index d8e79ea..127123d 100644
--- a/third_party/gofrontend/libffi/src/java_raw_api.c
+++ b/third_party/gofrontend/libffi/src/java_raw_api.c
@@ -60,6 +60,9 @@
 	case FFI_TYPE_STRUCT:
 	  /* No structure parameters in Java.	*/
 	  abort();
+	case FFI_TYPE_COMPLEX:
+	  /* Not supported yet.  */
+	  abort();
 	default:
 	  result += FFI_SIZEOF_JAVA_RAW;
       }
@@ -104,6 +107,10 @@
 	  *args = (void*) &(raw++)->ptr;
 	  break;
 
+	case FFI_TYPE_COMPLEX:
+	  /* Not supported yet.  */
+	  abort();
+
 	default:
 	  *args = raw;
 	  raw +=
@@ -126,6 +133,9 @@
 	  *args = (void*) raw;
 	  raw += 2;
 	  break;
+	case FFI_TYPE_COMPLEX:
+	  /* Not supported yet.  */
+	  abort();
 	default:
 	  *args = (void*) raw++;
       }
@@ -254,6 +264,10 @@
       *(SINT64 *)rvalue <<= 32;
       break;
 
+    case FFI_TYPE_COMPLEX:
+      /* Not supported yet.  */
+      abort();
+
     default:
       break;
     }
@@ -279,6 +293,10 @@
       *(SINT64 *)rvalue >>= 32;
       break;
 
+    case FFI_TYPE_COMPLEX:
+      /* Not supported yet.  */
+      abort();
+
     default:
       break;
     }
diff --git a/third_party/gofrontend/libffi/src/m68k/ffi.c b/third_party/gofrontend/libffi/src/m68k/ffi.c
index 37a0784..0dee938 100644
--- a/third_party/gofrontend/libffi/src/m68k/ffi.c
+++ b/third_party/gofrontend/libffi/src/m68k/ffi.c
@@ -123,6 +123,8 @@
 #define CIF_FLAGS_POINTER	32
 #define CIF_FLAGS_STRUCT1	64
 #define CIF_FLAGS_STRUCT2	128
+#define CIF_FLAGS_SINT8		256
+#define CIF_FLAGS_SINT16	512
 
 /* Perform machine dependent cif processing */
 ffi_status
@@ -200,6 +202,14 @@
       cif->flags = CIF_FLAGS_DINT;
       break;
 
+    case FFI_TYPE_SINT16:
+      cif->flags = CIF_FLAGS_SINT16;
+      break;
+
+    case FFI_TYPE_SINT8:
+      cif->flags = CIF_FLAGS_SINT8;
+      break;
+
     default:
       cif->flags = CIF_FLAGS_INT;
       break;
diff --git a/third_party/gofrontend/libffi/src/m68k/sysv.S b/third_party/gofrontend/libffi/src/m68k/sysv.S
index f6f4ef9..ec2b14f 100644
--- a/third_party/gofrontend/libffi/src/m68k/sysv.S
+++ b/third_party/gofrontend/libffi/src/m68k/sysv.S
@@ -2,9 +2,10 @@
 	
    sysv.S - Copyright (c) 2012 Alan Hourihane
 	    Copyright (c) 1998, 2012 Andreas Schwab
-	    Copyright (c) 2008 Red Hat, Inc. 
-   
-   m68k Foreign Function Interface 
+	    Copyright (c) 2008 Red Hat, Inc.
+	    Copyright (c) 2012 Thorsten Glaser
+
+   m68k Foreign Function Interface
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -168,8 +169,28 @@
 
 retstruct2:
 	btst	#7,%d2
-	jbeq	noretval
+	jbeq	retsint8
 	move.w	%d0,(%a1)
+	jbra	epilogue
+
+retsint8:
+	btst	#8,%d2
+	jbeq	retsint16
+	| NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
+#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
+	ext.w	%d0
+	ext.l	%d0
+#else
+	extb.l	%d0
+#endif
+	move.l	%d0,(%a1)
+	jbra	epilogue
+
+retsint16:
+	btst	#9,%d2
+	jbeq	noretval
+	ext.l	%d0
+	move.l	%d0,(%a1)
 
 noretval:
 epilogue:
@@ -201,8 +222,10 @@
 	lsr.l	#1,%d0
 	jne	1f
 	jcc	.Lcls_epilogue
+	| CIF_FLAGS_INT
 	move.l	-12(%fp),%d0
 .Lcls_epilogue:
+	| no CIF_FLAGS_*
 	unlk	%fp
 	rts
 1:
@@ -210,6 +233,7 @@
 	lsr.l	#2,%d0
 	jne	1f
 	jcs	.Lcls_ret_float
+	| CIF_FLAGS_DINT
 	move.l	(%a0)+,%d0
 	move.l	(%a0),%d1
 	jra	.Lcls_epilogue
@@ -224,6 +248,7 @@
 	lsr.l	#2,%d0
 	jne	1f
 	jcs	.Lcls_ret_ldouble
+	| CIF_FLAGS_DOUBLE
 #if defined(__MC68881__) || defined(__HAVE_68881__)
 	fmove.d	(%a0),%fp0
 #else
@@ -242,17 +267,37 @@
 	jra	.Lcls_epilogue
 1:
 	lsr.l	#2,%d0
-	jne	.Lcls_ret_struct2
+	jne	1f
 	jcs	.Lcls_ret_struct1
+	| CIF_FLAGS_POINTER
 	move.l	(%a0),%a0
 	move.l	%a0,%d0
 	jra	.Lcls_epilogue
 .Lcls_ret_struct1:
 	move.b	(%a0),%d0
 	jra	.Lcls_epilogue
-.Lcls_ret_struct2:
+1:
+	lsr.l	#2,%d0
+	jne	1f
+	jcs	.Lcls_ret_sint8
+	| CIF_FLAGS_STRUCT2
 	move.w	(%a0),%d0
 	jra	.Lcls_epilogue
+.Lcls_ret_sint8:
+	move.l	(%a0),%d0
+	| NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
+#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
+	ext.w	%d0
+	ext.l	%d0
+#else
+	extb.l	%d0
+#endif
+	jra	.Lcls_epilogue
+1:
+	| CIF_FLAGS_SINT16
+	move.l	(%a0),%d0
+	ext.l	%d0
+	jra	.Lcls_epilogue
 	CFI_ENDPROC()
 
 	.size	CALLFUNC(ffi_closure_SYSV),.-CALLFUNC(ffi_closure_SYSV)
diff --git a/third_party/gofrontend/libffi/src/m88k/ffi.c b/third_party/gofrontend/libffi/src/m88k/ffi.c
new file mode 100644
index 0000000..68df494
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/m88k/ffi.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2013 Miodrag Vallat.  <miod@openbsd.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * ``Software''), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * m88k Foreign Function Interface
+ *
+ * This file attempts to provide all the FFI entry points which can reliably
+ * be implemented in C.
+ *
+ * Only OpenBSD/m88k is currently supported; other platforms (such as
+ * Motorola's SysV/m88k) could be supported with the following tweaks:
+ *
+ * - non-OpenBSD systems use an `outgoing parameter area' as part of the
+ *   88BCS calling convention, which is not supported under OpenBSD from
+ *   release 3.6 onwards.  Supporting it should be as easy as taking it
+ *   into account when adjusting the stack, in the assembly code.
+ *
+ * - the logic deciding whether a function argument gets passed through
+ *   registers, or on the stack, has changed several times in OpenBSD in
+ *   edge cases (especially for structs larger than 32 bytes being passed
+ *   by value). The code below attemps to match the logic used by the
+ *   system compiler of OpenBSD 5.3, i.e. gcc 3.3.6 with many m88k backend
+ *   fixes.
+ */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+void ffi_call_OBSD (unsigned int, extended_cif *, unsigned int, void *,
+		    void (*fn) ());
+void *ffi_prep_args (void *, extended_cif *);
+void ffi_closure_OBSD (ffi_closure *);
+void ffi_closure_struct_OBSD (ffi_closure *);
+unsigned int ffi_closure_OBSD_inner (ffi_closure *, void *, unsigned int *,
+				     char *);
+void ffi_cacheflush_OBSD (unsigned int, unsigned int);
+
+#define CIF_FLAGS_INT		(1 << 0)
+#define CIF_FLAGS_DINT		(1 << 1)
+
+/*
+ * Foreign Function Interface API
+ */
+
+/* ffi_prep_args is called by the assembly routine once stack space has
+   been allocated for the function's arguments.  */
+
+void *
+ffi_prep_args (void *stack, extended_cif *ecif)
+{
+  unsigned int i;
+  void **p_argv;
+  char *argp, *stackp;
+  unsigned int *regp;
+  unsigned int regused;
+  ffi_type **p_arg;
+  void *struct_value_ptr;
+
+  regp = (unsigned int *)stack;
+  stackp = (char *)(regp + 8);
+  regused = 0;
+
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
+      && !ecif->cif->flags)
+    struct_value_ptr = ecif->rvalue;
+  else
+    struct_value_ptr = NULL;
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i != 0; i--, p_arg++)
+    {
+      size_t z;
+      unsigned short t, a;
+
+      z = (*p_arg)->size;
+      t = (*p_arg)->type;
+      a = (*p_arg)->alignment;
+
+      /*
+       * Figure out whether the argument can be passed through registers
+       * or on the stack.
+       * The rule is that registers can only receive simple types not larger
+       * than 64 bits, or structs the exact size of a register and aligned to
+       * the size of a register.
+       */
+      if (t == FFI_TYPE_STRUCT)
+	{
+	  if (z == sizeof (int) && a == sizeof (int) && regused < 8)
+	    argp = (char *)regp;
+	  else
+	    argp = stackp;
+	}
+      else
+	{
+	  if (z > sizeof (int) && regused < 8 - 1)
+	    {
+	      /* align to an even register pair */
+	      if (regused & 1)
+		{
+		  regp++;
+		  regused++;
+		}
+	    }
+	  if (regused < 8)
+	    argp = (char *)regp;
+	  else
+	    argp = stackp;
+	}
+
+      /* Enforce proper stack alignment of 64-bit types */
+      if (argp == stackp && a > sizeof (int))
+	{
+	  stackp = (char *) ALIGN(stackp, a);
+	  argp = stackp;
+	}
+
+      switch (t)
+	{
+	case FFI_TYPE_SINT8:
+	  *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
+	  break;
+
+	case FFI_TYPE_UINT8:
+	  *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
+	  break;
+
+	case FFI_TYPE_SINT16:
+	  *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
+	  break;
+
+	case FFI_TYPE_UINT16:
+	  *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
+	  break;
+
+	case FFI_TYPE_INT:
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_POINTER:
+	  *(unsigned int *) argp = *(unsigned int *) *p_argv;
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_STRUCT:
+	  memcpy (argp, *p_argv, z);
+	  break;
+
+	default:
+	  FFI_ASSERT (0);
+	}
+
+      /* Align if necessary.  */
+      if ((sizeof (int) - 1) & z)
+	z = ALIGN(z, sizeof (int));
+
+      p_argv++;
+
+      /* Be careful, once all registers are filled, and about to continue
+         on stack, regp == stackp.  Therefore the check for regused as well. */
+      if (argp == (char *)regp && regused < 8)
+	{
+	  regp += z / sizeof (int);
+	  regused += z / sizeof (int);
+	}
+      else
+	stackp += z;
+    }
+
+  return struct_value_ptr;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+      cif->flags = 0;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      if (cif->rtype->size == sizeof (int) &&
+	  cif->rtype->alignment == sizeof (int))
+	cif->flags = CIF_FLAGS_INT;
+      else
+	cif->flags = 0;
+      break;
+
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags = CIF_FLAGS_DINT;
+      break;
+
+    default:
+      cif->flags = CIF_FLAGS_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+void
+ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* If the return value is a struct and we don't have a return value
+     address then we need to make one.  */
+
+  if (rvalue == NULL
+      && cif->rtype->type == FFI_TYPE_STRUCT
+      && (cif->rtype->size != sizeof (int)
+	  || cif->rtype->alignment != sizeof (int)))
+    ecif.rvalue = alloca (cif->rtype->size);
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi)
+    {
+    case FFI_OBSD:
+      ffi_call_OBSD (cif->bytes, &ecif, cif->flags, ecif.rvalue, fn);
+      break;
+
+    default:
+      FFI_ASSERT (0);
+      break;
+    }
+}
+
+/*
+ * Closure API
+ */
+
+static void
+ffi_prep_closure_args_OBSD (ffi_cif *cif, void **avalue, unsigned int *regp,
+			    char *stackp)
+{
+  unsigned int i;
+  void **p_argv;
+  char *argp;
+  unsigned int regused;
+  ffi_type **p_arg;
+
+  regused = 0;
+
+  p_argv = avalue;
+
+  for (i = cif->nargs, p_arg = cif->arg_types; i != 0; i--, p_arg++)
+    {
+      size_t z;
+      unsigned short t, a;
+
+      z = (*p_arg)->size;
+      t = (*p_arg)->type;
+      a = (*p_arg)->alignment;
+
+      /*
+       * Figure out whether the argument has been passed through registers
+       * or on the stack.
+       * The rule is that registers can only receive simple types not larger
+       * than 64 bits, or structs the exact size of a register and aligned to
+       * the size of a register.
+       */
+      if (t == FFI_TYPE_STRUCT)
+	{
+	  if (z == sizeof (int) && a == sizeof (int) && regused < 8)
+	    argp = (char *)regp;
+	  else
+	    argp = stackp;
+	}
+      else
+	{
+	  if (z > sizeof (int) && regused < 8 - 1)
+	    {
+	      /* align to an even register pair */
+	      if (regused & 1)
+		{
+		  regp++;
+		  regused++;
+		}
+	    }
+	  if (regused < 8)
+	    argp = (char *)regp;
+	  else
+	    argp = stackp;
+	}
+
+      /* Enforce proper stack alignment of 64-bit types */
+      if (argp == stackp && a > sizeof (int))
+	{
+	  stackp = (char *) ALIGN(stackp, a);
+	  argp = stackp;
+	}
+
+      if (z < sizeof (int) && t != FFI_TYPE_STRUCT)
+	*p_argv = (void *) (argp + sizeof (int) - z);
+      else
+	*p_argv = (void *) argp;
+
+      /* Align if necessary */
+      if ((sizeof (int) - 1) & z)
+	z = ALIGN(z, sizeof (int));
+
+      p_argv++;
+
+      /* Be careful, once all registers are exhausted, and about to fetch from
+	 stack, regp == stackp.  Therefore the check for regused as well. */
+      if (argp == (char *)regp && regused < 8)
+	{
+	  regp += z / sizeof (int);
+	  regused += z / sizeof (int);
+	}
+      else
+	stackp += z;
+    }
+}
+
+unsigned int
+ffi_closure_OBSD_inner (ffi_closure *closure, void *resp, unsigned int *regp,
+			char *stackp)
+{
+  ffi_cif *cif;
+  void **arg_area;
+
+  cif = closure->cif;
+  arg_area = (void**) alloca (cif->nargs * sizeof (void *));
+
+  ffi_prep_closure_args_OBSD(cif, arg_area, regp, stackp);
+
+  (closure->fun) (cif, resp, arg_area, closure->user_data);
+
+  return cif->flags;
+}
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure, ffi_cif* cif,
+		      void (*fun)(ffi_cif*,void*,void**,void*),
+		      void *user_data, void *codeloc)
+{
+  unsigned int *tramp = (unsigned int *) codeloc;
+  void *fn;
+
+  FFI_ASSERT (cif->abi == FFI_OBSD);
+
+  if (cif->rtype->type == FFI_TYPE_STRUCT && !cif->flags)
+    fn = &ffi_closure_struct_OBSD;
+  else
+    fn = &ffi_closure_OBSD;
+
+  /* or.u %r10, %r0, %hi16(fn) */
+  tramp[0] = 0x5d400000 | (((unsigned int)fn) >> 16);
+  /* or.u %r13, %r0, %hi16(closure) */
+  tramp[1] = 0x5da00000 | ((unsigned int)closure >> 16);
+  /* or %r10, %r10, %lo16(fn) */
+  tramp[2] = 0x594a0000 | (((unsigned int)fn) & 0xffff);
+  /* jmp.n %r10 */
+  tramp[3] = 0xf400c40a;
+  /* or %r13, %r13, %lo16(closure) */
+  tramp[4] = 0x59ad0000 | ((unsigned int)closure & 0xffff);
+
+  ffi_cacheflush_OBSD((unsigned int)codeloc, FFI_TRAMPOLINE_SIZE);
+
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
diff --git a/third_party/gofrontend/libffi/src/m88k/ffitarget.h b/third_party/gofrontend/libffi/src/m88k/ffitarget.h
new file mode 100644
index 0000000..e52bf9f
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/m88k/ffitarget.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 Miodrag Vallat.  <miod@openbsd.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * ``Software''), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * m88k Foreign Function Interface
+ */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_ASM
+typedef unsigned long ffi_arg;
+typedef signed long ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_OBSD,
+  FFI_DEFAULT_ABI = FFI_OBSD,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 0x14
+#define FFI_NATIVE_RAW_API 0
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/m88k/obsd.S b/third_party/gofrontend/libffi/src/m88k/obsd.S
new file mode 100644
index 0000000..1944a23
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/m88k/obsd.S
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2013 Miodrag Vallat.  <miod@openbsd.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * ``Software''), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * m88k Foreign Function Interface
+ */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+	.text
+
+/*
+ * ffi_cacheflush_OBSD(unsigned int addr,	%r2
+ *		       unsigned int size);	%r3
+ */
+	.align	4
+	.globl	ffi_cacheflush_OBSD
+	.type	ffi_cacheflush_OBSD,@function
+ffi_cacheflush_OBSD:
+	tb0	0,   %r0, 451
+	or	%r0, %r0, %r0
+	jmp	%r1
+	.size	ffi_cacheflush_OBSD, . - ffi_cacheflush_OBSD
+
+/*
+ * ffi_call_OBSD(unsigned bytes,		%r2
+ *		 extended_cif *ecif,		%r3
+ *		 unsigned flags,		%r4
+ *		 void *rvalue,			%r5
+ *		 void (*fn)());			%r6
+ */
+	.align	4
+	.globl	ffi_call_OBSD
+	.type	ffi_call_OBSD,@function
+ffi_call_OBSD:
+	subu	%r31, %r31, 32
+	st	%r30, %r31, 4
+	st	%r1,  %r31, 0
+	addu	%r30, %r31, 32
+
+	| Save the few arguments we'll need after ffi_prep_args()
+	st.d	%r4, %r31, 8
+	st	%r6, %r31, 16
+
+	| Allocate room for the image of r2-r9, and the stack space for
+	| the args (rounded to a 16-byte boundary)
+	addu	%r2,  %r2,  (8 * 4) + 15
+	clr	%r2,  %r2,  4<0>
+	subu	%r31, %r31, %r2
+
+	| Fill register and stack image
+	or	%r2, %r31, %r0
+#ifdef PIC
+	bsr	ffi_prep_args#plt
+#else
+	bsr	ffi_prep_args
+#endif
+
+	| Save pointer to return struct address, if any
+	or	%r12, %r2, %r0
+
+	| Get function pointer
+	subu	%r4,  %r30, 32
+	ld	%r1,  %r4,  16
+
+	| Fetch the register arguments
+	ld.d	%r2, %r31, (0 * 4)
+	ld.d	%r4, %r31, (2 * 4)
+	ld.d	%r6, %r31, (4 * 4)
+	ld.d	%r8, %r31, (6 * 4)
+	addu	%r31, %r31, (8 * 4)
+
+	| Invoke the function
+	jsr	%r1
+
+	| Restore stack now that we don't need the args anymore
+	subu	%r31, %r30, 32
+
+	| Figure out what to return as the function's return value
+	ld	%r5, %r31, 12		| rvalue
+	ld	%r4, %r31, 8		| flags
+
+	bcnd	eq0, %r5, 9f
+
+	bb0	0, %r4, 1f		| CIF_FLAGS_INT
+	st	%r2, %r5, 0
+	br	9f
+
+1:
+	bb0	1, %r4, 1f		| CIF_FLAGS_DINT
+	st.d	%r2, %r5, 0
+	br	9f
+
+1:
+9:
+	ld	%r1,  %r31, 0
+	ld	%r30, %r31, 4
+	jmp.n	%r1
+	 addu	%r31, %r31, 32
+	.size	ffi_call_OBSD, . - ffi_call_OBSD
+
+/*
+ * ffi_closure_OBSD(ffi_closure *closure);	%r13
+ */
+	.align	4
+	.globl	ffi_closure_OBSD
+	.type	ffi_closure_OBSD, @function
+ffi_closure_OBSD:
+	subu	%r31, %r31, 16
+	st	%r30, %r31, 4
+	st	%r1,  %r31, 0
+	addu	%r30, %r31, 16
+
+	| Make room on the stack for saved register arguments and return
+	| value
+	subu	%r31, %r31, (8 * 4) + (2 * 4)
+	st.d	%r2,  %r31, (0 * 4)
+	st.d	%r4,  %r31, (2 * 4)
+	st.d	%r6,  %r31, (4 * 4)
+	st.d	%r8,  %r31, (6 * 4)
+
+	| Invoke the closure function
+	or	%r5,  %r30, 0			| calling stack
+	addu	%r4,  %r31, 0			| saved registers
+	addu	%r3,  %r31, (8 * 4)		| return value
+	or	%r2,  %r13, %r0			| closure
+#ifdef PIC
+	bsr	ffi_closure_OBSD_inner#plt
+#else
+	bsr	ffi_closure_OBSD_inner
+#endif
+
+	| Figure out what to return as the function's return value
+	bb0	0, %r2, 1f		| CIF_FLAGS_INT
+	ld	%r2, %r31, (8 * 4)
+	br	9f
+
+1:
+	bb0	1, %r2, 1f		| CIF_FLAGS_DINT
+	ld.d	%r2, %r31, (8 * 4)
+	br	9f
+
+1:
+9:
+	subu	%r31, %r30, 16
+	ld	%r1,  %r31, 0
+	ld	%r30, %r31, 4
+	jmp.n	%r1
+	 addu	%r31, %r31, 16
+	.size	ffi_closure_OBSD,.-ffi_closure_OBSD
+
+/*
+ * ffi_closure_struct_OBSD(ffi_closure *closure);	%r13
+ */
+	.align	4
+	.globl	ffi_closure_struct_OBSD
+	.type	ffi_closure_struct_OBSD, @function
+ffi_closure_struct_OBSD:
+	subu	%r31, %r31, 16
+	st	%r30, %r31, 4
+	st	%r1,  %r31, 0
+	addu	%r30, %r31, 16
+
+	| Make room on the stack for saved register arguments
+	subu	%r31, %r31, (8 * 4)
+	st.d	%r2,  %r31, (0 * 4)
+	st.d	%r4,  %r31, (2 * 4)
+	st.d	%r6,  %r31, (4 * 4)
+	st.d	%r8,  %r31, (6 * 4)
+
+	| Invoke the closure function
+	or	%r5,  %r30, 0			| calling stack
+	addu	%r4,  %r31, 0			| saved registers
+	or	%r3,  %r12, 0			| return value
+	or	%r2,  %r13, %r0			| closure
+#ifdef PIC
+	bsr	ffi_closure_OBSD_inner#plt
+#else
+	bsr	ffi_closure_OBSD_inner
+#endif
+
+	subu	%r31, %r30, 16
+	ld	%r1,  %r31, 0
+	ld	%r30, %r31, 4
+	jmp.n	%r1
+	 addu	%r31, %r31, 16
+	.size	ffi_closure_struct_OBSD,.-ffi_closure_struct_OBSD
diff --git a/third_party/gofrontend/libffi/src/metag/ffi.c b/third_party/gofrontend/libffi/src/metag/ffi.c
new file mode 100644
index 0000000..46b383e
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/metag/ffi.c
@@ -0,0 +1,330 @@
+/* ----------------------------------------------------------------------
+  ffi.c - Copyright (c) 2013 Imagination Technologies
+
+  Meta Foreign Function Interface
+  Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  `Software''), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be included
+  in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED `AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+  IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
+  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+/*
+ * ffi_prep_args is called by the assembly routine once stack space has been
+ * allocated for the function's arguments
+ */
+
+unsigned int ffi_prep_args(char *stack, extended_cif *ecif)
+{
+	register unsigned int i;
+	register void **p_argv;
+	register char *argp;
+	register ffi_type **p_arg;
+
+	argp = stack;
+
+	/* Store return value */
+	if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
+		argp -= 4;
+		*(void **) argp = ecif->rvalue;
+	}
+
+	p_argv = ecif->avalue;
+
+	/* point to next location */
+	for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; (i != 0); i--, p_arg++, p_argv++)
+	{
+		size_t z;
+
+		/* Move argp to address of argument */
+		z = (*p_arg)->size;
+		argp -= z;
+
+		/* Align if necessary */
+		argp = (char *) ALIGN_DOWN(ALIGN_DOWN(argp, (*p_arg)->alignment), 4);
+
+		if (z < sizeof(int)) {
+			z = sizeof(int);
+			switch ((*p_arg)->type)
+			{
+			case FFI_TYPE_SINT8:
+				*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+				break;
+			case FFI_TYPE_UINT8:
+				*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+				break;
+			case FFI_TYPE_SINT16:
+				*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+				break;
+			case FFI_TYPE_UINT16:
+				*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+			case FFI_TYPE_STRUCT:
+				memcpy(argp, *p_argv, (*p_arg)->size);
+				break;
+			default:
+				FFI_ASSERT(0);
+			}
+		} else if ( z == sizeof(int)) {
+			*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+		} else {
+			memcpy(argp, *p_argv, z);
+		}
+	}
+
+	/* return the size of the arguments to be passed in registers,
+	   padded to an 8 byte boundary to preserve stack alignment */
+	return ALIGN(MIN(stack - argp, 6*4), 8);
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+	ffi_type **ptr;
+	unsigned i, bytes = 0;
+
+	for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) {
+		if ((*ptr)->size == 0)
+			return FFI_BAD_TYPEDEF;
+
+		/* Perform a sanity check on the argument type, do this
+		   check after the initialization.  */
+		FFI_ASSERT_VALID_TYPE(*ptr);
+
+		/* Add any padding if necessary */
+		if (((*ptr)->alignment - 1) & bytes)
+			bytes = ALIGN(bytes, (*ptr)->alignment);
+
+		bytes += ALIGN((*ptr)->size, 4);
+	}
+
+	/* Ensure arg space is aligned to an 8-byte boundary */
+	bytes = ALIGN(bytes, 8);
+
+	/* Make space for the return structure pointer */
+	if (cif->rtype->type == FFI_TYPE_STRUCT) {
+		bytes += sizeof(void*);
+
+		/* Ensure stack is aligned to an 8-byte boundary */
+		bytes = ALIGN(bytes, 8);
+	}
+
+	cif->bytes = bytes;
+
+	/* Set the return type flag */
+	switch (cif->rtype->type) {
+	case FFI_TYPE_VOID:
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+		cif->flags = (unsigned) cif->rtype->type;
+		break;
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+		cif->flags = (unsigned) FFI_TYPE_SINT64;
+		break;
+	case FFI_TYPE_STRUCT:
+		/* Meta can store return values which are <= 64 bits */
+		if (cif->rtype->size <= 4)
+			/* Returned to D0Re0 as 32-bit value */
+			cif->flags = (unsigned)FFI_TYPE_INT;
+		else if ((cif->rtype->size > 4) && (cif->rtype->size <= 8))
+			/* Returned valued is stored to D1Re0|R0Re0 */
+			cif->flags = (unsigned)FFI_TYPE_DOUBLE;
+		else
+			/* value stored in memory */
+			cif->flags = (unsigned)FFI_TYPE_STRUCT;
+		break;
+	default:
+		cif->flags = (unsigned)FFI_TYPE_INT;
+		break;
+	}
+	return FFI_OK;
+}
+
+extern void ffi_call_SYSV(void (*fn)(void), extended_cif *, unsigned, unsigned, double *);
+
+/*
+ * Exported in API. Entry point
+ * cif -> ffi_cif object
+ * fn -> function pointer
+ * rvalue -> pointer to return value
+ * avalue -> vector of void * pointers pointing to memory locations holding the
+ * arguments
+ */
+void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+	extended_cif ecif;
+
+	int small_struct = (((cif->flags == FFI_TYPE_INT) || (cif->flags == FFI_TYPE_DOUBLE)) && (cif->rtype->type == FFI_TYPE_STRUCT));
+	ecif.cif = cif;
+	ecif.avalue = avalue;
+
+	double temp;
+
+	/*
+	 * If the return value is a struct and we don't have a return value address
+	 * then we need to make one
+	 */
+
+	if ((rvalue == NULL ) && (cif->flags == FFI_TYPE_STRUCT))
+		ecif.rvalue = alloca(cif->rtype->size);
+	else if (small_struct)
+		ecif.rvalue = &temp;
+	else
+		ecif.rvalue = rvalue;
+
+	switch (cif->abi) {
+	case FFI_SYSV:
+		ffi_call_SYSV(fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
+		break;
+	default:
+		FFI_ASSERT(0);
+		break;
+	}
+
+	if (small_struct)
+		memcpy (rvalue, &temp, cif->rtype->size);
+}
+
+/* private members */
+
+static void ffi_prep_incoming_args_SYSV (char *, void **, void **,
+	ffi_cif*, float *);
+
+void ffi_closure_SYSV (ffi_closure *);
+
+/* Do NOT change that without changing the FFI_TRAMPOLINE_SIZE */
+extern unsigned int ffi_metag_trampoline[10]; /* 10 instructions */
+
+/* end of private members */
+
+/*
+ * __tramp: trampoline memory location
+ * __fun: assembly routine
+ * __ctx: memory location for wrapper
+ *
+ * At this point, tramp[0] == __ctx !
+ */
+void ffi_init_trampoline(unsigned char *__tramp, unsigned int __fun, unsigned int __ctx) {
+	memcpy (__tramp, ffi_metag_trampoline, sizeof(ffi_metag_trampoline));
+	*(unsigned int*) &__tramp[40] = __ctx;
+	*(unsigned int*) &__tramp[44] = __fun;
+	/* This will flush the instruction cache */
+	__builtin_meta2_cachewd(&__tramp[0], 1);
+	__builtin_meta2_cachewd(&__tramp[47], 1);
+}
+
+
+
+/* the cif must already be prepared */
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure *closure,
+	ffi_cif* cif,
+	void (*fun)(ffi_cif*,void*,void**,void*),
+	void *user_data,
+	void *codeloc)
+{
+	void (*closure_func)(ffi_closure*) = NULL;
+
+	if (cif->abi == FFI_SYSV)
+		closure_func = &ffi_closure_SYSV;
+	else
+		return FFI_BAD_ABI;
+
+	ffi_init_trampoline(
+		(unsigned char*)&closure->tramp[0],
+		(unsigned int)closure_func,
+		(unsigned int)codeloc);
+
+	closure->cif = cif;
+	closure->user_data = user_data;
+	closure->fun = fun;
+
+	return FFI_OK;
+}
+
+
+/* This function is jumped to by the trampoline */
+unsigned int ffi_closure_SYSV_inner (closure, respp, args, vfp_args)
+	ffi_closure *closure;
+	void **respp;
+	void *args;
+	void *vfp_args;
+{
+	ffi_cif *cif;
+	void **arg_area;
+
+	cif = closure->cif;
+	arg_area = (void**) alloca (cif->nargs * sizeof (void*));
+
+	/*
+	 * This call will initialize ARG_AREA, such that each
+	 * element in that array points to the corresponding
+	 * value on the stack; and if the function returns
+	 * a structure, it will re-set RESP to point to the
+	 * structure return address.
+	 */
+	ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args);
+
+	(closure->fun) ( cif, *respp, arg_area, closure->user_data);
+
+	return cif->flags;
+}
+
+static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
+	void **avalue, ffi_cif *cif,
+	float *vfp_stack)
+{
+	register unsigned int i;
+	register void **p_argv;
+	register char *argp;
+	register ffi_type **p_arg;
+
+	/* stack points to original arguments */
+	argp = stack;
+
+	/* Store return value */
+	if ( cif->flags == FFI_TYPE_STRUCT ) {
+		argp -= 4;
+		*rvalue = *(void **) argp;
+	}
+
+	p_argv = avalue;
+
+	for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) {
+		size_t z;
+		size_t alignment;
+
+		alignment = (*p_arg)->alignment;
+		if (alignment < 4)
+			alignment = 4;
+		if ((alignment - 1) & (unsigned)argp)
+			argp = (char *) ALIGN(argp, alignment);
+
+		z = (*p_arg)->size;
+		*p_argv = (void*) argp;
+		p_argv++;
+		argp -= z;
+	}
+	return;
+}
diff --git a/third_party/gofrontend/libffi/src/metag/ffitarget.h b/third_party/gofrontend/libffi/src/metag/ffitarget.h
new file mode 100644
index 0000000..7b9dbeb
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/metag/ffitarget.h
@@ -0,0 +1,53 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2013 Imagination Technologies Ltd.
+   Target configuration macros for Meta
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1,
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 48
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff --git a/third_party/gofrontend/libffi/src/metag/sysv.S b/third_party/gofrontend/libffi/src/metag/sysv.S
new file mode 100644
index 0000000..b4b2a3b
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/metag/sysv.S
@@ -0,0 +1,311 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2013 Imagination Technologies Ltd.
+
+   Meta Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+#ifdef __USER_LABEL_PREFIX__
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+#else
+#define CNAME(x) x
+#endif
+#define ENTRY(x) .globl CNAME(x); .type CNAME(x), %function; CNAME(x):
+#endif
+
+#ifdef __ELF__
+#define LSYM(x) .x
+#else
+#define LSYM(x) x
+#endif
+
+.macro call_reg x=
+	.text
+	.balign 4
+	mov D1RtP, \x
+	swap D1RtP, PC
+.endm
+
+! Save register arguments
+.macro SAVE_ARGS
+	.text
+	.balign 4
+	setl	[A0StP++], D0Ar6, D1Ar5
+	setl	[A0StP++], D0Ar4, D1Ar3
+	setl	[A0StP++], D0Ar2, D1Ar1
+.endm
+
+! Save retrun, frame pointer and other regs
+.macro SAVE_REGS regs=
+	.text
+	.balign 4
+	setl	[A0StP++], D0FrT, D1RtP
+	! Needs to be a pair of regs
+	.ifnc "\regs",""
+	setl	[A0StP++], \regs
+	.endif
+.endm
+
+! Declare a global function
+.macro METAG_FUNC_START name
+	.text
+	.balign 4
+	ENTRY(\name)
+.endm
+
+! Return registers from the stack. Reverse SAVE_REGS operation
+.macro RET_REGS regs=, cond=
+	.ifnc "\regs", ""
+	getl	\regs, [--A0StP]
+	.endif
+	getl	D0FrT, D1RtP, [--A0StP]
+.endm
+
+! Return arguments
+.macro RET_ARGS
+	getl	D0Ar2, D1Ar1, [--A0StP]
+	getl	D0Ar4, D1Ar3, [--A0StP]
+	getl	D0Ar6, D1Ar5, [--A0StP]
+.endm
+
+
+	! D1Ar1:	fn
+	! D0Ar2:	&ecif
+	! D1Ar3:	cif->bytes
+	! D0Ar4:	fig->flags
+	! D1Ar5:	ecif.rvalue
+
+	! This assumes we are using GNU as
+METAG_FUNC_START ffi_call_SYSV
+	! Save argument registers
+
+	SAVE_ARGS
+
+	! new frame
+	mov	D0FrT, A0FrP
+	add     A0FrP, A0StP, #0
+
+	! Preserve the old frame pointer
+	SAVE_REGS "D1.5, D0.5"
+
+	! Make room for new args. cifs->bytes is the total space for input
+	! and return arguments
+
+	add	A0StP, A0StP, D1Ar3
+
+	! Preserve cifs->bytes & fn
+	mov	D0.5, D1Ar3
+	mov	D1.5, D1Ar1
+
+	! Place all of the ffi_prep_args in position
+	mov	D1Ar1, A0StP
+
+	! Call ffi_prep_args(stack, &ecif)
+#ifdef __PIC__
+	callr  D1RtP, CNAME(ffi_prep_args@PLT)
+#else
+	callr  D1RtP, CNAME(ffi_prep_args)
+#endif
+
+	! Restore fn pointer
+
+	! The foreign stack should look like this
+	! XXXXX XXXXXX <--- stack pointer
+	! FnArgN rvalue
+	! FnArgN+2 FnArgN+1
+	! FnArgN+4 FnArgN+3
+	! ....
+	!
+
+	! A0StP now points to the first (or return) argument + 4
+
+	! Preserve cif->bytes
+	getl	D0Ar2, D1Ar1, [--A0StP]
+	getl	D0Ar4, D1Ar3, [--A0StP]
+	getl	D0Ar6, D1Ar5, [--A0StP]
+
+	! Place A0StP to the first argument again
+	add	A0StP, A0StP, #24 ! That's because we loaded 6 regs x 4 byte each
+
+	! A0FrP points to the initial stack without the reserved space for the
+	! cifs->bytes, whilst A0StP points to the stack after the space allocation
+
+	! fn was the first argument of ffi_call_SYSV.
+	! The stack at this point looks like this:
+	!
+	! A0StP(on entry to _SYSV) ->	Arg6	Arg5     | low
+	!				Arg4	Arg3     |
+	! 				Arg2	Arg1     |
+	! A0FrP ---->			D0FrtP	D1RtP    |
+	!				D1.5	D0.5	 |
+	! A0StP(bf prep_args) ->	FnArgn	FnArgn-1 |
+	!				FnArgn-2FnArgn-3 |
+	!				................ | <= cifs->bytes
+	!				FnArg4  FnArg3	 |
+	! A0StP (prv_A0StP+cifs->bytes) FnArg2  FnArg1   | high
+	!
+	! fn was in Arg1 so it's located in in A0FrP+#-0xC
+	!
+
+	! D0Re0 contains the size of arguments stored in registers
+	sub	A0StP, A0StP, D0Re0
+
+	! Arg1 is the function pointer for the foreign call. This has been
+	! preserved in D1.5
+
+	! Time to call (fn). Arguments should be like this:
+	! Arg1-Arg6 are loaded to regs
+	! The rest of the arguments are stored in stack pointed by A0StP
+
+	call_reg D1.5
+
+	! Reset stack.
+
+	mov	A0StP, A0FrP
+
+	! Load Arg1 with the pointer to storage for the return type
+	! This was stored in Arg5
+
+	getd	D1Ar1, [A0FrP+#-20]
+
+	! Load D0Ar2 with the return type code. This was stored in Arg4 (flags)
+
+	getd	D0Ar2, [A0FrP+#-16]
+
+	! We are ready to start processing the return value
+	! D0Re0 (and D1Re0) hold the return value
+
+	! If the return value is NULL, assume no return value
+	cmp	D1Ar1, #0
+	beq	LSYM(Lepilogue)
+
+	! return INT
+	cmp		D0Ar2, #FFI_TYPE_INT
+	! Sadly, there is no setd{cc} instruction so we need to workaround that
+	bne	.INT64
+	setd	[D1Ar1], D0Re0
+	b	LSYM(Lepilogue)
+
+	! return INT64
+.INT64:
+	cmp	D0Ar2, #FFI_TYPE_SINT64
+	setleq	[D1Ar1], D0Re0, D1Re0
+
+	! return DOUBLE
+	cmp	D0Ar2, #FFI_TYPE_DOUBLE
+	setl	[D1AR1++], D0Re0, D1Re0
+
+LSYM(Lepilogue):
+	! At this point, the stack pointer points right after the argument
+	! saved area. We need to restore 4 regs, therefore we need to move
+	! 16 bytes ahead.
+	add     A0StP, A0StP, #16
+	RET_REGS "D1.5, D0.5"
+	RET_ARGS
+	getd	D0Re0, [A0StP]
+	mov     A0FrP, D0FrT
+	swap	D1RtP, PC
+
+.ffi_call_SYSV_end:
+       .size   CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+
+
+/*
+	(called by ffi_metag_trampoline)
+	void ffi_closure_SYSV (ffi_closure*)
+
+	(called by ffi_closure_SYSV)
+	unsigned int FFI_HIDDEN
+	ffi_closure_SYSV_inner (closure,respp, args)
+		ffi_closure *closure;
+		void **respp;
+		void *args;
+*/
+
+METAG_FUNC_START ffi_closure_SYSV
+	! We assume that D1Ar1 holds the address of the
+	! ffi_closure struct. We will use that to fetch the
+	! arguments. The stack pointer points to an empty space
+	! and it is ready to store more data.
+
+	! D1Ar1 is ready
+	! Allocate stack space for return value
+	add A0StP, A0StP, #8
+	! Store it to D0Ar2
+	sub D0Ar2, A0StP, #8
+
+	sub D1Ar3, A0FrP, #4
+
+	! D1Ar3 contains the address of the original D1Ar1 argument
+	! We need to subtract #4 later on
+
+	! Preverve D0Ar2
+	mov D0.5, D0Ar2
+
+#ifdef __PIC__
+	callr D1RtP, CNAME(ffi_closure_SYSV_inner@PLT)
+#else
+	callr D1RtP, CNAME(ffi_closure_SYSV_inner)
+#endif
+
+	! Check the return value and store it to D0.5
+	cmp D0Re0, #FFI_TYPE_INT
+	beq .Lretint
+	cmp D0Re0, #FFI_TYPE_DOUBLE
+	beq .Lretdouble
+.Lclosure_epilogue:
+	sub A0StP, A0StP, #8
+	RET_REGS "D1.5, D0.5"
+	RET_ARGS
+	swap	D1RtP, PC
+
+.Lretint:
+	setd [D0.5], D0Re0
+	b .Lclosure_epilogue
+.Lretdouble:
+	setl [D0.5++], D0Re0, D1Re0
+	b .Lclosure_epilogue
+.ffi_closure_SYSV_end:
+.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
+
+
+ENTRY(ffi_metag_trampoline)
+	SAVE_ARGS
+	! New frame
+	mov A0FrP, A0StP
+	SAVE_REGS "D1.5, D0.5"
+	mov D0.5, PC
+	! Load D1Ar1 the value of ffi_metag_trampoline
+	getd D1Ar1, [D0.5 + #8]
+	! Jump to ffi_closure_SYSV
+	getd PC, [D0.5 + #12]
diff --git a/third_party/gofrontend/libffi/src/microblaze/ffi.c b/third_party/gofrontend/libffi/src/microblaze/ffi.c
new file mode 100644
index 0000000..ea962ea
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/microblaze/ffi.c
@@ -0,0 +1,321 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2012, 2013 Xilinx, Inc
+
+   MicroBlaze Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+extern void ffi_call_SYSV(void (*)(void*, extended_cif*), extended_cif*,
+		unsigned int, unsigned int, unsigned int*, void (*fn)(void),
+		unsigned int, unsigned int);
+
+extern void ffi_closure_SYSV(void);
+
+#define WORD_SIZE			sizeof(unsigned int)
+#define ARGS_REGISTER_SIZE	(WORD_SIZE * 6)
+#define WORD_ALIGN(x)		ALIGN(x, WORD_SIZE)
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+void ffi_prep_args(void* stack, extended_cif* ecif)
+{
+	unsigned int i;
+	ffi_type** p_arg;
+	void** p_argv;
+	void* stack_args_p = stack;
+
+	p_argv = ecif->avalue;
+
+	if (ecif == NULL || ecif->cif == NULL) {
+		return; /* no description to prepare */
+	}
+
+	if ((ecif->cif->rtype != NULL) &&
+			(ecif->cif->rtype->type == FFI_TYPE_STRUCT))
+	{
+		/* if return type is a struct which is referenced on the stack/reg5,
+		 * by a pointer. Stored the return value pointer in r5.
+		 */
+		char* addr = stack_args_p;
+		memcpy(addr, &(ecif->rvalue), WORD_SIZE);
+		stack_args_p += WORD_SIZE;
+	}
+
+	if (ecif->avalue == NULL) {
+		return; /* no arguments to prepare */
+	}
+
+	for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
+			i++, p_arg++)
+	{
+		size_t size = (*p_arg)->size;
+		int type = (*p_arg)->type;
+		void* value = p_argv[i];
+		char* addr = stack_args_p;
+		int aligned_size = WORD_ALIGN(size);
+
+		/* force word alignment on the stack */
+		stack_args_p += aligned_size;
+		
+		switch (type)
+		{
+			case FFI_TYPE_UINT8:
+				*(unsigned int *)addr = (unsigned int)*(UINT8*)(value);
+				break;
+			case FFI_TYPE_SINT8:
+				*(signed int *)addr = (signed int)*(SINT8*)(value);
+				break;
+			case FFI_TYPE_UINT16:
+				*(unsigned int *)addr = (unsigned int)*(UINT16*)(value);
+				break;
+			case FFI_TYPE_SINT16:
+				*(signed int *)addr = (signed int)*(SINT16*)(value);
+				break;
+			case FFI_TYPE_STRUCT:
+#if __BIG_ENDIAN__
+				/*
+				 * MicroBlaze toolchain appears to emit:
+				 * bsrli r5, r5, 8 (caller)
+				 * ...
+				 * <branch to callee>
+				 * ...
+				 * bslli r5, r5, 8 (callee)
+				 * 
+				 * For structs like "struct a { uint8_t a[3]; };", when passed
+				 * by value.
+				 *
+				 * Structs like "struct b { uint16_t a; };" are also expected
+				 * to be packed strangely in registers.
+				 *
+				 * This appears to be because the microblaze toolchain expects
+				 * "struct b == uint16_t", which is only any issue for big
+				 * endian.
+				 *
+				 * The following is a work around for big-endian only, for the
+				 * above mentioned case, it will re-align the contents of a
+				 * <= 3-byte struct value.
+				 */
+				if (size < WORD_SIZE)
+				{
+				  memcpy (addr + (WORD_SIZE - size), value, size);
+				  break;
+				}
+#endif
+			case FFI_TYPE_SINT32:
+			case FFI_TYPE_UINT32:
+			case FFI_TYPE_FLOAT:
+			case FFI_TYPE_SINT64:
+			case FFI_TYPE_UINT64:
+			case FFI_TYPE_DOUBLE:
+			default:
+				memcpy(addr, value, aligned_size);
+		}
+	}
+}
+
+ffi_status ffi_prep_cif_machdep(ffi_cif* cif)
+{
+	/* check ABI */
+	switch (cif->abi)
+	{
+		case FFI_SYSV:
+			break;
+		default:
+			return FFI_BAD_ABI;
+	}
+	return FFI_OK;
+}
+
+void ffi_call(ffi_cif* cif, void (*fn)(void), void* rvalue, void** avalue)
+{
+	extended_cif ecif;
+	ecif.cif = cif;
+	ecif.avalue = avalue;
+
+	/* If the return value is a struct and we don't have a return */
+	/* value address then we need to make one */
+	if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
+		ecif.rvalue = alloca(cif->rtype->size);
+	} else {
+		ecif.rvalue = rvalue;
+	}
+
+	switch (cif->abi)
+	{
+	case FFI_SYSV:
+		ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags,
+				ecif.rvalue, fn, cif->rtype->type, cif->rtype->size);
+		break;
+	default:
+		FFI_ASSERT(0);
+		break;
+	}
+}
+
+void ffi_closure_call_SYSV(void* register_args, void* stack_args,
+			ffi_closure* closure, void* rvalue,
+			unsigned int* rtype, unsigned int* rsize)
+{
+	/* prepare arguments for closure call */
+	ffi_cif* cif = closure->cif;
+	ffi_type** arg_types = cif->arg_types;
+
+	/* re-allocate data for the args. This needs to be done in order to keep
+	 * multi-word objects (e.g. structs) in contiguous memory. Callers are not
+	 * required to store the value of args in the lower 6 words in the stack
+	 * (although they are allocated in the stack).
+	 */
+	char* stackclone = alloca(cif->bytes);
+	void** avalue = alloca(cif->nargs * sizeof(void*));
+	void* struct_rvalue = NULL;
+	char* ptr = stackclone;
+	int i;
+
+	/* copy registers into stack clone */
+	int registers_used = cif->bytes;
+	if (registers_used > ARGS_REGISTER_SIZE) {
+		registers_used = ARGS_REGISTER_SIZE;
+	}
+	memcpy(stackclone, register_args, registers_used);
+
+	/* copy stack allocated args into stack clone */
+	if (cif->bytes > ARGS_REGISTER_SIZE) {
+		int stack_used = cif->bytes - ARGS_REGISTER_SIZE;
+		memcpy(stackclone + ARGS_REGISTER_SIZE, stack_args, stack_used);
+	}
+
+	/* preserve struct type return pointer passing */
+	if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
+		struct_rvalue = *((void**)ptr);
+		ptr += WORD_SIZE;
+	}
+
+	/* populate arg pointer list */
+	for (i = 0; i < cif->nargs; i++)
+	{
+		switch (arg_types[i]->type)
+		{
+			case FFI_TYPE_SINT8:
+			case FFI_TYPE_UINT8:
+#ifdef __BIG_ENDIAN__
+				avalue[i] = ptr + 3;
+#else
+				avalue[i] = ptr;
+#endif
+				break;
+			case FFI_TYPE_SINT16:
+			case FFI_TYPE_UINT16:
+#ifdef __BIG_ENDIAN__
+				avalue[i] = ptr + 2;
+#else
+				avalue[i] = ptr;
+#endif
+				break;
+			case FFI_TYPE_STRUCT:
+#if __BIG_ENDIAN__
+				/*
+				 * Work around strange ABI behaviour.
+				 * (see info in ffi_prep_args)
+				 */
+				if (arg_types[i]->size < WORD_SIZE)
+				{
+				  memcpy (ptr, ptr + (WORD_SIZE - arg_types[i]->size), arg_types[i]->size);
+				}
+#endif
+				avalue[i] = (void*)ptr;
+				break;
+			case FFI_TYPE_UINT64:
+			case FFI_TYPE_SINT64:
+			case FFI_TYPE_DOUBLE:
+				avalue[i] = ptr;
+				break;
+			case FFI_TYPE_SINT32:
+			case FFI_TYPE_UINT32:
+			case FFI_TYPE_FLOAT:
+			default:
+				/* default 4-byte argument */
+				avalue[i] = ptr;
+				break;
+		}
+		ptr += WORD_ALIGN(arg_types[i]->size);
+	}
+
+	/* set the return type info passed back to the wrapper */
+	*rsize = cif->rtype->size;
+	*rtype = cif->rtype->type;
+	if (struct_rvalue != NULL) {
+		closure->fun(cif, struct_rvalue, avalue, closure->user_data);
+		/* copy struct return pointer value into function return value */
+		*((void**)rvalue) = struct_rvalue;
+	} else {
+		closure->fun(cif, rvalue, avalue, closure->user_data);
+	}
+}
+
+ffi_status ffi_prep_closure_loc(
+		ffi_closure* closure, ffi_cif* cif,
+		void (*fun)(ffi_cif*, void*, void**, void*),
+		void* user_data, void* codeloc)
+{
+	unsigned long* tramp = (unsigned long*)&(closure->tramp[0]);
+	unsigned long cls = (unsigned long)codeloc;
+	unsigned long fn = 0;
+	unsigned long fn_closure_call_sysv = (unsigned long)ffi_closure_call_SYSV;
+
+	closure->cif = cif;
+	closure->fun = fun;
+	closure->user_data = user_data;
+
+	switch (cif->abi)
+	{
+	case FFI_SYSV:
+		fn = (unsigned long)ffi_closure_SYSV;
+
+		/* load r11 (temp) with fn */
+		/* imm fn(upper) */
+		tramp[0] = 0xb0000000 | ((fn >> 16) & 0xffff);
+		/* addik r11, r0, fn(lower) */
+		tramp[1] = 0x31600000 | (fn & 0xffff);
+
+		/* load r12 (temp) with cls */
+		/* imm cls(upper) */
+		tramp[2] = 0xb0000000 | ((cls >> 16) & 0xffff);
+		/* addik r12, r0, cls(lower) */
+		tramp[3] = 0x31800000 | (cls & 0xffff);
+
+		/* load r3 (temp) with ffi_closure_call_SYSV */
+		/* imm fn_closure_call_sysv(upper) */
+		tramp[4] = 0xb0000000 | ((fn_closure_call_sysv >> 16) & 0xffff);
+		/* addik r3, r0, fn_closure_call_sysv(lower) */
+		tramp[5] = 0x30600000 | (fn_closure_call_sysv & 0xffff);
+		/* branch/jump to address stored in r11 (fn) */
+		tramp[6] = 0x98085800; /* bra r11 */
+
+		break;
+	default:
+		return FFI_BAD_ABI;
+	}
+	return FFI_OK;
+}
diff --git a/third_party/gofrontend/libffi/src/microblaze/ffitarget.h b/third_party/gofrontend/libffi/src/microblaze/ffitarget.h
new file mode 100644
index 0000000..c6fa5a4
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/microblaze/ffitarget.h
@@ -0,0 +1,53 @@
+/* -----------------------------------------------------------------------
+   ffitarget.h - Copyright (c) 2012, 2013 Xilinx, Inc
+
+   Target configuration macros for MicroBlaze.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long			ffi_arg;
+typedef signed long			ffi_sarg;
+
+typedef enum ffi_abi {
+	FFI_FIRST_ABI = 0,
+	FFI_SYSV,
+	FFI_LAST_ABI,
+	FFI_DEFAULT_ABI = FFI_SYSV
+} ffi_abi;
+#endif
+
+/* Definitions for closures */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+
+#define FFI_TRAMPOLINE_SIZE (4*8)
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/microblaze/sysv.S b/third_party/gofrontend/libffi/src/microblaze/sysv.S
new file mode 100644
index 0000000..ea43e9d
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/microblaze/sysv.S
@@ -0,0 +1,302 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2012, 2013 Xilinx, Inc
+
+   MicroBlaze Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+	/*
+	 * arg[0] (r5)  = ffi_prep_args,
+	 * arg[1] (r6)  = &ecif,
+	 * arg[2] (r7)  = cif->bytes,
+	 * arg[3] (r8)  = cif->flags,
+	 * arg[4] (r9)  = ecif.rvalue,
+	 * arg[5] (r10) = fn
+	 * arg[6] (sp[0]) = cif->rtype->type
+	 * arg[7] (sp[4]) = cif->rtype->size
+	 */
+	.text
+	.globl ffi_call_SYSV
+	.type ffi_call_SYSV, @function
+ffi_call_SYSV:
+	/* push callee saves */
+	addik r1, r1, -20
+	swi r19, r1, 0 /* Frame Pointer */
+	swi r20, r1, 4 /* PIC register */
+	swi r21, r1, 8 /* PIC register */
+	swi r22, r1, 12 /* save for locals */
+	swi r23, r1, 16 /* save for locals */
+	
+	/* save the r5-r10 registers in the stack */
+	addik r1, r1, -24 /* increment sp to store 6x 32-bit words */
+	swi r5, r1, 0
+	swi r6, r1, 4
+	swi r7, r1, 8
+	swi r8, r1, 12
+	swi r9, r1, 16
+	swi r10, r1, 20
+
+	/* save function pointer */
+	addik r3, r5, 0 /* copy ffi_prep_args into r3 */
+	addik r22, r1, 0 /* save sp for unallocated args into r22 (callee-saved) */
+	addik r23, r10, 0 /* save function address into r23 (callee-saved) */
+
+	/* prepare stack with allocation for n (bytes = r7) args */
+	rsub r1, r7, r1 /* subtract bytes from sp */
+
+	/* prep args for ffi_prep_args call */
+	addik r5, r1, 0 /* store stack pointer into arg[0] */
+	/* r6 still holds ecif for arg[1] */
+
+	/* Call ffi_prep_args(stack, &ecif). */
+	addik r1, r1, -4
+	swi r15, r1, 0 /* store the link register in the frame */
+	brald r15, r3
+	nop /* branch has delay slot */
+	lwi r15, r1, 0
+	addik r1, r1, 4 /* restore the link register from the frame */
+	/* returns calling stack pointer location */
+
+	/* prepare args for fn call, prep_args populates them onto the stack */
+	lwi r5, r1, 0 /* arg[0] */
+	lwi r6, r1, 4 /* arg[1] */
+	lwi r7, r1, 8 /* arg[2] */
+	lwi r8, r1, 12 /* arg[3] */
+	lwi r9, r1, 16 /* arg[4] */
+	lwi r10, r1, 20 /* arg[5] */
+
+	/* call (fn) (...). */
+	addik r1, r1, -4
+	swi r15, r1, 0 /* store the link register in the frame */
+	brald r15, r23
+	nop /* branch has delay slot */
+	lwi r15, r1, 0
+	addik r1, r1, 4 /* restore the link register from the frame */
+
+	/* Remove the space we pushed for the args. */
+	addik r1, r22, 0 /* restore old SP */
+
+	/* restore this functions parameters */
+	lwi r5, r1, 0 /* arg[0] */
+	lwi r6, r1, 4 /* arg[1] */
+	lwi r7, r1, 8 /* arg[2] */
+	lwi r8, r1, 12 /* arg[3] */
+	lwi r9, r1, 16 /* arg[4] */
+	lwi r10, r1, 20 /* arg[5] */
+	addik r1, r1, 24 /* decrement sp to de-allocate 6x 32-bit words */
+
+	/* If the return value pointer is NULL, assume no return value. */
+	beqi r9, ffi_call_SYSV_end
+
+	lwi r22, r1, 48 /* get return type (20 for locals + 28 for arg[6]) */
+	lwi r23, r1, 52 /* get return size (20 for locals + 32 for arg[7])  */
+	
+	/* Check if return type is actually a struct, do nothing */
+	rsubi r11, r22, FFI_TYPE_STRUCT
+	beqi r11, ffi_call_SYSV_end
+
+	/* Return 8bit */
+	rsubi r11, r23, 1
+	beqi r11, ffi_call_SYSV_store8
+
+	/* Return 16bit */
+	rsubi r11, r23, 2
+	beqi r11, ffi_call_SYSV_store16
+
+	/* Return 32bit */
+	rsubi r11, r23, 4
+	beqi r11, ffi_call_SYSV_store32
+
+	/* Return 64bit */
+	rsubi r11, r23, 8
+	beqi r11, ffi_call_SYSV_store64
+
+	/* Didn't match anything */
+	bri ffi_call_SYSV_end
+
+ffi_call_SYSV_store64:
+	swi r3, r9, 0 /* store word r3 into return value */
+	swi r4, r9, 4 /* store word r4 into return value */
+	bri ffi_call_SYSV_end
+
+ffi_call_SYSV_store32:
+	swi r3, r9, 0 /* store word r3 into return value */
+	bri ffi_call_SYSV_end
+
+ffi_call_SYSV_store16:
+#ifdef __BIG_ENDIAN__
+	shi r3, r9, 2 /* store half-word r3 into return value */
+#else
+	shi r3, r9, 0 /* store half-word r3 into return value */
+#endif
+	bri ffi_call_SYSV_end
+
+ffi_call_SYSV_store8:
+#ifdef __BIG_ENDIAN__
+	sbi r3, r9, 3 /* store byte r3 into return value */
+#else
+	sbi r3, r9, 0 /* store byte r3 into return value */
+#endif
+	bri ffi_call_SYSV_end
+
+ffi_call_SYSV_end:
+	/* callee restores */
+	lwi r19, r1, 0 /* frame pointer */
+	lwi r20, r1, 4 /* PIC register */
+	lwi r21, r1, 8 /* PIC register */
+	lwi r22, r1, 12
+	lwi r23, r1, 16
+	addik r1, r1, 20
+
+	/* return from sub-routine (with delay slot) */
+	rtsd r15, 8
+	nop
+
+	.size ffi_call_SYSV, . - ffi_call_SYSV
+
+/* ------------------------------------------------------------------------- */
+
+	/*
+	 * args passed into this function, are passed down to the callee.
+	 * this function is the target of the closure trampoline, as such r12 is 
+	 * a pointer to the closure object.
+	 */
+	.text
+	.globl ffi_closure_SYSV
+	.type ffi_closure_SYSV, @function
+ffi_closure_SYSV:
+	/* push callee saves */
+	addik r11, r1, 28 /* save stack args start location (excluding regs/link) */
+	addik r1, r1, -12
+	swi r19, r1, 0 /* Frame Pointer */
+	swi r20, r1, 4 /* PIC register */
+	swi r21, r1, 8 /* PIC register */
+
+	/* store register args on stack */
+	addik r1, r1, -24
+	swi r5, r1, 0
+	swi r6, r1, 4
+	swi r7, r1, 8
+	swi r8, r1, 12
+	swi r9, r1, 16
+	swi r10, r1, 20
+
+	/* setup args */
+	addik r5, r1, 0 /* register_args */
+	addik r6, r11, 0 /* stack_args */
+	addik r7, r12, 0 /* closure object */
+	addik r1, r1, -8 /* allocate return value */
+	addik r8, r1, 0 /* void* rvalue */
+	addik r1, r1, -8 /* allocate for return type/size values */
+	addik r9, r1, 0 /* void* rtype */
+	addik r10, r1, 4 /* void* rsize */
+
+	/* call the wrap_call function */
+	addik r1, r1, -28 /* allocate args + link reg */
+	swi r15, r1, 0 /* store the link register in the frame */
+	brald r15, r3
+	nop /* branch has delay slot */
+	lwi r15, r1, 0
+	addik r1, r1, 28 /* restore the link register from the frame */
+
+ffi_closure_SYSV_prepare_return:
+	lwi r9, r1, 0 /* rtype */
+	lwi r10, r1, 4 /* rsize */
+	addik r1, r1, 8 /* de-allocate return info values */
+
+	/* Check if return type is actually a struct, store 4 bytes */
+	rsubi r11, r9, FFI_TYPE_STRUCT
+	beqi r11, ffi_closure_SYSV_store32
+
+	/* Return 8bit */
+	rsubi r11, r10, 1
+	beqi r11, ffi_closure_SYSV_store8
+
+	/* Return 16bit */
+	rsubi r11, r10, 2
+	beqi r11, ffi_closure_SYSV_store16
+
+	/* Return 32bit */
+	rsubi r11, r10, 4
+	beqi r11, ffi_closure_SYSV_store32
+
+	/* Return 64bit */
+	rsubi r11, r10, 8
+	beqi r11, ffi_closure_SYSV_store64
+
+	/* Didn't match anything */
+	bri ffi_closure_SYSV_end
+
+ffi_closure_SYSV_store64:
+	lwi r3, r1, 0 /* store word r3 into return value */
+	lwi r4, r1, 4 /* store word r4 into return value */
+	/* 64 bits == 2 words, no sign extend occurs */
+	bri ffi_closure_SYSV_end
+
+ffi_closure_SYSV_store32:
+	lwi r3, r1, 0 /* store word r3 into return value */
+	/* 32 bits == 1 word, no sign extend occurs */
+	bri ffi_closure_SYSV_end
+
+ffi_closure_SYSV_store16:
+#ifdef __BIG_ENDIAN__
+	lhui r3, r1, 2 /* store half-word r3 into return value */
+#else
+	lhui r3, r1, 0 /* store half-word r3 into return value */
+#endif
+	rsubi r11, r9, FFI_TYPE_SINT16
+	bnei r11, ffi_closure_SYSV_end
+	sext16 r3, r3 /* fix sign extend of sint8 */
+	bri ffi_closure_SYSV_end
+
+ffi_closure_SYSV_store8:
+#ifdef __BIG_ENDIAN__
+	lbui r3, r1, 3 /* store byte r3 into return value */
+#else
+	lbui r3, r1, 0 /* store byte r3 into return value */
+#endif
+	rsubi r11, r9, FFI_TYPE_SINT8
+	bnei r11, ffi_closure_SYSV_end
+	sext8 r3, r3 /* fix sign extend of sint8 */
+	bri ffi_closure_SYSV_end
+
+ffi_closure_SYSV_end:
+	addik r1, r1, 8 /* de-allocate return value */
+
+	/* de-allocate stored args */
+	addik r1, r1, 24
+
+	/* callee restores */
+	lwi r19, r1, 0 /* frame pointer */
+	lwi r20, r1, 4 /* PIC register */
+	lwi r21, r1, 8 /* PIC register */
+	addik r1, r1, 12
+
+	/* return from sub-routine (with delay slot) */
+	rtsd r15, 8
+	nop
+
+	.size ffi_closure_SYSV, . - ffi_closure_SYSV
diff --git a/third_party/gofrontend/libffi/src/mips/ffi.c b/third_party/gofrontend/libffi/src/mips/ffi.c
index 03121e3..5d0dd70 100644
--- a/third_party/gofrontend/libffi/src/mips/ffi.c
+++ b/third_party/gofrontend/libffi/src/mips/ffi.c
@@ -170,7 +170,14 @@
 		break;
 		  
 	      case FFI_TYPE_UINT32:
+#ifdef FFI_MIPS_N32
+		/* The N32 ABI requires that 32-bit integers
+		   be sign-extended to 64-bits, regardless of
+		   whether they are signed or unsigned. */
+		*(ffi_arg *)argp = *(SINT32 *)(* p_argv);
+#else
 		*(ffi_arg *)argp = *(UINT32 *)(* p_argv);
+#endif
 		break;
 
 	      /* This can only happen with 64bit slots.  */
diff --git a/third_party/gofrontend/libffi/src/mips/n32.S b/third_party/gofrontend/libffi/src/mips/n32.S
index ff4bbce..c6985d3 100644
--- a/third_party/gofrontend/libffi/src/mips/n32.S
+++ b/third_party/gofrontend/libffi/src/mips/n32.S
@@ -108,10 +108,8 @@
 	REG_L	t6, 3*FFI_SIZEOF_ARG($fp)  # load the flags word into t6.
 
 	and	t4, t6, ((1<<FFI_FLAG_BITS)-1)
-	bnez	t4, arg1_floatp
 	REG_L	a0, 0*FFI_SIZEOF_ARG(t9)
-	b	arg1_next
-arg1_floatp:	
+	beqz	t4, arg1_next
 	bne	t4, FFI_TYPE_FLOAT, arg1_doublep
 	l.s	$f12, 0*FFI_SIZEOF_ARG(t9)
 	b	arg1_next
@@ -121,10 +119,8 @@
 	
 	SRL	t4, t6, 1*FFI_FLAG_BITS
 	and	t4, ((1<<FFI_FLAG_BITS)-1)
-	bnez	t4, arg2_floatp
 	REG_L	a1, 1*FFI_SIZEOF_ARG(t9)
-	b	arg2_next
-arg2_floatp:
+	beqz	t4, arg2_next
 	bne	t4, FFI_TYPE_FLOAT, arg2_doublep
 	l.s	$f13, 1*FFI_SIZEOF_ARG(t9)	
 	b	arg2_next
@@ -134,10 +130,8 @@
 	
 	SRL	t4, t6, 2*FFI_FLAG_BITS
 	and	t4, ((1<<FFI_FLAG_BITS)-1)
-	bnez	t4, arg3_floatp
 	REG_L	a2, 2*FFI_SIZEOF_ARG(t9)
-	b	arg3_next
-arg3_floatp:
+	beqz	t4, arg3_next
 	bne	t4, FFI_TYPE_FLOAT, arg3_doublep
 	l.s	$f14, 2*FFI_SIZEOF_ARG(t9)	
 	b	arg3_next
@@ -147,10 +141,8 @@
 	
 	SRL	t4, t6, 3*FFI_FLAG_BITS
 	and	t4, ((1<<FFI_FLAG_BITS)-1)
-	bnez	t4, arg4_floatp
 	REG_L	a3, 3*FFI_SIZEOF_ARG(t9)
-	b	arg4_next
-arg4_floatp:
+	beqz	t4, arg4_next
 	bne	t4, FFI_TYPE_FLOAT, arg4_doublep
 	l.s	$f15, 3*FFI_SIZEOF_ARG(t9)	
 	b	arg4_next
@@ -160,10 +152,8 @@
 	
 	SRL	t4, t6, 4*FFI_FLAG_BITS
 	and	t4, ((1<<FFI_FLAG_BITS)-1)
-	bnez	t4, arg5_floatp
 	REG_L	a4, 4*FFI_SIZEOF_ARG(t9)
-	b	arg5_next
-arg5_floatp:
+	beqz	t4, arg5_next
 	bne	t4, FFI_TYPE_FLOAT, arg5_doublep
 	l.s	$f16, 4*FFI_SIZEOF_ARG(t9)	
 	b	arg5_next
@@ -173,10 +163,8 @@
 	
 	SRL	t4, t6, 5*FFI_FLAG_BITS
 	and	t4, ((1<<FFI_FLAG_BITS)-1)
-	bnez	t4, arg6_floatp
 	REG_L	a5, 5*FFI_SIZEOF_ARG(t9)
-	b	arg6_next
-arg6_floatp:
+	beqz	t4, arg6_next
 	bne	t4, FFI_TYPE_FLOAT, arg6_doublep
 	l.s	$f17, 5*FFI_SIZEOF_ARG(t9)	
 	b	arg6_next
@@ -186,10 +174,8 @@
 	
 	SRL	t4, t6, 6*FFI_FLAG_BITS
 	and	t4, ((1<<FFI_FLAG_BITS)-1)
-	bnez	t4, arg7_floatp
 	REG_L	a6, 6*FFI_SIZEOF_ARG(t9)
-	b	arg7_next
-arg7_floatp:
+	beqz	t4, arg7_next
 	bne	t4, FFI_TYPE_FLOAT, arg7_doublep
 	l.s	$f18, 6*FFI_SIZEOF_ARG(t9)	
 	b	arg7_next
@@ -199,10 +185,8 @@
 	
 	SRL	t4, t6, 7*FFI_FLAG_BITS
 	and	t4, ((1<<FFI_FLAG_BITS)-1)
-	bnez	t4, arg8_floatp
 	REG_L	a7, 7*FFI_SIZEOF_ARG(t9)
-	b	arg8_next
-arg8_floatp:
+	beqz	t4, arg8_next
 	bne	t4, FFI_TYPE_FLOAT, arg8_doublep
  	l.s	$f19, 7*FFI_SIZEOF_ARG(t9)	
 	b	arg8_next
diff --git a/third_party/gofrontend/libffi/src/moxie/eabi.S b/third_party/gofrontend/libffi/src/moxie/eabi.S
new file mode 100644
index 0000000..ac7aceb
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/moxie/eabi.S
@@ -0,0 +1,101 @@
+/* -----------------------------------------------------------------------
+   eabi.S - Copyright (c) 2012, 2013  Anthony Green
+   
+   Moxie Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+	.globl ffi_prep_args_EABI
+
+	.text
+	.p2align 4
+	.globl ffi_call_EABI
+	.type ffi_call_EABI, @function
+
+	# $r0 :   ffi_prep_args
+	# $r1 :   &ecif
+	# $r2 :   cif->bytes
+	# $r3 :   fig->flags
+	# $r4 :   ecif.rvalue
+	# $r5 :   fn
+	
+ffi_call_EABI:
+	push	$sp, $r6
+	push	$sp, $r7
+	push	$sp, $r8
+	dec	$sp, 24
+
+	/* Store incoming args on stack.  */
+	sto.l	0($sp), $r0 /* ffi_prep_args */
+	sto.l	4($sp), $r1 /* ecif */
+	sto.l	8($sp), $r2 /* bytes */
+	sto.l	12($sp), $r3 /* flags */
+	sto.l	16($sp), $r4 /* &rvalue */
+	sto.l	20($sp), $r5 /* fn */
+	
+	/* Call ffi_prep_args.  */
+	mov 	$r6, $r4 /* Save result buffer */
+	mov	$r7, $r5 /* Save the target fn */
+	mov	$r8, $r3 /* Save the flags */
+	sub.l	$sp, $r2 /* Allocate stack space */
+	mov	$r0, $sp /* We can stomp over $r0 */
+	/* $r1 is already set up */
+	jsra 	ffi_prep_args
+
+	/* Load register arguments.  */
+	ldo.l	$r0, 0($sp)
+	ldo.l	$r1, 4($sp)
+	ldo.l	$r2, 8($sp)
+	ldo.l	$r3, 12($sp)
+	ldo.l	$r4, 16($sp)
+	ldo.l	$r5, 20($sp)
+	
+	/* Call the target function.  */
+	jsr	$r7
+
+	ldi.l	$r7, 0xffffffff
+	cmp	$r8, $r7
+	beq	retstruct
+
+	ldi.l	$r7, 4
+	cmp	$r8, $r7
+	bgt	ret2reg
+
+	st.l	($r6), $r0
+	jmpa	retdone
+
+ret2reg:	
+	st.l	($r6), $r0
+	sto.l	4($r6), $r1
+
+retstruct:
+retdone:	
+	/* Return.  */
+	ldo.l	$r6, -4($fp)
+	ldo.l	$r7, -8($fp)
+	ldo.l	$r8, -12($fp)
+	ret
+	.size ffi_call_EABI, .-ffi_call_EABI
+	
diff --git a/third_party/gofrontend/libffi/src/moxie/ffi.c b/third_party/gofrontend/libffi/src/moxie/ffi.c
new file mode 100644
index 0000000..540a042
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/moxie/ffi.c
@@ -0,0 +1,272 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (C) 2012, 2013  Anthony Green
+   
+   Moxie Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+void *ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+  register int count = 0;
+
+  p_argv = ecif->avalue;
+  argp = stack;
+
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += 4;
+    }
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0);
+       i--, p_arg++)
+    {
+      size_t z;
+      
+      z = (*p_arg)->size;
+
+      if ((*p_arg)->type == FFI_TYPE_STRUCT)
+	{
+	  z = sizeof(void*);
+	  *(void **) argp = *p_argv;
+	} 
+      else if (z < sizeof(int))
+	{
+	  z = sizeof(int);
+	  switch ((*p_arg)->type)
+	    {
+	    case FFI_TYPE_SINT8:
+	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+	      break;
+	      
+	    case FFI_TYPE_UINT8:
+	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+	      break;
+	      
+	    case FFI_TYPE_SINT16:
+	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+	      break;
+		  
+	    case FFI_TYPE_UINT16:
+	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+	      break;
+		  
+	    default:
+	      FFI_ASSERT(0);
+	    }
+	}
+      else if (z == sizeof(int))
+	{
+	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+	}
+      else
+	{
+	  memcpy(argp, *p_argv, z);
+	}
+      p_argv++;
+      argp += z;
+      count += z;
+    }
+
+  return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    cif->flags = -1;
+  else
+    cif->flags = cif->rtype->size;
+
+  cif->bytes = ALIGN (cif->bytes, 8);
+
+  return FFI_OK;
+}
+
+extern void ffi_call_EABI(void *(*)(char *, extended_cif *), 
+			  extended_cif *, 
+			  unsigned, unsigned, 
+			  unsigned *, 
+			  void (*fn)(void));
+
+void ffi_call(ffi_cif *cif, 
+	      void (*fn)(void), 
+	      void *rvalue, 
+	      void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return	*/
+  /* value address then we need to make one		        */
+
+  if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi) 
+    {
+    case FFI_EABI:
+      ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes, 
+		    cif->flags, ecif.rvalue, fn);
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
+		       unsigned arg4, unsigned arg5, unsigned arg6)
+{
+  /* This function is called by a trampoline.  The trampoline stows a
+     pointer to the ffi_closure object in $r7.  We must save this
+     pointer in a place that will persist while we do our work.  */
+  register ffi_closure *creg __asm__ ("$r12");
+  ffi_closure *closure = creg;
+
+  /* Arguments that don't fit in registers are found on the stack
+     at a fixed offset above the current frame pointer.  */
+  register char *frame_pointer __asm__ ("$fp");
+
+  /* Pointer to a struct return value.  */
+  void *struct_rvalue = (void *) arg1;
+
+  /* 6 words reserved for register args + 3 words from jsr */
+  char *stack_args = frame_pointer + 9*4; 
+
+  /* Lay the register arguments down in a continuous chunk of memory.  */
+  unsigned register_args[6] =
+    { arg1, arg2, arg3, arg4, arg5, arg6 };
+  char *register_args_ptr = (char *) register_args;
+
+  ffi_cif *cif = closure->cif;
+  ffi_type **arg_types = cif->arg_types;
+  void **avalue = alloca (cif->nargs * sizeof(void *));
+  char *ptr = (char *) register_args;
+  int i;
+
+  /* preserve struct type return pointer passing */
+  if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
+    ptr += 4;
+    register_args_ptr = (char *)&register_args[1];
+  }
+
+  /* Find the address of each argument.  */
+  for (i = 0; i < cif->nargs; i++)
+    {
+      switch (arg_types[i]->type)
+	{
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT8:
+	  avalue[i] = ptr + 3;
+	  break;
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+	  avalue[i] = ptr + 2;
+	  break;
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_POINTER:
+	  avalue[i] = ptr;
+	  break;
+	case FFI_TYPE_STRUCT:
+	  avalue[i] = *(void**)ptr;
+	  break;
+	default:
+	  /* This is an 8-byte value.  */
+	  avalue[i] = ptr;
+	  ptr += 4;
+	  break;
+	}
+      ptr += 4;
+
+      /* If we've handled more arguments than fit in registers,
+	 start looking at the those passed on the stack.  */
+      if (ptr == &register_args[6])
+	ptr = stack_args;
+    }
+
+  /* Invoke the closure.  */
+  if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      (closure->fun) (cif, struct_rvalue, avalue, closure->user_data);
+    }
+  else
+    {
+      /* Allocate space for the return value and call the function.  */
+      long long rvalue;
+      (closure->fun) (cif, &rvalue, avalue, closure->user_data);
+      asm ("mov $r12, %0\n ld.l $r0, ($r12)\n ldo.l $r1, 4($r12)" : : "r" (&rvalue));
+    }
+}
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*, void*, void**, void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  unsigned short *tramp = (unsigned short *) &closure->tramp[0];
+  unsigned long fn = (long) ffi_closure_eabi;
+  unsigned long cls = (long) codeloc;
+
+  if (cif->abi != FFI_EABI)
+    return FFI_BAD_ABI;
+
+  fn = (unsigned long) ffi_closure_eabi;
+
+  tramp[0] = 0x01e0; /* ldi.l $r7, .... */
+  tramp[1] = cls >> 16;
+  tramp[2] = cls & 0xffff;
+  tramp[3] = 0x1a00; /* jmpa .... */
+  tramp[4] = fn >> 16;
+  tramp[5] = fn & 0xffff;
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  return FFI_OK;
+}
diff --git a/third_party/gofrontend/libffi/src/moxie/ffitarget.h b/third_party/gofrontend/libffi/src/moxie/ffitarget.h
new file mode 100644
index 0000000..623e3ec
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/moxie/ffitarget.h
@@ -0,0 +1,52 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2012, 2013  Anthony Green
+   Target configuration macros for Moxie
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+/* ---- System specific configurations ----------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_EABI,
+  FFI_DEFAULT_ABI = FFI_EABI,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+
+/* Trampolines are 12-bytes long.  See ffi_prep_closure_loc.  */
+#define FFI_TRAMPOLINE_SIZE (12)
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/nios2/ffi.c b/third_party/gofrontend/libffi/src/nios2/ffi.c
new file mode 100644
index 0000000..2efa033
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/nios2/ffi.c
@@ -0,0 +1,304 @@
+/* libffi support for Altera Nios II.
+
+   Copyright (c) 2013 Mentor Graphics.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+   
+   The above copyright notice and this permission notice shall be
+   included in all copies or substantial portions of the Software.
+   
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* The Nios II Processor Reference Handbook defines the procedure call
+   ABI as follows.
+
+   Arguments are passed as if a structure containing the types of
+   the arguments were constructed.  The first 16 bytes are passed in r4
+   through r7, the remainder on the stack.  The first 16 bytes of a function
+   taking variable arguments are passed in r4-r7 in the same way.
+
+   Return values of types up to 8 bytes are returned in r2 and r3.  For
+   return values greater than 8 bytes, the caller must allocate memory for
+   the result and pass the address as if it were argument 0.  
+
+   While this isn't specified explicitly in the ABI documentation, GCC
+   promotes integral arguments smaller than int size to 32 bits.
+
+   Also of note, the ABI specifies that all structure objects are
+   aligned to 32 bits even if all their fields have a smaller natural
+   alignment.  See FFI_AGGREGATE_ALIGNMENT.  */
+
+
+/* Declare the assembly language hooks.  */
+
+extern UINT64 ffi_call_sysv (void (*) (char *, extended_cif *),
+			     extended_cif *,
+			     unsigned, 
+			     void (*fn) (void));
+extern void ffi_closure_sysv (void);
+
+/* Perform machine-dependent cif processing.  */
+
+ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  /* We always want at least 16 bytes in the parameter block since it
+     simplifies the low-level call function.  Also round the parameter
+     block size up to a multiple of 4 bytes to preserve
+     32-bit alignment of the stack pointer.  */
+  if (cif->bytes < 16)
+    cif->bytes = 16;
+  else
+    cif->bytes = (cif->bytes + 3) & ~3;
+
+  return FFI_OK;
+}
+
+
+/* ffi_prep_args is called by the assembly routine to transfer arguments
+   to the stack using the pointers in the ecif array.
+   Note that the stack buffer is big enough to fit all the arguments,
+   but the first 16 bytes will be copied to registers for the actual
+   call.  */
+
+void ffi_prep_args (char *stack, extended_cif *ecif)
+{
+  char *argp = stack;
+  unsigned int i;
+
+  /* The implicit return value pointer is passed as if it were a hidden
+     first argument.  */
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
+      && ecif->cif->rtype->size > 8)
+    {
+      (*(void **) argp) = ecif->rvalue;
+      argp += 4;
+    }
+
+  for (i = 0; i < ecif->cif->nargs; i++)
+    {
+      void *avalue = ecif->avalue[i];
+      ffi_type *atype = ecif->cif->arg_types[i];
+      size_t size = atype->size;
+      size_t alignment = atype->alignment;
+
+      /* Align argp as appropriate for the argument type.  */
+      if ((alignment - 1) & (unsigned) argp)
+	argp = (char *) ALIGN (argp, alignment);
+
+      /* Copy the argument, promoting integral types smaller than a
+	 word to word size.  */
+      if (size < sizeof (int))
+	{
+	  size = sizeof (int);
+	  switch (atype->type)
+	    {
+	    case FFI_TYPE_SINT8:
+	      *(signed int *) argp = (signed int) *(SINT8 *) avalue;
+	      break;
+		  
+	    case FFI_TYPE_UINT8:
+	      *(unsigned int *) argp = (unsigned int) *(UINT8 *) avalue;
+	      break;
+		  
+	    case FFI_TYPE_SINT16:
+	      *(signed int *) argp = (signed int) *(SINT16 *) avalue;
+	      break;
+		  
+	    case FFI_TYPE_UINT16:
+	      *(unsigned int *) argp = (unsigned int) *(UINT16 *) avalue;
+	      break;
+
+	    case FFI_TYPE_STRUCT:
+	      memcpy (argp, avalue, atype->size);
+	      break;
+
+	    default:
+	      FFI_ASSERT(0);
+	    }
+	}
+      else if (size == sizeof (int))
+	*(unsigned int *) argp = (unsigned int) *(UINT32 *) avalue;
+      else
+	memcpy (argp, avalue, size);
+      argp += size;
+    }
+}
+
+
+/* Call FN using the prepared CIF.  RVALUE points to space allocated by
+   the caller for the return value, and AVALUE is an array of argument
+   pointers.  */
+
+void ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
+{
+
+  extended_cif ecif;
+  UINT64 result;
+
+  /* If bigret is true, this is the case where a return value of larger
+     than 8 bytes is handled by being passed by reference as an implicit
+     argument.  */
+  int bigret = (cif->rtype->type == FFI_TYPE_STRUCT
+		&& cif->rtype->size > 8);
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* Allocate space for return value if this is the pass-by-reference case
+     and the caller did not provide a buffer.  */
+  if (rvalue == NULL && bigret)
+    ecif.rvalue = alloca (cif->rtype->size);
+  else
+    ecif.rvalue = rvalue;
+
+  result = ffi_call_sysv (ffi_prep_args, &ecif, cif->bytes, fn);
+
+  /* Now result contains the 64 bit contents returned from fn in
+     r2 and r3.  Copy the value of the appropriate size to the user-provided
+     rvalue buffer.  */
+  if (rvalue && !bigret)
+    switch (cif->rtype->size)
+      {
+      case 1:
+	*(UINT8 *)rvalue = (UINT8) result;
+	break;
+      case 2:
+	*(UINT16 *)rvalue = (UINT16) result;
+	break;
+      case 4:
+	*(UINT32 *)rvalue = (UINT32) result;
+	break;
+      case 8:
+	*(UINT64 *)rvalue = (UINT64) result;
+	break;
+      default:
+	memcpy (rvalue, (void *)&result, cif->rtype->size);
+	break;
+      }
+}
+
+/* This function is invoked from the closure trampoline to invoke
+   CLOSURE with argument block ARGS.  Parse ARGS according to
+   CLOSURE->cfi and invoke CLOSURE->fun.  */
+
+static UINT64
+ffi_closure_helper (unsigned char *args,
+		    ffi_closure *closure)
+{
+  ffi_cif *cif = closure->cif;
+  unsigned char *argp = args;
+  void **parsed_args = alloca (cif->nargs * sizeof (void *));
+  UINT64 result;
+  void *retptr;
+  unsigned int i;
+
+  /* First figure out what to do about the return type.  If this is the
+     big-structure-return case, the first arg is the hidden return buffer
+     allocated by the caller.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+      && cif->rtype->size > 8)
+    {
+      retptr = *((void **) argp);
+      argp += 4;
+    }
+  else
+    retptr = (void *) &result;
+
+  /* Fill in the array of argument pointers.  */
+  for (i = 0; i < cif->nargs; i++)
+    {
+      size_t size = cif->arg_types[i]->size;
+      size_t alignment = cif->arg_types[i]->alignment;
+
+      /* Align argp as appropriate for the argument type.  */
+      if ((alignment - 1) & (unsigned) argp)
+	argp = (char *) ALIGN (argp, alignment);
+
+      /* Arguments smaller than an int are promoted to int.  */
+      if (size < sizeof (int))
+	size = sizeof (int);
+
+      /* Store the pointer.  */
+      parsed_args[i] = argp;
+      argp += size;
+    }
+
+  /* Call the user-supplied function.  */
+  (closure->fun) (cif, retptr, parsed_args, closure->user_data);
+  return result;
+}
+
+
+/* Initialize CLOSURE with a trampoline to call FUN with
+   CIF and USER_DATA.  */
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun) (ffi_cif*, void*, void**, void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
+  int i;
+
+  if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+  /* The trampoline looks like:
+       movhi r8, %hi(ffi_closure_sysv)
+       ori r8, r8, %lo(ffi_closure_sysv)
+       movhi r9, %hi(ffi_closure_helper)
+       ori r0, r9, %lo(ffi_closure_helper)
+       movhi r10, %hi(closure)
+       ori r10, r10, %lo(closure)
+       jmp r8
+     and then ffi_closure_sysv retrieves the closure pointer out of r10
+     in addition to the arguments passed in the normal way for the call,
+     and invokes ffi_closure_helper.  We encode the pointer to
+     ffi_closure_helper in the trampoline because making a PIC call
+     to it in ffi_closure_sysv would be messy (it would have to indirect
+     through the GOT).  */
+
+#define HI(x) ((((unsigned int) (x)) >> 16) & 0xffff)
+#define LO(x) (((unsigned int) (x)) & 0xffff)
+  tramp[0] = (0 << 27) | (8 << 22) | (HI (ffi_closure_sysv) << 6) | 0x34;
+  tramp[1] = (8 << 27) | (8 << 22) | (LO (ffi_closure_sysv) << 6) | 0x14;
+  tramp[2] = (0 << 27) | (9 << 22) | (HI (ffi_closure_helper) << 6) | 0x34;
+  tramp[3] = (9 << 27) | (9 << 22) | (LO (ffi_closure_helper) << 6) | 0x14;
+  tramp[4] = (0 << 27) | (10 << 22) | (HI (closure) << 6) | 0x34;
+  tramp[5] = (10 << 27) | (10 << 22) | (LO (closure) << 6) | 0x14;
+  tramp[6] = (8 << 27) | (0x0d << 11) | 0x3a;
+#undef HI
+#undef LO
+
+  /* Flush the caches.
+     See Example 9-4 in the Nios II Software Developer's Handbook.  */
+  for (i = 0; i < 7; i++)
+    asm volatile ("flushd 0(%0); flushi %0" :: "r"(tramp + i) : "memory");
+  asm volatile ("flushp" ::: "memory");
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  return FFI_OK;
+}
+
diff --git a/third_party/gofrontend/libffi/src/nios2/ffitarget.h b/third_party/gofrontend/libffi/src/nios2/ffitarget.h
new file mode 100644
index 0000000..134d118
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/nios2/ffitarget.h
@@ -0,0 +1,52 @@
+/* libffi target includes for Altera Nios II.
+
+   Copyright (c) 2013 Mentor Graphics.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+   
+   The above copyright notice and this permission notice shall be
+   included in all copies or substantial portions of the Software.
+   
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_SYSV
+} ffi_abi;
+#endif
+
+/* Structures have a 4-byte alignment even if all the fields have lesser
+   alignment requirements.  */
+#define FFI_AGGREGATE_ALIGNMENT 4
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 28   /* 7 instructions */
+#define FFI_NATIVE_RAW_API 0
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/nios2/sysv.S b/third_party/gofrontend/libffi/src/nios2/sysv.S
new file mode 100644
index 0000000..75f442b
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/nios2/sysv.S
@@ -0,0 +1,136 @@
+/* Low-level libffi support for Altera Nios II.
+
+   Copyright (c) 2013 Mentor Graphics.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+   
+   The above copyright notice and this permission notice shall be
+   included in all copies or substantial portions of the Software.
+   
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+
+/* This function is declared on the C side as 
+
+   extern UINT64 ffi_call_sysv (void (*arghook) (char *, extended_cif *),
+	  		        extended_cif *ecif,
+				unsigned nbytes, 
+				void (*fn) (void));
+	
+   On input, the arguments appear as
+	r4 = arghook
+	r5 = ecif
+	r6 = nbytes
+	r7 = fn
+*/
+
+	.section	.text
+	.align	2
+	.global	ffi_call_sysv
+	.type	ffi_call_sysv, @function
+
+ffi_call_sysv:
+	.cfi_startproc
+
+	/* Create the stack frame, saving r16 so we can use it locally.  */
+	addi	sp, sp, -12
+	.cfi_def_cfa_offset 12
+	stw	ra, 8(sp)
+	stw	fp, 4(sp)
+	stw	r16, 0(sp)
+	.cfi_offset 31, -4
+	.cfi_offset 28, -8
+	.cfi_offset 16, -12
+	mov	fp, sp
+	.cfi_def_cfa_register 28
+	mov	r16, r7
+
+	/* Adjust the stack pointer to create the argument buffer
+	   nbytes long.  */
+	sub	sp, sp, r6
+
+	/* Call the arghook function.  */
+	mov	r2, r4		/* fn */
+	mov	r4, sp		/* argbuffer */
+	callr	r2		/* r5 already contains ecif */
+
+	/* Pop off the first 16 bytes of the argument buffer on the stack,
+	   transferring the contents to the argument registers.  */
+	ldw	r4, 0(sp)
+	ldw	r5, 4(sp)
+	ldw	r6, 8(sp)
+	ldw	r7, 12(sp)
+	addi	sp, sp, 16
+
+	/* Call the user function, which leaves its result in r2 and r3.  */
+	callr	r16
+
+	/* Pop off the stack frame.  */
+	mov	sp, fp
+	ldw	ra, 8(sp)
+	ldw	fp, 4(sp)
+	ldw	r16, 0(sp)
+	addi	sp, sp, 12
+	ret
+	.cfi_endproc
+	.size	ffi_call_sysv, .-ffi_call_sysv
+
+
+/* Closure trampolines jump here after putting the C helper address
+   in r9 and the closure pointer in r10.  The user-supplied arguments
+   to the closure are in the normal places, in r4-r7 and on the
+   stack.  Push the register arguments on the stack too and then call the
+   C helper function to deal with them.  */
+   
+	.section	.text
+	.align	2
+	.global	ffi_closure_sysv
+	.type	ffi_closure_sysv, @function
+
+ffi_closure_sysv:
+	.cfi_startproc
+
+	/* Create the stack frame, pushing the register args on the stack
+	   just below the stack args.  This is the same trick illustrated
+	   in Figure 7-3 in the Nios II Processor Reference Handbook, used
+	   for variable arguments and structures passed by value.  */
+	addi	sp, sp, -20
+	.cfi_def_cfa_offset 20
+	stw	ra, 0(sp)
+	.cfi_offset 31, -20
+	stw	r4, 4(sp)
+	.cfi_offset 4, -16
+	stw	r5, 8(sp)
+	.cfi_offset 5, -12
+	stw	r6, 12(sp)
+	.cfi_offset 6, -8
+	stw	r7, 16(sp)
+	.cfi_offset 7, -4
+
+	/* Call the helper.
+	   r4 = pointer to arguments on stack
+	   r5 = closure pointer (loaded in r10 by the trampoline)
+	   r9 = address of helper function (loaded by trampoline) */
+	addi	r4, sp, 4
+	mov	r5, r10
+	callr	r9
+	
+	/* Pop the stack and return.  */
+	ldw	ra, 0(sp)
+	addi	sp, sp, 20
+	.cfi_def_cfa_offset -20
+	ret
+	.cfi_endproc
+	.size	ffi_closure_sysv, .-ffi_closure_sysv
+
diff --git a/third_party/gofrontend/libffi/src/or1k/ffi.c b/third_party/gofrontend/libffi/src/or1k/ffi.c
new file mode 100644
index 0000000..2bad938
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/or1k/ffi.c
@@ -0,0 +1,328 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2014 Sebastian Macke <sebastian@macke.de>
+
+   OpenRISC Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include "ffi_common.h"
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+void* ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  char *stacktemp = stack;
+  int i, s;
+  ffi_type **arg;
+  int count = 0;
+  int nfixedargs;
+  
+  nfixedargs = ecif->cif->nfixedargs;
+  arg = ecif->cif->arg_types;
+  void **argv = ecif->avalue;
+
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      *(void **) stack = ecif->rvalue;
+      stack += 4;
+      count = 4;
+    } 
+  for(i=0; i<ecif->cif->nargs; i++)
+  {
+
+    /* variadic args are saved on stack */
+    if ((nfixedargs == 0) && (count < 24))
+      {
+        count = 24;
+        stack = stacktemp + 24;        
+      }
+    nfixedargs--;
+
+    s = 4;
+    switch((*arg)->type) 
+      {
+      case FFI_TYPE_STRUCT:
+        *(void **)stack = *argv;
+        break;
+
+      case FFI_TYPE_SINT8:
+        *(signed int *) stack = (signed int)*(SINT8 *)(* argv);
+        break;
+
+      case FFI_TYPE_UINT8:
+        *(unsigned int *) stack = (unsigned int)*(UINT8 *)(* argv);
+        break;
+
+      case FFI_TYPE_SINT16:
+        *(signed int *) stack = (signed int)*(SINT16 *)(* argv);
+        break;
+
+      case FFI_TYPE_UINT16:
+        *(unsigned int *) stack = (unsigned int)*(UINT16 *)(* argv);
+        break;
+
+      case FFI_TYPE_SINT32:
+      case FFI_TYPE_UINT32:
+      case FFI_TYPE_FLOAT:
+      case FFI_TYPE_POINTER:
+        *(int *)stack = *(int*)(*argv);
+        break;
+
+      default: /* 8 byte types */
+        if (count == 20) /* never split arguments */
+          {
+            stack += 4;
+            count += 4;
+          }  
+        s = (*arg)->size;
+        memcpy(stack, *argv, s);
+        break;
+      }
+
+    stack += s;
+    count += s;
+    argv++;
+    arg++;
+  }
+  return stacktemp + ((count>24)?24:0);
+}
+
+extern void ffi_call_SYSV(unsigned,
+                          extended_cif *,
+                          void *(*)(int *, extended_cif *),
+                          unsigned *,
+                          void (*fn)(void),
+                          unsigned);
+
+
+void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  int i;
+  int size;
+  ffi_type **arg;
+
+  /* Calculate size to allocate on stack */
+
+  for(i = 0, arg = cif->arg_types, size=0; i < cif->nargs; i++, arg++)
+    {
+      if ((*arg)->type == FFI_TYPE_STRUCT)
+        size += 4;
+      else
+      if ((*arg)->size <= 4)
+        size += 4;
+      else
+        size += 8;
+    }
+
+  /* for variadic functions more space is needed on the stack */
+  if (cif->nargs != cif->nfixedargs)
+    size += 24;
+
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    size += 4;
+
+
+  extended_cif ecif;
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  ecif.rvalue = rvalue;
+
+  switch (cif->abi) 
+  {
+    case FFI_SYSV:
+      ffi_call_SYSV(size, &ecif, ffi_prep_args, rvalue, fn, cif->flags);
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+  }
+}
+
+
+void ffi_closure_SYSV(unsigned long r3, unsigned long r4, unsigned long r5, 
+                      unsigned long r6, unsigned long r7, unsigned long r8)
+{
+  register int *sp __asm__ ("r17");
+  register int *r13 __asm__ ("r13");
+
+  ffi_closure* closure = (ffi_closure*) r13;
+  char *stack_args = sp;
+
+  /* Lay the register arguments down in a continuous chunk of memory.  */
+  unsigned register_args[6] =
+    { r3, r4, r5, r6, r7, r8 };
+
+  /* Pointer to a struct return value.  */
+  void *struct_rvalue = (void *) r3;
+
+  ffi_cif *cif = closure->cif;
+  ffi_type **arg_types = cif->arg_types;
+  void **avalue = alloca (cif->nargs * sizeof(void *));
+  char *ptr = (char *) register_args;
+  int count = 0;
+  int nfixedargs = cif->nfixedargs;
+  int i;
+
+  /* preserve struct type return pointer passing */
+
+  if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) 
+  {
+    ptr += 4;
+    count = 4;
+  }
+
+  /* Find the address of each argument.  */
+  for (i = 0; i < cif->nargs; i++)
+    {
+
+      /* variadic args are saved on stack */
+      if ((nfixedargs == 0) && (count < 24))
+        {
+          ptr = stack_args;
+          count = 24;
+        }
+      nfixedargs--;
+
+      switch (arg_types[i]->type)
+        {
+        case FFI_TYPE_SINT8:
+        case FFI_TYPE_UINT8:
+          avalue[i] = ptr + 3;
+          break;
+
+        case FFI_TYPE_SINT16:
+        case FFI_TYPE_UINT16:
+          avalue[i] = ptr + 2;
+          break;
+
+        case FFI_TYPE_SINT32:
+        case FFI_TYPE_UINT32:
+        case FFI_TYPE_FLOAT:
+        case FFI_TYPE_POINTER:
+          avalue[i] = ptr;
+          break;
+
+        case FFI_TYPE_STRUCT:
+          avalue[i] = *(void**)ptr;
+          break;
+
+        default:
+          /* 8-byte values  */
+
+          /* arguments are never splitted */
+          if (ptr == &register_args[5])
+            ptr = stack_args;
+          avalue[i] = ptr;
+          ptr += 4;
+          count += 4;
+          break;
+        }
+      ptr += 4;
+      count += 4;
+
+      /* If we've handled more arguments than fit in registers,
+         start looking at the those passed on the stack.  */
+
+      if (count == 24)
+        ptr = stack_args;
+    }
+
+  if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      (closure->fun) (cif, struct_rvalue, avalue, closure->user_data);
+    } else
+    {
+      long long rvalue;
+      (closure->fun) (cif, &rvalue, avalue, closure->user_data);
+      if (cif->rtype)
+        asm ("l.ori r12, %0, 0x0\n l.lwz r11, 0(r12)\n l.lwz r12, 4(r12)" : : "r" (&rvalue));      
+    }
+}
+
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+                      ffi_cif* cif,
+                      void (*fun)(ffi_cif*,void*,void**,void*),
+                      void *user_data,
+                      void *codeloc)
+{
+  unsigned short *tramp = (unsigned short *) closure->tramp;
+  unsigned long fn = (unsigned long) ffi_closure_SYSV;
+  unsigned long cls = (unsigned long) codeloc;
+
+  if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+  closure->cif = cif;
+  closure->user_data = user_data;
+  closure->fun = fun;
+
+  /* write pointers to temporary registers */
+  tramp[0] = (0x6 << 10) | (13 << 5); /* l.movhi r13, ... */
+  tramp[1] = cls >> 16;
+  tramp[2] = (0x2a << 10) | (13 << 5) | 13; /* l.ori r13, r13, ... */
+  tramp[3] = cls & 0xFFFF;
+
+  tramp[4] = (0x6 << 10) | (15 << 5); /* l.movhi r15, ... */
+  tramp[5] = fn >> 16;
+  tramp[6] = (0x2a << 10) | (15 << 5) | 15; /* l.ori r15, r15 ... */
+  tramp[7] = fn & 0xFFFF;
+
+  tramp[8] = (0x11 << 10); /* l.jr r15 */
+  tramp[9] = 15 << 11;
+
+  tramp[10] = (0x2a << 10) | (17 << 5) | 1; /* l.ori r17, r1, ... */
+  tramp[11] = 0x0;
+
+  return FFI_OK;
+}
+
+
+ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  cif->flags = 0;
+	
+  /* structures are returned as pointers */
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    cif->flags = FFI_TYPE_STRUCT;
+  else 
+  if (cif->rtype->size > 4)
+    cif->flags = FFI_TYPE_UINT64;
+
+  cif->nfixedargs = cif->nargs;
+
+  return FFI_OK;
+}
+
+
+ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
+         unsigned int nfixedargs, unsigned int ntotalargs)
+{
+  ffi_status status;
+
+  status = ffi_prep_cif_machdep (cif);
+  cif->nfixedargs = nfixedargs;
+  return status;
+} 
diff --git a/third_party/gofrontend/libffi/src/or1k/ffitarget.h b/third_party/gofrontend/libffi/src/or1k/ffitarget.h
new file mode 100644
index 0000000..e55da28
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/or1k/ffitarget.h
@@ -0,0 +1,58 @@
+/* -----------------------------------------------------------------------
+   ffitarget.h - Copyright (c) 2014 Sebastian Macke <sebastian@macke.de>
+
+   OpenRISC Target configuration macros
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
+#endif
+
+/* ---- System specific configurations ----------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_SYSV
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+#define FFI_TRAMPOLINE_SIZE (24)
+
+#define FFI_TARGET_SPECIFIC_VARIADIC 1
+#define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs;
+
+#endif
+
diff --git a/third_party/gofrontend/libffi/src/or1k/sysv.S b/third_party/gofrontend/libffi/src/or1k/sysv.S
new file mode 100644
index 0000000..df6570b
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/or1k/sysv.S
@@ -0,0 +1,107 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2014 Sebastian Macke <sebastian@macke.de>
+
+   OpenRISC Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+.text
+	.globl ffi_call_SYSV
+	.type ffi_call_SYSV, @function
+/*
+  r3: size to allocate on stack
+  r4: extended cif structure
+  r5: function pointer ffi_prep_args
+  r6: ret address
+  r7: function to call
+  r8: flag for return type
+*/
+
+ffi_call_SYSV:
+	/* Store registers used on stack */
+	l.sw -4(r1), r9 /* return address */
+	l.sw -8(r1), r1 /* stack address */
+	l.sw -12(r1), r14 /* callee saved registers */
+	l.sw -16(r1), r16
+	l.sw -20(r1), r18 
+	l.sw -24(r1), r20
+
+	l.ori r14, r1, 0x0 /* save stack pointer */
+	l.addi r1, r1, -24
+
+	l.ori r16, r7, 0x0 /* save function address */
+	l.ori r18, r6, 0x0 /* save ret address */
+	l.ori r20, r8, 0x0 /* save flag */
+
+	l.sub r1, r1, r3 /* reserve space on stack */
+
+	/* Call ffi_prep_args */
+	l.ori r3, r1, 0x0  /* first argument stack address, second already ecif */
+	l.jalr r5
+	l.nop
+
+	/* Load register arguments and call*/
+
+	l.lwz r3, 0(r1)
+	l.lwz r4, 4(r1)
+	l.lwz r5, 8(r1)
+	l.lwz r6, 12(r1)
+	l.lwz r7, 16(r1)
+	l.lwz r8, 20(r1)
+	l.ori r1, r11, 0x0 /* new stack pointer */
+	l.jalr r16
+	l.nop
+	
+	/* handle return values */
+
+	l.sfeqi r20, FFI_TYPE_STRUCT
+	l.bf ret  /* structs don't return an rvalue */
+	l.nop
+
+	/* copy ret address */
+
+	l.sfeqi r20, FFI_TYPE_UINT64
+	l.bnf four_byte_ret  /* 8 byte value is returned */
+	l.nop
+
+	l.sw 4(r18), r12
+
+four_byte_ret:
+	l.sw 0(r18), r11
+
+ret:
+	/* return */
+	l.ori r1, r14, 0x0 /* reset stack pointer */
+	l.lwz r9, -4(r1)
+	l.lwz r1, -8(r1)
+	l.lwz r14, -12(r1)
+	l.lwz r16, -16(r1)
+	l.lwz r18, -20(r1)
+	l.lwz r20, -24(r1)
+	l.jr r9
+	l.nop
+
+.size ffi_call_SYSV, .-ffi_call_SYSV
diff --git a/third_party/gofrontend/libffi/src/pa/ffitarget.h b/third_party/gofrontend/libffi/src/pa/ffitarget.h
index 5e364d3..fff4c6b 100644
--- a/third_party/gofrontend/libffi/src/pa/ffitarget.h
+++ b/third_party/gofrontend/libffi/src/pa/ffitarget.h
@@ -62,6 +62,8 @@
 } ffi_abi;
 #endif
 
+#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
+
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
diff --git a/third_party/gofrontend/libffi/src/powerpc/aix.S b/third_party/gofrontend/libffi/src/powerpc/aix.S
index 213f2db..349e78c 100644
--- a/third_party/gofrontend/libffi/src/powerpc/aix.S
+++ b/third_party/gofrontend/libffi/src/powerpc/aix.S
@@ -137,7 +137,7 @@
 	mtcrf	0x40, r31
 	mtctr	r0
 	/* Load all those argument registers.  */
-	// We have set up a nice stack frame, just load it into registers.
+	/* We have set up a nice stack frame, just load it into registers. */
 	ld	r3, 40+(1*8)(r1)
 	ld	r4, 40+(2*8)(r1)
 	ld	r5, 40+(3*8)(r1)
@@ -150,7 +150,7 @@
 
 L1:
 	/* Load all the FP registers.  */
-	bf	6,L2 // 2f + 0x18
+	bf	6,L2 /* 2f + 0x18 */
 	lfd	f1,-32-(13*8)(r28)
 	lfd	f2,-32-(12*8)(r28)
 	lfd	f3,-32-(11*8)(r28)
@@ -239,7 +239,7 @@
 	mtcrf	0x40, r31
 	mtctr	r0
 	/* Load all those argument registers.  */
-	// We have set up a nice stack frame, just load it into registers.
+	/* We have set up a nice stack frame, just load it into registers. */
 	lwz	r3, 20+(1*4)(r1)
 	lwz	r4, 20+(2*4)(r1)
 	lwz	r5, 20+(3*4)(r1)
@@ -252,7 +252,7 @@
 
 L1:
 	/* Load all the FP registers.  */
-	bf	6,L2 // 2f + 0x18
+	bf	6,L2 /* 2f + 0x18 */
 	lfd	f1,-16-(13*8)(r28)
 	lfd	f2,-16-(12*8)(r28)
 	lfd	f3,-16-(11*8)(r28)
@@ -307,7 +307,7 @@
 #endif
 	.long 0
 	.byte 0,0,0,1,128,4,0,0
-//END(ffi_call_AIX)
+/* END(ffi_call_AIX) */
 
 .csect .text[PR]
 	.align 2
@@ -325,4 +325,4 @@
 	blr
 	.long 0
 	.byte 0,0,0,0,0,0,0,0
-//END(ffi_call_DARWIN)
+/* END(ffi_call_DARWIN) */
diff --git a/third_party/gofrontend/libffi/src/powerpc/darwin.S b/third_party/gofrontend/libffi/src/powerpc/darwin.S
index 4f987dc..066eb82 100644
--- a/third_party/gofrontend/libffi/src/powerpc/darwin.S
+++ b/third_party/gofrontend/libffi/src/powerpc/darwin.S
@@ -318,11 +318,6 @@
 
 #define EH_DATA_ALIGN_FACT MODE_CHOICE(0x7c,0x78)
 
-	.static_data
-	.align LOG2_GPR_BYTES
-LLFB0$non_lazy_ptr:
-	.g_long Lstartcode
-
 	.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
 EH_frame1:
 	.set	L$set$0,LECIE1-LSCIE1
@@ -335,7 +330,7 @@
 	.byte	EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
 	.byte	0x41	; CIE RA Column
 	.byte	0x1	; uleb128 0x1; Augmentation size
-	.byte	0x10	; FDE Encoding (indirect pcrel)
+	.byte	0x10	; FDE Encoding (pcrel)
 	.byte	0xc	; DW_CFA_def_cfa
 	.byte	0x1	; uleb128 0x1
 	.byte	0x0	; uleb128 0x0
@@ -349,7 +344,7 @@
 	.long	L$set$1	; FDE Length
 LASFDE1:
 	.long	LASFDE1-EH_frame1 ; FDE CIE offset
-	.g_long	LLFB0$non_lazy_ptr-.	; FDE initial location
+	.g_long	Lstartcode-.	; FDE initial location
 	.set	L$set$3,LFE1-Lstartcode
 	.g_long	L$set$3	; FDE address range
 	.byte   0x0     ; uleb128 0x0; Augmentation size
diff --git a/third_party/gofrontend/libffi/src/powerpc/darwin_closure.S b/third_party/gofrontend/libffi/src/powerpc/darwin_closure.S
index 3f6790f..c7734d4 100644
--- a/third_party/gofrontend/libffi/src/powerpc/darwin_closure.S
+++ b/third_party/gofrontend/libffi/src/powerpc/darwin_closure.S
@@ -192,7 +192,7 @@
 	lg	r0,0(r3)		; size => r0
 	lhz	r3,FFI_TYPE_TYPE(r3)	; type => r3
 
-	/* The helper will have intercepted struture returns and inserted
+	/* The helper will have intercepted structure returns and inserted
 	   the caller`s destination address for structs returned by ref.  */
 
 	/* r3 contains the return type  so use it to look up in a table
@@ -467,11 +467,6 @@
 #define EH_FRAME_OFFSETA MODE_CHOICE(176,0x90)
 #define EH_FRAME_OFFSETB MODE_CHOICE(1,3)
 
-	.static_data
-	.align LOG2_GPR_BYTES
-LLFB1$non_lazy_ptr:
-	.g_long Lstartcode
-
 	.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
 EH_frame1:
 	.set	L$set$0,LECIE1-LSCIE1
@@ -484,7 +479,7 @@
 	.byte	EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
 	.byte	0x41	; CIE RA Column
 	.byte	0x1	; uleb128 0x1; Augmentation size
-	.byte	0x10	; FDE Encoding (indirect pcrel)
+	.byte	0x10	; FDE Encoding (pcrel)
 	.byte	0xc	; DW_CFA_def_cfa
 	.byte	0x1	; uleb128 0x1
 	.byte	0x0	; uleb128 0x0
@@ -498,7 +493,7 @@
 
 LASFDE1:
 	.long	LASFDE1-EH_frame1	; FDE CIE offset
-	.g_long	LLFB1$non_lazy_ptr-.	; FDE initial location
+	.g_long	Lstartcode-.	; FDE initial location
 	.set	L$set$3,LFE1-Lstartcode
 	.g_long	L$set$3	; FDE address range
 	.byte   0x0     ; uleb128 0x0; Augmentation size
@@ -523,12 +518,12 @@
 L_ffi_closure_helper_DARWIN$stub:
 	.indirect_symbol _ffi_closure_helper_DARWIN
 	mflr r0
-	bcl 20,31,"L00000000001$spb"
-"L00000000001$spb":
+	bcl 20,31,"L1$spb"
+"L1$spb":
 	mflr r11
-	addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L00000000001$spb")
+	addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L1$spb")
 	mtlr r0
-	lwzu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L00000000001$spb")(r11)
+	lwzu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L1$spb")(r11)
 	mtctr r12
 	bctr
 	.lazy_symbol_pointer
@@ -542,12 +537,12 @@
 L_darwin64_struct_ret_by_value_p$stub:
 	.indirect_symbol _darwin64_struct_ret_by_value_p
 	mflr r0
-	bcl 20,31,"L00000000002$spb"
-"L00000000002$spb":
+	bcl 20,31,"L2$spb"
+"L2$spb":
 	mflr r11
-	addis r11,r11,ha16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L00000000002$spb")
+	addis r11,r11,ha16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L2$spb")
 	mtlr r0
-	lwzu r12,lo16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L00000000002$spb")(r11)
+	lwzu r12,lo16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L2$spb")(r11)
 	mtctr r12
 	bctr
 	.lazy_symbol_pointer
@@ -560,12 +555,12 @@
 L_darwin64_pass_struct_floats$stub:
 	.indirect_symbol _darwin64_pass_struct_floats
 	mflr r0
-	bcl 20,31,"L00000000003$spb"
-"L00000000003$spb":
+	bcl 20,31,"L3$spb"
+"L3$spb":
 	mflr r11
-	addis r11,r11,ha16(L_darwin64_pass_struct_floats$lazy_ptr-"L00000000003$spb")
+	addis r11,r11,ha16(L_darwin64_pass_struct_floats$lazy_ptr-"L3$spb")
 	mtlr r0
-	lwzu r12,lo16(L_darwin64_pass_struct_floats$lazy_ptr-"L00000000003$spb")(r11)
+	lwzu r12,lo16(L_darwin64_pass_struct_floats$lazy_ptr-"L3$spb")(r11)
 	mtctr r12
 	bctr
 	.lazy_symbol_pointer
diff --git a/third_party/gofrontend/libffi/src/powerpc/ffi.c b/third_party/gofrontend/libffi/src/powerpc/ffi.c
index efb441b..7eb543e 100644
--- a/third_party/gofrontend/libffi/src/powerpc/ffi.c
+++ b/third_party/gofrontend/libffi/src/powerpc/ffi.c
@@ -70,8 +70,12 @@
 #endif
 }
 
-void
-ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+static void
+ffi_call_int (ffi_cif *cif,
+	      void (*fn) (void),
+	      void *rvalue,
+	      void **avalue,
+	      void *closure)
 {
   /* The final SYSV ABI says that structures smaller or equal 8 bytes
      are returned in r3/r4.  A draft ABI used by linux instead returns
@@ -97,9 +101,10 @@
     ecif.rvalue = alloca (cif->rtype->size);
 
 #ifdef POWERPC64
-  ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
+  ffi_call_LINUX64 (&ecif, fn, ecif.rvalue, cif->flags, closure,
+		    -(long) cif->bytes);
 #else
-  ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
+  ffi_call_SYSV (&ecif, fn, ecif.rvalue, cif->flags, closure, -cif->bytes);
 #endif
 
   /* Check for a bounce-buffered return value */
@@ -125,6 +130,18 @@
     }
 }
 
+void
+ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, NULL);
+}
+
+void
+ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
+	     void *closure)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, closure);
+}
 
 ffi_status
 ffi_prep_closure_loc (ffi_closure *closure,
@@ -139,3 +156,18 @@
   return ffi_prep_closure_loc_sysv (closure, cif, fun, user_data, codeloc);
 #endif
 }
+
+ffi_status
+ffi_prep_go_closure (ffi_go_closure *closure,
+		     ffi_cif *cif,
+		     void (*fun) (ffi_cif *, void *, void **, void *))
+{
+#ifdef POWERPC64
+  closure->tramp = ffi_go_closure_linux64;
+#else
+  closure->tramp = ffi_go_closure_sysv;
+#endif
+  closure->cif = cif;
+  closure->fun = fun;
+  return FFI_OK;
+}
diff --git a/third_party/gofrontend/libffi/src/powerpc/ffi_darwin.c b/third_party/gofrontend/libffi/src/powerpc/ffi_darwin.c
index dd897f4..cf6fb6d 100644
--- a/third_party/gofrontend/libffi/src/powerpc/ffi_darwin.c
+++ b/third_party/gofrontend/libffi/src/powerpc/ffi_darwin.c
@@ -302,10 +302,10 @@
     }
 
   /* Check that we didn't overrun the stack...  */
-  //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
-  //FFI_ASSERT((unsigned *)fpr_base
-  //	     <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
-  //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
+  /* FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
+     FFI_ASSERT((unsigned *)fpr_base
+     	     <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
+     FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);  */
 }
 
 #if defined(POWERPC_DARWIN64)
@@ -593,7 +593,7 @@
       /* Natural alignment for all items.  */
       align = p->alignment;
 #else
-      /* Natrual alignment for the first item... */
+      /* Natural alignment for the first item... */
       if (i == 0)
 	align = p->alignment;
       else if (p->alignment == 16 || p->alignment < 4)
diff --git a/third_party/gofrontend/libffi/src/powerpc/ffi_linux64.c b/third_party/gofrontend/libffi/src/powerpc/ffi_linux64.c
index 33f24b3..b84b91f 100644
--- a/third_party/gofrontend/libffi/src/powerpc/ffi_linux64.c
+++ b/third_party/gofrontend/libffi/src/powerpc/ffi_linux64.c
@@ -667,7 +667,8 @@
 }
 #endif
 
-ffi_status
+
+ffi_status FFI_HIDDEN
 ffi_prep_closure_loc_linux64 (ffi_closure *closure,
 			      ffi_cif *cif,
 			      void (*fun) (ffi_cif *, void *, void **, void *),
@@ -688,16 +689,17 @@
 				/* 2:	.quad	context		*/
   *(void **) &tramp[4] = (void *) ffi_closure_LINUX64;
   *(void **) &tramp[6] = codeloc;
-  flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
+  flush_icache ((char *) tramp, (char *) codeloc, 4 * 4);
 #else
   void **tramp = (void **) &closure->tramp[0];
 
   if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI)
     return FFI_BAD_ABI;
 
-  /* Copy function address and TOC from ffi_closure_LINUX64.  */
-  memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
-  tramp[2] = codeloc;
+  /* Copy function address and TOC from ffi_closure_LINUX64 OPD.  */
+  memcpy (&tramp[0], (void **) ffi_closure_LINUX64, sizeof (void *));
+  tramp[1] = codeloc;
+  memcpy (&tramp[2], (void **) ffi_closure_LINUX64 + 1, sizeof (void *));
 #endif
 
   closure->cif = cif;
@@ -709,8 +711,12 @@
 
 
 int FFI_HIDDEN
-ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
-			    unsigned long *pst, ffi_dblfl *pfr)
+ffi_closure_helper_LINUX64 (ffi_cif *cif,
+			    void (*fun) (ffi_cif *, void *, void **, void *),
+			    void *user_data,
+			    void *rvalue,
+			    unsigned long *pst,
+			    ffi_dblfl *pfr)
 {
   /* rvalue is the pointer to space for return value in closure assembly */
   /* pst is the pointer to parameter save area
@@ -720,11 +726,9 @@
   void **avalue;
   ffi_type **arg_types;
   unsigned long i, avn, nfixedargs;
-  ffi_cif *cif;
   ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
   unsigned long align;
 
-  cif = closure->cif;
   avalue = alloca (cif->nargs * sizeof (void *));
 
   /* Copy the caller's structure return value address so that the
@@ -924,8 +928,7 @@
       i++;
     }
 
-
-  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+  (*fun) (cif, rvalue, avalue, user_data);
 
   /* Tell ffi_closure_LINUX64 how to perform return type promotions.  */
   if ((cif->flags & FLAG_RETURNS_SMST) != 0)
diff --git a/third_party/gofrontend/libffi/src/powerpc/ffi_powerpc.h b/third_party/gofrontend/libffi/src/powerpc/ffi_powerpc.h
index 2e61653..3dcd6b5 100644
--- a/third_party/gofrontend/libffi/src/powerpc/ffi_powerpc.h
+++ b/third_party/gofrontend/libffi/src/powerpc/ffi_powerpc.h
@@ -56,22 +56,39 @@
 } ffi_dblfl;
 
 void FFI_HIDDEN ffi_closure_SYSV (void);
-void FFI_HIDDEN ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *,
-			      void (*)(void));
+void FFI_HIDDEN ffi_go_closure_sysv (void);
+void FFI_HIDDEN ffi_call_SYSV(extended_cif *, void (*)(void), void *,
+			      unsigned, void *, int);
 
 void FFI_HIDDEN ffi_prep_types_sysv (ffi_abi);
 ffi_status FFI_HIDDEN ffi_prep_cif_sysv (ffi_cif *);
-int FFI_HIDDEN ffi_closure_helper_SYSV (ffi_closure *, void *, unsigned long *,
+ffi_status FFI_HIDDEN ffi_prep_closure_loc_sysv (ffi_closure *,
+						 ffi_cif *,
+						 void (*) (ffi_cif *, void *,
+							   void **, void *),
+						 void *, void *);
+int FFI_HIDDEN ffi_closure_helper_SYSV (ffi_cif *,
+					void (*) (ffi_cif *, void *,
+						  void **, void *),
+					void *, void *, unsigned long *,
 					ffi_dblfl *, unsigned long *);
 
-void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long, unsigned long,
-				 unsigned long *, void (*)(void));
+void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, void (*) (void), void *,
+				 unsigned long, void *, long);
 void FFI_HIDDEN ffi_closure_LINUX64 (void);
+void FFI_HIDDEN ffi_go_closure_linux64 (void);
 
 void FFI_HIDDEN ffi_prep_types_linux64 (ffi_abi);
 ffi_status FFI_HIDDEN ffi_prep_cif_linux64 (ffi_cif *);
 ffi_status FFI_HIDDEN ffi_prep_cif_linux64_var (ffi_cif *, unsigned int,
 						unsigned int);
 void FFI_HIDDEN ffi_prep_args64 (extended_cif *, unsigned long *const);
-int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
+ffi_status FFI_HIDDEN ffi_prep_closure_loc_linux64 (ffi_closure *, ffi_cif *,
+						    void (*) (ffi_cif *, void *,
+							      void **, void *),
+						    void *, void *);
+int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_cif *,
+					   void (*) (ffi_cif *, void *,
+						     void **, void *),
+					   void *, void *,
 					   unsigned long *, ffi_dblfl *);
diff --git a/third_party/gofrontend/libffi/src/powerpc/ffi_sysv.c b/third_party/gofrontend/libffi/src/powerpc/ffi_sysv.c
index fbe85fe..646c340 100644
--- a/third_party/gofrontend/libffi/src/powerpc/ffi_sysv.c
+++ b/third_party/gofrontend/libffi/src/powerpc/ffi_sysv.c
@@ -36,7 +36,7 @@
 
 
 /* About the SYSV ABI.  */
-#define ASM_NEEDS_REGISTERS 4
+#define ASM_NEEDS_REGISTERS 6
 #define NUM_GPR_ARG_REGISTERS 8
 #define NUM_FPR_ARG_REGISTERS 8
 
@@ -654,18 +654,18 @@
 
   tramp = (unsigned int *) &closure->tramp[0];
   tramp[0] = 0x7c0802a6;  /*   mflr    r0 */
-  tramp[1] = 0x4800000d;  /*   bl      10 <trampoline_initial+0x10> */
-  tramp[4] = 0x7d6802a6;  /*   mflr    r11 */
-  tramp[5] = 0x7c0803a6;  /*   mtlr    r0 */
-  tramp[6] = 0x800b0000;  /*   lwz     r0,0(r11) */
-  tramp[7] = 0x816b0004;  /*   lwz     r11,4(r11) */
-  tramp[8] = 0x7c0903a6;  /*   mtctr   r0 */
-  tramp[9] = 0x4e800420;  /*   bctr */
-  *(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
-  *(void **) &tramp[3] = codeloc;                   /* context */
+  tramp[1] = 0x429f0005;  /*   bcl     20,31,.+4 */
+  tramp[2] = 0x7d6802a6;  /*   mflr    r11 */
+  tramp[3] = 0x7c0803a6;  /*   mtlr    r0 */
+  tramp[4] = 0x800b0018;  /*   lwz     r0,24(r11) */
+  tramp[5] = 0x816b001c;  /*   lwz     r11,28(r11) */
+  tramp[6] = 0x7c0903a6;  /*   mtctr   r0 */
+  tramp[7] = 0x4e800420;  /*   bctr */
+  *(void **) &tramp[8] = (void *) ffi_closure_SYSV; /* function */
+  *(void **) &tramp[9] = codeloc;                   /* context */
 
   /* Flush the icache.  */
-  flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
+  flush_icache ((char *)tramp, (char *)codeloc, 8 * 4);
 
   closure->cif = cif;
   closure->fun = fun;
@@ -682,8 +682,12 @@
    following helper function to do most of the work.  */
 
 int
-ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
-			 unsigned long *pgr, ffi_dblfl *pfr,
+ffi_closure_helper_SYSV (ffi_cif *cif,
+			 void (*fun) (ffi_cif *, void *, void **, void *),
+			 void *user_data,
+			 void *rvalue,
+			 unsigned long *pgr,
+			 ffi_dblfl *pfr,
 			 unsigned long *pst)
 {
   /* rvalue is the pointer to space for return value in closure assembly */
@@ -699,7 +703,6 @@
 #endif
   long             ng = 0;   /* number of general registers already used */
 
-  ffi_cif *cif = closure->cif;
   unsigned       size     = cif->rtype->size;
   unsigned short rtypenum = cif->rtype->type;
 
@@ -915,7 +918,7 @@
     i++;
   }
 
-  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+  (*fun) (cif, rvalue, avalue, user_data);
 
   /* Tell ffi_closure_SYSV how to perform return type promotions.
      Because the FFI_SYSV ABI returns the structures <= 8 bytes in
diff --git a/third_party/gofrontend/libffi/src/powerpc/ffitarget.h b/third_party/gofrontend/libffi/src/powerpc/ffitarget.h
index b47b0f5..0f66d31 100644
--- a/third_party/gofrontend/libffi/src/powerpc/ffitarget.h
+++ b/third_party/gofrontend/libffi/src/powerpc/ffitarget.h
@@ -138,23 +138,35 @@
 #define FFI_CLOSURES 1
 #define FFI_NATIVE_RAW_API 0
 #if defined (POWERPC) || defined (POWERPC_FREEBSD)
+# define FFI_GO_CLOSURES 1
 # define FFI_TARGET_SPECIFIC_VARIADIC 1
 # define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs
 #endif
 
-/* For additional types like the below, take care about the order in
-   ppc_closures.S. They must follow after the FFI_TYPE_LAST.  */
+/* ppc_closure.S and linux64_closure.S expect this.  */
+#define FFI_PPC_TYPE_LAST FFI_TYPE_POINTER
+
+/* We define additional types below.  If generic types are added that
+   must be supported by powerpc libffi then it is likely that
+   FFI_PPC_TYPE_LAST needs increasing *and* the jump tables in
+   ppc_closure.S and linux64_closure.S be extended.  */
+
+#if !(FFI_TYPE_LAST == FFI_PPC_TYPE_LAST		\
+      || (FFI_TYPE_LAST == FFI_TYPE_COMPLEX		\
+	  && !defined FFI_TARGET_HAS_COMPLEX_TYPE))
+# error "You likely have a broken powerpc libffi"
+#endif
 
 /* Needed for soft-float long-double-128 support.  */
-#define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1)
+#define FFI_TYPE_UINT128 (FFI_PPC_TYPE_LAST + 1)
 
 /* Needed for FFI_SYSV small structure returns.  */
-#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2)
+#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_PPC_TYPE_LAST + 2)
 
 /* Used by ELFv2 for homogenous structure returns.  */
-#define FFI_V2_TYPE_FLOAT_HOMOG		(FFI_TYPE_LAST + 1)
-#define FFI_V2_TYPE_DOUBLE_HOMOG	(FFI_TYPE_LAST + 2)
-#define FFI_V2_TYPE_SMALL_STRUCT	(FFI_TYPE_LAST + 3)
+#define FFI_V2_TYPE_FLOAT_HOMOG		(FFI_PPC_TYPE_LAST + 1)
+#define FFI_V2_TYPE_DOUBLE_HOMOG	(FFI_PPC_TYPE_LAST + 2)
+#define FFI_V2_TYPE_SMALL_STRUCT	(FFI_PPC_TYPE_LAST + 3)
 
 #if _CALL_ELF == 2
 # define FFI_TRAMPOLINE_SIZE 32
diff --git a/third_party/gofrontend/libffi/src/powerpc/linux64.S b/third_party/gofrontend/libffi/src/powerpc/linux64.S
index d2acb70..b2ae60e 100644
--- a/third_party/gofrontend/libffi/src/powerpc/linux64.S
+++ b/third_party/gofrontend/libffi/src/powerpc/linux64.S
@@ -32,8 +32,9 @@
 #ifdef POWERPC64
 	.hidden	ffi_call_LINUX64
 	.globl	ffi_call_LINUX64
-# if _CALL_ELF == 2
 	.text
+	.cfi_startproc
+# if _CALL_ELF == 2
 ffi_call_LINUX64:
 	addis	%r2, %r12, .TOC.-ffi_call_LINUX64@ha
 	addi	%r2, %r2, .TOC.-ffi_call_LINUX64@l
@@ -57,20 +58,26 @@
 .ffi_call_LINUX64:
 #  endif
 # endif
-.LFB1:
 	mflr	%r0
 	std	%r28, -32(%r1)
 	std	%r29, -24(%r1)
 	std	%r30, -16(%r1)
 	std	%r31, -8(%r1)
+	std	%r7, 8(%r1)	/* closure, saved in cr field.  */
 	std	%r0, 16(%r1)
 
 	mr	%r28, %r1	/* our AP.  */
-.LCFI0:
-	stdux	%r1, %r1, %r4
-	mr	%r31, %r5	/* flags, */
-	mr	%r30, %r6	/* rvalue, */
-	mr	%r29, %r7	/* function address.  */
+	.cfi_def_cfa_register 28
+	.cfi_offset 65, 16
+	.cfi_offset 31, -8
+	.cfi_offset 30, -16
+	.cfi_offset 29, -24
+	.cfi_offset 28, -32
+
+	stdux	%r1, %r1, %r8
+	mr	%r31, %r6	/* flags, */
+	mr	%r30, %r5	/* rvalue, */
+	mr	%r29, %r4	/* function address.  */
 /* Save toc pointer, not for the ffi_prep_args64 call, but for the later
    bctrl function call.  */
 # if _CALL_ELF == 2
@@ -92,7 +99,6 @@
 # else
 	ld	%r12, 0(%r29)
 	ld	%r2, 8(%r29)
-	ld	%r11, 16(%r29)
 # endif
 	/* Now do the call.  */
 	/* Set up cr1 with bits 4-7 of the flags.  */
@@ -130,6 +136,7 @@
 2:
 
 	/* Make the call.  */
+	ld	%r11, 8(%r28)
 	bctrl
 
 	/* This must follow the call immediately, the unwinder
@@ -151,6 +158,7 @@
 .Ldone_return_value:
 	/* Restore the registers we used and return.  */
 	mr	%r1, %r28
+	.cfi_def_cfa_register 1
 	ld	%r0, 16(%r28)
 	ld	%r28, -32(%r28)
 	mtlr	%r0
@@ -160,6 +168,7 @@
 	blr
 
 .Lfp_return_value:
+	.cfi_def_cfa_register 28
 	bf	28, .Lfloat_return_value
 	stfd	%f1, 0(%r30)
 	mtcrf	0x02, %r31 /* cr6  */
@@ -199,61 +208,19 @@
 	std	%r4, 8(%r30)
 	b	.Ldone_return_value
 
-.LFE1:
-	.long	0
-	.byte	0,12,0,1,128,4,0,0
+	.cfi_endproc
 # if _CALL_ELF == 2
 	.size	ffi_call_LINUX64,.-ffi_call_LINUX64
 # else
 #  ifdef _CALL_LINUX
 	.size	ffi_call_LINUX64,.-.L.ffi_call_LINUX64
 #  else
+	.long	0
+	.byte	0,12,0,1,128,4,0,0
 	.size	.ffi_call_LINUX64,.-.ffi_call_LINUX64
 #  endif
 # endif
 
-	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
-.Lframe1:
-	.4byte	.LECIE1-.LSCIE1	 # Length of Common Information Entry
-.LSCIE1:
-	.4byte	0x0	 # CIE Identifier Tag
-	.byte	0x1	 # CIE Version
-	.ascii "zR\0"	 # CIE Augmentation
-	.uleb128 0x1	 # CIE Code Alignment Factor
-	.sleb128 -8	 # CIE Data Alignment Factor
-	.byte	0x41	 # CIE RA Column
-	.uleb128 0x1	 # Augmentation size
-	.byte	0x14	 # FDE Encoding (pcrel udata8)
-	.byte	0xc	 # DW_CFA_def_cfa
-	.uleb128 0x1
-	.uleb128 0x0
-	.align 3
-.LECIE1:
-.LSFDE1:
-	.4byte	.LEFDE1-.LASFDE1	 # FDE Length
-.LASFDE1:
-	.4byte	.LASFDE1-.Lframe1	 # FDE CIE offset
-	.8byte	.LFB1-.	 # FDE initial location
-	.8byte	.LFE1-.LFB1	 # FDE address range
-	.uleb128 0x0	 # Augmentation size
-	.byte	0x2	 # DW_CFA_advance_loc1
-	.byte	.LCFI0-.LFB1
-	.byte	0xd	 # DW_CFA_def_cfa_register
-	.uleb128 0x1c
-	.byte	0x11	 # DW_CFA_offset_extended_sf
-	.uleb128 0x41
-	.sleb128 -2
-	.byte	0x9f	 # DW_CFA_offset, column 0x1f
-	.uleb128 0x1
-	.byte	0x9e	 # DW_CFA_offset, column 0x1e
-	.uleb128 0x2
-	.byte	0x9d	 # DW_CFA_offset, column 0x1d
-	.uleb128 0x3
-	.byte	0x9c	 # DW_CFA_offset, column 0x1c
-	.uleb128 0x4
-	.align 3
-.LEFDE1:
-
 #endif
 
 #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
diff --git a/third_party/gofrontend/libffi/src/powerpc/linux64_closure.S b/third_party/gofrontend/libffi/src/powerpc/linux64_closure.S
index 1d80a39..6487d2a 100644
--- a/third_party/gofrontend/libffi/src/powerpc/linux64_closure.S
+++ b/third_party/gofrontend/libffi/src/powerpc/linux64_closure.S
@@ -33,8 +33,9 @@
 #ifdef POWERPC64
 	FFI_HIDDEN (ffi_closure_LINUX64)
 	.globl  ffi_closure_LINUX64
-# if _CALL_ELF == 2
 	.text
+	.cfi_startproc
+# if _CALL_ELF == 2
 ffi_closure_LINUX64:
 	addis	%r2, %r12, .TOC.-ffi_closure_LINUX64@ha
 	addi	%r2, %r2, .TOC.-ffi_closure_LINUX64@l
@@ -73,20 +74,18 @@
 #  define RETVAL PARMSAVE+64
 # endif
 
-.LFB1:
 # if _CALL_ELF == 2
 	ld	%r12, FFI_TRAMPOLINE_SIZE(%r11)		# closure->cif
 	mflr	%r0
 	lwz	%r12, 28(%r12)				# cif->flags
 	mtcrf	0x40, %r12
 	addi	%r12, %r1, PARMSAVE
-	bt	7, .Lparmsave
+	bt	7, 0f
 	# Our caller has not allocated a parameter save area.
 	# We need to allocate one here and use it to pass gprs to
 	# ffi_closure_helper_LINUX64.
 	addi	%r12, %r1, -STACKFRAME+PARMSAVE
-.Lparmsave:
-	std	%r0, 16(%r1)
+0:
 	# Save general regs into parm save area
 	std	%r3, 0(%r12)
 	std	%r4, 8(%r12)
@@ -98,8 +97,12 @@
 	std	%r10, 56(%r12)
 
 	# load up the pointer to the parm save area
-	mr	%r5, %r12
+	mr	%r7, %r12
 # else
+	# copy r2 to r11 and load TOC into r2
+	mr	%r11, %r2
+	ld	%r2, 16(%r2)
+
 	mflr	%r0
 	# Save general regs into parm save area
 	# This is the parameter save area set up by our caller.
@@ -112,12 +115,19 @@
 	std	%r9, PARMSAVE+48(%r1)
 	std	%r10, PARMSAVE+56(%r1)
 
+	# load up the pointer to the parm save area
+	addi	%r7, %r1, PARMSAVE
+# endif
 	std	%r0, 16(%r1)
 
-	# load up the pointer to the parm save area
-	addi	%r5, %r1, PARMSAVE
-# endif
+	# closure->cif
+	ld	%r3, FFI_TRAMPOLINE_SIZE(%r11)
+	# closure->fun
+	ld	%r4, FFI_TRAMPOLINE_SIZE+8(%r11)
+	# closure->user_data
+	ld	%r5, FFI_TRAMPOLINE_SIZE+16(%r11)
 
+.Ldoclosure:
 	# next save fpr 1 to fpr 13
 	stfd	%f1, -104+(0*8)(%r1)
 	stfd	%f2, -104+(1*8)(%r1)
@@ -134,16 +144,14 @@
 	stfd	%f13, -104+(12*8)(%r1)
 
 	# load up the pointer to the saved fpr registers */
-	addi	%r6, %r1, -104
+	addi	%r8, %r1, -104
 
 	# load up the pointer to the result storage
-	addi	%r4, %r1, -STACKFRAME+RETVAL
+	addi	%r6, %r1, -STACKFRAME+RETVAL
 
 	stdu	%r1, -STACKFRAME(%r1)
-.LCFI0:
-
-	# get the context pointer from the trampoline
-	mr	%r3, %r11
+	.cfi_def_cfa_offset STACKFRAME
+	.cfi_offset 65, 16
 
 	# make the call
 # if defined _CALL_LINUX || _CALL_ELF == 2
@@ -178,7 +186,9 @@
 # case FFI_TYPE_VOID
 	mtlr %r0
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 	nop
 # case FFI_TYPE_INT
 # ifdef __LITTLE_ENDIAN__
@@ -188,17 +198,23 @@
 # endif
 	mtlr %r0
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 # case FFI_TYPE_FLOAT
 	lfs %f1, RETVAL+0(%r1)
 	mtlr %r0
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 # case FFI_TYPE_DOUBLE
 	lfd %f1, RETVAL+0(%r1)
 	mtlr %r0
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 # case FFI_TYPE_LONGDOUBLE
 	lfd %f1, RETVAL+0(%r1)
 	mtlr %r0
@@ -212,7 +228,9 @@
 # endif
 	mtlr %r0
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 # case FFI_TYPE_SINT8
 # ifdef __LITTLE_ENDIAN__
 	lbz %r3, RETVAL+0(%r1)
@@ -231,7 +249,9 @@
 	mtlr %r0
 .Lfinish:
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 # case FFI_TYPE_SINT16
 # ifdef __LITTLE_ENDIAN__
 	lha %r3, RETVAL+0(%r1)
@@ -240,7 +260,9 @@
 # endif
 	mtlr %r0
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 # case FFI_TYPE_UINT32
 # ifdef __LITTLE_ENDIAN__
 	lwz %r3, RETVAL+0(%r1)
@@ -249,7 +271,9 @@
 # endif
 	mtlr %r0
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 # case FFI_TYPE_SINT32
 # ifdef __LITTLE_ENDIAN__
 	lwa %r3, RETVAL+0(%r1)
@@ -258,27 +282,37 @@
 # endif
 	mtlr %r0
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 # case FFI_TYPE_UINT64
 	ld %r3, RETVAL+0(%r1)
 	mtlr %r0
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 # case FFI_TYPE_SINT64
 	ld %r3, RETVAL+0(%r1)
 	mtlr %r0
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 # case FFI_TYPE_STRUCT
 	mtlr %r0
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 	nop
 # case FFI_TYPE_POINTER
 	ld %r3, RETVAL+0(%r1)
 	mtlr %r0
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 # case FFI_V2_TYPE_FLOAT_HOMOG
 	lfs %f1, RETVAL+0(%r1)
 	lfs %f2, RETVAL+4(%r1)
@@ -295,7 +329,9 @@
 	lfd %f7, RETVAL+48(%r1)
 	lfd %f8, RETVAL+56(%r1)
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 .Lmorefloat:
 	lfs %f4, RETVAL+12(%r1)
 	mtlr %r0
@@ -304,13 +340,16 @@
 	lfs %f7, RETVAL+24(%r1)
 	lfs %f8, RETVAL+28(%r1)
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 .Lsmall:
 # ifdef __LITTLE_ENDIAN__
 	ld %r3,RETVAL+0(%r1)
 	mtlr %r0
 	ld %r4,RETVAL+8(%r1)
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
 # else
 	# A struct smaller than a dword is returned in the low bits of r3
@@ -324,63 +363,124 @@
 	mtlr %r0
 	ld %r4,RETVAL+8(%r1)
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset STACKFRAME
 .Lsmalldown:
 	addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
 	mtlr %r0
 	sldi %r5, %r5, 3
 	addi %r1, %r1, STACKFRAME
+	.cfi_def_cfa_offset 0
 	srd %r3, %r3, %r5
 	blr
 # endif
 
-.LFE1:
-	.long	0
-	.byte	0,12,0,1,128,0,0,0
+	.cfi_endproc
 # if _CALL_ELF == 2
 	.size	ffi_closure_LINUX64,.-ffi_closure_LINUX64
 # else
 #  ifdef _CALL_LINUX
 	.size	ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
 #  else
+	.long	0
+	.byte	0,12,0,1,128,0,0,0
 	.size	.ffi_closure_LINUX64,.-.ffi_closure_LINUX64
 #  endif
 # endif
 
-	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
-.Lframe1:
-	.4byte	.LECIE1-.LSCIE1	 # Length of Common Information Entry
-.LSCIE1:
-	.4byte	0x0	 # CIE Identifier Tag
-	.byte	0x1	 # CIE Version
-	.ascii "zR\0"	 # CIE Augmentation
-	.uleb128 0x1	 # CIE Code Alignment Factor
-	.sleb128 -8	 # CIE Data Alignment Factor
-	.byte	0x41	 # CIE RA Column
-	.uleb128 0x1	 # Augmentation size
-	.byte	0x14	 # FDE Encoding (pcrel udata8)
-	.byte	0xc	 # DW_CFA_def_cfa
-	.uleb128 0x1
-	.uleb128 0x0
-	.align 3
-.LECIE1:
-.LSFDE1:
-	.4byte	.LEFDE1-.LASFDE1	 # FDE Length
-.LASFDE1:
-	.4byte	.LASFDE1-.Lframe1	 # FDE CIE offset
-	.8byte	.LFB1-.	 # FDE initial location
-	.8byte	.LFE1-.LFB1	 # FDE address range
-	.uleb128 0x0	 # Augmentation size
-	.byte	0x2	 # DW_CFA_advance_loc1
-	.byte	.LCFI0-.LFB1
-	.byte	0xe	 # DW_CFA_def_cfa_offset
-	.uleb128 STACKFRAME
-	.byte	0x11	 # DW_CFA_offset_extended_sf
-	.uleb128 0x41
-	.sleb128 -2
-	.align 3
-.LEFDE1:
 
+	FFI_HIDDEN (ffi_go_closure_linux64)
+	.globl  ffi_go_closure_linux64
+	.text
+	.cfi_startproc
+# if _CALL_ELF == 2
+ffi_go_closure_linux64:
+	addis	%r2, %r12, .TOC.-ffi_go_closure_linux64@ha
+	addi	%r2, %r2, .TOC.-ffi_go_closure_linux64@l
+	.localentry ffi_go_closure_linux64, . - ffi_go_closure_linux64
+# else
+	.section        ".opd","aw"
+	.align  3
+ffi_go_closure_linux64:
+#  ifdef _CALL_LINUX
+	.quad   .L.ffi_go_closure_linux64,.TOC.@tocbase,0
+	.type   ffi_go_closure_linux64,@function
+	.text
+.L.ffi_go_closure_linux64:
+#  else
+	FFI_HIDDEN (.ffi_go_closure_linux64)
+	.globl  .ffi_go_closure_linux64
+	.quad   .ffi_go_closure_linux64,.TOC.@tocbase,0
+	.size   ffi_go_closure_linux64,24
+	.type   .ffi_go_closure_linux64,@function
+	.text
+.ffi_go_closure_linux64:
+#  endif
+# endif
+
+# if _CALL_ELF == 2
+	ld	%r12, 8(%r11)				# closure->cif
+	mflr	%r0
+	lwz	%r12, 28(%r12)				# cif->flags
+	mtcrf	0x40, %r12
+	addi	%r12, %r1, PARMSAVE
+	bt	7, 0f
+	# Our caller has not allocated a parameter save area.
+	# We need to allocate one here and use it to pass gprs to
+	# ffi_closure_helper_LINUX64.
+	addi	%r12, %r1, -STACKFRAME+PARMSAVE
+0:
+	# Save general regs into parm save area
+	std	%r3, 0(%r12)
+	std	%r4, 8(%r12)
+	std	%r5, 16(%r12)
+	std	%r6, 24(%r12)
+	std	%r7, 32(%r12)
+	std	%r8, 40(%r12)
+	std	%r9, 48(%r12)
+	std	%r10, 56(%r12)
+
+	# load up the pointer to the parm save area
+	mr	%r7, %r12
+# else
+	mflr	%r0
+	# Save general regs into parm save area
+	# This is the parameter save area set up by our caller.
+	std	%r3, PARMSAVE+0(%r1)
+	std	%r4, PARMSAVE+8(%r1)
+	std	%r5, PARMSAVE+16(%r1)
+	std	%r6, PARMSAVE+24(%r1)
+	std	%r7, PARMSAVE+32(%r1)
+	std	%r8, PARMSAVE+40(%r1)
+	std	%r9, PARMSAVE+48(%r1)
+	std	%r10, PARMSAVE+56(%r1)
+
+	# load up the pointer to the parm save area
+	addi	%r7, %r1, PARMSAVE
+# endif
+	std	%r0, 16(%r1)
+
+	# closure->cif
+	ld	%r3, 8(%r11)
+	# closure->fun
+	ld	%r4, 16(%r11)
+	# user_data
+	mr	%r5, %r11
+	b	.Ldoclosure
+
+	.cfi_endproc
+# if _CALL_ELF == 2
+	.size	ffi_go_closure_linux64,.-ffi_go_closure_linux64
+# else
+#  ifdef _CALL_LINUX
+	.size	ffi_go_closure_linux64,.-.L.ffi_go_closure_linux64
+#  else
+	.long	0
+	.byte	0,12,0,1,128,0,0,0
+	.size	.ffi_go_closure_linux64,.-.ffi_go_closure_linux64
+#  endif
+# endif
 #endif
 
 #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
diff --git a/third_party/gofrontend/libffi/src/powerpc/ppc_closure.S b/third_party/gofrontend/libffi/src/powerpc/ppc_closure.S
index 0507128..b6d209d 100644
--- a/third_party/gofrontend/libffi/src/powerpc/ppc_closure.S
+++ b/third_party/gofrontend/libffi/src/powerpc/ppc_closure.S
@@ -33,13 +33,14 @@
 
 #ifndef POWERPC64
 
+FFI_HIDDEN(ffi_closure_SYSV)
 ENTRY(ffi_closure_SYSV)
-.LFB1:
+	.cfi_startproc
 	stwu %r1,-144(%r1)
-.LCFI0:
+	.cfi_def_cfa_offset 144
 	mflr %r0
-.LCFI1:
 	stw %r0,148(%r1)
+	.cfi_offset 65, 4
 
 # we want to build up an areas for the parameters passed
 # in registers (both floating point and integer)
@@ -48,6 +49,17 @@
 	stw   %r3, 16(%r1)
 	stw   %r4, 20(%r1)
 	stw   %r5, 24(%r1)
+
+	# set up registers for the routine that does the work
+
+	# closure->cif
+	lwz %r3,FFI_TRAMPOLINE_SIZE(%r11)
+	# closure->fun
+	lwz %r4,FFI_TRAMPOLINE_SIZE+4(%r11)
+	# closure->user_data
+	lwz %r5,FFI_TRAMPOLINE_SIZE+8(%r11)
+
+.Ldoclosure:
 	stw   %r6, 28(%r1)
 	stw   %r7, 32(%r1)
 	stw   %r8, 36(%r1)
@@ -66,23 +78,18 @@
 	stfd  %f8, 104(%r1)
 #endif
 
-	# set up registers for the routine that actually does the work
-	# get the context pointer from the trampoline
-	mr %r3,%r11
+	# pointer to the result storage
+	addi %r6,%r1,112
 
-	# now load up the pointer to the result storage
-	addi %r4,%r1,112
+	# pointer to the saved gpr registers
+	addi %r7,%r1,16
 
-	# now load up the pointer to the saved gpr registers
-	addi %r5,%r1,16
+	# pointer to the saved fpr registers
+	addi %r8,%r1,48
 
-	# now load up the pointer to the saved fpr registers */
-	addi %r6,%r1,48
-
-	# now load up the pointer to the outgoing parameter
-	# stack in the previous frame
+	# pointer to the outgoing parameter save area in the previous frame
 	# i.e. the previous frame pointer + 8
-	addi %r7,%r1,152
+	addi %r9,%r1,152
 
 	# make the call
 	bl ffi_closure_helper_SYSV@local
@@ -101,7 +108,6 @@
 	add %r3,%r3,%r4		# add contents of table to table address
 	mtctr %r3
 	bctr			# jump to it
-.LFE1:
 
 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
@@ -111,7 +117,9 @@
 .Lret_type0:
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 	nop
 
 # case FFI_TYPE_INT
@@ -119,31 +127,33 @@
 	mtlr %r0
 .Lfinish:
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 
 # case FFI_TYPE_FLOAT
 #ifndef __NO_FPRS__
 	lfs %f1,112+0(%r1)
-	mtlr %r0
-	addi %r1,%r1,144
 #else
 	nop
-	nop
-	nop
 #endif
+	mtlr %r0
+	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 
 # case FFI_TYPE_DOUBLE
 #ifndef __NO_FPRS__
 	lfd %f1,112+0(%r1)
-	mtlr %r0
-	addi %r1,%r1,144
 #else
 	nop
-	nop
-	nop
 #endif
+	mtlr %r0
+	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 
 # case FFI_TYPE_LONGDOUBLE
 #ifndef __NO_FPRS__
@@ -152,10 +162,12 @@
 	mtlr %r0
 	b .Lfinish
 #else
-	nop
-	nop
-	nop
+	mtlr %r0
+	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
+	nop
 #endif
 
 # case FFI_TYPE_UINT8
@@ -166,7 +178,9 @@
 #endif
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 
 # case FFI_TYPE_SINT8
 #ifdef __LITTLE_ENDIAN__
@@ -186,7 +200,9 @@
 #endif
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 
 # case FFI_TYPE_SINT16
 #ifdef __LITTLE_ENDIAN__
@@ -196,19 +212,25 @@
 #endif
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 
 # case FFI_TYPE_UINT32
 	lwz %r3,112+0(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 
 # case FFI_TYPE_SINT32
 	lwz %r3,112+0(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 
 # case FFI_TYPE_UINT64
 	lwz %r3,112+0(%r1)
@@ -225,14 +247,18 @@
 # case FFI_TYPE_STRUCT
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 	nop
 
 # case FFI_TYPE_POINTER
 	lwz %r3,112+0(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 
 # case FFI_TYPE_UINT128
 	lwz %r3,112+0(%r1)
@@ -245,20 +271,26 @@
 	lbz %r3,112+0(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
 	lhz %r3,112+0(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
 	lwz %r3,112+0(%r1)
 #ifdef __LITTLE_ENDIAN__
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 #else
 	srwi %r3,%r3,8
 	mtlr %r0
@@ -269,7 +301,9 @@
 	lwz %r3,112+0(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
 	lwz %r3,112+0(%r1)
@@ -319,64 +353,43 @@
 	or %r4,%r6,%r4
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
+	.cfi_def_cfa_offset 144
 #endif
 
 .Luint128:
 	lwz %r6,112+12(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
+	.cfi_def_cfa_offset 0
 	blr
-
+	.cfi_endproc
 END(ffi_closure_SYSV)
 
-	.section	".eh_frame",EH_FRAME_FLAGS,@progbits
-.Lframe1:
-	.4byte	.LECIE1-.LSCIE1	 # Length of Common Information Entry
-.LSCIE1:
-	.4byte	0x0	 # CIE Identifier Tag
-	.byte	0x1	 # CIE Version
-#if defined _RELOCATABLE || defined __PIC__
-	.ascii "zR\0"	 # CIE Augmentation
-#else
-	.ascii "\0"	 # CIE Augmentation
-#endif
-	.uleb128 0x1	 # CIE Code Alignment Factor
-	.sleb128 -4	 # CIE Data Alignment Factor
-	.byte	0x41	 # CIE RA Column
-#if defined _RELOCATABLE || defined __PIC__
-	.uleb128 0x1	 # Augmentation size
-	.byte	0x1b	 # FDE Encoding (pcrel sdata4)
-#endif
-	.byte	0xc	 # DW_CFA_def_cfa
-	.uleb128 0x1
-	.uleb128 0x0
-	.align 2
-.LECIE1:
-.LSFDE1:
-	.4byte	.LEFDE1-.LASFDE1	 # FDE Length
-.LASFDE1:
-	.4byte	.LASFDE1-.Lframe1	 # FDE CIE offset
-#if defined _RELOCATABLE || defined __PIC__
-	.4byte	.LFB1-.	 # FDE initial location
-#else
-	.4byte	.LFB1	 # FDE initial location
-#endif
-	.4byte	.LFE1-.LFB1	 # FDE address range
-#if defined _RELOCATABLE || defined __PIC__
-	.uleb128 0x0	 # Augmentation size
-#endif
-	.byte	0x4	 # DW_CFA_advance_loc4
-	.4byte	.LCFI0-.LFB1
-	.byte	0xe	 # DW_CFA_def_cfa_offset
-	.uleb128 144
-	.byte	0x4	 # DW_CFA_advance_loc4
-	.4byte	.LCFI1-.LCFI0
-	.byte	0x11	 # DW_CFA_offset_extended_sf
-	.uleb128 0x41
-	.sleb128 -1
-	.align 2
-.LEFDE1:
+
+FFI_HIDDEN(ffi_go_closure_sysv)
+ENTRY(ffi_go_closure_sysv)
+	.cfi_startproc
+	stwu %r1,-144(%r1)
+	.cfi_def_cfa_offset 144
+	mflr %r0
+	stw %r0,148(%r1)
+	.cfi_offset 65, 4
+
+	stw   %r3, 16(%r1)
+	stw   %r4, 20(%r1)
+	stw   %r5, 24(%r1)
+
+	# closure->cif
+	lwz %r3,4(%r11)
+	# closure->fun
+	lwz %r4,8(%r11)
+	# user_data
+	mr %r5,%r11
+	b .Ldoclosure
+	.cfi_endproc
+END(ffi_go_closure_sysv)
 
 #if defined __ELF__ && defined __linux__
 	.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/gofrontend/libffi/src/powerpc/sysv.S b/third_party/gofrontend/libffi/src/powerpc/sysv.S
index fed2380..1474ce7 100644
--- a/third_party/gofrontend/libffi/src/powerpc/sysv.S
+++ b/third_party/gofrontend/libffi/src/powerpc/sysv.S
@@ -31,34 +31,35 @@
 #include <powerpc/asm.h>
 
 #ifndef POWERPC64
-	.globl ffi_prep_args_SYSV
+FFI_HIDDEN(ffi_call_SYSV)
 ENTRY(ffi_call_SYSV)
-.LFB1:
+	.cfi_startproc
 	/* Save the old stack pointer as AP.  */
-	mr	%r8,%r1
+	mr	%r10,%r1
+	.cfi_def_cfa_register 10
 
-.LCFI0:
 	/* Allocate the stack space we need.  */
-	stwux	%r1,%r1,%r4
+	stwux	%r1,%r1,%r8
 	/* Save registers we use.  */
 	mflr	%r9
-	stw	%r28,-16(%r8)
-.LCFI1:
-	stw	%r29,-12(%r8)
-.LCFI2:
-	stw	%r30, -8(%r8)
-.LCFI3:
-	stw	%r31, -4(%r8)
-.LCFI4:
-	stw	%r9,   4(%r8)
-.LCFI5:
+	stw	%r28,-16(%r10)
+	stw	%r29,-12(%r10)
+	stw	%r30, -8(%r10)
+	stw	%r31, -4(%r10)
+	stw	%r9,   4(%r10)
+	.cfi_offset 65, 4
+	.cfi_offset 31, -4
+	.cfi_offset 30, -8
+	.cfi_offset 29, -12
+	.cfi_offset 28, -16
 
 	/* Save arguments over call...  */
-	mr	%r31,%r5	/* flags, */
-	mr	%r30,%r6	/* rvalue, */
-	mr	%r29,%r7	/* function address, */
-	mr	%r28,%r8	/* our AP. */
-.LCFI6:
+	stw	%r7,   -20(%r10)	/* closure, */
+	mr	%r31,%r6		/* flags, */
+	mr	%r30,%r5		/* rvalue, */
+	mr	%r29,%r4		/* function address, */
+	mr	%r28,%r10		/* our AP. */
+	.cfi_def_cfa_register 28
 
 	/* Call ffi_prep_args_SYSV.  */
 	mr	%r4,%r1
@@ -70,35 +71,36 @@
 	/* Get the address to call into CTR.  */
 	mtctr	%r29
 	/* Load all those argument registers.  */
-	lwz	%r3,-16-(8*4)(%r28)
-	lwz	%r4,-16-(7*4)(%r28)
-	lwz	%r5,-16-(6*4)(%r28)
-	lwz	%r6,-16-(5*4)(%r28)
+	lwz	%r3,-24-(8*4)(%r28)
+	lwz	%r4,-24-(7*4)(%r28)
+	lwz	%r5,-24-(6*4)(%r28)
+	lwz	%r6,-24-(5*4)(%r28)
 	bf-	5,1f
 	nop
-	lwz	%r7,-16-(4*4)(%r28)
-	lwz	%r8,-16-(3*4)(%r28)
-	lwz	%r9,-16-(2*4)(%r28)
-	lwz	%r10,-16-(1*4)(%r28)
+	lwz	%r7,-24-(4*4)(%r28)
+	lwz	%r8,-24-(3*4)(%r28)
+	lwz	%r9,-24-(2*4)(%r28)
+	lwz	%r10,-24-(1*4)(%r28)
 	nop
 1:
 
 #ifndef __NO_FPRS__
 	/* Load all the FP registers.  */
 	bf-	6,2f
-	lfd	%f1,-16-(8*4)-(8*8)(%r28)
-	lfd	%f2,-16-(8*4)-(7*8)(%r28)
-	lfd	%f3,-16-(8*4)-(6*8)(%r28)
-	lfd	%f4,-16-(8*4)-(5*8)(%r28)
+	lfd	%f1,-24-(8*4)-(8*8)(%r28)
+	lfd	%f2,-24-(8*4)-(7*8)(%r28)
+	lfd	%f3,-24-(8*4)-(6*8)(%r28)
+	lfd	%f4,-24-(8*4)-(5*8)(%r28)
 	nop
-	lfd	%f5,-16-(8*4)-(4*8)(%r28)
-	lfd	%f6,-16-(8*4)-(3*8)(%r28)
-	lfd	%f7,-16-(8*4)-(2*8)(%r28)
-	lfd	%f8,-16-(8*4)-(1*8)(%r28)
+	lfd	%f5,-24-(8*4)-(4*8)(%r28)
+	lfd	%f6,-24-(8*4)-(3*8)(%r28)
+	lfd	%f7,-24-(8*4)-(2*8)(%r28)
+	lfd	%f8,-24-(8*4)-(1*8)(%r28)
 #endif
 2:
 
 	/* Make the call.  */
+	lwz	%r11, -20(%r28)
 	bctrl
 
 	/* Now, deal with the return value.  */
@@ -125,11 +127,24 @@
 	lwz	%r30, -8(%r28)
 	lwz	%r29,-12(%r28)
 	lwz	%r28,-16(%r28)
+	.cfi_remember_state
+	/* At this point we don't have a cfa register.  Say all our
+	   saved regs have been restored.  */
+	.cfi_same_value 65
+	.cfi_same_value 31
+	.cfi_same_value 30
+	.cfi_same_value 29
+	.cfi_same_value 28
+	/* Hopefully this works..  */
+	.cfi_def_cfa_register 1
+	.cfi_offset 1, 0
 	lwz	%r1,0(%r1)
+	.cfi_same_value 1
 	blr
 
 #ifndef __NO_FPRS__
 L(fp_return_value):
+	.cfi_restore_state
 	bf	28,L(float_return_value)
 	stfd	%f1,0(%r30)
 	mtcrf   0x02,%r31 /* cr6  */
@@ -150,70 +165,10 @@
 	stw %r3, 0(%r30)
 	stw %r4, 4(%r30)
 	b L(done_return_value)
+	.cfi_endproc
 
-.LFE1:
 END(ffi_call_SYSV)
 
-      .section	".eh_frame",EH_FRAME_FLAGS,@progbits
-.Lframe1:
-      .4byte    .LECIE1-.LSCIE1  /*  Length of Common Information Entry */
-.LSCIE1:
-      .4byte    0x0      /*  CIE Identifier Tag */
-      .byte     0x1      /*  CIE Version */
-#if defined _RELOCATABLE || defined __PIC__
-      .ascii	"zR\0"   /*  CIE Augmentation */
-#else
-      .ascii	"\0"	 /*  CIE Augmentation */
-#endif
-      .uleb128  0x1      /*  CIE Code Alignment Factor */
-      .sleb128  -4	 /*  CIE Data Alignment Factor */
-      .byte     0x41     /*  CIE RA Column */
-#if defined _RELOCATABLE || defined __PIC__
-      .uleb128  0x1      /*  Augmentation size */
-      .byte	0x1b	 /*  FDE Encoding (pcrel sdata4) */
-#endif
-      .byte     0xc      /*  DW_CFA_def_cfa */
-      .uleb128  0x1
-      .uleb128  0x0
-      .align 2
-.LECIE1:
-.LSFDE1:
-      .4byte    .LEFDE1-.LASFDE1         /*  FDE Length */
-.LASFDE1:
-      .4byte    .LASFDE1-.Lframe1         /*  FDE CIE offset */
-#if defined _RELOCATABLE || defined __PIC__
-      .4byte    .LFB1-.  /*  FDE initial location */
-#else
-      .4byte    .LFB1    /*  FDE initial location */
-#endif
-      .4byte    .LFE1-.LFB1      /*  FDE address range */
-#if defined _RELOCATABLE || defined __PIC__
-      .uleb128  0x0	 /*  Augmentation size */
-#endif
-      .byte     0x4      /*  DW_CFA_advance_loc4 */
-      .4byte    .LCFI0-.LFB1
-      .byte     0xd      /*  DW_CFA_def_cfa_register */
-      .uleb128  0x08
-      .byte     0x4      /*  DW_CFA_advance_loc4 */
-      .4byte    .LCFI5-.LCFI0
-      .byte     0x11     /*  DW_CFA_offset_extended_sf */
-      .uleb128  0x41
-      .sleb128  -1
-      .byte     0x9f     /*  DW_CFA_offset, column 0x1f */
-      .uleb128  0x1
-      .byte     0x9e     /*  DW_CFA_offset, column 0x1e */
-      .uleb128  0x2
-      .byte     0x9d     /*  DW_CFA_offset, column 0x1d */
-      .uleb128  0x3
-      .byte     0x9c     /*  DW_CFA_offset, column 0x1c */
-      .uleb128  0x4
-      .byte     0x4      /*  DW_CFA_advance_loc4 */
-      .4byte    .LCFI6-.LCFI5
-      .byte     0xd      /*  DW_CFA_def_cfa_register */
-      .uleb128  0x1c
-      .align 2
-.LEFDE1:
-
 #if defined __ELF__ && defined __linux__
 	.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/third_party/gofrontend/libffi/src/prep_cif.c b/third_party/gofrontend/libffi/src/prep_cif.c
index 866ed34..5881ceb 100644
--- a/third_party/gofrontend/libffi/src/prep_cif.c
+++ b/third_party/gofrontend/libffi/src/prep_cif.c
@@ -76,6 +76,13 @@
      total size of 3*sizeof(long).  */
   arg->size = ALIGN (arg->size, arg->alignment);
 
+  /* On some targets, the ABI defines that structures have an additional
+     alignment beyond the "natural" one based on their elements.  */
+#ifdef FFI_AGGREGATE_ALIGNMENT
+  if (FFI_AGGREGATE_ALIGNMENT > arg->alignment)
+    arg->alignment = FFI_AGGREGATE_ALIGNMENT;
+#endif
+
   if (arg->size == 0)
     return FFI_BAD_TYPEDEF;
   else
@@ -111,13 +118,8 @@
   FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
   FFI_ASSERT(nfixedargs <= ntotalargs);
 
-#ifndef X86_WIN32
   if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
     return FFI_BAD_ABI;
-#else
-  if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI || abi == FFI_THISCALL))
-    return FFI_BAD_ABI;
-#endif
 
   cif->abi = abi;
   cif->arg_types = atypes;
@@ -134,19 +136,26 @@
   if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
     return FFI_BAD_TYPEDEF;
 
+#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
+  if (rtype->type == FFI_TYPE_COMPLEX)
+    abort();
+#endif
   /* Perform a sanity check on the return type */
   FFI_ASSERT_VALID_TYPE(cif->rtype);
 
   /* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
-#if !defined M68K && !defined X86_ANY && !defined S390 && !defined PA
+#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
   /* Make space for the return structure pointer */
   if (cif->rtype->type == FFI_TYPE_STRUCT
-#ifdef SPARC
-      && (cif->abi != FFI_V9 || cif->rtype->size > 32)
-#endif
 #ifdef TILE
       && (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
 #endif
+#ifdef XTENSA
+      && (cif->rtype->size > 16)
+#endif
+#ifdef NIOS2
+      && (cif->rtype->size > 8)
+#endif
      )
     bytes = STACK_ARG_SIZE(sizeof(void*));
 #endif
@@ -158,23 +167,19 @@
       if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
 	return FFI_BAD_TYPEDEF;
 
+#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
+      if ((*ptr)->type == FFI_TYPE_COMPLEX)
+	abort();
+#endif
       /* Perform a sanity check on the argument type, do this
 	 check after the initialization.  */
       FFI_ASSERT_VALID_TYPE(*ptr);
 
-#if !defined X86_ANY && !defined S390 && !defined PA
-#ifdef SPARC
-      if (((*ptr)->type == FFI_TYPE_STRUCT
-	   && ((*ptr)->size > 16 || cif->abi != FFI_V9))
-	  || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
-	      && cif->abi != FFI_V9))
-	bytes += sizeof(void*);
-      else
-#endif
+#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
 	{
 	  /* Add any padding if necessary */
 	  if (((*ptr)->alignment - 1) & bytes)
-	    bytes = ALIGN(bytes, (*ptr)->alignment);
+	    bytes = (unsigned)ALIGN(bytes, (*ptr)->alignment);
 
 #ifdef TILE
 	  if (bytes < 10 * FFI_SIZEOF_ARG &&
@@ -185,6 +190,10 @@
 	      bytes = 10 * FFI_SIZEOF_ARG;
 	    }
 #endif
+#ifdef XTENSA
+	  if (bytes <= 6*4 && bytes + STACK_ARG_SIZE((*ptr)->size) > 6*4)
+	    bytes = 6*4;
+#endif
 
 	  bytes += STACK_ARG_SIZE((*ptr)->size);
 	}
diff --git a/third_party/gofrontend/libffi/src/raw_api.c b/third_party/gofrontend/libffi/src/raw_api.c
index ce21372..276cb22 100644
--- a/third_party/gofrontend/libffi/src/raw_api.c
+++ b/third_party/gofrontend/libffi/src/raw_api.c
@@ -88,6 +88,10 @@
 	  break;
 #endif
 
+	case FFI_TYPE_COMPLEX:
+	  *args = (raw++)->ptr;
+	  break;
+
 	case FFI_TYPE_POINTER:
 	  *args = (void*) &(raw++)->ptr;
 	  break;
@@ -112,6 +116,11 @@
 	}
       else
 #endif
+      if ((*tp)->type == FFI_TYPE_COMPLEX)
+	{
+	  *args = (raw++)->ptr;
+	}
+      else
 	{
 	  *args = (void*) raw;
 	  raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
@@ -167,6 +176,10 @@
 	  break;
 #endif
 
+	case FFI_TYPE_COMPLEX:
+	  (raw++)->ptr = *args;
+	  break;
+
 	case FFI_TYPE_POINTER:
 	  (raw++)->ptr = **(void***) args;
 	  break;
diff --git a/third_party/gofrontend/libffi/src/s390/ffi.c b/third_party/gofrontend/libffi/src/s390/ffi.c
index 8adb5bc..4035b6e 100644
--- a/third_party/gofrontend/libffi/src/s390/ffi.c
+++ b/third_party/gofrontend/libffi/src/s390/ffi.c
@@ -1,9 +1,9 @@
 /* -----------------------------------------------------------------------
    ffi.c - Copyright (c) 2000, 2007 Software AG
            Copyright (c) 2008 Red Hat, Inc
- 
+
    S390 Foreign Function Interface
- 
+
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    ``Software''), to deal in the Software without restriction, including
@@ -11,10 +11,10 @@
    distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to
    the following conditions:
- 
+
    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.
- 
+
    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,24 +27,23 @@
 /*                          Includes                                  */
 /*                          --------                                  */
 /*====================================================================*/
- 
+
 #include <ffi.h>
 #include <ffi_common.h>
- 
-#include <stdlib.h>
-#include <stdio.h>
- 
+#include <stdint.h>
+#include "internal.h"
+
 /*====================== End of Includes =============================*/
- 
+
 /*====================================================================*/
 /*                           Defines                                  */
 /*                           -------                                  */
 /*====================================================================*/
 
-/* Maximum number of GPRs available for argument passing.  */ 
+/* Maximum number of GPRs available for argument passing.  */
 #define MAX_GPRARGS 5
 
-/* Maximum number of FPRs available for argument passing.  */ 
+/* Maximum number of FPRs available for argument passing.  */
 #ifdef __s390x__
 #define MAX_FPRARGS 4
 #else
@@ -54,47 +53,30 @@
 /* Round to multiple of 16.  */
 #define ROUND_SIZE(size) (((size) + 15) & ~15)
 
-/* If these values change, sysv.S must be adapted!  */
-#define FFI390_RET_VOID		0
-#define FFI390_RET_STRUCT	1
-#define FFI390_RET_FLOAT	2
-#define FFI390_RET_DOUBLE	3
-#define FFI390_RET_INT32	4
-#define FFI390_RET_INT64	5
-
 /*===================== End of Defines ===============================*/
- 
-/*====================================================================*/
-/*                          Prototypes                                */
-/*                          ----------                                */
-/*====================================================================*/
- 
-static void ffi_prep_args (unsigned char *, extended_cif *);
-void
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
-__attribute__ ((visibility ("hidden")))
-#endif
-ffi_closure_helper_SYSV (ffi_closure *, unsigned long *, 
-			 unsigned long long *, unsigned long *);
 
-/*====================== End of Prototypes ===========================*/
- 
 /*====================================================================*/
 /*                          Externals                                 */
 /*                          ---------                                 */
 /*====================================================================*/
- 
-extern void ffi_call_SYSV(unsigned,
-			  extended_cif *,
-			  void (*)(unsigned char *, extended_cif *),
-			  unsigned,
-			  void *,
-			  void (*fn)(void));
+
+struct call_frame
+{
+  void *back_chain;
+  void *eos;
+  unsigned long gpr_args[5];
+  unsigned long gpr_save[9];
+  unsigned long long fpr_args[4];
+};
+
+extern void FFI_HIDDEN ffi_call_SYSV(struct call_frame *, unsigned, void *,
+			             void (*fn)(void), void *);
 
 extern void ffi_closure_SYSV(void);
- 
+extern void ffi_go_closure_SYSV(void);
+
 /*====================== End of Externals ============================*/
- 
+
 /*====================================================================*/
 /*                                                                    */
 /* Name     - ffi_check_struct_type.                                  */
@@ -103,7 +85,7 @@
 /*            general purpose or floating point register.             */
 /*                                                                    */
 /*====================================================================*/
- 
+
 static int
 ffi_check_struct_type (ffi_type *arg)
 {
@@ -111,7 +93,7 @@
 
   /* If the struct has just one element, look at that element
      to find out whether to consider the struct as floating point.  */
-  while (arg->type == FFI_TYPE_STRUCT 
+  while (arg->type == FFI_TYPE_STRUCT
          && arg->elements[0] && !arg->elements[1])
     arg = arg->elements[0];
 
@@ -144,190 +126,9 @@
   /* Other structs are passed via a pointer to the data.  */
   return FFI_TYPE_POINTER;
 }
- 
-/*======================== End of Routine ============================*/
- 
-/*====================================================================*/
-/*                                                                    */
-/* Name     - ffi_prep_args.                                          */
-/*                                                                    */
-/* Function - Prepare parameters for call to function.                */
-/*                                                                    */
-/* ffi_prep_args is called by the assembly routine once stack space   */
-/* has been allocated for the function's arguments.                   */
-/*                                                                    */
-/*====================================================================*/
- 
-static void
-ffi_prep_args (unsigned char *stack, extended_cif *ecif)
-{
-  /* The stack space will be filled with those areas:
-
-	FPR argument register save area     (highest addresses)
-	GPR argument register save area
-	temporary struct copies
-	overflow argument area              (lowest addresses)
-
-     We set up the following pointers:
-
-        p_fpr: bottom of the FPR area (growing upwards)
-	p_gpr: bottom of the GPR area (growing upwards)
-	p_ov: bottom of the overflow area (growing upwards)
-	p_struct: top of the struct copy area (growing downwards)
-
-     All areas are kept aligned to twice the word size.  */
-
-  int gpr_off = ecif->cif->bytes;
-  int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long));
-
-  unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off);
-  unsigned long *p_gpr = (unsigned long *)(stack + gpr_off);
-  unsigned char *p_struct = (unsigned char *)p_gpr;
-  unsigned long *p_ov = (unsigned long *)stack;
-
-  int n_fpr = 0;
-  int n_gpr = 0;
-  int n_ov = 0;
-
-  ffi_type **ptr;
-  void **p_argv = ecif->avalue;
-  int i;
- 
-  /* If we returning a structure then we set the first parameter register
-     to the address of where we are returning this structure.  */
-
-  if (ecif->cif->flags == FFI390_RET_STRUCT)
-    p_gpr[n_gpr++] = (unsigned long) ecif->rvalue;
-
-  /* Now for the arguments.  */
- 
-  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
-       i > 0;
-       i--, ptr++, p_argv++)
-    {
-      void *arg = *p_argv;
-      int type = (*ptr)->type;
-
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-      /* 16-byte long double is passed like a struct.  */
-      if (type == FFI_TYPE_LONGDOUBLE)
-	type = FFI_TYPE_STRUCT;
-#endif
-
-      /* Check how a structure type is passed.  */
-      if (type == FFI_TYPE_STRUCT)
-	{
-	  type = ffi_check_struct_type (*ptr);
-
-	  /* If we pass the struct via pointer, copy the data.  */
-	  if (type == FFI_TYPE_POINTER)
-	    {
-	      p_struct -= ROUND_SIZE ((*ptr)->size);
-	      memcpy (p_struct, (char *)arg, (*ptr)->size);
-	      arg = &p_struct;
-	    }
-	}
-
-      /* Now handle all primitive int/pointer/float data types.  */
-      switch (type) 
-	{
-	  case FFI_TYPE_DOUBLE:
-	    if (n_fpr < MAX_FPRARGS)
-	      p_fpr[n_fpr++] = *(unsigned long long *) arg;
-	    else
-#ifdef __s390x__
-	      p_ov[n_ov++] = *(unsigned long *) arg;
-#else
-	      p_ov[n_ov++] = ((unsigned long *) arg)[0],
-	      p_ov[n_ov++] = ((unsigned long *) arg)[1];
-#endif
-	    break;
-	
-	  case FFI_TYPE_FLOAT:
-	    if (n_fpr < MAX_FPRARGS)
-	      p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32;
-	    else
-	      p_ov[n_ov++] = *(unsigned int *) arg;
-	    break;
-
-	  case FFI_TYPE_POINTER:
-	    if (n_gpr < MAX_GPRARGS)
-	      p_gpr[n_gpr++] = (unsigned long)*(unsigned char **) arg;
-	    else
-	      p_ov[n_ov++] = (unsigned long)*(unsigned char **) arg;
-	    break;
- 
-	  case FFI_TYPE_UINT64:
-	  case FFI_TYPE_SINT64:
-#ifdef __s390x__
-	    if (n_gpr < MAX_GPRARGS)
-	      p_gpr[n_gpr++] = *(unsigned long *) arg;
-	    else
-	      p_ov[n_ov++] = *(unsigned long *) arg;
-#else
-	    if (n_gpr == MAX_GPRARGS-1)
-	      n_gpr = MAX_GPRARGS;
-	    if (n_gpr < MAX_GPRARGS)
-	      p_gpr[n_gpr++] = ((unsigned long *) arg)[0],
-	      p_gpr[n_gpr++] = ((unsigned long *) arg)[1];
-	    else
-	      p_ov[n_ov++] = ((unsigned long *) arg)[0],
-	      p_ov[n_ov++] = ((unsigned long *) arg)[1];
-#endif
-	    break;
- 
-	  case FFI_TYPE_UINT32:
-	    if (n_gpr < MAX_GPRARGS)
-	      p_gpr[n_gpr++] = *(unsigned int *) arg;
-	    else
-	      p_ov[n_ov++] = *(unsigned int *) arg;
-	    break;
- 
-	  case FFI_TYPE_INT:
-	  case FFI_TYPE_SINT32:
-	    if (n_gpr < MAX_GPRARGS)
-	      p_gpr[n_gpr++] = *(signed int *) arg;
-	    else
-	      p_ov[n_ov++] = *(signed int *) arg;
-	    break;
- 
-	  case FFI_TYPE_UINT16:
-	    if (n_gpr < MAX_GPRARGS)
-	      p_gpr[n_gpr++] = *(unsigned short *) arg;
-	    else
-	      p_ov[n_ov++] = *(unsigned short *) arg;
-	    break;
- 
-	  case FFI_TYPE_SINT16:
-	    if (n_gpr < MAX_GPRARGS)
-	      p_gpr[n_gpr++] = *(signed short *) arg;
-	    else
-	      p_ov[n_ov++] = *(signed short *) arg;
-	    break;
-
-	  case FFI_TYPE_UINT8:
-	    if (n_gpr < MAX_GPRARGS)
-	      p_gpr[n_gpr++] = *(unsigned char *) arg;
-	    else
-	      p_ov[n_ov++] = *(unsigned char *) arg;
-	    break;
- 
-	  case FFI_TYPE_SINT8:
-	    if (n_gpr < MAX_GPRARGS)
-	      p_gpr[n_gpr++] = *(signed char *) arg;
-	    else
-	      p_ov[n_ov++] = *(signed char *) arg;
-	    break;
- 
-	  default:
-	    FFI_ASSERT (0);
-	    break;
-        }
-    }
-}
 
 /*======================== End of Routine ============================*/
- 
+
 /*====================================================================*/
 /*                                                                    */
 /* Name     - ffi_prep_cif_machdep.                                   */
@@ -335,8 +136,8 @@
 /* Function - Perform machine dependent CIF processing.               */
 /*                                                                    */
 /*====================================================================*/
- 
-ffi_status
+
+ffi_status FFI_HIDDEN
 ffi_prep_cif_machdep(ffi_cif *cif)
 {
   size_t struct_size = 0;
@@ -347,7 +148,7 @@
   ffi_type **ptr;
   int i;
 
-  /* Determine return value handling.  */ 
+  /* Determine return value handling.  */
 
   switch (cif->rtype->type)
     {
@@ -356,11 +157,12 @@
 	cif->flags = FFI390_RET_VOID;
 	break;
 
-      /* Structures are returned via a hidden pointer.  */
+      /* Structures and complex are returned via a hidden pointer.  */
       case FFI_TYPE_STRUCT:
+      case FFI_TYPE_COMPLEX:
 	cif->flags = FFI390_RET_STRUCT;
 	n_gpr++;  /* We need one GPR to pass the pointer.  */
-	break; 
+	break;
 
       /* Floating point values are returned in fpr 0.  */
       case FFI_TYPE_FLOAT:
@@ -399,14 +201,14 @@
 	cif->flags = FFI390_RET_INT32;
 #endif
 	break;
- 
+
       default:
         FFI_ASSERT (0);
         break;
     }
 
   /* Now for the arguments.  */
- 
+
   for (ptr = cif->arg_types, i = cif->nargs;
        i > 0;
        i--, ptr++)
@@ -420,9 +222,12 @@
 #endif
 
       /* Check how a structure type is passed.  */
-      if (type == FFI_TYPE_STRUCT)
+      if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
 	{
-	  type = ffi_check_struct_type (*ptr);
+	  if (type == FFI_TYPE_COMPLEX)
+	    type = FFI_TYPE_POINTER;
+	  else
+	    type = ffi_check_struct_type (*ptr);
 
 	  /* If we pass the struct via pointer, we must reserve space
 	     to copy its data for proper call-by-value semantics.  */
@@ -431,7 +236,7 @@
 	}
 
       /* Now handle all primitive int/float data types.  */
-      switch (type) 
+      switch (type)
 	{
 	  /* The first MAX_FPRARGS floating point arguments
 	     go in FPRs, the rest overflow to the stack.  */
@@ -442,7 +247,7 @@
 	    else
 	      n_ov += sizeof (double) / sizeof (long);
 	    break;
-	
+
 	  case FFI_TYPE_FLOAT:
 	    if (n_fpr < MAX_FPRARGS)
 	      n_fpr++;
@@ -452,9 +257,9 @@
 
 	  /* On 31-bit machines, 64-bit integers are passed in GPR pairs,
 	     if one is still available, or else on the stack.  If only one
-	     register is free, skip the register (it won't be used for any 
+	     register is free, skip the register (it won't be used for any
 	     subsequent argument either).  */
-	      
+
 #ifndef __s390x__
 	  case FFI_TYPE_UINT64:
 	  case FFI_TYPE_SINT64:
@@ -470,7 +275,7 @@
 	  /* Everything else is passed in GPRs (until MAX_GPRARGS
 	     have been used) or overflows to the stack.  */
 
-	  default: 
+	  default:
 	    if (n_gpr < MAX_GPRARGS)
 	      n_gpr++;
 	    else
@@ -483,12 +288,12 @@
      and temporary structure copies.  */
 
   cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
- 
+
   return FFI_OK;
 }
- 
+
 /*======================== End of Routine ============================*/
- 
+
 /*====================================================================*/
 /*                                                                    */
 /* Name     - ffi_call.                                               */
@@ -496,42 +301,195 @@
 /* Function - Call the FFI routine.                                   */
 /*                                                                    */
 /*====================================================================*/
- 
-void
-ffi_call(ffi_cif *cif,
-	 void (*fn)(void),
-	 void *rvalue,
-	 void **avalue)
+
+static void
+ffi_call_int(ffi_cif *cif,
+	     void (*fn)(void),
+	     void *rvalue,
+	     void **avalue,
+	     void *closure)
 {
   int ret_type = cif->flags;
-  extended_cif ecif;
- 
-  ecif.cif    = cif;
-  ecif.avalue = avalue;
-  ecif.rvalue = rvalue;
+  size_t rsize = 0, bytes = cif->bytes;
+  unsigned char *stack, *p_struct;
+  struct call_frame *frame;
+  unsigned long *p_ov, *p_gpr;
+  unsigned long long *p_fpr;
+  int n_fpr, n_gpr, n_ov, i, n;
+  ffi_type **arg_types;
+
+  FFI_ASSERT (cif->abi == FFI_SYSV);
 
   /* If we don't have a return value, we need to fake one.  */
   if (rvalue == NULL)
     {
-      if (ret_type == FFI390_RET_STRUCT)
-	ecif.rvalue = alloca (cif->rtype->size);
+      if (ret_type & FFI390_RET_IN_MEM)
+	rsize = cif->rtype->size;
       else
 	ret_type = FFI390_RET_VOID;
-    } 
-
-  switch (cif->abi)
-    {
-      case FFI_SYSV:
-        ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
-		       ret_type, ecif.rvalue, fn);
-        break;
- 
-      default:
-        FFI_ASSERT (0);
-        break;
     }
+
+  /* The stack space will be filled with those areas:
+
+	dummy structure return		    (highest addresses)
+	  FPR argument register save area
+	  GPR argument register save area
+	stack frame for ffi_call_SYSV
+	temporary struct copies
+	overflow argument area              (lowest addresses)
+
+     We set up the following pointers:
+
+        p_fpr: bottom of the FPR area (growing upwards)
+	p_gpr: bottom of the GPR area (growing upwards)
+	p_ov: bottom of the overflow area (growing upwards)
+	p_struct: top of the struct copy area (growing downwards)
+
+     All areas are kept aligned to twice the word size.
+
+     Note that we're going to create the stack frame for both
+     ffi_call_SYSV _and_ the target function right here.  This
+     works because we don't make any function calls with more
+     than 5 arguments (indeed only memcpy and ffi_call_SYSV),
+     and thus we don't have any stacked outgoing parameters.  */
+
+  stack = alloca (bytes + sizeof(struct call_frame) + rsize);
+  frame = (struct call_frame *)(stack + bytes);
+  if (rsize)
+    rvalue = frame + 1;
+
+  /* Link the new frame back to the one from this function.  */
+  frame->back_chain = __builtin_frame_address (0);
+
+  /* Fill in all of the argument stuff.  */
+  p_ov = (unsigned long *)stack;
+  p_struct = (unsigned char *)frame;
+  p_gpr = frame->gpr_args;
+  p_fpr = frame->fpr_args;
+  n_fpr = n_gpr = n_ov = 0;
+
+  /* If we returning a structure then we set the first parameter register
+     to the address of where we are returning this structure.  */
+  if (cif->flags & FFI390_RET_IN_MEM)
+    p_gpr[n_gpr++] = (uintptr_t) rvalue;
+
+  /* Now for the arguments.  */
+  arg_types = cif->arg_types;
+  for (i = 0, n = cif->nargs; i < n; ++i)
+    {
+      ffi_type *ty = arg_types[i];
+      void *arg = avalue[i];
+      int type = ty->type;
+      ffi_arg val;
+
+    restart:
+      switch (type)
+	{
+	case FFI_TYPE_SINT8:
+	  val = *(SINT8 *)arg;
+	  goto do_int;
+	case FFI_TYPE_UINT8:
+	  val = *(UINT8 *)arg;
+	  goto do_int;
+	case FFI_TYPE_SINT16:
+	  val = *(SINT16 *)arg;
+	  goto do_int;
+	case FFI_TYPE_UINT16:
+	  val = *(UINT16 *)arg;
+	  goto do_int;
+	case FFI_TYPE_INT:
+	case FFI_TYPE_SINT32:
+	  val = *(SINT32 *)arg;
+	  goto do_int;
+	case FFI_TYPE_UINT32:
+	  val = *(UINT32 *)arg;
+	  goto do_int;
+	case FFI_TYPE_POINTER:
+	  val = *(uintptr_t *)arg;
+	do_int:
+	  *(n_gpr < MAX_GPRARGS ? p_gpr + n_gpr++ : p_ov + n_ov++) = val;
+	  break;
+
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+#ifdef __s390x__
+	  val = *(UINT64 *)arg;
+	  goto do_int;
+#else
+	  if (n_gpr == MAX_GPRARGS-1)
+	    n_gpr = MAX_GPRARGS;
+	  if (n_gpr < MAX_GPRARGS)
+	    p_gpr[n_gpr++] = ((UINT32 *) arg)[0],
+	    p_gpr[n_gpr++] = ((UINT32 *) arg)[1];
+	  else
+	    p_ov[n_ov++] = ((UINT32 *) arg)[0],
+	    p_ov[n_ov++] = ((UINT32 *) arg)[1];
+#endif
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  if (n_fpr < MAX_FPRARGS)
+	    p_fpr[n_fpr++] = *(UINT64 *) arg;
+	  else
+	    {
+#ifdef __s390x__
+	      p_ov[n_ov++] = *(UINT64 *) arg;
+#else
+	      p_ov[n_ov++] = ((UINT32 *) arg)[0],
+	      p_ov[n_ov++] = ((UINT32 *) arg)[1];
+#endif
+	    }
+	  break;
+
+	case FFI_TYPE_FLOAT:
+	  val = *(UINT32 *)arg;
+	  if (n_fpr < MAX_FPRARGS)
+	    p_fpr[n_fpr++] = (UINT64)val << 32;
+	  else
+	    p_ov[n_ov++] = val;
+	  break;
+
+	case FFI_TYPE_STRUCT:
+          /* Check how a structure type is passed.  */
+	  type = ffi_check_struct_type (ty);
+	  /* Some structures are passed via a type they contain.  */
+	  if (type != FFI_TYPE_POINTER)
+	    goto restart;
+	  /* ... otherwise, passed by reference.  fallthru.  */
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+	  /* 16-byte long double is passed via reference.  */
+#endif
+	case FFI_TYPE_COMPLEX:
+	  /* Complex types are passed via reference.  */
+	  p_struct -= ROUND_SIZE (ty->size);
+	  memcpy (p_struct, arg, ty->size);
+	  val = (uintptr_t)p_struct;
+	  goto do_int;
+
+	default:
+	  FFI_ASSERT (0);
+	  break;
+        }
+    }
+
+  ffi_call_SYSV (frame, ret_type & FFI360_RET_MASK, rvalue, fn, closure);
 }
- 
+
+void
+ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  ffi_call_int(cif, fn, rvalue, avalue, NULL);
+}
+
+void
+ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
+	     void **avalue, void *closure)
+{
+  ffi_call_int(cif, fn, rvalue, avalue, closure);
+}
+
 /*======================== End of Routine ============================*/
 
 /*====================================================================*/
@@ -541,9 +499,11 @@
 /* Function - Call a FFI closure target function.                     */
 /*                                                                    */
 /*====================================================================*/
- 
-void
-ffi_closure_helper_SYSV (ffi_closure *closure,
+
+void FFI_HIDDEN
+ffi_closure_helper_SYSV (ffi_cif *cif,
+			 void (*fun)(ffi_cif*,void*,void**,void*),
+			 void *user_data,
 			 unsigned long *p_gpr,
 			 unsigned long long *p_fpr,
 			 unsigned long *p_ov)
@@ -562,21 +522,16 @@
   int i;
 
   /* Allocate buffer for argument list pointers.  */
+  p_arg = avalue = alloca (cif->nargs * sizeof (void *));
 
-  p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *));
-
-  /* If we returning a structure, pass the structure address 
-     directly to the target function.  Otherwise, have the target 
+  /* If we returning a structure, pass the structure address
+     directly to the target function.  Otherwise, have the target
      function store the return value to the GPR save area.  */
-
-  if (closure->cif->flags == FFI390_RET_STRUCT)
+  if (cif->flags & FFI390_RET_IN_MEM)
     rvalue = (void *) p_gpr[n_gpr++];
 
   /* Now for the arguments.  */
-
-  for (ptr = closure->cif->arg_types, i = closure->cif->nargs;
-       i > 0;
-       i--, p_arg++, ptr++)
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, p_arg++, ptr++)
     {
       int deref_struct_pointer = 0;
       int type = (*ptr)->type;
@@ -588,11 +543,14 @@
 #endif
 
       /* Check how a structure type is passed.  */
-      if (type == FFI_TYPE_STRUCT)
+      if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
 	{
-	  type = ffi_check_struct_type (*ptr);
+	  if (type == FFI_TYPE_COMPLEX)
+	    type = FFI_TYPE_POINTER;
+	  else
+	    type = ffi_check_struct_type (*ptr);
 
-	  /* If we pass the struct via pointer, remember to 
+	  /* If we pass the struct via pointer, remember to
 	     retrieve the pointer later.  */
 	  if (type == FFI_TYPE_POINTER)
 	    deref_struct_pointer = 1;
@@ -600,30 +558,32 @@
 
       /* Pointers are passed like UINTs of the same size.  */
       if (type == FFI_TYPE_POINTER)
+	{
 #ifdef __s390x__
-	type = FFI_TYPE_UINT64;
+	  type = FFI_TYPE_UINT64;
 #else
-	type = FFI_TYPE_UINT32;
+	  type = FFI_TYPE_UINT32;
 #endif
+	}
 
       /* Now handle all primitive int/float data types.  */
-      switch (type) 
+      switch (type)
 	{
 	  case FFI_TYPE_DOUBLE:
 	    if (n_fpr < MAX_FPRARGS)
 	      *p_arg = &p_fpr[n_fpr++];
 	    else
-	      *p_arg = &p_ov[n_ov], 
+	      *p_arg = &p_ov[n_ov],
 	      n_ov += sizeof (double) / sizeof (long);
 	    break;
-	
+
 	  case FFI_TYPE_FLOAT:
 	    if (n_fpr < MAX_FPRARGS)
 	      *p_arg = &p_fpr[n_fpr++];
 	    else
 	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
 	    break;
- 
+
 	  case FFI_TYPE_UINT64:
 	  case FFI_TYPE_SINT64:
 #ifdef __s390x__
@@ -640,7 +600,7 @@
 	      *p_arg = &p_ov[n_ov], n_ov += 2;
 #endif
 	    break;
- 
+
 	  case FFI_TYPE_INT:
 	  case FFI_TYPE_UINT32:
 	  case FFI_TYPE_SINT32:
@@ -649,7 +609,7 @@
 	    else
 	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
 	    break;
- 
+
 	  case FFI_TYPE_UINT16:
 	  case FFI_TYPE_SINT16:
 	    if (n_gpr < MAX_GPRARGS)
@@ -665,7 +625,7 @@
 	    else
 	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1;
 	    break;
- 
+
 	  default:
 	    FFI_ASSERT (0);
 	    break;
@@ -679,14 +639,15 @@
 
 
   /* Call the target function.  */
-  (closure->fun) (closure->cif, rvalue, avalue, closure->user_data);
+  (fun) (cif, rvalue, avalue, user_data);
 
   /* Convert the return value.  */
-  switch (closure->cif->rtype->type)
+  switch (cif->rtype->type)
     {
       /* Void is easy, and so is struct.  */
       case FFI_TYPE_VOID:
       case FFI_TYPE_STRUCT:
+      case FFI_TYPE_COMPLEX:
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
       case FFI_TYPE_LONGDOUBLE:
 #endif
@@ -732,7 +693,7 @@
         break;
     }
 }
- 
+
 /*======================== End of Routine ============================*/
 
 /*====================================================================*/
@@ -742,7 +703,7 @@
 /* Function - Prepare a FFI closure.                                  */
 /*                                                                    */
 /*====================================================================*/
- 
+
 ffi_status
 ffi_prep_closure_loc (ffi_closure *closure,
 		      ffi_cif *cif,
@@ -750,32 +711,46 @@
 		      void *user_data,
 		      void *codeloc)
 {
+  static unsigned short const template[] = {
+    0x0d10,			/* basr %r1,0 */
+#ifndef __s390x__
+    0x9801, 0x1006,		/* lm %r0,%r1,6(%r1) */
+#else
+    0xeb01, 0x100e, 0x0004,	/* lmg %r0,%r1,14(%r1) */
+#endif
+    0x07f1			/* br %r1 */
+  };
+
+  unsigned long *tramp = (unsigned long *)&closure->tramp;
+
   if (cif->abi != FFI_SYSV)
     return FFI_BAD_ABI;
 
-#ifndef __s390x__
-  *(short *)&closure->tramp [0] = 0x0d10;   /* basr %r1,0 */
-  *(short *)&closure->tramp [2] = 0x9801;   /* lm %r0,%r1,6(%r1) */
-  *(short *)&closure->tramp [4] = 0x1006;
-  *(short *)&closure->tramp [6] = 0x07f1;   /* br %r1 */
-  *(long  *)&closure->tramp [8] = (long)codeloc;
-  *(long  *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
-#else
-  *(short *)&closure->tramp [0] = 0x0d10;   /* basr %r1,0 */
-  *(short *)&closure->tramp [2] = 0xeb01;   /* lmg %r0,%r1,14(%r1) */
-  *(short *)&closure->tramp [4] = 0x100e;
-  *(short *)&closure->tramp [6] = 0x0004;
-  *(short *)&closure->tramp [8] = 0x07f1;   /* br %r1 */
-  *(long  *)&closure->tramp[16] = (long)codeloc;
-  *(long  *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
-#endif 
- 
+  memcpy (tramp, template, sizeof(template));
+  tramp[2] = (unsigned long)codeloc;
+  tramp[3] = (unsigned long)&ffi_closure_SYSV;
+
   closure->cif = cif;
-  closure->user_data = user_data;
   closure->fun = fun;
- 
+  closure->user_data = user_data;
+
   return FFI_OK;
 }
 
 /*======================== End of Routine ============================*/
- 
+
+/* Build a Go language closure.  */
+
+ffi_status
+ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
+		     void (*fun)(ffi_cif*,void*,void**,void*))
+{
+  if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+  closure->tramp = ffi_go_closure_SYSV;
+  closure->cif = cif;
+  closure->fun = fun;
+
+  return FFI_OK;
+}
diff --git a/third_party/gofrontend/libffi/src/s390/ffitarget.h b/third_party/gofrontend/libffi/src/s390/ffitarget.h
index 97fa5c4..d8a4ee4 100644
--- a/third_party/gofrontend/libffi/src/s390/ffitarget.h
+++ b/third_party/gofrontend/libffi/src/s390/ffitarget.h
@@ -52,10 +52,13 @@
 } ffi_abi;
 #endif
 
+#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
+#define FFI_TARGET_HAS_COMPLEX_TYPE
 
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
+#define FFI_GO_CLOSURES 1
 #ifdef S390X
 #define FFI_TRAMPOLINE_SIZE 32
 #else
diff --git a/third_party/gofrontend/libffi/src/s390/internal.h b/third_party/gofrontend/libffi/src/s390/internal.h
new file mode 100644
index 0000000..b875578
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/s390/internal.h
@@ -0,0 +1,11 @@
+/* If these values change, sysv.S must be adapted!  */
+#define FFI390_RET_DOUBLE	0
+#define FFI390_RET_FLOAT	1
+#define FFI390_RET_INT64	2
+#define FFI390_RET_INT32	3
+#define FFI390_RET_VOID		4
+
+#define FFI360_RET_MASK		7
+#define FFI390_RET_IN_MEM	8
+
+#define FFI390_RET_STRUCT	(FFI390_RET_VOID | FFI390_RET_IN_MEM)
diff --git a/third_party/gofrontend/libffi/src/s390/sysv.S b/third_party/gofrontend/libffi/src/s390/sysv.S
index 4731a31..c4b5006 100644
--- a/third_party/gofrontend/libffi/src/s390/sysv.S
+++ b/third_party/gofrontend/libffi/src/s390/sysv.S
@@ -1,9 +1,9 @@
 /* -----------------------------------------------------------------------
    sysv.S - Copyright (c) 2000 Software AG
             Copyright (c) 2008 Red Hat, Inc.
- 
+
    S390 Foreign Function Interface
- 
+
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    ``Software''), to deal in the Software without restriction, including
@@ -11,10 +11,10 @@
    distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to
    the following conditions:
- 
+
    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.
- 
+
    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -29,405 +29,296 @@
 #include <fficonfig.h>
 #include <ffi.h>
 
-#ifndef __s390x__
- 
-.text
+	.text
 
-	# r2:	cif->bytes
-	# r3:	&ecif
-	# r4:	ffi_prep_args
-	# r5:	ret_type
-	# r6:	ecif.rvalue
-	# ov:	fn 
- 
+#ifndef __s390x__
+
+	# r2:	frame
+	# r3:	ret_type
+	# r4:	ret_addr
+	# r5:	fun
+	# r6:	closure
+
 	# This assumes we are using gas.
+	.balign	8
 	.globl	ffi_call_SYSV
+	FFI_HIDDEN(ffi_call_SYSV)
 	.type	ffi_call_SYSV,%function
 ffi_call_SYSV:
-.LFB1:
-	stm	%r6,%r15,24(%r15)		# Save registers
-.LCFI0:
-	basr	%r13,0				# Set up base register
-.Lbase:
-	lr	%r11,%r15			# Set up frame pointer
-.LCFI1:
-	sr	%r15,%r2
-	ahi	%r15,-96-48			# Allocate stack
-	lr	%r8,%r6				# Save ecif.rvalue
-	sr	%r9,%r9
-	ic	%r9,.Ltable-.Lbase(%r13,%r5)	# Load epilog address
-	l	%r7,96(%r11)			# Load function address
-	st	%r11,0(%r15)			# Set up back chain
-	ahi	%r11,-48			# Register save area
-.LCFI2:
+	.cfi_startproc
+	st	%r6,44(%r2)			# Save registers
+	stm	%r12,%r14,48(%r2)
+	lr	%r13,%r2			# Install frame pointer
+	.cfi_rel_offset r6, 44
+	.cfi_rel_offset r12, 48
+	.cfi_rel_offset r13, 52
+	.cfi_rel_offset r14, 56
+	.cfi_def_cfa_register r13
+	st	%r2,0(%r15)			# Set up back chain
+	sla	%r3,3				# ret_type *= 8
+	lr	%r12,%r4			# Save ret_addr
+	lr	%r1,%r5				# Save fun
+	lr	%r0,%r6				# Install static chain
 
-	la	%r2,96(%r15)			# Save area
-						# r3 already holds &ecif
-	basr	%r14,%r4			# Call ffi_prep_args
+	# Set return address, so that there is only one indirect jump.
+#ifdef HAVE_AS_S390_ZARCH
+	larl	%r14,.Ltable
+	ar	%r14,%r3
+#else
+	basr	%r14,0
+0:	la	%r14,.Ltable-0b(%r14,%r3)
+#endif
 
-	lm	%r2,%r6,0(%r11)			# Load arguments
-	ld	%f0,32(%r11)
-	ld	%f2,40(%r11)
-	la	%r14,0(%r13,%r9)		# Set return address
-	br	%r7				# ... and call function
+	lm	%r2,%r6,8(%r13)			# Load arguments
+	ld	%f0,64(%r13)
+	ld	%f2,72(%r13)
+	br	%r1				# ... and call function
 
-.LretNone:					# Return void
-	l	%r4,48+56(%r11)
-	lm	%r6,%r15,48+24(%r11)
-	br	%r4
-
-.LretFloat:
-	l	%r4,48+56(%r11)
-	ste	%f0,0(%r8)			# Return float
-	lm	%r6,%r15,48+24(%r11)
-	br	%r4
- 
-.LretDouble:
-	l	%r4,48+56(%r11)
-	std	%f0,0(%r8)			# Return double
-	lm	%r6,%r15,48+24(%r11)
-	br	%r4
-
-.LretInt32:
-	l	%r4,48+56(%r11)
-	st	%r2,0(%r8)			# Return int
-	lm	%r6,%r15,48+24(%r11)
-	br	%r4
- 
-.LretInt64:
-	l	%r4,48+56(%r11)
-	stm	%r2,%r3,0(%r8)			# Return long long
-	lm	%r6,%r15,48+24(%r11)
-	br	%r4
- 
+	.balign	8
 .Ltable:
-	.byte	.LretNone-.Lbase		# FFI390_RET_VOID
-	.byte	.LretNone-.Lbase		# FFI390_RET_STRUCT
-	.byte	.LretFloat-.Lbase		# FFI390_RET_FLOAT
-	.byte	.LretDouble-.Lbase		# FFI390_RET_DOUBLE
-	.byte	.LretInt32-.Lbase		# FFI390_RET_INT32
-	.byte	.LretInt64-.Lbase		# FFI390_RET_INT64
+# FFI390_RET_DOUBLE
+	std	%f0,0(%r12)
+	j	.Ldone
 
-.LFE1: 
-.ffi_call_SYSV_end:
-	.size	 ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
+	.balign	8
+# FFI390_RET_FLOAT
+	ste	%f0,0(%r12)
+	j	.Ldone
+
+	.balign	8
+# FFI390_RET_INT64
+	st	%r3,4(%r12)
+	nop
+	# fallthru
+
+	.balign	8
+# FFI390_RET_INT32
+	st	%r2,0(%r12)
+	nop
+	# fallthru
+
+	.balign	8
+# FFI390_RET_VOID
+.Ldone:
+	l	%r14,56(%r13)
+	l	%r12,48(%r13)
+	l	%r6,44(%r13)
+	l	%r13,52(%r13)
+	.cfi_restore 14
+	.cfi_restore 13
+	.cfi_restore 12
+	.cfi_restore 6
+	.cfi_def_cfa r15, 96
+	br	%r14
+	.cfi_endproc
+	.size	 ffi_call_SYSV,.-ffi_call_SYSV
 
 
+	.balign	8
+	.globl	ffi_go_closure_SYSV
+	FFI_HIDDEN(ffi_go_closure_SYSV)
+	.type	ffi_go_closure_SYSV,%function
+ffi_go_closure_SYSV:
+	.cfi_startproc
+	stm	%r2,%r6,8(%r15)			# Save arguments
+	lr	%r4,%r0				# Load closure -> user_data
+	l	%r2,4(%r4)			#   ->cif
+	l	%r3,8(%r4)			#   ->fun
+	j	.Ldoclosure
+	.cfi_endproc
+
+	.balign	8
 	.globl	ffi_closure_SYSV
+	FFI_HIDDEN(ffi_closure_SYSV)
 	.type	ffi_closure_SYSV,%function
 ffi_closure_SYSV:
-.LFB2:
+	.cfi_startproc
+	stm	%r2,%r6,8(%r15)			# Save arguments
+	lr	%r4,%r0				# Closure
+	l	%r2,16(%r4)			#   ->cif
+	l	%r3,20(%r4)			#   ->fun
+	l	%r4,24(%r4)			#   ->user_data
+.Ldoclosure:
 	stm	%r12,%r15,48(%r15)		# Save registers
-.LCFI10:
+	lr	%r12,%r15
+	.cfi_def_cfa_register r12
+	.cfi_rel_offset r6, 24
+	.cfi_rel_offset r12, 48
+	.cfi_rel_offset r13, 52
+	.cfi_rel_offset r14, 56
+	.cfi_rel_offset r15, 60
+#ifndef HAVE_AS_S390_ZARCH
 	basr	%r13,0				# Set up base register
 .Lcbase:
-	stm	%r2,%r6,8(%r15)			# Save arguments
-	std	%f0,64(%r15)
-	std	%f2,72(%r15)
-	lr	%r1,%r15			# Set up stack frame
-	ahi	%r15,-96
-.LCFI11:
-	l	%r12,.Lchelper-.Lcbase(%r13)	# Get helper function
-	lr	%r2,%r0				# Closure
-	la	%r3,8(%r1)			# GPRs
-	la	%r4,64(%r1)			# FPRs
-	la	%r5,96(%r1)			# Overflow
-	st	%r1,0(%r15)			# Set up back chain
+	l	%r1,.Lchelper-.Lcbase(%r13)	# Get helper function
+#endif
+	ahi	%r15,-96-8			# Set up stack frame
+	st	%r12,0(%r15)			# Set up back chain
 
-	bas	%r14,0(%r12,%r13)		# Call helper
+	std	%f0,64(%r12)			# Save fp arguments
+	std	%f2,72(%r12)
 
-	l	%r4,96+56(%r15)
-	ld	%f0,96+64(%r15)			# Load return registers
-	lm	%r2,%r3,96+8(%r15)
-	lm	%r12,%r15,96+48(%r15)
-	br	%r4
+	la	%r5,96(%r12)			# Overflow
+	st	%r5,96(%r15)
+	la	%r6,64(%r12)			# FPRs
+	la	%r5,8(%r12)			# GPRs
+#ifdef HAVE_AS_S390_ZARCH
+	brasl	%r14,ffi_closure_helper_SYSV
+#else
+	bas	%r14,0(%r1,%r13)		# Call helper
+#endif
 
+	lr	%r15,%r12
+	.cfi_def_cfa_register r15
+	lm	%r12,%r14,48(%r12)		# Restore saved registers
+	l	%r6,24(%r15)
+	ld	%f0,64(%r15)			# Load return registers
+	lm	%r2,%r3,8(%r15)
+	br	%r14
+	.cfi_endproc
+
+#ifndef HAVE_AS_S390_ZARCH
 	.align 4
 .Lchelper:
 	.long	ffi_closure_helper_SYSV-.Lcbase
+#endif
 
-.LFE2: 
-
-.ffi_closure_SYSV_end:
-	.size	 ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
-
-
-	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
-.Lframe1:
-	.4byte	.LECIE1-.LSCIE1	# Length of Common Information Entry
-.LSCIE1:
-	.4byte	0x0	# CIE Identifier Tag
-	.byte	0x1	# CIE Version
-	.ascii "zR\0"	# CIE Augmentation
-	.uleb128 0x1	# CIE Code Alignment Factor
-	.sleb128 -4	# CIE Data Alignment Factor
-	.byte	0xe	# CIE RA Column
-	.uleb128 0x1	# Augmentation size
-	.byte	0x1b	# FDE Encoding (pcrel sdata4)
-	.byte	0xc	# DW_CFA_def_cfa
-	.uleb128 0xf
-	.uleb128 0x60
-	.align	4
-.LECIE1:
-.LSFDE1:
-	.4byte	.LEFDE1-.LASFDE1	# FDE Length
-.LASFDE1:
-	.4byte	.LASFDE1-.Lframe1	# FDE CIE offset
-	.4byte	.LFB1-.	# FDE initial location
-	.4byte	.LFE1-.LFB1	# FDE address range
-	.uleb128 0x0	# Augmentation size
-	.byte	0x4	# DW_CFA_advance_loc4
-	.4byte	.LCFI0-.LFB1
-	.byte	0x8f	# DW_CFA_offset, column 0xf
-	.uleb128 0x9
-	.byte	0x8e	# DW_CFA_offset, column 0xe
-	.uleb128 0xa
-	.byte	0x8d	# DW_CFA_offset, column 0xd
-	.uleb128 0xb
-	.byte	0x8c	# DW_CFA_offset, column 0xc
-	.uleb128 0xc
-	.byte	0x8b	# DW_CFA_offset, column 0xb
-	.uleb128 0xd
-	.byte	0x8a	# DW_CFA_offset, column 0xa
-	.uleb128 0xe
-	.byte	0x89	# DW_CFA_offset, column 0x9
-	.uleb128 0xf
-	.byte	0x88	# DW_CFA_offset, column 0x8
-	.uleb128 0x10
-	.byte	0x87	# DW_CFA_offset, column 0x7
-	.uleb128 0x11
-	.byte	0x86	# DW_CFA_offset, column 0x6
-	.uleb128 0x12
-	.byte	0x4	# DW_CFA_advance_loc4
-	.4byte	.LCFI1-.LCFI0
-	.byte	0xd	# DW_CFA_def_cfa_register
-	.uleb128 0xb
-	.byte	0x4	# DW_CFA_advance_loc4
-	.4byte	.LCFI2-.LCFI1
-	.byte	0xe	# DW_CFA_def_cfa_offset
-	.uleb128 0x90
-	.align	4
-.LEFDE1:
-.LSFDE2:
-	.4byte	.LEFDE2-.LASFDE2	# FDE Length
-.LASFDE2:
-	.4byte	.LASFDE2-.Lframe1	# FDE CIE offset
-	.4byte	.LFB2-.	# FDE initial location
-	.4byte	.LFE2-.LFB2	# FDE address range
-	.uleb128 0x0	# Augmentation size
-	.byte	0x4	# DW_CFA_advance_loc4
-	.4byte	.LCFI10-.LFB2
-	.byte	0x8f	# DW_CFA_offset, column 0xf
-	.uleb128 0x9
-	.byte	0x8e	# DW_CFA_offset, column 0xe
-	.uleb128 0xa
-	.byte	0x8d	# DW_CFA_offset, column 0xd
-	.uleb128 0xb
-	.byte	0x8c	# DW_CFA_offset, column 0xc
-	.uleb128 0xc
-	.byte	0x4	# DW_CFA_advance_loc4
-	.4byte	.LCFI11-.LCFI10
-	.byte	0xe	# DW_CFA_def_cfa_offset
-	.uleb128 0xc0
-	.align	4
-.LEFDE2:
+	.size	 ffi_closure_SYSV,.-ffi_closure_SYSV
 
 #else
- 
-.text
- 
-	# r2:	cif->bytes
-	# r3:	&ecif
-	# r4:	ffi_prep_args
-	# r5:	ret_type
-	# r6:	ecif.rvalue
-	# ov:	fn 
- 
+
+	# r2:	frame
+	# r3:	ret_type
+	# r4:	ret_addr
+	# r5:	fun
+	# r6:	closure
+
 	# This assumes we are using gas.
+	.balign	8
 	.globl	ffi_call_SYSV
+	FFI_HIDDEN(ffi_call_SYSV)
 	.type	ffi_call_SYSV,%function
 ffi_call_SYSV:
-.LFB1:
-	stmg	%r6,%r15,48(%r15)		# Save registers
-.LCFI0:
-	larl	%r13,.Lbase			# Set up base register
-	lgr	%r11,%r15			# Set up frame pointer
-.LCFI1:
-	sgr	%r15,%r2
-	aghi	%r15,-160-80			# Allocate stack
-	lgr	%r8,%r6				# Save ecif.rvalue
-	llgc	%r9,.Ltable-.Lbase(%r13,%r5)	# Load epilog address
-	lg	%r7,160(%r11)			# Load function address
-	stg	%r11,0(%r15)			# Set up back chain
-	aghi	%r11,-80			# Register save area
-.LCFI2:
+	.cfi_startproc
+	stg	%r6,88(%r2)			# Save registers
+	stmg	%r12,%r14,96(%r2)
+	lgr	%r13,%r2			# Install frame pointer
+	.cfi_rel_offset r6, 88
+	.cfi_rel_offset r12, 96
+	.cfi_rel_offset r13, 104
+	.cfi_rel_offset r14, 112
+	.cfi_def_cfa_register r13
+	stg	%r2,0(%r15)			# Set up back chain
+	larl	%r14,.Ltable			# Set up return address
+	slag	%r3,%r3,3			# ret_type *= 8
+	lgr	%r12,%r4			# Save ret_addr
+	lgr	%r1,%r5				# Save fun
+	lgr	%r0,%r6				# Install static chain
+	agr	%r14,%r3
+	lmg	%r2,%r6,16(%r13)		# Load arguments
+	ld	%f0,128(%r13)
+	ld	%f2,136(%r13)
+	ld	%f4,144(%r13)
+	ld	%f6,152(%r13)
+	br	%r1				# ... and call function
 
-	la	%r2,160(%r15)			# Save area
-						# r3 already holds &ecif
-	basr	%r14,%r4			# Call ffi_prep_args
-
-	lmg	%r2,%r6,0(%r11)			# Load arguments
-	ld	%f0,48(%r11)
-	ld	%f2,56(%r11)
-	ld	%f4,64(%r11)
-	ld	%f6,72(%r11)
-	la	%r14,0(%r13,%r9)		# Set return address
-	br	%r7				# ... and call function
-
-.Lbase:
-.LretNone:					# Return void
-	lg	%r4,80+112(%r11)
-	lmg	%r6,%r15,80+48(%r11)
-	br	%r4
-
-.LretFloat:
-	lg	%r4,80+112(%r11)
-	ste	%f0,0(%r8)			# Return float
-	lmg	%r6,%r15,80+48(%r11)
-	br	%r4
- 
-.LretDouble:
-	lg	%r4,80+112(%r11)
-	std	%f0,0(%r8)			# Return double
-	lmg	%r6,%r15,80+48(%r11)
-	br	%r4
-
-.LretInt32:
-	lg	%r4,80+112(%r11)
-	st	%r2,0(%r8)			# Return int
-	lmg	%r6,%r15,80+48(%r11)
-	br	%r4
- 
-.LretInt64:
-	lg	%r4,80+112(%r11)
-	stg	%r2,0(%r8)			# Return long
-	lmg	%r6,%r15,80+48(%r11)
-	br	%r4
- 
+	.balign	8
 .Ltable:
-	.byte	.LretNone-.Lbase		# FFI390_RET_VOID
-	.byte	.LretNone-.Lbase		# FFI390_RET_STRUCT
-	.byte	.LretFloat-.Lbase		# FFI390_RET_FLOAT
-	.byte	.LretDouble-.Lbase		# FFI390_RET_DOUBLE
-	.byte	.LretInt32-.Lbase		# FFI390_RET_INT32
-	.byte	.LretInt64-.Lbase		# FFI390_RET_INT64
+# FFI390_RET_DOUBLE
+	std	%f0,0(%r12)
+	j	.Ldone
 
-.LFE1: 
-.ffi_call_SYSV_end:
-	.size	 ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
+	.balign	8
+# FFI390_RET_DOUBLE
+	ste	%f0,0(%r12)
+	j	.Ldone
+
+	.balign	8
+# FFI390_RET_INT64
+	stg	%r2,0(%r12)
+
+	.balign	8
+# FFI390_RET_INT32
+	# Never used, as we always store type ffi_arg.
+	# But the stg above is 6 bytes and we cannot
+	# jump around this case, so fall through.
+	nop
+	nop
+
+	.balign	8
+# FFI390_RET_VOID
+.Ldone:
+	lg	%r14,112(%r13)
+	lg	%r12,96(%r13)
+	lg	%r6,88(%r13)
+	lg	%r13,104(%r13)
+	.cfi_restore r14
+	.cfi_restore r13
+	.cfi_restore r12
+	.cfi_restore r6
+	.cfi_def_cfa r15, 160
+	br	%r14
+	.cfi_endproc
+	.size	 ffi_call_SYSV,.-ffi_call_SYSV
 
 
+	.balign	8
+	.globl	ffi_go_closure_SYSV
+	FFI_HIDDEN(ffi_go_closure_SYSV)
+	.type	ffi_go_closure_SYSV,%function
+ffi_go_closure_SYSV:
+	.cfi_startproc
+	stmg	%r2,%r6,16(%r15)		# Save arguments
+	lgr	%r4,%r0				# Load closure -> user_data
+	lg	%r2,8(%r4)			#   ->cif
+	lg	%r3,16(%r4)			#   ->fun
+	j	.Ldoclosure
+	.cfi_endproc
+	.size	 ffi_go_closure_SYSV,.-ffi_go_closure_SYSV
+
+
+	.balign	8
 	.globl	ffi_closure_SYSV
+	FFI_HIDDEN(ffi_closure_SYSV)
 	.type	ffi_closure_SYSV,%function
 ffi_closure_SYSV:
-.LFB2:
-	stmg	%r14,%r15,112(%r15)		# Save registers
-.LCFI10:
+	.cfi_startproc
 	stmg	%r2,%r6,16(%r15)		# Save arguments
-	std	%f0,128(%r15)
-	std	%f2,136(%r15)
-	std	%f4,144(%r15)
-	std	%f6,152(%r15)
-	lgr	%r1,%r15			# Set up stack frame
-	aghi	%r15,-160
-.LCFI11:
-	lgr	%r2,%r0				# Closure
-	la	%r3,16(%r1)			# GPRs
-	la	%r4,128(%r1)			# FPRs
-	la	%r5,160(%r1)			# Overflow
-	stg	%r1,0(%r15)			# Set up back chain
+	lgr	%r4,%r0				# Load closure
+	lg	%r2,32(%r4)			#   ->cif
+	lg	%r3,40(%r4)			#   ->fun
+	lg	%r4,48(%r4)			#   ->user_data
+.Ldoclosure:
+	stmg	%r13,%r15,104(%r15)		# Save registers
+	lgr	%r13,%r15
+	.cfi_def_cfa_register r13
+	.cfi_rel_offset r6, 48
+	.cfi_rel_offset r13, 104
+	.cfi_rel_offset r14, 112
+	.cfi_rel_offset r15, 120
+	aghi	%r15,-160-16			# Set up stack frame
+	stg	%r13,0(%r15)			# Set up back chain
 
+	std	%f0,128(%r13)			# Save fp arguments
+	std	%f2,136(%r13)
+	std	%f4,144(%r13)
+	std	%f6,152(%r13)
+	la	%r5,160(%r13)			# Overflow
+	stg	%r5,160(%r15)
+	la	%r6,128(%r13)			# FPRs
+	la	%r5,16(%r13)			# GPRs
 	brasl	%r14,ffi_closure_helper_SYSV	# Call helper
 
-	lg	%r14,160+112(%r15)
-	ld	%f0,160+128(%r15)		# Load return registers
-	lg	%r2,160+16(%r15)
-	la	%r15,160(%r15)
+	lgr	%r15,%r13
+	.cfi_def_cfa_register r15
+	lmg	%r13,%r14,104(%r13)		# Restore saved registers
+	lg	%r6,48(%r15)
+	ld	%f0,128(%r15)			# Load return registers
+	lg	%r2,16(%r15)
 	br	%r14
-.LFE2: 
-
-.ffi_closure_SYSV_end:
-	.size	 ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
-
-
-
-	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
-.Lframe1:
-	.4byte	.LECIE1-.LSCIE1	# Length of Common Information Entry
-.LSCIE1:
-	.4byte	0x0	# CIE Identifier Tag
-	.byte	0x1	# CIE Version
-	.ascii "zR\0"	# CIE Augmentation
-	.uleb128 0x1	# CIE Code Alignment Factor
-	.sleb128 -8	# CIE Data Alignment Factor
-	.byte	0xe	# CIE RA Column
-	.uleb128 0x1	# Augmentation size
-	.byte	0x1b	# FDE Encoding (pcrel sdata4)
-	.byte	0xc	# DW_CFA_def_cfa
-	.uleb128 0xf
-	.uleb128 0xa0
-	.align	8
-.LECIE1:
-.LSFDE1:
-	.4byte	.LEFDE1-.LASFDE1	# FDE Length
-.LASFDE1:
-	.4byte	.LASFDE1-.Lframe1	# FDE CIE offset
-	.4byte	.LFB1-.	# FDE initial location
-	.4byte	.LFE1-.LFB1	# FDE address range
-	.uleb128 0x0	# Augmentation size
-	.byte	0x4	# DW_CFA_advance_loc4
-	.4byte	.LCFI0-.LFB1
-	.byte	0x8f	# DW_CFA_offset, column 0xf
-	.uleb128 0x5
-	.byte	0x8e	# DW_CFA_offset, column 0xe
-	.uleb128 0x6
-	.byte	0x8d	# DW_CFA_offset, column 0xd
-	.uleb128 0x7
-	.byte	0x8c	# DW_CFA_offset, column 0xc
-	.uleb128 0x8
-	.byte	0x8b	# DW_CFA_offset, column 0xb
-	.uleb128 0x9
-	.byte	0x8a	# DW_CFA_offset, column 0xa
-	.uleb128 0xa
-	.byte	0x89	# DW_CFA_offset, column 0x9
-	.uleb128 0xb
-	.byte	0x88	# DW_CFA_offset, column 0x8
-	.uleb128 0xc
-	.byte	0x87	# DW_CFA_offset, column 0x7
-	.uleb128 0xd
-	.byte	0x86	# DW_CFA_offset, column 0x6
-	.uleb128 0xe
-	.byte	0x4	# DW_CFA_advance_loc4
-	.4byte	.LCFI1-.LCFI0
-	.byte	0xd	# DW_CFA_def_cfa_register
-	.uleb128 0xb
-	.byte	0x4	# DW_CFA_advance_loc4
-	.4byte	.LCFI2-.LCFI1
-	.byte	0xe	# DW_CFA_def_cfa_offset
-	.uleb128 0xf0
-	.align	8
-.LEFDE1:
-.LSFDE2:
-	.4byte	.LEFDE2-.LASFDE2	# FDE Length
-.LASFDE2:
-	.4byte	.LASFDE2-.Lframe1	# FDE CIE offset
-	.4byte	.LFB2-.	# FDE initial location
-	.4byte	.LFE2-.LFB2	# FDE address range
-	.uleb128 0x0	# Augmentation size
-	.byte	0x4	# DW_CFA_advance_loc4
-	.4byte	.LCFI10-.LFB2
-	.byte	0x8f	# DW_CFA_offset, column 0xf
-	.uleb128 0x5
-	.byte	0x8e	# DW_CFA_offset, column 0xe
-	.uleb128 0x6
-	.byte	0x4	# DW_CFA_advance_loc4
-	.4byte	.LCFI11-.LCFI10
-	.byte	0xe	# DW_CFA_def_cfa_offset
-	.uleb128 0x140
-	.align	8
-.LEFDE2:
-
-#endif
+	.cfi_endproc
+	.size	 ffi_closure_SYSV,.-ffi_closure_SYSV
+#endif /* !s390x */
 
 #if defined __ELF__ && defined __linux__
 	.section	.note.GNU-stack,"",@progbits
diff --git a/third_party/gofrontend/libffi/src/sh/ffi.c b/third_party/gofrontend/libffi/src/sh/ffi.c
index 3515b91..9ec86bf 100644
--- a/third_party/gofrontend/libffi/src/sh/ffi.c
+++ b/third_party/gofrontend/libffi/src/sh/ffi.c
@@ -41,7 +41,7 @@
 #define STRUCT_VALUE_ADDRESS_WITH_ARG 0
 #endif
 
-/* If the structure has essentialy an unique element, return its type.  */
+/* If the structure has essentially an unique element, return its type.  */
 static int
 simple_type (ffi_type *arg)
 {
diff --git a/third_party/gofrontend/libffi/src/sparc/ffi.c b/third_party/gofrontend/libffi/src/sparc/ffi.c
index 77e3822..d5212d8 100644
--- a/third_party/gofrontend/libffi/src/sparc/ffi.c
+++ b/third_party/gofrontend/libffi/src/sparc/ffi.c
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------
-   ffi.c - Copyright (c) 2011 Anthony Green
+   ffi.c - Copyright (c) 2011, 2013 Anthony Green
            Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
-
+   
    SPARC Foreign Function Interface 
 
    Permission is hereby granted, free of charge, to any person obtaining
@@ -27,697 +27,442 @@
 
 #include <ffi.h>
 #include <ffi_common.h>
-
 #include <stdlib.h>
+#include "internal.h"
 
+#ifndef SPARC64
 
-/* ffi_prep_args is called by the assembly routine once stack space
-   has been allocated for the function's arguments */
-
-#ifdef SPARC64
-
-int
-ffi_prep_args_v9(char *stack, extended_cif *ecif)
-{
-  int i, ret = 0;
-  int tmp;
-  void **p_argv;
-  char *argp;
-  ffi_type **p_arg;
-
-  tmp = 0;
-
-  /* Skip 16 words for the window save area */
-  argp = stack + 16*sizeof(long long);
-
-#ifdef USING_PURIFY
-  /* Purify will probably complain in our assembly routine, unless we
-     zero out this memory. */
-
-  ((long long*)argp)[0] = 0;
-  ((long long*)argp)[1] = 0;
-  ((long long*)argp)[2] = 0;
-  ((long long*)argp)[3] = 0;
-  ((long long*)argp)[4] = 0;
-  ((long long*)argp)[5] = 0;
-#endif
-
-  p_argv = ecif->avalue;
-
-  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT &&
-      ecif->cif->rtype->size > 32)
-    {
-      *(unsigned long long *) argp = (unsigned long)ecif->rvalue;
-      argp += sizeof(long long);
-      tmp = 1;
-    }
-
-  for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
-       i++, p_arg++)
-    {
-      size_t z;
-
-      z = (*p_arg)->size;
-      switch ((*p_arg)->type)
-	{
-	case FFI_TYPE_STRUCT:
-	  if (z > 16)
-	    {
-	      /* For structures larger than 16 bytes we pass reference.  */
-	      *(unsigned long long *) argp = (unsigned long)* p_argv;
-	      argp += sizeof(long long);
-	      tmp++;
-	      p_argv++;
-	      continue;
-	    }
-	  /* FALLTHROUGH */
-	case FFI_TYPE_FLOAT:
-	case FFI_TYPE_DOUBLE:
+/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
+   all further uses in this file will refer to the 128-bit type.  */
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	case FFI_TYPE_LONGDOUBLE:
-#endif
-	  ret = 1; /* We should promote into FP regs as well as integer.  */
-	  break;
-	}
-      if (z < sizeof(long long))
-	{
-	  switch ((*p_arg)->type)
-	    {
-	    case FFI_TYPE_SINT8:
-	      *(signed long long *) argp = *(SINT8 *)(* p_argv);
-	      break;
-
-	    case FFI_TYPE_UINT8:
-	      *(unsigned long long *) argp = *(UINT8 *)(* p_argv);
-	      break;
-
-	    case FFI_TYPE_SINT16:
-	      *(signed long long *) argp = *(SINT16 *)(* p_argv);
-	      break;
-
-	    case FFI_TYPE_UINT16:
-	      *(unsigned long long *) argp = *(UINT16 *)(* p_argv);
-	      break;
-
-	    case FFI_TYPE_SINT32:
-	      *(signed long long *) argp = *(SINT32 *)(* p_argv);
-	      break;
-
-	    case FFI_TYPE_UINT32:
-	      *(unsigned long long *) argp = *(UINT32 *)(* p_argv);
-	      break;
-
-	    case FFI_TYPE_FLOAT:
-	      *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */
-	      break;
-
-	    case FFI_TYPE_STRUCT:
-	      memcpy(argp, *p_argv, z);
-	      break;
-
-	    default:
-	      FFI_ASSERT(0);
-	    }
-	  z = sizeof(long long);
-	  tmp++;
-	}
-      else if (z == sizeof(long long))
-	{
-	  memcpy(argp, *p_argv, z);
-	  z = sizeof(long long);
-	  tmp++;
-	}
-      else
-	{
-	  if ((tmp & 1) && (*p_arg)->alignment > 8)
-	    {
-	      tmp++;
-	      argp += sizeof(long long);
-	    }
-	  memcpy(argp, *p_argv, z);
-	  z = 2 * sizeof(long long);
-	  tmp += 2;
-	}
-      p_argv++;
-      argp += z;
-    }
-
-  return ret;
-}
-
+# if FFI_TYPE_LONGDOUBLE != 4
+#  error FFI_TYPE_LONGDOUBLE out of date
+# endif
 #else
-
-void
-ffi_prep_args_v8(char *stack, extended_cif *ecif)
-{
-  int i;
-  void **p_argv;
-  char *argp;
-  ffi_type **p_arg;
-
-  /* Skip 16 words for the window save area */
-  argp = stack + 16*sizeof(int);
-
-  /* This should only really be done when we are returning a structure,
-     however, it's faster just to do it all the time...
-
-  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
-  *(int *) argp = (long)ecif->rvalue;
-
-  /* And 1 word for the  structure return value. */
-  argp += sizeof(int);
-
-#ifdef USING_PURIFY
-  /* Purify will probably complain in our assembly routine, unless we
-     zero out this memory. */
-
-  ((int*)argp)[0] = 0;
-  ((int*)argp)[1] = 0;
-  ((int*)argp)[2] = 0;
-  ((int*)argp)[3] = 0;
-  ((int*)argp)[4] = 0;
-  ((int*)argp)[5] = 0;
-#endif
-
-  p_argv = ecif->avalue;
-
-  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
-    {
-      size_t z;
-
-	  if ((*p_arg)->type == FFI_TYPE_STRUCT
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	      || (*p_arg)->type == FFI_TYPE_LONGDOUBLE
-#endif
-	      )
-	    {
-	      *(unsigned int *) argp = (unsigned long)(* p_argv);
-	      z = sizeof(int);
-	    }
-	  else
-	    {
-	      z = (*p_arg)->size;
-	      if (z < sizeof(int))
-		{
-		  z = sizeof(int);
-		  switch ((*p_arg)->type)
-		    {
-		    case FFI_TYPE_SINT8:
-		      *(signed int *) argp = *(SINT8 *)(* p_argv);
-		      break;
-		      
-		    case FFI_TYPE_UINT8:
-		      *(unsigned int *) argp = *(UINT8 *)(* p_argv);
-		      break;
-		      
-		    case FFI_TYPE_SINT16:
-		      *(signed int *) argp = *(SINT16 *)(* p_argv);
-		      break;
-		      
-		    case FFI_TYPE_UINT16:
-		      *(unsigned int *) argp = *(UINT16 *)(* p_argv);
-		      break;
-
-		    default:
-		      FFI_ASSERT(0);
-		    }
-		}
-	      else
-		{
-		  memcpy(argp, *p_argv, z);
-		}
-	    }
-	  p_argv++;
-	  argp += z;
-    }
-  
-  return;
-}
-
+# undef FFI_TYPE_LONGDOUBLE
+# define FFI_TYPE_LONGDOUBLE 4
 #endif
 
 /* Perform machine dependent cif processing */
-
-static
-ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
+ffi_status FFI_HIDDEN
+ffi_prep_cif_machdep(ffi_cif *cif)
 {
-  int wordsize;
-
-  if (!V9_ABI_P (cif->abi))
-    {
-      wordsize = 4;
-
-      /* If we are returning a struct, this will already have been added.
-	 Otherwise we need to add it because it's always got to be there! */
-
-      if (cif->rtype->type != FFI_TYPE_STRUCT)
-	cif->bytes += wordsize;
-
-      /* sparc call frames require that space is allocated for 6 args,
-	 even if they aren't used. Make that space if necessary. */
-  
-      if (cif->bytes < 4*6+4)
-	cif->bytes = 4*6+4;
-    }
-  else
-    {
-      wordsize = 8;
-
-      /* sparc call frames require that space is allocated for 6 args,
-	 even if they aren't used. Make that space if necessary. */
-  
-      if (cif->bytes < 8*6)
-	cif->bytes = 8*6;
-    }
-
-  /* Adjust cif->bytes. to include 16 words for the window save area,
-     and maybe the struct/union return pointer area, */
-
-  cif->bytes += 16 * wordsize;
-
-  /* The stack must be 2 word aligned, so round bytes up
-     appropriately. */
-
-  cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
+  ffi_type *rtype = cif->rtype;
+  int rtt = rtype->type;
+  size_t bytes;
+  int i, n, flags;
 
   /* Set the return type flag */
-  switch (cif->rtype->type)
+  switch (rtt)
     {
     case FFI_TYPE_VOID:
+      flags = SPARC_RET_VOID;
+      break;
     case FFI_TYPE_FLOAT:
+      flags = SPARC_RET_F_1;
+      break;
     case FFI_TYPE_DOUBLE:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      flags = SPARC_RET_F_2;
+      break;
     case FFI_TYPE_LONGDOUBLE:
-#endif
-      cif->flags = cif->rtype->type;
-      break;
-
     case FFI_TYPE_STRUCT:
-      if (V9_ABI_P (cif->abi) && cif->rtype->size > 32)
-	cif->flags = FFI_TYPE_VOID;
-      else
-	cif->flags = FFI_TYPE_STRUCT;
+      flags = (rtype->size & 0xfff) << SPARC_SIZEMASK_SHIFT;
+      flags |= SPARC_RET_STRUCT;
       break;
-
     case FFI_TYPE_SINT8:
-    case FFI_TYPE_UINT8:
-    case FFI_TYPE_SINT16:
-    case FFI_TYPE_UINT16:
-      if (V9_ABI_P (cif->abi))
-	cif->flags = FFI_TYPE_INT;
-      else
-	cif->flags = cif->rtype->type;
+      flags = SPARC_RET_SINT8;
       break;
-
+    case FFI_TYPE_UINT8:
+      flags = SPARC_RET_UINT8;
+      break;
+    case FFI_TYPE_SINT16:
+      flags = SPARC_RET_SINT16;
+      break;
+    case FFI_TYPE_UINT16:
+      flags = SPARC_RET_UINT16;
+      break;
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_POINTER:
+      flags = SPARC_RET_UINT32;
+      break;
     case FFI_TYPE_SINT64:
     case FFI_TYPE_UINT64:
-      if (V9_ABI_P (cif->abi))
-	cif->flags = FFI_TYPE_INT;
-      else
-	cif->flags = FFI_TYPE_SINT64;
+      flags = SPARC_RET_INT64;
       break;
-
+    case FFI_TYPE_COMPLEX:
+      rtt = rtype->elements[0]->type;
+      switch (rtt)
+	{
+	case FFI_TYPE_FLOAT:
+	  flags = SPARC_RET_F_2;
+	  break;
+	case FFI_TYPE_DOUBLE:
+	  flags = SPARC_RET_F_4;
+	  break;
+	case FFI_TYPE_LONGDOUBLE:
+	  flags = SPARC_RET_F_8;
+	  break;
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	  flags = SPARC_RET_INT128;
+	  break;
+	case FFI_TYPE_INT:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+	  flags = SPARC_RET_INT64;
+	  break;
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+	  flags = SP_V8_RET_CPLX16;
+	  break;
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT8:
+	  flags = SP_V8_RET_CPLX8;
+	  break;
+	default:
+	  abort();
+	}
+      break;
     default:
-      cif->flags = FFI_TYPE_INT;
-      break;
+      abort();
     }
+  cif->flags = flags;
+
+  bytes = 0;
+  for (i = 0, n = cif->nargs; i < n; ++i)
+    {
+      ffi_type *ty = cif->arg_types[i];
+      size_t z = ty->size;
+      int tt = ty->type;
+
+      switch (tt)
+	{
+	case FFI_TYPE_STRUCT:
+	case FFI_TYPE_LONGDOUBLE:
+	by_reference:
+	  /* Passed by reference.  */
+	  z = 4;
+	  break;
+
+	case FFI_TYPE_COMPLEX:
+	  tt = ty->elements[0]->type;
+	  if (tt == FFI_TYPE_FLOAT || z > 8)
+	    goto by_reference;
+	  /* FALLTHRU */
+
+	default:
+	  z = ALIGN(z, 4);
+	}
+      bytes += z;
+    }
+
+  /* Sparc call frames require that space is allocated for 6 args,
+     even if they aren't used. Make that space if necessary.  */
+  if (bytes < 6 * 4)
+    bytes = 6 * 4;
+
+  /* The ABI always requires space for the struct return pointer.  */
+  bytes += 4;
+
+  /* The stack must be 2 word aligned, so round bytes up appropriately. */
+  bytes = ALIGN(bytes, 2 * 4);
+
+  /* Include the call frame to prep_args.  */
+  bytes += 4*16 + 4*8;
+  cif->bytes = bytes;
+
   return FFI_OK;
 }
 
-ffi_status
-ffi_prep_cif_machdep(ffi_cif *cif)
+extern void ffi_call_v8(ffi_cif *cif, void (*fn)(void), void *rvalue,
+			void **avalue, size_t bytes, void *closure) FFI_HIDDEN;
+
+int FFI_HIDDEN
+ffi_prep_args_v8(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
 {
-#ifdef SPARC64
-  if (cif->abi != FFI_COMPAT_V9)
-    cif->nfixedargs = cif->nargs;
-#endif
-  return ffi_prep_cif_machdep_core (cif);
-}
+  ffi_type **p_arg;
+  int flags = cif->flags;
+  int i, nargs;
 
-ffi_status
-ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs,
-			 unsigned int ntotalargs)
-{
-#ifdef SPARC64
-  if (cif->abi != FFI_COMPAT_V9)
-    cif->nfixedargs = nfixedargs;
-#endif
-  return ffi_prep_cif_machdep_core (cif);
-}
-
-#ifdef SPARC64
-
-int
-ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
-{
-  ffi_type **ptr = &arg->elements[0];
-
-  while (*ptr != NULL)
+  if (rvalue == NULL)
     {
-      if (off & ((*ptr)->alignment - 1))
-	off = ALIGN(off, (*ptr)->alignment);
+      if ((flags & SPARC_FLAG_RET_MASK) == SPARC_RET_STRUCT)
+	{
+	  /* Since we pass the pointer to the callee, we need a value.
+	     We allowed for this space in ffi_call, before ffi_call_v8
+	     alloca'd the space.  */
+	  rvalue = (char *)argp + cif->bytes;
+	}
+      else
+	{
+	  /* Otherwise, we can ignore the return value.  */
+	  flags = SPARC_RET_VOID;
+	}
+    }
 
-      switch ((*ptr)->type)
+  /* This could only really be done when we are returning a structure.
+     However, the space is reserved so we can do it unconditionally.  */
+  *argp++ = (unsigned long)rvalue;
+
+#ifdef USING_PURIFY
+  /* Purify will probably complain in our assembly routine,
+     unless we zero out this memory. */
+  memset(argp, 0, 6*4);
+#endif
+
+  p_arg = cif->arg_types;
+  for (i = 0, nargs = cif->nargs; i < nargs; i++)
+    {
+      ffi_type *ty = p_arg[i];
+      void *a = avalue[i];
+      int tt = ty->type;
+      size_t z;
+
+      switch (tt)
 	{
 	case FFI_TYPE_STRUCT:
-	  off = ffi_v9_layout_struct(*ptr, off, ret, intg, flt);
-	  off = ALIGN(off, FFI_SIZEOF_ARG);
-	  break;
-	case FFI_TYPE_FLOAT:
-	case FFI_TYPE_DOUBLE:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 	case FFI_TYPE_LONGDOUBLE:
-#endif
-	  memmove(ret + off, flt + off, (*ptr)->size);
-	  off += (*ptr)->size;
+	by_reference:
+	  *argp++ = (unsigned long)a;
 	  break;
-	default:
-	  memmove(ret + off, intg + off, (*ptr)->size);
-	  off += (*ptr)->size;
+
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	  memcpy(argp, a, 8);
+	  argp += 2;
 	  break;
-	}
-      ptr++;
-    }
-  return off;
-}
 
-#endif
+	case FFI_TYPE_INT:
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_POINTER:
+	  *argp++ = *(unsigned *)a;
+	  break;
 
-#ifdef SPARC64
-extern int ffi_call_v9(void *, extended_cif *, unsigned, 
-		       unsigned, unsigned *, void (*fn)(void));
-#else
-extern int ffi_call_v8(void *, extended_cif *, unsigned, 
-		       unsigned, unsigned *, void (*fn)(void));
-#endif
+	case FFI_TYPE_UINT8:
+	  *argp++ = *(UINT8 *)a;
+	  break;
+	case FFI_TYPE_SINT8:
+	  *argp++ = *(SINT8 *)a;
+	  break;
+	case FFI_TYPE_UINT16:
+	  *argp++ = *(UINT16 *)a;
+	  break;
+	case FFI_TYPE_SINT16:
+	  *argp++ = *(SINT16 *)a;
+	  break;
 
-void
-ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
-{
-  extended_cif ecif;
-#ifdef SPARC64
-  void *rval = rvalue;
-#endif
-
-  ecif.cif = cif;
-  ecif.avalue = avalue;
-  ecif.rvalue = rvalue;
-
-  /* If the return value is a struct and we don't have a return value address,
-     then we need to make one.  */
-  if (cif->rtype->type == FFI_TYPE_STRUCT)
-    {
-      if (ecif.rvalue == NULL)
-	ecif.rvalue = alloca(cif->rtype->size);
-
-#ifdef SPARC64
-      if (cif->rtype->size <= 32)
-	rval = alloca(64);
-      else
-	rval = NULL;
-#endif
-    }
-
-  switch (cif->abi) 
-    {
-    case FFI_V8:
-    case FFI_V8PLUS:
-#ifdef SPARC64
-      /* We don't yet support calling 32bit code from 64bit */
-      FFI_ASSERT(0);
-#else
-      if (rvalue && (cif->rtype->type == FFI_TYPE_STRUCT
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	  || cif->flags == FFI_TYPE_LONGDOUBLE
-#endif
-	  ))
-	{
-	  /* For v8, we need an "unimp" with size of returning struct */
-	  /* behind "call", so we alloc some executable space for it. */
-	  /* l7 is used, we need to make sure v8.S doesn't use %l7.   */
-	  unsigned int *call_struct = NULL;
-	  ffi_closure_alloc(32, (void **)&call_struct);
-	  if (call_struct)
+        case FFI_TYPE_COMPLEX:
+	  tt = ty->elements[0]->type;
+	  z = ty->size;
+	  if (tt == FFI_TYPE_FLOAT || z > 8)
+	    goto by_reference;
+	  if (z < 4)
 	    {
-	      unsigned long f = (unsigned long)fn;
-	      call_struct[0] = 0xae10001f;		 /* mov   %i7, %l7	 */
-	      call_struct[1] = 0xbe10000f;		 /* mov   %o7, %i7	 */
-	      call_struct[2] = 0x03000000 | f >> 10;     /* sethi %hi(fn), %g1	 */
-	      call_struct[3] = 0x9fc06000 | (f & 0x3ff); /* jmp %g1+%lo(fn), %o7 */
-	      call_struct[4] = 0x01000000;		 /* nop			 */
-	      if (cif->rtype->size < 0x7f)
-		call_struct[5] = cif->rtype->size;	 /* unimp		 */
-	      else
-		call_struct[5] = 0x01000000;	     	 /* nop			 */
-	      call_struct[6] = 0x81c7e008;		 /* ret			 */
-	      call_struct[7] = 0xbe100017;		 /* mov   %l7, %i7	 */
-	      asm volatile ("iflush %0; iflush %0+8; iflush %0+16; iflush %0+24" : :
-			    "r" (call_struct) : "memory");
-	      /* SPARC v8 requires 5 instructions for flush to be visible */
-	      asm volatile ("nop; nop; nop; nop; nop");
-	      ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
-			  cif->flags, rvalue, (void (*)(void)) call_struct);
-	      ffi_closure_free(call_struct);
+	      memcpy((char *)argp + 4 - z, a, z);
+	      argp++;
 	    }
 	  else
 	    {
-	      ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
-			  cif->flags, rvalue, fn);
+	      memcpy(argp, a, z);
+	      argp += z / 4;
 	    }
+	  break;
+
+	default:
+	  abort();
 	}
-      else
-	{
-	  ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
-		      cif->flags, rvalue, fn);
-	}
-#endif
-      break;
-    case FFI_COMPAT_V9:
-    case FFI_V9:
-#ifdef SPARC64
-      ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes, cif->flags, rval, fn);
-      if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
-	ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval,
-			     ((char *)rval)+32);
-#else
-      /* And vice versa */
-      FFI_ASSERT(0);
-#endif
-      break;
-    default:
-      FFI_ASSERT(0);
-      break;
     }
+
+  return flags;
 }
 
+static void
+ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
+	      void **avalue, void *closure)
+{
+  size_t bytes = cif->bytes;
 
-#ifdef SPARC64
-extern void ffi_closure_v9(void);
+  FFI_ASSERT (cif->abi == FFI_V8);
+
+  /* If we've not got a return value, we need to create one if we've
+     got to pass the return value to the callee.  Otherwise ignore it.  */
+  if (rvalue == NULL
+      && (cif->flags & SPARC_FLAG_RET_MASK) == SPARC_RET_STRUCT)
+    bytes += ALIGN (cif->rtype->size, 8);
+
+  ffi_call_v8(cif, fn, rvalue, avalue, -bytes, closure);
+}
+
+void
+ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, NULL);
+}
+
+void
+ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
+	     void **avalue, void *closure)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, closure);
+}
+
+#ifdef __GNUC__
+static inline void
+ffi_flush_icache (void *p)
+{
+  /* SPARC v8 requires 5 instructions for flush to be visible */
+  asm volatile ("iflush	%0; iflush %0+8; nop; nop; nop; nop; nop"
+		: : "r" (p) : "memory");
+}
 #else
-extern void ffi_closure_v8(void);
+extern void ffi_flush_icache (void *) FFI_HIDDEN;
 #endif
 
+extern void ffi_closure_v8(void) FFI_HIDDEN;
+extern void ffi_go_closure_v8(void) FFI_HIDDEN;
+
 ffi_status
-ffi_prep_closure_loc (ffi_closure* closure,
-		      ffi_cif* cif,
+ffi_prep_closure_loc (ffi_closure *closure,
+		      ffi_cif *cif,
 		      void (*fun)(ffi_cif*, void*, void**, void*),
 		      void *user_data,
 		      void *codeloc)
 {
   unsigned int *tramp = (unsigned int *) &closure->tramp[0];
-  unsigned long fn;
-#ifdef SPARC64
-  /* Trampoline address is equal to the closure address.  We take advantage
-     of that to reduce the trampoline size by 8 bytes. */
-  if (!V9_ABI_P (cif->abi))
+  unsigned long ctx = (unsigned long) closure;
+  unsigned long fn = (unsigned long) ffi_closure_v8;
+
+  if (cif->abi != FFI_V8)
     return FFI_BAD_ABI;
-  fn = (unsigned long) ffi_closure_v9;
-  tramp[0] = 0x83414000;	/* rd	%pc, %g1	*/
-  tramp[1] = 0xca586010;	/* ldx	[%g1+16], %g5	*/
-  tramp[2] = 0x81c14000;	/* jmp	%g5		*/
-  tramp[3] = 0x01000000;	/* nop			*/
-  *((unsigned long *) &tramp[4]) = fn;
-#else
-  unsigned long ctx = (unsigned long) codeloc;
-  if (!V8_ABI_P (cif->abi))
-    return FFI_BAD_ABI;
-  fn = (unsigned long) ffi_closure_v8;
+
   tramp[0] = 0x03000000 | fn >> 10;	/* sethi %hi(fn), %g1	*/
   tramp[1] = 0x05000000 | ctx >> 10;	/* sethi %hi(ctx), %g2	*/
   tramp[2] = 0x81c06000 | (fn & 0x3ff);	/* jmp   %g1+%lo(fn)	*/
   tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or    %g2, %lo(ctx)	*/
-#endif
 
   closure->cif = cif;
   closure->fun = fun;
   closure->user_data = user_data;
 
-  /* Flush the Icache.  closure is 8 bytes aligned.  */
-#ifdef SPARC64
-  asm volatile ("flush	%0; flush %0+8" : : "r" (closure) : "memory");
-#else
-  asm volatile ("iflush	%0; iflush %0+8" : : "r" (closure) : "memory");
-  /* SPARC v8 requires 5 instructions for flush to be visible */
-  asm volatile ("nop; nop; nop; nop; nop");
-#endif
+  ffi_flush_icache (closure);
 
   return FFI_OK;
 }
 
-#ifdef SPARC64
-
-int
-ffi_closure_sparc_inner_v9(ffi_closure *closure, void *rvalue,
-			   unsigned long *gpr, double *fpr)
+ffi_status
+ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
+		     void (*fun)(ffi_cif*, void*, void**, void*))
 {
-  ffi_cif *cif;
-  ffi_type **arg_types;
-  void **avalue;
-  int i, argn, fp_slot_max;
+  if (cif->abi != FFI_V8)
+    return FFI_BAD_ABI;
 
-  cif = closure->cif;
-  arg_types = cif->arg_types;
-  avalue = alloca(cif->nargs * sizeof(void *));
+  closure->tramp = ffi_go_closure_v8;
+  closure->cif = cif;
+  closure->fun = fun;
 
-  /* Copy the caller's structure return address so that the closure
-     returns the data directly to the caller.  */
-  if (cif->flags == FFI_TYPE_VOID && cif->rtype->type == FFI_TYPE_STRUCT)
-    {
-      rvalue = (void *) gpr[0];
-      /* Skip the structure return address.  */
-      argn = 1;
-    }
-  else
-    argn = 0;
-
-  fp_slot_max = 16 - argn;
-
-  /* Grab the addresses of the arguments from the stack frame.  */
-  for (i = 0; i < cif->nargs; i++)
-    {
-      /* If the function is variadic, FP arguments are passed in FP
-	 registers only if the corresponding parameter is named.  */
-      const int named
-	= (cif->abi == FFI_COMPAT_V9 ? 1 : i < cif->nfixedargs);
-
-      if (arg_types[i]->type == FFI_TYPE_STRUCT)
-	{
-	  if (arg_types[i]->size > 16)
-	    {
-	      /* Straight copy of invisible reference.  */
-	      avalue[i] = (void *)gpr[argn++];
-	    }
-	  else
-	    {
-	      /* Left-justify.  */
-	      ffi_v9_layout_struct(arg_types[i],
-				   0,
-				   (char *) &gpr[argn],
-				   (char *) &gpr[argn],
-				   named
-				   ? (char *) &fpr[argn]
-				   : (char *) &gpr[argn]);
-	      avalue[i] = &gpr[argn];
-	      argn
-	        += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
-	    }
-	}
-      else
-	{
-	  /* Right-justify.  */
-	  argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
-
-	  /* Align on a 16-byte boundary.  */
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	  if (arg_types[i]->type == FFI_TYPE_LONGDOUBLE && (argn % 2) != 0)
-	    argn++;
-#endif
-	  if (i < fp_slot_max
-	      && named
-	      && (arg_types[i]->type == FFI_TYPE_FLOAT
-		  || arg_types[i]->type == FFI_TYPE_DOUBLE
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-		  || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
-#endif
-		  ))
-	    avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
-	  else
-	    avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
-	}
-    }
-
-  /* Invoke the closure.  */
-  closure->fun (cif, rvalue, avalue, closure->user_data);
-
-  /* Tell ffi_closure_sparc how to perform return type promotions.  */
-  return cif->rtype->type;
+  return FFI_OK;
 }
 
-#else
-
-int
-ffi_closure_sparc_inner_v8(ffi_closure *closure, void *rvalue,
-			   unsigned long *gpr, unsigned long *scratch)
+int FFI_HIDDEN
+ffi_closure_sparc_inner_v8(ffi_cif *cif, 
+			   void (*fun)(ffi_cif*, void*, void**, void*),
+			   void *user_data, void *rvalue,
+			   unsigned long *argp)
 {
-  ffi_cif *cif;
   ffi_type **arg_types;
   void **avalue;
-  int i, argn;
+  int i, nargs, flags;
 
-  cif = closure->cif;
   arg_types = cif->arg_types;
-  avalue = alloca(cif->nargs * sizeof(void *));
+  nargs = cif->nargs;
+  flags = cif->flags;
+  avalue = alloca(nargs * sizeof(void *));
 
   /* Copy the caller's structure return address so that the closure
-     returns the data directly to the caller.  */
-  if (cif->flags == FFI_TYPE_STRUCT
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE  
-      || cif->flags == FFI_TYPE_LONGDOUBLE
-#endif
-     )
-    rvalue = (void *) gpr[0];
+     returns the data directly to the caller.  Also install it so we
+     can return the address in %o0.  */
+  if ((flags & SPARC_FLAG_RET_MASK) == SPARC_RET_STRUCT)
+    {
+      void *new_rvalue = (void *)*argp;
+      *(void **)rvalue = new_rvalue;
+      rvalue = new_rvalue;
+    }
 
   /* Always skip the structure return address.  */
-  argn = 1;
+  argp++;
 
   /* Grab the addresses of the arguments from the stack frame.  */
-  for (i = 0; i < cif->nargs; i++)
+  for (i = 0; i < nargs; i++)
     {
-      if (arg_types[i]->type == FFI_TYPE_STRUCT
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	  || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
-#endif
-         )
+      ffi_type *ty = arg_types[i];
+      int tt = ty->type;
+      void *a = argp;
+      size_t z;
+
+      switch (tt)
 	{
+	case FFI_TYPE_STRUCT:
+	case FFI_TYPE_LONGDOUBLE:
+	by_reference:
 	  /* Straight copy of invisible reference.  */
-	  avalue[i] = (void *)gpr[argn++];
+	  a = (void *)*argp;
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	  if ((unsigned long)a & 7)
+	    {
+	      /* Align on a 8-byte boundary.  */
+	      UINT64 *tmp = alloca(8);
+	      *tmp = ((UINT64)argp[0] << 32) | argp[1];
+	      a = tmp;
+	    }
+	  argp++;
+	  break;
+
+	case FFI_TYPE_INT:
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_POINTER:
+	  break;
+        case FFI_TYPE_UINT16:
+        case FFI_TYPE_SINT16:
+	  a += 2;
+	  break;
+        case FFI_TYPE_UINT8:
+        case FFI_TYPE_SINT8:
+	  a += 3;
+	  break;
+
+        case FFI_TYPE_COMPLEX:
+	  tt = ty->elements[0]->type;
+	  z = ty->size;
+	  if (tt == FFI_TYPE_FLOAT || z > 8)
+	    goto by_reference;
+	  if (z < 4)
+	    a += 4 - z;
+	  else if (z > 4)
+	    argp++;
+	  break;
+
+	default:
+	  abort();
 	}
-      else if ((arg_types[i]->type == FFI_TYPE_DOUBLE
-	       || arg_types[i]->type == FFI_TYPE_SINT64
-	       || arg_types[i]->type == FFI_TYPE_UINT64)
-	       /* gpr is 8-byte aligned.  */
-	       && (argn % 2) != 0)
-	{
-	  /* Align on a 8-byte boundary.  */
-	  scratch[0] = gpr[argn];
-	  scratch[1] = gpr[argn+1];
-	  avalue[i] = scratch;
-	  scratch -= 2;
-	  argn += 2;
-	}
-      else
-	{
-	  /* Always right-justify.  */
-	  argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
-	  avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
-	}
+      argp++;
+      avalue[i] = a;
     }
 
   /* Invoke the closure.  */
-  closure->fun (cif, rvalue, avalue, closure->user_data);
+  fun (cif, rvalue, avalue, user_data);
 
   /* Tell ffi_closure_sparc how to perform return type promotions.  */
-  return cif->rtype->type;
+  return flags;
 }
-
-#endif
+#endif /* !SPARC64 */
diff --git a/third_party/gofrontend/libffi/src/sparc/ffi64.c b/third_party/gofrontend/libffi/src/sparc/ffi64.c
new file mode 100644
index 0000000..340b198
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/sparc/ffi64.c
@@ -0,0 +1,608 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2011, 2013 Anthony Green
+           Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
+
+   SPARC Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+#include <stdlib.h>
+#include "internal.h"
+
+/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
+   all further uses in this file will refer to the 128-bit type.  */
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+# if FFI_TYPE_LONGDOUBLE != 4
+#  error FFI_TYPE_LONGDOUBLE out of date
+# endif
+#else
+# undef FFI_TYPE_LONGDOUBLE
+# define FFI_TYPE_LONGDOUBLE 4
+#endif
+
+#ifdef SPARC64
+
+/* Flatten the contents of a structure to the parts that are passed in
+   floating point registers.  The return is a bit mask wherein bit N
+   set means bytes [4*n, 4*n+3] are passed in %fN.
+
+   We encode both the (running) size (maximum 32) and mask (maxumum 255)
+   into one integer.  The size is placed in the low byte, so that align
+   and addition work correctly.  The mask is placed in the second byte.  */
+
+static int
+ffi_struct_float_mask (ffi_type *outer_type, int size_mask)
+{
+  ffi_type **elts;
+  ffi_type *t;
+
+  if (outer_type->type == FFI_TYPE_COMPLEX)
+    {
+      int m = 0, tt = outer_type->elements[0]->type;
+      size_t z = outer_type->size;
+
+      if (tt == FFI_TYPE_FLOAT
+	  || tt == FFI_TYPE_DOUBLE
+	  || tt == FFI_TYPE_LONGDOUBLE)
+        m = (1 << (z / 4)) - 1;
+      return (m << 8) | z;
+    }
+  FFI_ASSERT (outer_type->type == FFI_TYPE_STRUCT);
+
+  for (elts = outer_type->elements; (t = *elts) != NULL; elts++)
+    {
+      size_t z = t->size;
+      int o, m, tt;
+
+      size_mask = ALIGN(size_mask, t->alignment);
+      switch (t->type)
+	{
+	case FFI_TYPE_STRUCT:
+	  size_mask = ffi_struct_float_mask (t, size_mask);
+	  continue;
+	case FFI_TYPE_COMPLEX:
+	  tt = t->elements[0]->type;
+	  if (tt != FFI_TYPE_FLOAT
+	      && tt != FFI_TYPE_DOUBLE
+	      && tt != FFI_TYPE_LONGDOUBLE)
+	    break;
+	  /* FALLTHRU */
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_LONGDOUBLE:
+	  m = (1 << (z / 4)) - 1;	/* compute mask for type */
+	  o = (size_mask >> 2) & 0x3f;	/* extract word offset */
+	  size_mask |= m << (o + 8);	/* insert mask into place */
+	  break;
+	}
+      size_mask += z;
+    }
+
+  size_mask = ALIGN(size_mask, outer_type->alignment);
+  FFI_ASSERT ((size_mask & 0xff) == outer_type->size);
+
+  return size_mask;
+}
+
+/* Merge floating point data into integer data.  If the structure is
+   entirely floating point, simply return a pointer to the fp data.  */
+
+static void *
+ffi_struct_float_merge (int size_mask, void *vi, void *vf)
+{
+  int size = size_mask & 0xff;
+  int mask = size_mask >> 8;
+  int n = size >> 2;
+
+  if (mask == 0)
+    return vi;
+  else if (mask == (1 << n) - 1)
+    return vf;
+  else
+    {
+      unsigned int *wi = vi, *wf = vf;
+      int i;
+
+      for (i = 0; i < n; ++i)
+	if ((mask >> i) & 1)
+	  wi[i] = wf[i];
+
+      return vi;
+    }
+}
+
+/* Similar, but place the data into VD in the end.  */
+
+void FFI_HIDDEN
+ffi_struct_float_copy (int size_mask, void *vd, void *vi, void *vf)
+{
+  int size = size_mask & 0xff;
+  int mask = size_mask >> 8;
+  int n = size >> 2;
+
+  if (mask == 0)
+    ;
+  else if (mask == (1 << n) - 1)
+    vi = vf;
+  else
+    {
+      unsigned int *wd = vd, *wi = vi, *wf = vf;
+      int i;
+
+      for (i = 0; i < n; ++i)
+	wd[i] = ((mask >> i) & 1 ? wf : wi)[i];
+      return;
+    }
+  memcpy (vd, vi, size);
+}
+
+/* Perform machine dependent cif processing */
+
+static ffi_status
+ffi_prep_cif_machdep_core(ffi_cif *cif)
+{
+  ffi_type *rtype = cif->rtype;
+  int rtt = rtype->type;
+  size_t bytes = 0;
+  int i, n, flags;
+
+  /* Set the return type flag */
+  switch (rtt)
+    {
+    case FFI_TYPE_VOID:
+      flags = SPARC_RET_VOID;
+      break;
+    case FFI_TYPE_FLOAT:
+      flags = SPARC_RET_F_1;
+      break;
+    case FFI_TYPE_DOUBLE:
+      flags = SPARC_RET_F_2;
+      break;
+    case FFI_TYPE_LONGDOUBLE:
+      flags = SPARC_RET_F_4;
+      break;
+
+    case FFI_TYPE_COMPLEX:
+    case FFI_TYPE_STRUCT:
+      if (rtype->size > 32)
+	{
+	  flags = SPARC_RET_VOID | SPARC_FLAG_RET_IN_MEM;
+	  bytes = 8;
+	}
+      else
+	{
+	  int size_mask = ffi_struct_float_mask (rtype, 0);
+	  int word_size = (size_mask >> 2) & 0x3f;
+	  int all_mask = (1 << word_size) - 1;
+	  int fp_mask = size_mask >> 8;
+
+	  flags = (size_mask << SPARC_SIZEMASK_SHIFT) | SPARC_RET_STRUCT;
+
+	  /* For special cases of all-int or all-fp, we can return
+	     the value directly without popping through a struct copy.  */
+	  if (fp_mask == 0)
+	    {
+	      if (rtype->alignment >= 8)
+		{
+		  if (rtype->size == 8)
+		    flags = SPARC_RET_INT64;
+		  else if (rtype->size == 16)
+		    flags = SPARC_RET_INT128;
+		}
+	    }
+	  else if (fp_mask == all_mask)
+	    switch (word_size)
+	      {
+	      case 1: flags = SPARC_RET_F_1; break;
+	      case 2: flags = SPARC_RET_F_2; break;
+	      case 3: flags = SP_V9_RET_F_3; break;
+	      case 4: flags = SPARC_RET_F_4; break;
+	      /* 5 word structures skipped; handled via RET_STRUCT.  */
+	      case 6: flags = SPARC_RET_F_6; break;
+	      /* 7 word structures skipped; handled via RET_STRUCT.  */
+	      case 8: flags = SPARC_RET_F_8; break;
+	      }
+	}
+      break;
+
+    case FFI_TYPE_SINT8:
+      flags = SPARC_RET_SINT8;
+      break;
+    case FFI_TYPE_UINT8:
+      flags = SPARC_RET_UINT8;
+      break;
+    case FFI_TYPE_SINT16:
+      flags = SPARC_RET_SINT16;
+      break;
+    case FFI_TYPE_UINT16:
+      flags = SPARC_RET_UINT16;
+      break;
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+      flags = SP_V9_RET_SINT32;
+      break;
+    case FFI_TYPE_UINT32:
+      flags = SPARC_RET_UINT32;
+      break;
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_POINTER:
+      flags = SPARC_RET_INT64;
+      break;
+
+    default:
+      abort();
+    }
+
+  bytes = 0;
+  for (i = 0, n = cif->nargs; i < n; ++i)
+    {
+      ffi_type *ty = cif->arg_types[i];
+      size_t z = ty->size;
+      size_t a = ty->alignment;
+
+      switch (ty->type)
+	{
+	case FFI_TYPE_COMPLEX:
+	case FFI_TYPE_STRUCT:
+	  /* Large structs passed by reference.  */
+	  if (z > 16)
+	    {
+	      a = z = 8;
+	      break;
+	    }
+	  /* Small structs may be passed in integer or fp regs or both.  */
+	  if (bytes >= 16*8)
+	    break;
+	  if ((ffi_struct_float_mask (ty, 0) & 0xff00) == 0)
+	    break;
+	  /* FALLTHRU */
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_LONGDOUBLE:
+	  flags |= SPARC_FLAG_FP_ARGS;
+	  break;
+	}
+      bytes = ALIGN(bytes, a);
+      bytes += ALIGN(z, 8);
+    }
+
+  /* Sparc call frames require that space is allocated for 6 args,
+     even if they aren't used. Make that space if necessary. */
+  if (bytes < 6 * 8)
+    bytes = 6 * 8;
+
+  /* The stack must be 2 word aligned, so round bytes up appropriately. */
+  bytes = ALIGN(bytes, 16);
+
+  /* Include the call frame to prep_args.  */
+  bytes += 8*16 + 8*8;
+
+  cif->bytes = bytes;
+  cif->flags = flags;
+  return FFI_OK;
+}
+
+ffi_status FFI_HIDDEN
+ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  cif->nfixedargs = cif->nargs;
+  return ffi_prep_cif_machdep_core(cif);
+}
+
+ffi_status FFI_HIDDEN
+ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned nfixedargs, unsigned ntotalargs)
+{
+  cif->nfixedargs = nfixedargs;
+  return ffi_prep_cif_machdep_core(cif);
+}
+
+extern void ffi_call_v9(ffi_cif *cif, void (*fn)(void), void *rvalue,
+			void **avalue, size_t bytes, void *closure) FFI_HIDDEN;
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+int FFI_HIDDEN
+ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
+{
+  ffi_type **p_arg;
+  int flags = cif->flags;
+  int i, nargs;
+
+  if (rvalue == NULL)
+    {
+      if (flags & SPARC_FLAG_RET_IN_MEM)
+	{
+	  /* Since we pass the pointer to the callee, we need a value.
+	     We allowed for this space in ffi_call, before ffi_call_v8
+	     alloca'd the space.  */
+	  rvalue = (char *)argp + cif->bytes;
+	}
+      else
+	{
+	  /* Otherwise, we can ignore the return value.  */
+	  flags = SPARC_RET_VOID;
+	}
+    }
+
+#ifdef USING_PURIFY
+  /* Purify will probably complain in our assembly routine,
+     unless we zero out this memory. */
+  memset(argp, 0, 6*8);
+#endif
+
+  if (flags & SPARC_FLAG_RET_IN_MEM)
+    *argp++ = (unsigned long)rvalue;
+
+  p_arg = cif->arg_types;
+  for (i = 0, nargs = cif->nargs; i < nargs; i++)
+    {
+      ffi_type *ty = p_arg[i];
+      void *a = avalue[i];
+      size_t z;
+
+      switch (ty->type)
+	{
+	case FFI_TYPE_SINT8:
+	  *argp++ = *(SINT8 *)a;
+	  break;
+	case FFI_TYPE_UINT8:
+	  *argp++ = *(UINT8 *)a;
+	  break;
+	case FFI_TYPE_SINT16:
+	  *argp++ = *(SINT16 *)a;
+	  break;
+	case FFI_TYPE_UINT16:
+	  *argp++ = *(UINT16 *)a;
+	  break;
+	case FFI_TYPE_INT:
+	case FFI_TYPE_SINT32:
+	  *argp++ = *(SINT32 *)a;
+	  break;
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_FLOAT:
+	  *argp++ = *(UINT32 *)a;
+	  break;
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_POINTER:
+	case FFI_TYPE_DOUBLE:
+	  *argp++ = *(UINT64 *)a;
+	  break;
+
+	case FFI_TYPE_LONGDOUBLE:
+	case FFI_TYPE_COMPLEX:
+	case FFI_TYPE_STRUCT:
+	  z = ty->size;
+	  if (z > 16)
+	    {
+	      /* For structures larger than 16 bytes we pass reference.  */
+	      *argp++ = (unsigned long)a;
+	      break;
+	    }
+	  if (((unsigned long)argp & 15) && ty->alignment > 8)
+	    argp++;
+	  memcpy(argp, a, z);
+	  argp += ALIGN(z, 8) / 8;
+	  break;
+
+	default:
+	  abort();
+	}
+    }
+
+  return flags;
+}
+
+static void
+ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue,
+	     void **avalue, void *closure)
+{
+  size_t bytes = cif->bytes;
+
+  FFI_ASSERT (cif->abi == FFI_V9);
+
+  if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM))
+    bytes += ALIGN (cif->rtype->size, 16);
+
+  ffi_call_v9(cif, fn, rvalue, avalue, -bytes, closure);
+}
+
+void
+ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  ffi_call_int(cif, fn, rvalue, avalue, NULL);
+}
+
+void
+ffi_call_go(ffi_cif *cif, void (*fn)(void), void *rvalue,
+	    void **avalue, void *closure)
+{
+  ffi_call_int(cif, fn, rvalue, avalue, closure);
+}
+
+#ifdef __GNUC__
+static inline void
+ffi_flush_icache (void *p)
+{
+  asm volatile ("flush	%0; flush %0+8" : : "r" (p) : "memory");
+}
+#else
+extern void ffi_flush_icache (void *) FFI_HIDDEN;
+#endif
+
+extern void ffi_closure_v9(void) FFI_HIDDEN;
+extern void ffi_go_closure_v9(void) FFI_HIDDEN;
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*, void*, void**, void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
+  unsigned long fn;
+
+  if (cif->abi != FFI_V9)
+    return FFI_BAD_ABI;
+
+  /* Trampoline address is equal to the closure address.  We take advantage
+     of that to reduce the trampoline size by 8 bytes. */
+  fn = (unsigned long) ffi_closure_v9;
+  tramp[0] = 0x83414000;	/* rd	%pc, %g1	*/
+  tramp[1] = 0xca586010;	/* ldx	[%g1+16], %g5	*/
+  tramp[2] = 0x81c14000;	/* jmp	%g5		*/
+  tramp[3] = 0x01000000;	/* nop			*/
+  *((unsigned long *) &tramp[4]) = fn;
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  ffi_flush_icache (closure);
+
+  return FFI_OK;
+}
+
+ffi_status
+ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
+		     void (*fun)(ffi_cif*, void*, void**, void*))
+{
+  if (cif->abi != FFI_V9)
+    return FFI_BAD_ABI;
+
+  closure->tramp = ffi_go_closure_v9;
+  closure->cif = cif;
+  closure->fun = fun;
+
+  return FFI_OK;
+}
+
+int FFI_HIDDEN
+ffi_closure_sparc_inner_v9(ffi_cif *cif,
+			   void (*fun)(ffi_cif*, void*, void**, void*),
+			   void *user_data, void *rvalue,
+			   unsigned long *gpr, unsigned long *fpr)
+{
+  ffi_type **arg_types;
+  void **avalue;
+  int i, argn, argx, nargs, flags, nfixedargs;
+
+  arg_types = cif->arg_types;
+  nargs = cif->nargs;
+  flags = cif->flags;
+  nfixedargs = cif->nfixedargs;
+
+  avalue = alloca(nargs * sizeof(void *));
+
+  /* Copy the caller's structure return address so that the closure
+     returns the data directly to the caller.  */
+  if (flags & SPARC_FLAG_RET_IN_MEM)
+    {
+      rvalue = (void *) gpr[0];
+      /* Skip the structure return address.  */
+      argn = 1;
+    }
+  else
+    argn = 0;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  for (i = 0; i < nargs; i++, argn = argx)
+    {
+      int named = i < nfixedargs;
+      ffi_type *ty = arg_types[i];
+      void *a = &gpr[argn];
+      size_t z;
+
+      argx = argn + 1;
+      switch (ty->type)
+	{
+	case FFI_TYPE_COMPLEX:
+	case FFI_TYPE_STRUCT:
+	  z = ty->size;
+	  if (z > 16)
+	    a = *(void **)a;
+	  else
+	    {
+	      argx = argn + ALIGN (z, 8) / 8;
+	      if (named && argn < 16)
+		{
+		  int size_mask = ffi_struct_float_mask (ty, 0);
+		  int argn_mask = (0xffff00 >> argn) & 0xff00;
+
+		  /* Eliminate fp registers off the end.  */
+		  size_mask = (size_mask & 0xff) | (size_mask & argn_mask);
+		  a = ffi_struct_float_merge (size_mask, gpr+argn, fpr+argn);
+		}
+	    }
+	  break;
+
+	case FFI_TYPE_LONGDOUBLE:
+	  argn = ALIGN (argn, 2);
+	  a = (named && argn < 16 ? fpr : gpr) + argn;
+	  argx = argn + 2;
+	  break;
+	case FFI_TYPE_DOUBLE:
+	  if (named && argn < 16)
+	    a = fpr + argn;
+	  break;
+	case FFI_TYPE_FLOAT:
+	  if (named && argn < 16)
+	    a = fpr + argn;
+	  a += 4;
+	  break;
+
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_POINTER:
+	  break;
+	case FFI_TYPE_INT:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	  a += 4;
+	  break;
+        case FFI_TYPE_UINT16:
+        case FFI_TYPE_SINT16:
+	  a += 6;
+	  break;
+        case FFI_TYPE_UINT8:
+        case FFI_TYPE_SINT8:
+	  a += 7;
+	  break;
+
+	default:
+	  abort();
+	}
+      avalue[i] = a;
+    }
+
+  /* Invoke the closure.  */
+  fun (cif, rvalue, avalue, user_data);
+
+  /* Tell ffi_closure_sparc how to perform return type promotions.  */
+  return flags;
+}
+#endif /* SPARC64 */
diff --git a/third_party/gofrontend/libffi/src/sparc/ffitarget.h b/third_party/gofrontend/libffi/src/sparc/ffitarget.h
index 6489ac0..2f4cd9a 100644
--- a/third_party/gofrontend/libffi/src/sparc/ffitarget.h
+++ b/third_party/gofrontend/libffi/src/sparc/ffitarget.h
@@ -46,42 +46,36 @@
 
 typedef enum ffi_abi {
   FFI_FIRST_ABI = 0,
-  FFI_V8,
-  FFI_V8PLUS,
-  /* See below for the COMPAT_V9 rationale.  */
-  FFI_COMPAT_V9,
-  FFI_V9,
-  FFI_LAST_ABI,
 #ifdef SPARC64
-  FFI_DEFAULT_ABI = FFI_V9
+  FFI_V9,
+  FFI_DEFAULT_ABI = FFI_V9,
 #else
-  FFI_DEFAULT_ABI = FFI_V8
+  FFI_V8,
+  FFI_DEFAULT_ABI = FFI_V8,
 #endif
+  FFI_LAST_ABI
 } ffi_abi;
 #endif
 
-#define V8_ABI_P(abi) ((abi) == FFI_V8 || (abi) == FFI_V8PLUS)
-#define V9_ABI_P(abi) ((abi) == FFI_COMPAT_V9 || (abi) == FFI_V9)
+#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION 1
+#define FFI_TARGET_HAS_COMPLEX_TYPE 1
 
-#define FFI_TARGET_SPECIFIC_VARIADIC 1
-
-/* The support of variadic functions was broken in the original implementation
-   of the FFI_V9 ABI.  This has been fixed by adding one extra field to the
-   CIF structure (nfixedargs field), which means that the ABI of libffi itself
-   has changed.  In order to support applications using the original ABI, we
-   have renamed FFI_V9 into FFI_COMPAT_V9 and defined a new FFI_V9 value.  */
 #ifdef SPARC64
-#define FFI_EXTRA_CIF_FIELDS unsigned int nfixedargs
+# define FFI_TARGET_SPECIFIC_VARIADIC 1
+# define FFI_EXTRA_CIF_FIELDS  unsigned int nfixedargs
 #endif
 
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
+#define FFI_GO_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+
 #ifdef SPARC64
 #define FFI_TRAMPOLINE_SIZE 24
 #else
 #define FFI_TRAMPOLINE_SIZE 16
 #endif
-#define FFI_NATIVE_RAW_API 0
 
 #endif
+
diff --git a/third_party/gofrontend/libffi/src/sparc/internal.h b/third_party/gofrontend/libffi/src/sparc/internal.h
new file mode 100644
index 0000000..0a66472
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/sparc/internal.h
@@ -0,0 +1,26 @@
+#define SPARC_RET_VOID		0
+#define SPARC_RET_STRUCT	1
+#define SPARC_RET_UINT8		2
+#define SPARC_RET_SINT8		3
+#define SPARC_RET_UINT16	4
+#define SPARC_RET_SINT16	5
+#define SPARC_RET_UINT32	6
+#define SP_V9_RET_SINT32	7	/* v9 only */
+#define SP_V8_RET_CPLX16	7	/* v8 only */
+#define SPARC_RET_INT64		8
+#define SPARC_RET_INT128	9
+
+/* Note that F_7 is missing, and is handled by SPARC_RET_STRUCT.  */
+#define SPARC_RET_F_8		10
+#define SPARC_RET_F_6		11
+#define SPARC_RET_F_4		12
+#define SPARC_RET_F_2		13
+#define SP_V9_RET_F_3		14	/* v9 only */
+#define SP_V8_RET_CPLX8		14	/* v8 only */
+#define SPARC_RET_F_1		15
+
+#define SPARC_FLAG_RET_MASK	15
+#define SPARC_FLAG_RET_IN_MEM	32
+#define SPARC_FLAG_FP_ARGS	64
+
+#define SPARC_SIZEMASK_SHIFT	8
diff --git a/third_party/gofrontend/libffi/src/sparc/v8.S b/third_party/gofrontend/libffi/src/sparc/v8.S
index 7ec6e1c..3a811ef 100644
--- a/third_party/gofrontend/libffi/src/sparc/v8.S
+++ b/third_party/gofrontend/libffi/src/sparc/v8.S
@@ -1,7 +1,8 @@
 /* -----------------------------------------------------------------------
-   v8.S - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
+   v8.S - Copyright (c) 2013  The Written Word, Inc.
+	  Copyright (c) 1996, 1997, 2003, 2004, 2008  Red Hat, Inc.
 
-   SPARC Foreign Function Interface 
+   SPARC Foreign Function Interface
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -24,153 +25,243 @@
    DEALINGS IN THE SOFTWARE.
    ----------------------------------------------------------------------- */
 
-#define LIBFFI_ASM	
+#define LIBFFI_ASM
 #include <fficonfig.h>
 #include <ffi.h>
+#include <ffi_cfi.h>
+#include "internal.h"
 
 #ifndef SPARC64
 
-#define STACKFRAME 96		/* Minimum stack framesize for SPARC */
-#define ARGS (64+4)		/* Offset of register area in frame */
+#define C2(X, Y)  X ## Y
+#define C1(X, Y)  C2(X, Y)
 
-.text
+#ifdef __USER_LABEL_PREFIX__
+# define C(Y)	C1(__USER_LABEL_PREFIX__, Y)
+#else
+# define C(Y)	Y
+#endif
+#define L(Y)	C1(.L, Y)
+
+	.text
+
+#ifndef __GNUC__
         .align 8
-.globl ffi_call_v8
-.globl _ffi_call_v8
+	.globl	C(ffi_flush_icache)
+	.type	C(ffi_flush_icache),@function
+	FFI_HIDDEN(C(ffi_flush_icache))
 
-ffi_call_v8:
-_ffi_call_v8:
-.LLFB1:
-	save	%sp, -STACKFRAME, %sp
-.LLCFI0:
-	
-	sub	%sp, %i2, %sp	! alloca() space in stack for frame to set up
-	add	%sp, STACKFRAME, %l0	! %l0 has start of 
-					! frame to set up
-
-	mov	%l0, %o0	! call routine to set up frame
-	call	%i0
-	mov	%i1, %o1	! (delay)
-
-	ld	[%l0+ARGS], %o0	! call foreign function
-	ld	[%l0+ARGS+4], %o1
-	ld	[%l0+ARGS+8], %o2
-	ld	[%l0+ARGS+12], %o3
-	ld	[%l0+ARGS+16], %o4
-	ld	[%l0+ARGS+20], %o5
-	call	%i5
-	mov	%l0, %sp	! (delay) switch to frame
-	nop			! STRUCT returning functions skip 12 instead of 8 bytes
-
-	! If the return value pointer is NULL, assume no return value.
-	tst	%i4
-	bz	done
+C(ffi_flush_icache):
+	cfi_startproc
+1:	iflush %o0
+	iflush %o+8
 	nop
+	nop
+	nop
+	nop
+	nop
+	retl
+	 nop
+	cfi_endproc
+	.size	C(ffi_flush_icache), . - C(ffi_flush_icache)
+#endif
 
-	cmp	%i3, FFI_TYPE_INT
-	be,a	done
-	st	%o0, [%i4]	! (delay)
+.macro E index
+	.align	16
+	.org	2b + \index * 16
+.endm
 
-	cmp	%i3, FFI_TYPE_FLOAT
-	be,a	done
-	st	%f0, [%i4+0]	! (delay)
+        .align 8
+	.globl	C(ffi_call_v8)
+	.type	C(ffi_call_v8),@function
+	FFI_HIDDEN(C(ffi_call_v8))
 
-	cmp	%i3, FFI_TYPE_DOUBLE
-	be,a	double
-	st	%f0, [%i4+0]	! (delay)
+C(ffi_call_v8):
+	cfi_startproc
+	! Allocate a stack frame sized by ffi_call.
+	save	%sp, %o4, %sp
+	cfi_def_cfa_register(%fp)
+	cfi_window_save
 
-	cmp	%i3, FFI_TYPE_SINT8
-	be,a	sint8
-	sll	%o0, 24, %o0	! (delay)
+	mov	%i0, %o0		! copy cif
+	add	%sp, 64+32, %o1		! load args area
+	mov	%i2, %o2		! copy rvalue
+	call	C(ffi_prep_args_v8)
+	 mov	%i3, %o3		! copy avalue
 
-	cmp	%i3, FFI_TYPE_UINT8
-	be,a	uint8
-	sll	%o0, 24, %o0	! (delay)
+	add	%sp, 32, %sp		! deallocate prep frame
+	and	%o0, SPARC_FLAG_RET_MASK, %l0	! save return type
+	srl	%o0, SPARC_SIZEMASK_SHIFT, %l1	! save return size
+	ld	[%sp+64+4], %o0		! load all argument registers
+	ld	[%sp+64+8], %o1
+	ld	[%sp+64+12], %o2
+	ld	[%sp+64+16], %o3
+	cmp	%l0, SPARC_RET_STRUCT	! struct return needs an unimp 4
+	ld	[%sp+64+20], %o4
+	be	8f
+	 ld	[%sp+64+24], %o5
 
-	cmp	%i3, FFI_TYPE_SINT16
-	be,a	sint16
-	sll	%o0, 16, %o0	! (delay)
+	! Call foreign function
+	call	%i1
+	 mov	%i5, %g2		! load static chain
 
-	cmp	%i3, FFI_TYPE_UINT16
-	be,a	uint16
-	sll	%o0, 16, %o0	! (delay)
+0:	call	1f		! load pc in %o7
+	 sll	%l0, 4, %l0
+1:	add	%o7, %l0, %o7	! o7 = 0b + ret_type*16
+	jmp	%o7+(2f-0b)
+	 nop
 
-	cmp	%i3, FFI_TYPE_SINT64
-	be,a	longlong
-	st	%o0, [%i4+0]	! (delay)
-done:
+	! Note that each entry is 4 insns, enforced by the E macro.
+	.align	16
+2:
+E SPARC_RET_VOID
 	ret
-	restore
-
-double:
-	st	%f1, [%i4+4]
+	 restore
+E SPARC_RET_STRUCT
+	unimp
+E SPARC_RET_UINT8
+	and	%o0, 0xff, %o0
+	st	%o0, [%i2]
 	ret
-	restore
-
-sint8:
-	sra	%o0, 24, %o0
-	st	%o0, [%i4+0]
+	 restore
+E SPARC_RET_SINT8
+	sll	%o0, 24, %o0
+	b	7f
+	 sra	%o0, 24, %o0
+E SPARC_RET_UINT16
+	sll	%o0, 16, %o0
+	b	7f
+	 srl	%o0, 16, %o0
+E SPARC_RET_SINT16
+	sll	%o0, 16, %o0
+	b	7f
+	 sra	%o0, 16, %o0
+E SPARC_RET_UINT32
+7:	st	%o0, [%i2]
 	ret
-	restore
-
-uint8:
-	srl	%o0, 24, %o0
-	st	%o0, [%i4+0]
+	 restore
+E SP_V8_RET_CPLX16
+	sth	%o0, [%i2+2]
+	b	9f
+	 srl	%o0, 16, %o0
+E SPARC_RET_INT64
+	st	%o0, [%i2]
+	st	%o1, [%i2+4]
 	ret
-	restore
-
-sint16:
-	sra	%o0, 16, %o0
-	st	%o0, [%i4+0]
+	 restore
+E SPARC_RET_INT128
+	std	%o0, [%i2]
+	std	%o2, [%i2+8]
 	ret
-	restore
-
-uint16:
-	srl	%o0, 16, %o0
-	st	%o0, [%i4+0]
+	 restore
+E SPARC_RET_F_8
+	st	%f7, [%i2+7*4]
+	nop
+	st	%f6, [%i2+6*4]
+	nop
+E SPARC_RET_F_6
+	st	%f5, [%i2+5*4]
+	nop
+	st	%f4, [%i2+4*4]
+	nop
+E SPARC_RET_F_4
+	st	%f3, [%i2+3*4]
+	nop
+	st	%f2, [%i2+2*4]
+	nop
+E SPARC_RET_F_2
+	st	%f1, [%i2+4]
+	st	%f0, [%i2]
 	ret
-	restore
-
-longlong:
-	st	%o1, [%i4+4]
+	 restore
+E SP_V8_RET_CPLX8
+	stb	%o0, [%i2+1]
+	b	10f
+	 srl	%o0, 8, %o0
+E SPARC_RET_F_1
+	st	%f0, [%i2]
 	ret
-	restore
-.LLFE1:
+	 restore
 
-.ffi_call_v8_end:
-	.size	ffi_call_v8,.ffi_call_v8_end-ffi_call_v8
+	.align	8
+9:	sth	%o0, [%i2]
+	ret
+	 restore
+	.align	8
+10:	stb	%o0, [%i2]
+	ret
+	 restore
+
+	! Struct returning functions expect and skip the unimp here.
+	! To make it worse, conforming callees examine the unimp and
+	! make sure the low 12 bits of the unimp match the size of
+	! the struct being returned.
+	.align	8
+8:	call	1f				! load pc in %o7
+	 sll	%l1, 2, %l0			! size * 4
+1:	sll	%l1, 4, %l1			! size * 16
+	add	%l0, %l1, %l0			! size * 20
+	add	%o7, %l0, %o7			! o7 = 0b + size*20
+	jmp	%o7+(2f-8b)
+	 mov	%i5, %g2			! load static chain
+2:
+.rept	0x1000
+	call	%i1
+	 nop
+	unimp	(. - 2b) / 20
+	ret
+	 restore
+.endr
+
+	cfi_endproc
+	.size	C(ffi_call_v8),. - C(ffi_call_v8)
 
 
-#undef STACKFRAME
-#define	STACKFRAME	104	/* 16*4 register window +
-				   1*4 struct return +	
-				   6*4 args backing store +
-				   3*4 locals */
+/* 16*4 register window + 1*4 struct return + 6*4 args backing store
+   + 8*4 return storage + 1*4 alignment.  */
+#define	STACKFRAME	(16*4 + 4 + 6*4 + 8*4 + 4)
 
 /* ffi_closure_v8(...)
 
    Receives the closure argument in %g2.   */
 
-	.text
-	.align 8
-	.globl ffi_closure_v8
-
-ffi_closure_v8:
 #ifdef HAVE_AS_REGISTER_PSEUDO_OP
-		.register	%g2, #scratch
+	.register	%g2, #scratch
 #endif
-.LLFB2:
-	! Reserve frame space for all arguments in case
-	! we need to align them on a 8-byte boundary.
-	ld	[%g2+FFI_TRAMPOLINE_SIZE], %g1
-	ld	[%g1+4], %g1
-	sll	%g1, 3, %g1
-	add	%g1, STACKFRAME, %g1
-	! %g1 == STACKFRAME + 8*nargs
-	neg	%g1
-	save	%sp, %g1, %sp
-.LLCFI1:
 
+	.align 8
+	.globl	C(ffi_go_closure_v8)
+	.type	C(ffi_go_closure_v8),@function
+	FFI_HIDDEN(C(ffi_go_closure_v8))
+
+C(ffi_go_closure_v8):
+	cfi_startproc
+	save	%sp, -STACKFRAME, %sp
+	cfi_def_cfa_register(%fp)
+	cfi_window_save
+
+	ld	[%g2+4], %o0			! load cif
+	ld	[%g2+8], %o1			! load fun
+	b	0f
+	 mov	%g2, %o2			! load user_data
+	cfi_endproc
+	.size	C(ffi_go_closure_v8), . - C(ffi_go_closure_v8)
+
+	.align 8
+	.globl	C(ffi_closure_v8)
+	.type	C(ffi_closure_v8),@function
+	FFI_HIDDEN(C(ffi_closure_v8))
+
+C(ffi_closure_v8):
+	cfi_startproc
+	save	%sp, -STACKFRAME, %sp
+	cfi_def_cfa_register(%fp)
+	cfi_window_save
+
+	ld	[%g2+FFI_TRAMPOLINE_SIZE], %o0		! load cif
+	ld	[%g2+FFI_TRAMPOLINE_SIZE+4], %o1	! load fun
+	ld	[%g2+FFI_TRAMPOLINE_SIZE+8], %o2	! load user_data
+0:
 	! Store all of the potential argument registers in va_list format.
 	st	%i0, [%fp+68+0]
 	st	%i1, [%fp+68+4]
@@ -180,137 +271,91 @@
 	st	%i5, [%fp+68+20]
 
 	! Call ffi_closure_sparc_inner to do the bulk of the work.
-	mov	%g2, %o0
-	add	%fp, -8, %o1
-	add	%fp,  64, %o2
+	add	%fp, -8*4, %o3
 	call	ffi_closure_sparc_inner_v8
-	 add	%fp, -16, %o3
+	 add	%fp,  64, %o4
 
-	! Load up the return value in the proper type.
-	! See ffi_prep_cif_machdep for the list of cases.
-	cmp	%o0, FFI_TYPE_VOID
-	be	done1
-
-	cmp	%o0, FFI_TYPE_INT
-	be	done1
-	 ld	[%fp-8], %i0
-
-	cmp	%o0, FFI_TYPE_FLOAT
-	be,a	done1
-	 ld	[%fp-8], %f0
-
-	cmp	%o0, FFI_TYPE_DOUBLE
-	be,a	done1
-	 ldd	[%fp-8], %f0
-
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	cmp	%o0, FFI_TYPE_LONGDOUBLE
-	be	done2
-#endif
-
-	cmp	%o0, FFI_TYPE_STRUCT
-	be	done2
-
-	cmp	%o0, FFI_TYPE_SINT64
-	be,a	done1
-	 ldd	[%fp-8], %i0
-
-	ld	[%fp-8], %i0
-done1:
-	jmp	%i7+8
+0:	call	1f
+	 and	%o0, SPARC_FLAG_RET_MASK, %o0
+1:	sll	%o0, 4, %o0	! o0 = o0 * 16
+	add	%o7, %o0, %o7	! o7 = 0b + o0*16
+	jmp	%o7+(2f-0b)
+	 add	%fp, -8*4, %i2
+	 
+	! Note that each entry is 4 insns, enforced by the E macro.
+	.align	16
+2:
+E SPARC_RET_VOID
+	ret
 	 restore
-done2:
-	! Skip 'unimp'.
+E SPARC_RET_STRUCT
+	ld	[%i2], %i0
 	jmp	%i7+12
 	 restore
-.LLFE2:
+E SPARC_RET_UINT8
+	ldub	[%i2+3], %i0
+	ret
+	 restore
+E SPARC_RET_SINT8
+	ldsb	[%i2+3], %i0
+	ret
+	 restore
+E SPARC_RET_UINT16
+	lduh	[%i2+2], %i0
+	ret
+	 restore
+E SPARC_RET_SINT16
+	ldsh	[%i2+2], %i0
+	ret
+	 restore
+E SPARC_RET_UINT32
+	ld	[%i2], %i0
+	ret
+	 restore
+E SP_V8_RET_CPLX16
+	ld	[%i2], %i0
+	ret
+	 restore
+E SPARC_RET_INT64
+	ldd	[%i2], %i0
+	ret
+	 restore
+E SPARC_RET_INT128
+	ldd	[%i2], %i0
+	ldd	[%i2+8], %i2
+	ret
+	 restore
+E SPARC_RET_F_8
+	ld	[%i2+7*4], %f7
+	nop
+	ld	[%i2+6*4], %f6
+	nop
+E SPARC_RET_F_6
+	ld	[%i2+5*4], %f5
+	nop
+	ld	[%i2+4*4], %f4
+	nop
+E SPARC_RET_F_4
+	ld	[%i2+3*4], %f3
+	nop
+	ld	[%i2+2*4], %f2
+	nop
+E SPARC_RET_F_2
+	ldd	[%i2], %f0
+	ret
+	 restore
+E SP_V8_RET_CPLX8
+	lduh	[%i2], %i0
+	ret
+	 restore
+E SPARC_RET_F_1
+	ld	[%i2], %f0
+	ret
+	 restore
 
-.ffi_closure_v8_end:
-	.size	ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8
-
-#ifdef SPARC64
-#define WS 8
-#define nword	xword
-#define uanword	uaxword
-#else
-#define WS 4
-#define nword	long
-#define uanword	uaword
-#endif
-
-#ifdef HAVE_RO_EH_FRAME
-	.section	".eh_frame",#alloc
-#else
-	.section	".eh_frame",#alloc,#write
-#endif
-.LLframe1:
-	.uaword	.LLECIE1-.LLSCIE1	! Length of Common Information Entry
-.LLSCIE1:
-	.uaword	0x0	! CIE Identifier Tag
-	.byte	0x1	! CIE Version
-	.ascii "zR\0"	! CIE Augmentation
-	.byte	0x1	! uleb128 0x1; CIE Code Alignment Factor
-	.byte	0x80-WS	! sleb128 -WS; CIE Data Alignment Factor
-	.byte	0xf	! CIE RA Column
-	.byte	0x1	! uleb128 0x1; Augmentation size
-#ifdef HAVE_AS_SPARC_UA_PCREL
-	.byte	0x1b	! FDE Encoding (pcrel sdata4)
-#else
-	.byte	0x50	! FDE Encoding (aligned absolute)
-#endif
-	.byte	0xc	! DW_CFA_def_cfa
-	.byte	0xe	! uleb128 0xe
-	.byte	0x0	! uleb128 0x0
-	.align	WS
-.LLECIE1:
-.LLSFDE1:
-	.uaword	.LLEFDE1-.LLASFDE1	! FDE Length
-.LLASFDE1:
-	.uaword	.LLASFDE1-.LLframe1	! FDE CIE offset
-#ifdef HAVE_AS_SPARC_UA_PCREL
-	.uaword	%r_disp32(.LLFB1)
-	.uaword	.LLFE1-.LLFB1	! FDE address range
-#else
-	.align	WS
-	.nword	.LLFB1
-	.uanword .LLFE1-.LLFB1	! FDE address range
-#endif
-	.byte	0x0	! uleb128 0x0; Augmentation size
-	.byte	0x4	! DW_CFA_advance_loc4
-	.uaword	.LLCFI0-.LLFB1
-	.byte	0xd	! DW_CFA_def_cfa_register
-	.byte	0x1e	! uleb128 0x1e
-	.byte	0x2d	! DW_CFA_GNU_window_save
-	.byte	0x9	! DW_CFA_register
-	.byte	0xf	! uleb128 0xf
-	.byte	0x1f	! uleb128 0x1f
-	.align	WS
-.LLEFDE1:
-.LLSFDE2:
-	.uaword	.LLEFDE2-.LLASFDE2	! FDE Length
-.LLASFDE2:
-	.uaword	.LLASFDE2-.LLframe1	! FDE CIE offset
-#ifdef HAVE_AS_SPARC_UA_PCREL
-	.uaword	%r_disp32(.LLFB2)
-	.uaword	.LLFE2-.LLFB2	! FDE address range
-#else
-	.align	WS
-	.nword	.LLFB2
-	.uanword .LLFE2-.LLFB2	! FDE address range
-#endif
-	.byte	0x0	! uleb128 0x0; Augmentation size
-	.byte	0x4	! DW_CFA_advance_loc4
-	.uaword	.LLCFI1-.LLFB2
-	.byte	0xd	! DW_CFA_def_cfa_register
-	.byte	0x1e	! uleb128 0x1e
-	.byte	0x2d	! DW_CFA_GNU_window_save
-	.byte	0x9	! DW_CFA_register
-	.byte	0xf	! uleb128 0xf
-	.byte	0x1f	! uleb128 0x1f
-	.align	WS
-.LLEFDE2:
-#endif
-
+	cfi_endproc
+	.size	C(ffi_closure_v8), . - C(ffi_closure_v8)
+#endif /* !SPARC64 */
 #if defined __ELF__ && defined __linux__
 	.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/third_party/gofrontend/libffi/src/sparc/v9.S b/third_party/gofrontend/libffi/src/sparc/v9.S
index 2c97673..52732d3 100644
--- a/third_party/gofrontend/libffi/src/sparc/v9.S
+++ b/third_party/gofrontend/libffi/src/sparc/v9.S
@@ -1,6 +1,6 @@
 /* -----------------------------------------------------------------------
    v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc.
-
+   
    SPARC 64-bit Foreign Function Interface 
 
    Permission is hereby granted, free of charge, to any person obtaining
@@ -27,103 +27,178 @@
 #define LIBFFI_ASM	
 #include <fficonfig.h>
 #include <ffi.h>
+#include <ffi_cfi.h>
+#include "internal.h"
 
 #ifdef SPARC64
 
-#define STACKFRAME 176		/* Minimum stack framesize for SPARC 64-bit */
+#define C2(X, Y)  X ## Y
+#define C1(X, Y)  C2(X, Y)
+
+#ifdef __USER_LABEL_PREFIX__
+# define C(Y)	C1(__USER_LABEL_PREFIX__, Y)
+#else
+# define C(Y)	Y
+#endif
+#define L(Y)	C1(.L, Y)
+
+.macro E index
+	.align	16
+	.org	2b + \index * 16
+.endm
+
 #define STACK_BIAS 2047
-#define ARGS (128)		/* Offset of register area in frame */
 
-.text
+	.text
         .align 8
-.globl ffi_call_v9
-.globl _ffi_call_v9
+	.globl	C(ffi_call_v9)
+	.type	C(ffi_call_v9),@function
+	FFI_HIDDEN(C(ffi_call_v9))
 
-ffi_call_v9:
-_ffi_call_v9:
-.LLFB1:
-	save	%sp, -STACKFRAME, %sp
-.LLCFI0:
+C(ffi_call_v9):
+	cfi_startproc
+	save	%sp, %o4, %sp
+	cfi_def_cfa_register(%fp)
+	cfi_window_save
 	
-	sub	%sp, %i2, %sp	! alloca() space in stack for frame to set up
-	add	%sp, STACKFRAME+STACK_BIAS, %l0	! %l0 has start of 
-						! frame to set up
+	mov	%i0, %o0			! copy cif
+	add	%sp, STACK_BIAS+128+48, %o1	! load args area
+	mov	%i2, %o2			! copy rvalue
+	call	C(ffi_prep_args_v9)
+	 mov	%i3, %o3			! copy avalue
 
-	mov	%l0, %o0	! call routine to set up frame
-	call	%i0
-	 mov	%i1, %o1	! (delay)
-	brz,pt	%o0, 1f
-	 ldx	[%l0+ARGS], %o0	! call foreign function
+	andcc	%o0, SPARC_FLAG_FP_ARGS, %g0	! need fp regs?
+	add	%sp, 48, %sp			! deallocate prep frame
+	be,pt	%xcc, 1f
+	 mov	%o0, %l0			! save flags
 
-	ldd	[%l0+ARGS], %f0
-	ldd	[%l0+ARGS+8], %f2
-	ldd	[%l0+ARGS+16], %f4
-	ldd	[%l0+ARGS+24], %f6
-	ldd	[%l0+ARGS+32], %f8
-	ldd	[%l0+ARGS+40], %f10
-	ldd	[%l0+ARGS+48], %f12
-	ldd	[%l0+ARGS+56], %f14
-	ldd	[%l0+ARGS+64], %f16
-	ldd	[%l0+ARGS+72], %f18
-	ldd	[%l0+ARGS+80], %f20
-	ldd	[%l0+ARGS+88], %f22
-	ldd	[%l0+ARGS+96], %f24
-	ldd	[%l0+ARGS+104], %f26
-	ldd	[%l0+ARGS+112], %f28
-	ldd	[%l0+ARGS+120], %f30
+	ldd	[%sp+STACK_BIAS+128], %f0	! load all fp arg regs
+	ldd	[%sp+STACK_BIAS+128+8], %f2
+	ldd	[%sp+STACK_BIAS+128+16], %f4
+	ldd	[%sp+STACK_BIAS+128+24], %f6
+	ldd	[%sp+STACK_BIAS+128+32], %f8
+	ldd	[%sp+STACK_BIAS+128+40], %f10
+	ldd	[%sp+STACK_BIAS+128+48], %f12
+	ldd	[%sp+STACK_BIAS+128+56], %f14
+	ldd	[%sp+STACK_BIAS+128+64], %f16
+	ldd	[%sp+STACK_BIAS+128+72], %f18
+	ldd	[%sp+STACK_BIAS+128+80], %f20
+	ldd	[%sp+STACK_BIAS+128+88], %f22
+	ldd	[%sp+STACK_BIAS+128+96], %f24
+	ldd	[%sp+STACK_BIAS+128+104], %f26
+	ldd	[%sp+STACK_BIAS+128+112], %f28
+	ldd	[%sp+STACK_BIAS+128+120], %f30
 
-1:	ldx	[%l0+ARGS+8], %o1
-	ldx	[%l0+ARGS+16], %o2
-	ldx	[%l0+ARGS+24], %o3
-	ldx	[%l0+ARGS+32], %o4
-	ldx	[%l0+ARGS+40], %o5
-	call	%i5
-	 sub	%l0, STACK_BIAS, %sp	! (delay) switch to frame
+1:	ldx	[%sp+STACK_BIAS+128], %o0	! load all int arg regs
+	ldx	[%sp+STACK_BIAS+128+8], %o1
+	ldx	[%sp+STACK_BIAS+128+16], %o2
+	ldx	[%sp+STACK_BIAS+128+24], %o3
+	ldx	[%sp+STACK_BIAS+128+32], %o4
+	ldx	[%sp+STACK_BIAS+128+40], %o5
+	call	%i1
+	 mov	%i5, %g5			! load static chain
 
-	! If the return value pointer is NULL, assume no return value.
-	brz,pn	%i4, done
+0:	call	1f		! load pc in %o7
+	 and	%l0, SPARC_FLAG_RET_MASK, %l1
+1:	sll	%l1, 4, %l1
+	add	%o7, %l1, %o7	! o7 = 0b + ret_type*16
+	jmp	%o7+(2f-0b)
 	 nop
 
-	cmp	%i3, FFI_TYPE_INT
-	be,a,pt	%icc, done
-	 stx	%o0, [%i4+0]	! (delay)
-
-	cmp	%i3, FFI_TYPE_FLOAT
-	be,a,pn	%icc, done
-	 st	%f0, [%i4+0]	! (delay)
-
-	cmp	%i3, FFI_TYPE_DOUBLE
-	be,a,pn	%icc, done
-	 std	%f0, [%i4+0]	! (delay)
-
-	cmp	%i3, FFI_TYPE_STRUCT
-	be,pn	%icc, dostruct
-
-	cmp	%i3, FFI_TYPE_LONGDOUBLE
-	bne,pt	%icc, done
+	.align	16
+2:
+E SPARC_RET_VOID
+	return	%i7+8
 	 nop
-	std	%f0, [%i4+0]
-	std	%f2, [%i4+8]
+E SPARC_RET_STRUCT
+	add	%sp, STACK_BIAS-64+128+48, %l2
+	sub	%sp, 64, %sp
+	b	8f
+	 stx	%o0, [%l2]
+E SPARC_RET_UINT8
+	and	%o0, 0xff, %i0
+	return	%i7+8
+	  stx	%o0, [%o2]
+E SPARC_RET_SINT8
+	sll	%o0, 24, %o0
+	sra	%o0, 24, %i0
+	return	%i7+8
+	 stx	%o0, [%o2]
+E SPARC_RET_UINT16
+	sll	%o0, 16, %o0
+	srl	%o0, 16, %i0
+	return	%i7+8
+	 stx	%o0, [%o2]
+E SPARC_RET_SINT16
+	sll	%o0, 16, %o0
+	sra	%o0, 16, %i0
+	return	%i7+8
+	 stx	%o0, [%o2]
+E SPARC_RET_UINT32
+	srl	%o0, 0, %i0
+	return	%i7+8
+	 stx	%o0, [%o2]
+E SP_V9_RET_SINT32
+	sra	%o0, 0, %i0
+	return	%i7+8
+	 stx	%o0, [%o2]
+E SPARC_RET_INT64
+	stx	%o0, [%i2]
+	return	%i7+8
+	 nop
+E SPARC_RET_INT128
+	stx	%o0, [%i2]
+	stx	%o1, [%i2+8]
+	return	%i7+8
+	 nop
+E SPARC_RET_F_8
+	st	%f7, [%i2+7*4]
+	nop
+	st	%f6, [%i2+6*4]
+	nop
+E SPARC_RET_F_6
+	st	%f5, [%i2+5*4]
+	nop
+	st	%f4, [%i2+4*4]
+	nop
+E SPARC_RET_F_4
+	std	%f2, [%i2+2*4]
+	return	%i7+8
+	 std	%f0, [%o2]
+E SPARC_RET_F_2
+	return	%i7+8
+	 std	%f0, [%o2]
+E SP_V9_RET_F_3
+	st	%f2, [%i2+2*4]
+	nop
+	st	%f1, [%i2+1*4]
+	nop
+E SPARC_RET_F_1
+	return	%i7+8
+	 st	%f0, [%o2]
 
-done:	ret
-	 restore
+	! Finish the SPARC_RET_STRUCT sequence.
+	.align	8
+8:	stx	%o1, [%l2+8]
+	stx	%o2, [%l2+16]
+	stx	%o3, [%l2+24]
+	std	%f0, [%l2+32]
+	std	%f2, [%l2+40]
+	std	%f4, [%l2+48]
+	std	%f6, [%l2+56]
 
-dostruct:
-	/* This will not work correctly for unions. */
-	stx	%o0, [%i4+0]
-	stx	%o1, [%i4+8]
-	stx	%o2, [%i4+16]
-	stx	%o3, [%i4+24]
-	std	%f0, [%i4+32]
-	std	%f2, [%i4+40]
-	std	%f4, [%i4+48]
-	std	%f6, [%i4+56]
-	ret
-	 restore
-.LLFE1:
+	! Copy the structure into place.
+	srl	%l0, SPARC_SIZEMASK_SHIFT, %o0	! load size_mask
+	mov	%i2, %o1			! load dst
+	mov	%l2, %o2			! load src_gp
+	call	C(ffi_struct_float_copy)
+	 add	%l2, 32, %o3			! load src_fp
 
-.ffi_call_v9_end:
-	.size	ffi_call_v9,.ffi_call_v9_end-ffi_call_v9
+	return	%i7+8
+	 nop
+
+	cfi_endproc
+	.size	C(ffi_call_v9), . - C(ffi_call_v9)
 
 
 #undef STACKFRAME
@@ -136,15 +211,40 @@
 
    Receives the closure argument in %g1.   */
 
-	.text
 	.align 8
-	.globl ffi_closure_v9
+	.globl	C(ffi_go_closure_v9)
+	.type	C(ffi_go_closure_v9),@function
+	FFI_HIDDEN(C(ffi_go_closure_v9))
 
-ffi_closure_v9:
-.LLFB2:
+C(ffi_go_closure_v9):
+	cfi_startproc
 	save	%sp, -STACKFRAME, %sp
-.LLCFI1:
+	cfi_def_cfa_register(%fp)
+	cfi_window_save
 
+	ldx	[%g5+8], %o0
+	ldx	[%g5+16], %o1
+	b	0f
+	 mov	%g5, %o2
+
+	cfi_endproc
+	.size	C(ffi_go_closure_v9), . - C(ffi_go_closure_v9)
+
+	.align 8
+	.globl	C(ffi_closure_v9)
+	.type	C(ffi_closure_v9),@function
+	FFI_HIDDEN(C(ffi_closure_v9))
+
+C(ffi_closure_v9):
+	cfi_startproc
+	save	%sp, -STACKFRAME, %sp
+	cfi_def_cfa_register(%fp)
+	cfi_window_save
+
+	ldx	[%g1+FFI_TRAMPOLINE_SIZE], %o0
+	ldx	[%g1+FFI_TRAMPOLINE_SIZE+8], %o1
+	ldx	[%g1+FFI_TRAMPOLINE_SIZE+16], %o2
+0:
 	! Store all of the potential argument registers in va_list format.
 	stx	%i0, [FP+128+0]
 	stx	%i1, [FP+128+8]
@@ -172,134 +272,106 @@
 	std     %f30, [FP-8]
 
 	! Call ffi_closure_sparc_inner to do the bulk of the work.
-	mov	%g1, %o0
-	add	%fp, STACK_BIAS-160, %o1
-	add	%fp, STACK_BIAS+128, %o2
-	call	ffi_closure_sparc_inner_v9
-	 add	%fp, STACK_BIAS-128, %o3
+	add	%fp, STACK_BIAS-160, %o3
+	add	%fp, STACK_BIAS+128, %o4
+	call	C(ffi_closure_sparc_inner_v9)
+	 add	%fp, STACK_BIAS-128, %o5
 
-	! Load up the return value in the proper type.
-	! See ffi_prep_cif_machdep for the list of cases.
-	cmp	%o0, FFI_TYPE_VOID
-	be,pn	%icc, done1
+0:	call	1f		! load pc in %o7
+	 and	%o0, SPARC_FLAG_RET_MASK, %o0
+1:	sll	%o0, 4, %o0	! o2 = i2 * 16
+	add	%o7, %o0, %o7	! o7 = 0b + i2*16
+	jmp	%o7+(2f-0b)
+	 nop
 
-	cmp	%o0, FFI_TYPE_INT
-	be,pn	%icc, integer
-
-	cmp	%o0, FFI_TYPE_FLOAT
-	be,a,pn	%icc, done1
-	 ld	[FP-160], %f0
-
-	cmp	%o0, FFI_TYPE_DOUBLE
-	be,a,pn	%icc, done1
-	 ldd	[FP-160], %f0
-
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	cmp	%o0, FFI_TYPE_LONGDOUBLE
-	be,a,pn	%icc, longdouble1
-	 ldd	[FP-160], %f0
-#endif
-
-	! FFI_TYPE_STRUCT
-	ldx	[FP-152], %i1
-	ldx	[FP-144], %i2
-	ldx	[FP-136], %i3
-	ldd	[FP-160], %f0
-	ldd	[FP-152], %f2
-	ldd	[FP-144], %f4
-	ldd	[FP-136], %f6
-
-integer:
+	! Note that we cannot load the data in the delay slot of
+	! the return insn because the data is in the stack frame
+	! that is deallocated by the return.
+	.align	16
+2:
+E SPARC_RET_VOID
+	return	%i7+8
+	 nop
+E SPARC_RET_STRUCT
 	ldx	[FP-160], %i0
+	ldd	[FP-160], %f0
+	b	8f
+	 ldx	[FP-152], %i1
+E SPARC_RET_UINT8
+	ldub	[FP-160+7], %i0
+	return	%i7+8
+	 nop
+E SPARC_RET_SINT8
+	ldsb	[FP-160+7], %i0
+	return	%i7+8
+	 nop
+E SPARC_RET_UINT16
+	lduh	[FP-160+6], %i0
+	return	%i7+8
+	 nop
+E SPARC_RET_SINT16
+	ldsh	[FP-160+6], %i0
+	return	%i7+8
+	 nop
+E SPARC_RET_UINT32
+	lduw	[FP-160+4], %i0
+	return	%i7+8
+	 nop
+E SP_V9_RET_SINT32
+	ldsw	[FP-160+4], %i0
+	return	%i7+8
+	 nop
+E SPARC_RET_INT64
+	ldx	[FP-160], %i0
+	return	%i7+8
+	 nop
+E SPARC_RET_INT128
+	ldx	[FP-160], %i0
+	ldx	[FP-160+8], %i1
+	return	%i7+8
+	 nop
+E SPARC_RET_F_8
+	ld	[FP-160+7*4], %f7
+	nop
+	ld	[FP-160+6*4], %f6
+	nop
+E SPARC_RET_F_6
+	ld	[FP-160+5*4], %f5
+	nop
+	ld	[FP-160+4*4], %f4
+	nop
+E SPARC_RET_F_4
+	ldd	[FP-160], %f0
+	ldd	[FP-160+8], %f2
+	return	%i7+8
+	 nop
+E SPARC_RET_F_2
+	ldd	[FP-160], %f0
+	return	%i7+8
+	 nop
+E SP_V9_RET_F_3
+	ld	[FP-160+2*4], %f2
+	nop
+	ld	[FP-160+1*4], %f1
+	nop
+E SPARC_RET_F_1
+	ld	[FP-160], %f0
+	return	%i7+8
+	 nop
 
-done1:
-	ret
-	 restore
+	! Finish the SPARC_RET_STRUCT sequence.
+	.align	8
+8:	ldd	[FP-152], %f2
+	ldx	[FP-144], %i2
+	ldd	[FP-144], %f4
+	ldx	[FP-136], %i3
+	ldd	[FP-136], %f6
+	return	%i7+8
+	 nop
 
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-longdouble1:
-	ldd	[FP-152], %f2
-	ret
-	 restore
-#endif
-.LLFE2:
-
-.ffi_closure_v9_end:
-	.size	ffi_closure_v9,.ffi_closure_v9_end-ffi_closure_v9
-
-#ifdef HAVE_RO_EH_FRAME
-	.section	".eh_frame",#alloc
-#else
-	.section	".eh_frame",#alloc,#write
-#endif
-.LLframe1:
-	.uaword	.LLECIE1-.LLSCIE1	! Length of Common Information Entry
-.LLSCIE1:
-	.uaword	0x0	! CIE Identifier Tag
-	.byte	0x1	! CIE Version
-	.ascii "zR\0"	! CIE Augmentation
-	.byte	0x1	! uleb128 0x1; CIE Code Alignment Factor
-	.byte	0x78	! sleb128 -8; CIE Data Alignment Factor
-	.byte	0xf	! CIE RA Column
-	.byte	0x1	! uleb128 0x1; Augmentation size
-#ifdef HAVE_AS_SPARC_UA_PCREL
-	.byte	0x1b	! FDE Encoding (pcrel sdata4)
-#else
-	.byte	0x50	! FDE Encoding (aligned absolute)
-#endif
-	.byte	0xc	! DW_CFA_def_cfa
-	.byte	0xe	! uleb128 0xe
-	.byte	0xff,0xf	! uleb128 0x7ff
-	.align 8
-.LLECIE1:
-.LLSFDE1:
-	.uaword	.LLEFDE1-.LLASFDE1	! FDE Length
-.LLASFDE1:
-	.uaword	.LLASFDE1-.LLframe1	! FDE CIE offset
-#ifdef HAVE_AS_SPARC_UA_PCREL
-	.uaword	%r_disp32(.LLFB1)
-	.uaword	.LLFE1-.LLFB1		! FDE address range
-#else
-	.align 8
-	.xword	.LLFB1
-	.uaxword	.LLFE1-.LLFB1	! FDE address range
-#endif
-	.byte	0x0	! uleb128 0x0; Augmentation size
-	.byte	0x4	! DW_CFA_advance_loc4
-	.uaword	.LLCFI0-.LLFB1
-	.byte	0xd	! DW_CFA_def_cfa_register
-	.byte	0x1e	! uleb128 0x1e
-	.byte	0x2d	! DW_CFA_GNU_window_save
-	.byte	0x9	! DW_CFA_register
-	.byte	0xf	! uleb128 0xf
-	.byte	0x1f	! uleb128 0x1f
-	.align 8
-.LLEFDE1:
-.LLSFDE2:
-	.uaword	.LLEFDE2-.LLASFDE2	! FDE Length
-.LLASFDE2:
-	.uaword	.LLASFDE2-.LLframe1	! FDE CIE offset
-#ifdef HAVE_AS_SPARC_UA_PCREL
-	.uaword	%r_disp32(.LLFB2)
-	.uaword	.LLFE2-.LLFB2		! FDE address range
-#else
-	.align 8
-	.xword	.LLFB2
-	.uaxword	.LLFE2-.LLFB2	! FDE address range
-#endif
-	.byte	0x0	! uleb128 0x0; Augmentation size
-	.byte	0x4	! DW_CFA_advance_loc4
-	.uaword	.LLCFI1-.LLFB2
-	.byte	0xd	! DW_CFA_def_cfa_register
-	.byte	0x1e	! uleb128 0x1e
-	.byte	0x2d	! DW_CFA_GNU_window_save
-	.byte	0x9	! DW_CFA_register
-	.byte	0xf	! uleb128 0xf
-	.byte	0x1f	! uleb128 0x1f
-	.align 8
-.LLEFDE2:
-#endif
-
+	cfi_endproc
+	.size	C(ffi_closure_v9), . - C(ffi_closure_v9)
+#endif /* SPARC64 */
 #ifdef __linux__
 	.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/third_party/gofrontend/libffi/src/tile/tile.S b/third_party/gofrontend/libffi/src/tile/tile.S
index a186e1f..d1f82cb 100644
--- a/third_party/gofrontend/libffi/src/tile/tile.S
+++ b/third_party/gofrontend/libffi/src/tile/tile.S
@@ -60,7 +60,7 @@
                        void (*fnaddr)(void));
 
         On entry, REG_ARGS contain the outgoing register values,
-        and STACK_ARGS containts STACK_ARG_BYTES of additional values
+        and STACK_ARGS contains STACK_ARG_BYTES of additional values
         to be passed on the stack. If STACK_ARG_BYTES is zero, then
         STACK_ARGS is ignored.
 
diff --git a/third_party/gofrontend/libffi/src/types.c b/third_party/gofrontend/libffi/src/types.c
index 0de5994..7e80aec 100644
--- a/third_party/gofrontend/libffi/src/types.c
+++ b/third_party/gofrontend/libffi/src/types.c
@@ -33,26 +33,30 @@
 
 /* Type definitions */
 
-#define FFI_TYPEDEF(name, type, id)		\
+#define FFI_TYPEDEF(name, type, id, maybe_const)\
 struct struct_align_##name {			\
   char c;					\
   type x;					\
 };						\
-const ffi_type ffi_type_##name = {		\
+maybe_const ffi_type ffi_type_##name = {	\
   sizeof(type),					\
   offsetof(struct struct_align_##name, x),	\
   id, NULL					\
 }
 
-#define FFI_NONCONST_TYPEDEF(name, type, id)	\
-struct struct_align_##name {			\
-  char c;					\
-  type x;					\
-};						\
-ffi_type ffi_type_##name = {			\
-  sizeof(type),					\
-  offsetof(struct struct_align_##name, x),	\
-  id, NULL					\
+#define FFI_COMPLEX_TYPEDEF(name, type, maybe_const)	\
+static ffi_type *ffi_elements_complex_##name [2] = {	\
+	(ffi_type *)(&ffi_type_##name), NULL		\
+};							\
+struct struct_align_complex_##name {			\
+  char c;						\
+  _Complex type x;					\
+};							\
+maybe_const ffi_type ffi_type_complex_##name = {	\
+  sizeof(_Complex type),				\
+  offsetof(struct struct_align_complex_##name, x),	\
+  FFI_TYPE_COMPLEX,					\
+  (ffi_type **)ffi_elements_complex_##name		\
 }
 
 /* Size and alignment are fake here. They must not be 0. */
@@ -60,19 +64,25 @@
   1, 1, FFI_TYPE_VOID, NULL
 };
 
-FFI_TYPEDEF(uint8, UINT8, FFI_TYPE_UINT8);
-FFI_TYPEDEF(sint8, SINT8, FFI_TYPE_SINT8);
-FFI_TYPEDEF(uint16, UINT16, FFI_TYPE_UINT16);
-FFI_TYPEDEF(sint16, SINT16, FFI_TYPE_SINT16);
-FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32);
-FFI_TYPEDEF(sint32, SINT32, FFI_TYPE_SINT32);
-FFI_TYPEDEF(uint64, UINT64, FFI_TYPE_UINT64);
-FFI_TYPEDEF(sint64, SINT64, FFI_TYPE_SINT64);
+FFI_TYPEDEF(uint8, UINT8, FFI_TYPE_UINT8, const);
+FFI_TYPEDEF(sint8, SINT8, FFI_TYPE_SINT8, const);
+FFI_TYPEDEF(uint16, UINT16, FFI_TYPE_UINT16, const);
+FFI_TYPEDEF(sint16, SINT16, FFI_TYPE_SINT16, const);
+FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32, const);
+FFI_TYPEDEF(sint32, SINT32, FFI_TYPE_SINT32, const);
+FFI_TYPEDEF(uint64, UINT64, FFI_TYPE_UINT64, const);
+FFI_TYPEDEF(sint64, SINT64, FFI_TYPE_SINT64, const);
 
-FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER);
+FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER, const);
 
-FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT);
-FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE);
+FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT, const);
+FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE, const);
+
+#if !defined HAVE_LONG_DOUBLE_VARIANT || defined __alpha__
+#define FFI_LDBL_CONST const
+#else
+#define FFI_LDBL_CONST
+#endif
 
 #ifdef __alpha__
 /* Even if we're not configured to default to 128-bit long double, 
@@ -84,9 +94,13 @@
 # endif
 const ffi_type ffi_type_longdouble = { 16, 16, 4, NULL };
 #elif FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-# if HAVE_LONG_DOUBLE_VARIANT
-FFI_NONCONST_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE);
-# else
-FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE);
-# endif
+FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE, FFI_LDBL_CONST);
+#endif
+
+#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
+FFI_COMPLEX_TYPEDEF(float, float, const);
+FFI_COMPLEX_TYPEDEF(double, double, const);
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+FFI_COMPLEX_TYPEDEF(longdouble, long double, FFI_LDBL_CONST);
+#endif
 #endif
diff --git a/third_party/gofrontend/libffi/src/vax/elfbsd.S b/third_party/gofrontend/libffi/src/vax/elfbsd.S
new file mode 100644
index 0000000..01ca313
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/vax/elfbsd.S
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2013 Miodrag Vallat.  <miod@openbsd.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * ``Software''), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * vax Foreign Function Interface
+ */
+
+#define LIBFFI_ASM	
+#include <fficonfig.h>
+#include <ffi.h>
+
+	.text
+
+/*
+ * void *					%r0
+ * ffi_call_elfbsd(extended_cif *ecif,		4(%ap)
+ *		   unsigned bytes,		8(%ap)
+ *		   unsigned flags,		12(%ap)
+ *		   void *rvalue,		16(%ap)
+ *		   void (*fn)());		20(%ap)
+ */
+	.globl	ffi_call_elfbsd
+	.type	ffi_call_elfbsd,@function
+	.align	2
+ffi_call_elfbsd:
+	.word	0x00c		# save R2 and R3
+
+	# Allocate stack space for the args
+	subl2	8(%ap), %sp
+
+	# Call ffi_prep_args
+	pushl	%sp
+	pushl	4(%ap)
+	calls	$2, ffi_prep_args
+
+	# Get function pointer
+	movl	20(%ap), %r1
+
+	# Build a CALLS frame
+	ashl	$-2, 8(%ap), %r0
+	pushl	%r0		# argument stack usage
+	movl	%sp, %r0	# future %ap
+	# saved registers
+	bbc	$11, 0(%r1), 1f
+	pushl	%r11
+1:	bbc	$10, 0(%r1), 1f
+	pushl	%r10
+1:	bbc	$9, 0(%r1), 1f
+	pushl	%r9
+1:	bbc	$8, 0(%r1), 1f
+	pushl	%r8
+1:	bbc	$7, 0(%r1), 1f
+	pushl	%r7
+1:	bbc	$6, 0(%r1), 1f
+	pushl	%r6
+1:	bbc	$5, 0(%r1), 1f
+	pushl	%r5
+1:	bbc	$4, 0(%r1), 1f
+	pushl	%r4
+1:	bbc	$3, 0(%r1), 1f
+	pushl	%r3
+1:	bbc	$2, 0(%r1), 1f
+	pushl	%r2
+1:	
+	pushal	9f
+	pushl	%fp
+	pushl	%ap
+	movl	16(%ap), %r3	# struct return address, if needed
+	movl	%r0, %ap
+	movzwl	4(%fp), %r0	# previous PSW, without the saved registers mask
+	bisl2	$0x20000000, %r0 # calls frame
+	movzwl	0(%r1), %r2
+	bicw2	$0xf003, %r2	# only keep R11-R2
+	ashl	$16, %r2, %r2
+	bisl2	%r2, %r0	# saved register mask of the called function
+	pushl	%r0	
+	pushl	$0
+	movl	%sp, %fp
+
+	# Invoke the function
+	pushal	2(%r1)		# skip procedure entry mask
+	movl	%r3, %r1
+	bicpsw	$0x000f
+	rsb
+
+9:
+	# Copy return value if necessary
+	tstl	16(%ap)
+	jeql	9f
+	movl	16(%ap), %r2
+
+	bbc	$0, 12(%ap), 1f	# CIF_FLAGS_CHAR
+	movb	%r0, 0(%r2)
+	brb	9f
+1:
+	bbc	$1, 12(%ap), 1f	# CIF_FLAGS_SHORT
+	movw	%r0, 0(%r2)
+	brb	9f
+1:
+	bbc	$2, 12(%ap), 1f	# CIF_FLAGS_INT
+	movl	%r0, 0(%r2)
+	brb	9f
+1:
+	bbc	$3, 12(%ap), 1f	# CIF_FLAGS_DINT
+	movq	%r0, 0(%r2)
+	brb	9f
+1:
+	movl	%r1, %r0	# might have been a struct
+	#brb	9f
+
+9:
+	ret
+
+/*
+ * ffi_closure_elfbsd(void);
+ * invoked with	%r0: ffi_closure *closure
+ */
+	.globl	ffi_closure_elfbsd
+	.type	ffi_closure_elfbsd, @function
+	.align	2
+ffi_closure_elfbsd:
+	.word	0
+
+	# Allocate room on stack for return value
+	subl2	$8, %sp
+
+	# Invoke the closure function
+	pushal	4(%ap)		# calling stack
+	pushal	4(%sp)		# return value
+	pushl	%r0		# closure
+	calls	$3, ffi_closure_elfbsd_inner
+
+	# Copy return value if necessary
+	bitb	$1, %r0		# CIF_FLAGS_CHAR
+	beql	1f
+	movb	0(%sp), %r0
+	brb	9f
+1:
+	bitb	$2, %r0		# CIF_FLAGS_SHORT
+	beql	1f
+	movw	0(%sp), %r0
+	brb	9f
+1:
+	bitb	$4, %r0		# CIF_FLAGS_INT
+	beql	1f
+	movl	0(%sp), %r0
+	brb	9f
+1:
+	bitb	$8, %r0		# CIF_FLAGS_DINT
+	beql	1f
+	movq	0(%sp), %r0
+	#brb	9f
+1:
+
+9:
+	ret
+
+/*
+ * ffi_closure_struct_elfbsd(void);
+ * invoked with	%r0: ffi_closure *closure
+ *		%r1: struct return address
+ */
+	.globl	ffi_closure_struct_elfbsd
+	.type	ffi_closure_struct_elfbsd, @function
+	.align	2
+ffi_closure_struct_elfbsd:
+	.word	0
+
+	# Invoke the closure function
+	pushal	4(%ap)		# calling stack
+	pushl	%r1		# return value
+	pushl	%r0		# closure
+	calls	$3, ffi_closure_elfbsd_inner
+
+	ret
diff --git a/third_party/gofrontend/libffi/src/vax/ffi.c b/third_party/gofrontend/libffi/src/vax/ffi.c
new file mode 100644
index 0000000..f4d6bbb
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/vax/ffi.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2013 Miodrag Vallat.  <miod@openbsd.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * ``Software''), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * vax Foreign Function Interface
+ *
+ * This file attempts to provide all the FFI entry points which can reliably
+ * be implemented in C.
+ */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#define CIF_FLAGS_CHAR		1	/* for struct only */
+#define CIF_FLAGS_SHORT		2	/* for struct only */
+#define CIF_FLAGS_INT		4
+#define CIF_FLAGS_DINT		8
+
+/*
+ * Foreign Function Interface API
+ */
+
+void ffi_call_elfbsd (extended_cif *, unsigned, unsigned, void *,
+		       void (*) ());
+void *ffi_prep_args (extended_cif *ecif, void *stack);
+
+void *
+ffi_prep_args (extended_cif *ecif, void *stack)
+{
+  unsigned int i;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+  void *struct_value_ptr;
+
+  argp = stack;
+
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
+      && !ecif->cif->flags)
+    struct_value_ptr = ecif->rvalue;
+  else
+    struct_value_ptr = NULL;
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       i != 0;
+       i--, p_arg++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof (int))
+	{
+	  switch ((*p_arg)->type)
+	    {
+	    case FFI_TYPE_SINT8:
+	      *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
+	      break;
+
+	    case FFI_TYPE_UINT8:
+	      *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
+	      break;
+
+	    case FFI_TYPE_SINT16:
+	      *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
+	      break;
+
+	    case FFI_TYPE_UINT16:
+	      *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
+	      break;
+
+	    case FFI_TYPE_STRUCT:
+	      memcpy (argp, *p_argv, z);
+	      break;
+
+	    default:
+	      FFI_ASSERT (0);
+	    }
+	  z = sizeof (int);
+	}
+      else
+	{
+	  memcpy (argp, *p_argv, z);
+
+	  /* Align if necessary.  */
+	  if ((sizeof(int) - 1) & z)
+	    z = ALIGN(z, sizeof(int));
+	}
+
+      p_argv++;
+      argp += z;
+    }
+
+  return struct_value_ptr;
+}
+
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+      cif->flags = 0;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      if (cif->rtype->elements[0]->type == FFI_TYPE_STRUCT &&
+	  cif->rtype->elements[1])
+	{
+	  cif->flags = 0;
+	  break;
+	}
+
+      if (cif->rtype->size == sizeof (char))
+	cif->flags = CIF_FLAGS_CHAR;
+      else if (cif->rtype->size == sizeof (short))
+	cif->flags = CIF_FLAGS_SHORT;
+      else if (cif->rtype->size == sizeof (int))
+	cif->flags = CIF_FLAGS_INT;
+      else if (cif->rtype->size == 2 * sizeof (int))
+	cif->flags = CIF_FLAGS_DINT;
+      else
+	cif->flags = 0;
+      break;
+
+    default:
+      if (cif->rtype->size <= sizeof (int))
+	cif->flags = CIF_FLAGS_INT;
+      else
+	cif->flags = CIF_FLAGS_DINT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+void
+ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* If the return value is a struct and we don't have a return value
+     address then we need to make one.  */
+
+  if (rvalue == NULL
+      && cif->rtype->type == FFI_TYPE_STRUCT
+      && cif->flags == 0)
+    ecif.rvalue = alloca (cif->rtype->size);
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi)
+    {
+    case FFI_ELFBSD:
+      ffi_call_elfbsd (&ecif, cif->bytes, cif->flags, ecif.rvalue, fn);
+      break;
+
+    default:
+      FFI_ASSERT (0);
+      break;
+    }
+}
+
+/*
+ * Closure API
+ */
+
+void ffi_closure_elfbsd (void);
+void ffi_closure_struct_elfbsd (void);
+unsigned int ffi_closure_elfbsd_inner (ffi_closure *, void *, char *);
+
+static void
+ffi_prep_closure_elfbsd (ffi_cif *cif, void **avalue, char *stackp)
+{
+  unsigned int i;
+  void **p_argv;
+  ffi_type **p_arg;
+
+  p_argv = avalue;
+
+  for (i = cif->nargs, p_arg = cif->arg_types; i != 0; i--, p_arg++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      *p_argv = stackp;
+
+      /* Align if necessary */
+      if ((sizeof (int) - 1) & z)
+	z = ALIGN(z, sizeof (int));
+
+      p_argv++;
+      stackp += z;
+    }
+}
+
+unsigned int
+ffi_closure_elfbsd_inner (ffi_closure *closure, void *resp, char *stack)
+{
+  ffi_cif *cif;
+  void **arg_area;
+
+  cif = closure->cif;
+  arg_area = (void **) alloca (cif->nargs * sizeof (void *));
+
+  ffi_prep_closure_elfbsd (cif, arg_area, stack);
+
+  (closure->fun) (cif, resp, arg_area, closure->user_data);
+
+  return cif->flags;
+}
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure *closure, ffi_cif *cif,
+		      void (*fun)(ffi_cif *, void *, void **, void *),
+		      void *user_data, void *codeloc)
+{
+  char *tramp = (char *) codeloc;
+  void *fn;
+
+  FFI_ASSERT (cif->abi == FFI_ELFBSD);
+
+  /* entry mask */
+  *(unsigned short *)(tramp + 0) = 0x0000;
+  /* movl #closure, r0 */
+  tramp[2] = 0xd0;
+  tramp[3] = 0x8f;
+  *(unsigned int *)(tramp + 4) = (unsigned int) closure;
+  tramp[8] = 0x50;
+
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+      && !cif->flags)
+    fn = &ffi_closure_struct_elfbsd;
+  else
+    fn = &ffi_closure_elfbsd;
+
+  /* jmpl #fn */
+  tramp[9] = 0x17;
+  tramp[10] = 0xef;
+  *(unsigned int *)(tramp + 11) = (unsigned int)fn + 2 -
+				  (unsigned int)tramp - 9 - 6;
+
+  closure->cif = cif;
+  closure->user_data = user_data;
+  closure->fun = fun;
+
+  return FFI_OK;
+}
diff --git a/third_party/gofrontend/libffi/src/vax/ffitarget.h b/third_party/gofrontend/libffi/src/vax/ffitarget.h
new file mode 100644
index 0000000..2fc9488
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/vax/ffitarget.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 Miodrag Vallat.  <miod@openbsd.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * ``Software''), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * vax Foreign Function Interface
+ */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_ASM
+typedef unsigned long ffi_arg;
+typedef signed long ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_ELFBSD,
+  FFI_DEFAULT_ABI = FFI_ELFBSD,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 15
+#define FFI_NATIVE_RAW_API 0
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/x86/darwin64_c.c b/third_party/gofrontend/libffi/src/x86/darwin64_c.c
new file mode 100644
index 0000000..1daa1c0
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/darwin64_c.c
@@ -0,0 +1,643 @@
+/* -----------------------------------------------------------------------
+   ffi64.c - Copyright (c) 20011  Anthony Green
+             Copyright (c) 2008, 2010  Red Hat, Inc.
+             Copyright (c) 2002, 2007  Bo Thorsen <bo@suse.de>
+             
+   x86-64 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#ifdef __x86_64__
+
+#define MAX_GPR_REGS 6
+#define MAX_SSE_REGS 8
+
+#ifdef __INTEL_COMPILER
+#define UINT128 __m128
+#else
+#define UINT128 __int128_t
+#endif
+
+struct register_args
+{
+  /* Registers for argument passing.  */
+  UINT64 gpr[MAX_GPR_REGS];
+  UINT128 sse[MAX_SSE_REGS];
+};
+
+extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
+			     void *raddr, void (*fnaddr)(void), unsigned ssecount);
+
+/* All reference to register classes here is identical to the code in
+   gcc/config/i386/i386.c. Do *not* change one without the other.  */
+
+/* Register class used for passing given 64bit part of the argument.
+   These represent classes as documented by the PS ABI, with the
+   exception of SSESF, SSEDF classes, that are basically SSE class,
+   just gcc will use SF or DFmode move instead of DImode to avoid
+   reformatting penalties.
+
+   Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
+   whenever possible (upper half does contain padding).  */
+enum x86_64_reg_class
+  {
+    X86_64_NO_CLASS,
+    X86_64_INTEGER_CLASS,
+    X86_64_INTEGERSI_CLASS,
+    X86_64_SSE_CLASS,
+    X86_64_SSESF_CLASS,
+    X86_64_SSEDF_CLASS,
+    X86_64_SSEUP_CLASS,
+    X86_64_X87_CLASS,
+    X86_64_X87UP_CLASS,
+    X86_64_COMPLEX_X87_CLASS,
+    X86_64_MEMORY_CLASS
+  };
+
+#define MAX_CLASSES 4
+
+#define SSE_CLASS_P(X)	((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
+
+/* x86-64 register passing implementation.  See x86-64 ABI for details.  Goal
+   of this code is to classify each 8bytes of incoming argument by the register
+   class and assign registers accordingly.  */
+
+/* Return the union class of CLASS1 and CLASS2.
+   See the x86-64 PS ABI for details.  */
+
+static enum x86_64_reg_class
+merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
+{
+  /* Rule #1: If both classes are equal, this is the resulting class.  */
+  if (class1 == class2)
+    return class1;
+
+  /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
+     the other class.  */
+  if (class1 == X86_64_NO_CLASS)
+    return class2;
+  if (class2 == X86_64_NO_CLASS)
+    return class1;
+
+  /* Rule #3: If one of the classes is MEMORY, the result is MEMORY.  */
+  if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
+    return X86_64_MEMORY_CLASS;
+
+  /* Rule #4: If one of the classes is INTEGER, the result is INTEGER.  */
+  if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
+      || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
+    return X86_64_INTEGERSI_CLASS;
+  if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
+      || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
+    return X86_64_INTEGER_CLASS;
+
+  /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
+     MEMORY is used.  */
+  if (class1 == X86_64_X87_CLASS
+      || class1 == X86_64_X87UP_CLASS
+      || class1 == X86_64_COMPLEX_X87_CLASS
+      || class2 == X86_64_X87_CLASS
+      || class2 == X86_64_X87UP_CLASS
+      || class2 == X86_64_COMPLEX_X87_CLASS)
+    return X86_64_MEMORY_CLASS;
+
+  /* Rule #6: Otherwise class SSE is used.  */
+  return X86_64_SSE_CLASS;
+}
+
+/* Classify the argument of type TYPE and mode MODE.
+   CLASSES will be filled by the register class used to pass each word
+   of the operand.  The number of words is returned.  In case the parameter
+   should be passed in memory, 0 is returned. As a special case for zero
+   sized containers, classes[0] will be NO_CLASS and 1 is returned.
+
+   See the x86-64 PS ABI for details.
+*/
+static int
+classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
+		   size_t byte_offset)
+{
+  switch (type->type)
+    {
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_POINTER:
+      {
+	int size = byte_offset + type->size;
+
+	if (size <= 4)
+	  {
+	    classes[0] = X86_64_INTEGERSI_CLASS;
+	    return 1;
+	  }
+	else if (size <= 8)
+	  {
+	    classes[0] = X86_64_INTEGER_CLASS;
+	    return 1;
+	  }
+	else if (size <= 12)
+	  {
+	    classes[0] = X86_64_INTEGER_CLASS;
+	    classes[1] = X86_64_INTEGERSI_CLASS;
+	    return 2;
+	  }
+	else if (size <= 16)
+	  {
+	    classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
+	    return 2;
+	  }
+	else
+	  FFI_ASSERT (0);
+      }
+    case FFI_TYPE_FLOAT:
+      if (!(byte_offset % 8))
+	classes[0] = X86_64_SSESF_CLASS;
+      else
+	classes[0] = X86_64_SSE_CLASS;
+      return 1;
+    case FFI_TYPE_DOUBLE:
+      classes[0] = X86_64_SSEDF_CLASS;
+      return 1;
+    case FFI_TYPE_LONGDOUBLE:
+      classes[0] = X86_64_X87_CLASS;
+      classes[1] = X86_64_X87UP_CLASS;
+      return 2;
+    case FFI_TYPE_STRUCT:
+      {
+	const int UNITS_PER_WORD = 8;
+	int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+	ffi_type **ptr; 
+	int i;
+	enum x86_64_reg_class subclasses[MAX_CLASSES];
+
+	/* If the struct is larger than 32 bytes, pass it on the stack.  */
+	if (type->size > 32)
+	  return 0;
+
+	for (i = 0; i < words; i++)
+	  classes[i] = X86_64_NO_CLASS;
+
+	/* Zero sized arrays or structures are NO_CLASS.  We return 0 to
+	   signalize memory class, so handle it as special case.  */
+	if (!words)
+	  {
+	    classes[0] = X86_64_NO_CLASS;
+	    return 1;
+	  }
+
+	/* Merge the fields of structure.  */
+	for (ptr = type->elements; *ptr != NULL; ptr++)
+	  {
+	    int num;
+
+	    byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
+
+	    num = classify_argument (*ptr, subclasses, byte_offset % 8);
+	    if (num == 0)
+	      return 0;
+	    for (i = 0; i < num; i++)
+	      {
+		int pos = byte_offset / 8;
+		classes[i + pos] =
+		  merge_classes (subclasses[i], classes[i + pos]);
+	      }
+
+	    byte_offset += (*ptr)->size;
+	  }
+
+	if (words > 2)
+	  {
+	    /* When size > 16 bytes, if the first one isn't
+	       X86_64_SSE_CLASS or any other ones aren't
+	       X86_64_SSEUP_CLASS, everything should be passed in
+	       memory.  */
+	    if (classes[0] != X86_64_SSE_CLASS)
+	      return 0;
+
+	    for (i = 1; i < words; i++)
+	      if (classes[i] != X86_64_SSEUP_CLASS)
+		return 0;
+	  }
+
+	/* Final merger cleanup.  */
+	for (i = 0; i < words; i++)
+	  {
+	    /* If one class is MEMORY, everything should be passed in
+	       memory.  */
+	    if (classes[i] == X86_64_MEMORY_CLASS)
+	      return 0;
+
+	    /* The X86_64_SSEUP_CLASS should be always preceded by
+	       X86_64_SSE_CLASS or X86_64_SSEUP_CLASS.  */
+	    if (classes[i] == X86_64_SSEUP_CLASS
+		&& classes[i - 1] != X86_64_SSE_CLASS
+		&& classes[i - 1] != X86_64_SSEUP_CLASS)
+	      {
+		/* The first one should never be X86_64_SSEUP_CLASS.  */
+		FFI_ASSERT (i != 0);
+		classes[i] = X86_64_SSE_CLASS;
+	      }
+
+	    /*  If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
+		everything should be passed in memory.  */
+	    if (classes[i] == X86_64_X87UP_CLASS
+		&& (classes[i - 1] != X86_64_X87_CLASS))
+	      {
+		/* The first one should never be X86_64_X87UP_CLASS.  */
+		FFI_ASSERT (i != 0);
+		return 0;
+	      }
+	  }
+	return words;
+      }
+
+    default:
+      FFI_ASSERT(0);
+    }
+  return 0; /* Never reached.  */
+}
+
+/* Examine the argument and return set number of register required in each
+   class.  Return zero iff parameter should be passed in memory, otherwise
+   the number of registers.  */
+
+static int
+examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES],
+		  _Bool in_return, int *pngpr, int *pnsse)
+{
+  int i, n, ngpr, nsse;
+
+  n = classify_argument (type, classes, 0);
+  if (n == 0)
+    return 0;
+
+  ngpr = nsse = 0;
+  for (i = 0; i < n; ++i)
+    switch (classes[i])
+      {
+      case X86_64_INTEGER_CLASS:
+      case X86_64_INTEGERSI_CLASS:
+	ngpr++;
+	break;
+      case X86_64_SSE_CLASS:
+      case X86_64_SSESF_CLASS:
+      case X86_64_SSEDF_CLASS:
+	nsse++;
+	break;
+      case X86_64_NO_CLASS:
+      case X86_64_SSEUP_CLASS:
+	break;
+      case X86_64_X87_CLASS:
+      case X86_64_X87UP_CLASS:
+      case X86_64_COMPLEX_X87_CLASS:
+	return in_return != 0;
+      default:
+	abort ();
+      }
+
+  *pngpr = ngpr;
+  *pnsse = nsse;
+
+  return n;
+}
+
+/* Perform machine dependent cif processing.  */
+
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  int gprcount, ssecount, i, avn, n, ngpr, nsse, flags;
+  enum x86_64_reg_class classes[MAX_CLASSES];
+  size_t bytes;
+
+  gprcount = ssecount = 0;
+
+  flags = cif->rtype->type;
+  if (flags != FFI_TYPE_VOID)
+    {
+      n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
+      if (n == 0)
+	{
+	  /* The return value is passed in memory.  A pointer to that
+	     memory is the first argument.  Allocate a register for it.  */
+	  gprcount++;
+	  /* We don't have to do anything in asm for the return.  */
+	  flags = FFI_TYPE_VOID;
+	}
+      else if (flags == FFI_TYPE_STRUCT)
+	{
+	  /* Mark which registers the result appears in.  */
+	  _Bool sse0 = SSE_CLASS_P (classes[0]);
+	  _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
+	  if (sse0 && !sse1)
+	    flags |= 1 << 8;
+	  else if (!sse0 && sse1)
+	    flags |= 1 << 9;
+	  else if (sse0 && sse1)
+	    flags |= 1 << 10;
+	  /* Mark the true size of the structure.  */
+	  flags |= cif->rtype->size << 12;
+	}
+    }
+
+  /* Go over all arguments and determine the way they should be passed.
+     If it's in a register and there is space for it, let that be so. If
+     not, add it's size to the stack byte count.  */
+  for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
+    {
+      if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
+	  || gprcount + ngpr > MAX_GPR_REGS
+	  || ssecount + nsse > MAX_SSE_REGS)
+	{
+	  long align = cif->arg_types[i]->alignment;
+
+	  if (align < 8)
+	    align = 8;
+
+	  bytes = ALIGN (bytes, align);
+	  bytes += cif->arg_types[i]->size;
+	}
+      else
+	{
+	  gprcount += ngpr;
+	  ssecount += nsse;
+	}
+    }
+  if (ssecount)
+    flags |= 1 << 11;
+  cif->flags = flags;
+  cif->bytes = ALIGN (bytes, 8);
+
+  return FFI_OK;
+}
+
+void
+ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  enum x86_64_reg_class classes[MAX_CLASSES];
+  char *stack, *argp;
+  ffi_type **arg_types;
+  int gprcount, ssecount, ngpr, nsse, i, avn;
+  _Bool ret_in_memory;
+  struct register_args *reg_args;
+
+  /* Can't call 32-bit mode from 64-bit mode.  */
+  FFI_ASSERT (cif->abi == FFI_UNIX64);
+
+  /* If the return value is a struct and we don't have a return value
+     address then we need to make one.  Note the setting of flags to
+     VOID above in ffi_prep_cif_machdep.  */
+  ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
+		   && (cif->flags & 0xff) == FFI_TYPE_VOID);
+  if (rvalue == NULL && ret_in_memory)
+    rvalue = alloca (cif->rtype->size);
+
+  /* Allocate the space for the arguments, plus 4 words of temp space.  */
+  stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
+  reg_args = (struct register_args *) stack;
+  argp = stack + sizeof (struct register_args);
+
+  gprcount = ssecount = 0;
+
+  /* If the return value is passed in memory, add the pointer as the
+     first integer argument.  */
+  if (ret_in_memory)
+    reg_args->gpr[gprcount++] = (unsigned long) rvalue;
+
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  for (i = 0; i < avn; ++i)
+    {
+      size_t size = arg_types[i]->size;
+      int n;
+
+      n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
+      if (n == 0
+	  || gprcount + ngpr > MAX_GPR_REGS
+	  || ssecount + nsse > MAX_SSE_REGS)
+	{
+	  long align = arg_types[i]->alignment;
+
+	  /* Stack arguments are *always* at least 8 byte aligned.  */
+	  if (align < 8)
+	    align = 8;
+
+	  /* Pass this argument in memory.  */
+	  argp = (void *) ALIGN (argp, align);
+	  memcpy (argp, avalue[i], size);
+	  argp += size;
+	}
+      else
+	{
+	  /* The argument is passed entirely in registers.  */
+	  char *a = (char *) avalue[i];
+	  int j;
+
+	  for (j = 0; j < n; j++, a += 8, size -= 8)
+	    {
+	      switch (classes[j])
+		{
+		case X86_64_INTEGER_CLASS:
+		case X86_64_INTEGERSI_CLASS:
+		  reg_args->gpr[gprcount] = 0;
+		  memcpy (&reg_args->gpr[gprcount], a, size < 8 ? size : 8);
+		  gprcount++;
+		  break;
+		case X86_64_SSE_CLASS:
+		case X86_64_SSEDF_CLASS:
+		  reg_args->sse[ssecount++] = *(UINT64 *) a;
+		  break;
+		case X86_64_SSESF_CLASS:
+		  reg_args->sse[ssecount++] = *(UINT32 *) a;
+		  break;
+		default:
+		  abort();
+		}
+	    }
+	}
+    }
+
+  ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),
+		   cif->flags, rvalue, fn, ssecount);
+}
+
+
+extern void ffi_closure_unix64(void);
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*, void*, void**, void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  volatile unsigned short *tramp;
+
+  /* Sanity check on the cif ABI.  */
+  {
+    int abi = cif->abi;
+    if (UNLIKELY (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI)))
+      return FFI_BAD_ABI;
+  }
+
+  tramp = (volatile unsigned short *) &closure->tramp[0];
+
+  tramp[0] = 0xbb49;		/* mov <code>, %r11	*/
+  *((unsigned long long * volatile) &tramp[1])
+    = (unsigned long) ffi_closure_unix64;
+  tramp[5] = 0xba49;		/* mov <data>, %r10	*/
+  *((unsigned long long * volatile) &tramp[6])
+    = (unsigned long) codeloc;
+
+  /* Set the carry bit iff the function uses any sse registers.
+     This is clc or stc, together with the first byte of the jmp.  */
+  tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
+
+  tramp[11] = 0xe3ff;			/* jmp *%r11    */
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  return FFI_OK;
+}
+
+int
+ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
+			 struct register_args *reg_args, char *argp)
+{
+  ffi_cif *cif;
+  void **avalue;
+  ffi_type **arg_types;
+  long i, avn;
+  int gprcount, ssecount, ngpr, nsse;
+  int ret;
+
+  cif = closure->cif;
+  avalue = alloca(cif->nargs * sizeof(void *));
+  gprcount = ssecount = 0;
+
+  ret = cif->rtype->type;
+  if (ret != FFI_TYPE_VOID)
+    {
+      enum x86_64_reg_class classes[MAX_CLASSES];
+      int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
+      if (n == 0)
+	{
+	  /* The return value goes in memory.  Arrange for the closure
+	     return value to go directly back to the original caller.  */
+	  rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++];
+	  /* We don't have to do anything in asm for the return.  */
+	  ret = FFI_TYPE_VOID;
+	}
+      else if (ret == FFI_TYPE_STRUCT && n == 2)
+	{
+	  /* Mark which register the second word of the structure goes in.  */
+	  _Bool sse0 = SSE_CLASS_P (classes[0]);
+	  _Bool sse1 = SSE_CLASS_P (classes[1]);
+	  if (!sse0 && sse1)
+	    ret |= 1 << 8;
+	  else if (sse0 && !sse1)
+	    ret |= 1 << 9;
+	}
+    }
+
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+  
+  for (i = 0; i < avn; ++i)
+    {
+      enum x86_64_reg_class classes[MAX_CLASSES];
+      int n;
+
+      n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
+      if (n == 0
+	  || gprcount + ngpr > MAX_GPR_REGS
+	  || ssecount + nsse > MAX_SSE_REGS)
+	{
+	  long align = arg_types[i]->alignment;
+
+	  /* Stack arguments are *always* at least 8 byte aligned.  */
+	  if (align < 8)
+	    align = 8;
+
+	  /* Pass this argument in memory.  */
+	  argp = (void *) ALIGN (argp, align);
+	  avalue[i] = argp;
+	  argp += arg_types[i]->size;
+	}
+      /* If the argument is in a single register, or two consecutive
+	 integer registers, then we can use that address directly.  */
+      else if (n == 1
+	       || (n == 2 && !(SSE_CLASS_P (classes[0])
+			       || SSE_CLASS_P (classes[1]))))
+	{
+	  /* The argument is in a single register.  */
+	  if (SSE_CLASS_P (classes[0]))
+	    {
+	      avalue[i] = &reg_args->sse[ssecount];
+	      ssecount += n;
+	    }
+	  else
+	    {
+	      avalue[i] = &reg_args->gpr[gprcount];
+	      gprcount += n;
+	    }
+	}
+      /* Otherwise, allocate space to make them consecutive.  */
+      else
+	{
+	  char *a = alloca (16);
+	  int j;
+
+	  avalue[i] = a;
+	  for (j = 0; j < n; j++, a += 8)
+	    {
+	      if (SSE_CLASS_P (classes[j]))
+		memcpy (a, &reg_args->sse[ssecount++], 8);
+	      else
+		memcpy (a, &reg_args->gpr[gprcount++], 8);
+	    }
+	}
+    }
+
+  /* Invoke the closure.  */
+  closure->fun (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell assembly how to perform return type promotions.  */
+  return ret;
+}
+
+#endif /* __x86_64__ */
diff --git a/third_party/gofrontend/libffi/src/x86/darwin_c.c b/third_party/gofrontend/libffi/src/x86/darwin_c.c
new file mode 100644
index 0000000..6338de2
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/darwin_c.c
@@ -0,0 +1,843 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008  Red Hat, Inc.
+           Copyright (c) 2002  Ranjit Mathew
+           Copyright (c) 2002  Bo Thorsen
+           Copyright (c) 2002  Roger Sayle
+           Copyright (C) 2008, 2010  Free Software Foundation, Inc.
+
+   x86 Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#if !defined(__x86_64__) || defined(_WIN64) || defined(__CYGWIN__)
+
+#ifdef _WIN64
+#include <windows.h>
+#endif
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+void ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+#ifdef X86_WIN32
+  size_t p_stack_args[2];
+  void *p_stack_data[2];
+  char *argp2 = stack;
+  int stack_args_count = 0;
+  int cabi = ecif->cif->abi;
+#endif
+
+  argp = stack;
+
+  if ((ecif->cif->flags == FFI_TYPE_STRUCT
+       || ecif->cif->flags == FFI_TYPE_MS_STRUCT)
+#ifdef X86_WIN64
+      && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
+          && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
+#endif
+      )
+    {
+      *(void **) argp = ecif->rvalue;
+#ifdef X86_WIN32
+      /* For fastcall/thiscall this is first register-passed
+         argument.  */
+      if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
+	{
+	  p_stack_args[stack_args_count] = sizeof (void*);
+	  p_stack_data[stack_args_count] = argp;
+	  ++stack_args_count;
+	}
+#endif
+      argp += sizeof(void*);
+    }
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       i != 0;
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if ((sizeof(void*) - 1) & (size_t) argp)
+        argp = (char *) ALIGN(argp, sizeof(void*));
+
+      z = (*p_arg)->size;
+#ifdef X86_WIN64
+      if (z > sizeof(ffi_arg)
+          || ((*p_arg)->type == FFI_TYPE_STRUCT
+              && (z != 1 && z != 2 && z != 4 && z != 8))
+#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
+          || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
+#endif
+          )
+        {
+          z = sizeof(ffi_arg);
+          *(void **)argp = *p_argv;
+        }
+      else if ((*p_arg)->type == FFI_TYPE_FLOAT)
+        {
+          memcpy(argp, *p_argv, z);
+        }
+      else
+#endif
+      if (z < sizeof(ffi_arg))
+        {
+          z = sizeof(ffi_arg);
+          switch ((*p_arg)->type)
+            {
+            case FFI_TYPE_SINT8:
+              *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
+              break;
+
+            case FFI_TYPE_UINT8:
+              *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
+              break;
+
+            case FFI_TYPE_SINT16:
+              *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
+              break;
+
+            case FFI_TYPE_UINT16:
+              *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
+              break;
+
+            case FFI_TYPE_SINT32:
+              *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
+              break;
+
+            case FFI_TYPE_UINT32:
+              *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
+              break;
+
+            case FFI_TYPE_STRUCT:
+              *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
+              break;
+
+            default:
+              FFI_ASSERT(0);
+            }
+        }
+      else
+        {
+          memcpy(argp, *p_argv, z);
+        }
+
+#ifdef X86_WIN32
+    /* For thiscall/fastcall convention register-passed arguments
+       are the first two none-floating-point arguments with a size
+       smaller or equal to sizeof (void*).  */
+    if ((cabi == FFI_THISCALL && stack_args_count < 1)
+        || (cabi == FFI_FASTCALL && stack_args_count < 2))
+      {
+	if (z <= 4
+	    && ((*p_arg)->type != FFI_TYPE_FLOAT
+	        && (*p_arg)->type != FFI_TYPE_STRUCT))
+	  {
+	    p_stack_args[stack_args_count] = z;
+	    p_stack_data[stack_args_count] = argp;
+	    ++stack_args_count;
+	  }
+      }
+#endif
+      p_argv++;
+#ifdef X86_WIN64
+      argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
+#else
+      argp += z;
+#endif
+    }
+
+#ifdef X86_WIN32
+  /* We need to move the register-passed arguments for thiscall/fastcall
+     on top of stack, so that those can be moved to registers ecx/edx by
+     call-handler.  */
+  if (stack_args_count > 0)
+    {
+      size_t zz = (p_stack_args[0] + 3) & ~3;
+      char *h;
+
+      /* Move first argument to top-stack position.  */
+      if (p_stack_data[0] != argp2)
+	{
+	  h = alloca (zz + 1);
+	  memcpy (h, p_stack_data[0], zz);
+	  memmove (argp2 + zz, argp2,
+	           (size_t) ((char *) p_stack_data[0] - (char*)argp2));
+	  memcpy (argp2, h, zz);
+	}
+
+      argp2 += zz;
+      --stack_args_count;
+      if (zz > 4)
+	stack_args_count = 0;
+
+      /* If we have a second argument, then move it on top
+         after the first one.  */
+      if (stack_args_count > 0 && p_stack_data[1] != argp2)
+	{
+	  zz = p_stack_args[1];
+	  zz = (zz + 3) & ~3;
+	  h = alloca (zz + 1);
+	  h = alloca (zz + 1);
+	  memcpy (h, p_stack_data[1], zz);
+	  memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2));
+	  memcpy (argp2, h, zz);
+	}
+    }
+#endif
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  unsigned int i;
+  ffi_type **ptr;
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_SINT16:
+#ifdef X86_WIN64
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_SINT32:
+#endif
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+#ifndef X86_WIN64
+#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+#endif
+#endif
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_UINT64:
+#ifdef X86_WIN64
+    case FFI_TYPE_POINTER:
+#endif
+      cif->flags = FFI_TYPE_SINT64;
+      break;
+
+    case FFI_TYPE_STRUCT:
+#ifndef X86
+      if (cif->rtype->size == 1)
+        {
+          cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
+        }
+      else if (cif->rtype->size == 2)
+        {
+          cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
+        }
+      else if (cif->rtype->size == 4)
+        {
+#ifdef X86_WIN64
+          cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
+#else
+          cif->flags = FFI_TYPE_INT; /* same as int type */
+#endif
+        }
+      else if (cif->rtype->size == 8)
+        {
+          cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
+        }
+      else
+#endif
+        {
+#ifdef X86_WIN32
+          if (cif->abi == FFI_MS_CDECL)
+            cif->flags = FFI_TYPE_MS_STRUCT;
+          else
+#endif
+            cif->flags = FFI_TYPE_STRUCT;
+          /* allocate space for return value pointer */
+          cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
+        }
+      break;
+
+    default:
+#ifdef X86_WIN64
+      cif->flags = FFI_TYPE_SINT64;
+      break;
+    case FFI_TYPE_INT:
+      cif->flags = FFI_TYPE_SINT32;
+#else
+      cif->flags = FFI_TYPE_INT;
+#endif
+      break;
+    }
+
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+    {
+      if (((*ptr)->alignment - 1) & cif->bytes)
+        cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
+      cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
+    }
+
+#ifdef X86_WIN64
+  /* ensure space for storing four registers */
+  cif->bytes += 4 * sizeof(ffi_arg);
+#endif
+
+#ifdef X86_DARWIN
+  cif->bytes = (cif->bytes + 15) & ~0xF;
+#endif
+
+  return FFI_OK;
+}
+
+#ifdef X86_WIN64
+extern int
+ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
+               unsigned, unsigned, unsigned *, void (*fn)(void));
+#elif defined(X86_WIN32)
+extern void
+ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
+               unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
+#else
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
+                          unsigned, unsigned, unsigned *, void (*fn)(void));
+#endif
+
+void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return */
+  /* value address then we need to make one                     */
+
+#ifdef X86_WIN64
+  if (rvalue == NULL
+      && cif->flags == FFI_TYPE_STRUCT
+      && cif->rtype->size != 1 && cif->rtype->size != 2
+      && cif->rtype->size != 4 && cif->rtype->size != 8)
+    {
+      ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
+    }
+#else
+  if (rvalue == NULL
+      && (cif->flags == FFI_TYPE_STRUCT
+          || cif->flags == FFI_TYPE_MS_STRUCT))
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+#endif
+  else
+    ecif.rvalue = rvalue;
+    
+  
+  switch (cif->abi) 
+    {
+#ifdef X86_WIN64
+    case FFI_WIN64:
+      ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
+                     cif->flags, ecif.rvalue, fn);
+      break;
+#elif defined(X86_WIN32)
+    case FFI_SYSV:
+    case FFI_STDCALL:
+    case FFI_MS_CDECL:
+      ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
+		     ecif.rvalue, fn);
+      break;
+    case FFI_THISCALL:
+    case FFI_FASTCALL:
+      {
+	unsigned int abi = cif->abi;
+	unsigned int i, passed_regs = 0;
+
+	if (cif->flags == FFI_TYPE_STRUCT)
+	  ++passed_regs;
+
+	for (i=0; i < cif->nargs && passed_regs < 2;i++)
+	  {
+	    size_t sz;
+
+	    if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
+	        || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
+	      continue;
+	    sz = (cif->arg_types[i]->size + 3) & ~3;
+	    if (sz == 0 || sz > 4)
+	      continue;
+	    ++passed_regs;
+	  }
+	if (passed_regs < 2 && abi == FFI_FASTCALL)
+	  abi = FFI_THISCALL;
+	if (passed_regs < 1 && abi == FFI_THISCALL)
+	  abi = FFI_STDCALL;
+        ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
+                       ecif.rvalue, fn);
+      }
+      break;
+#else
+    case FFI_SYSV:
+      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
+                    fn);
+      break;
+#endif
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+
+/** private members **/
+
+/* The following __attribute__((regparm(1))) decorations will have no effect
+   on MSVC - standard cdecl convention applies. */
+static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
+                                         void** args, ffi_cif* cif);
+void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
+     __attribute__ ((regparm(1)));
+unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
+     __attribute__ ((regparm(1)));
+void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
+     __attribute__ ((regparm(1)));
+#ifdef X86_WIN32
+void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
+     __attribute__ ((regparm(1)));
+void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
+     __attribute__ ((regparm(1)));
+void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
+     __attribute__ ((regparm(1)));
+#endif
+#ifdef X86_WIN64
+void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
+#endif
+
+/* This function is jumped to by the trampoline */
+
+#ifdef X86_WIN64
+void * FFI_HIDDEN
+ffi_closure_win64_inner (ffi_closure *closure, void *args) {
+  ffi_cif       *cif;
+  void         **arg_area;
+  void          *result;
+  void          *resp = &result;
+
+  cif         = closure->cif;
+  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
+
+  /* this call will initialize ARG_AREA, such that each
+   * element in that array points to the corresponding 
+   * value on the stack; and if the function returns
+   * a structure, it will change RESP to point to the
+   * structure return address.  */
+
+  ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
+  
+  (closure->fun) (cif, resp, arg_area, closure->user_data);
+
+  /* The result is returned in rax.  This does the right thing for
+     result types except for floats; we have to 'mov xmm0, rax' in the
+     caller to correct this.
+     TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
+  */
+  return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
+}
+
+#else
+unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
+ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
+{
+  /* our various things...  */
+  ffi_cif       *cif;
+  void         **arg_area;
+
+  cif         = closure->cif;
+  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
+
+  /* this call will initialize ARG_AREA, such that each
+   * element in that array points to the corresponding 
+   * value on the stack; and if the function returns
+   * a structure, it will change RESP to point to the
+   * structure return address.  */
+
+  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
+
+  (closure->fun) (cif, *respp, arg_area, closure->user_data);
+
+  return cif->flags;
+}
+#endif /* !X86_WIN64 */
+
+static void
+ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
+                            ffi_cif *cif)
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+#ifdef X86_WIN64
+  if (cif->rtype->size > sizeof(ffi_arg)
+      || (cif->flags == FFI_TYPE_STRUCT
+          && (cif->rtype->size != 1 && cif->rtype->size != 2
+              && cif->rtype->size != 4 && cif->rtype->size != 8))) {
+    *rvalue = *(void **) argp;
+    argp += sizeof(void *);
+  }
+#else
+  if ( cif->flags == FFI_TYPE_STRUCT
+       || cif->flags == FFI_TYPE_MS_STRUCT ) {
+    *rvalue = *(void **) argp;
+    argp += sizeof(void *);
+  }
+#endif
+
+  p_argv = avalue;
+
+  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if ((sizeof(void*) - 1) & (size_t) argp) {
+        argp = (char *) ALIGN(argp, sizeof(void*));
+      }
+
+#ifdef X86_WIN64
+      if ((*p_arg)->size > sizeof(ffi_arg)
+          || ((*p_arg)->type == FFI_TYPE_STRUCT
+              && ((*p_arg)->size != 1 && (*p_arg)->size != 2
+                  && (*p_arg)->size != 4 && (*p_arg)->size != 8)))
+        {
+          z = sizeof(void *);
+          *p_argv = *(void **)argp;
+        }
+      else
+#endif
+        {
+          z = (*p_arg)->size;
+          
+          /* because we're little endian, this is what it turns into.   */
+          
+          *p_argv = (void*) argp;
+        }
+          
+      p_argv++;
+#ifdef X86_WIN64
+      argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
+#else
+      argp += z;
+#endif
+    }
+  
+  return;
+}
+
+#define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+   void*  __fun = (void*)(FUN); \
+   void*  __ctx = (void*)(CTX); \
+   *(unsigned char*) &__tramp[0] = 0x41; \
+   *(unsigned char*) &__tramp[1] = 0xbb; \
+   *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
+   *(unsigned char*) &__tramp[6] = 0x48; \
+   *(unsigned char*) &__tramp[7] = 0xb8; \
+   *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
+   *(unsigned char *)  &__tramp[16] = 0x49; \
+   *(unsigned char *)  &__tramp[17] = 0xba; \
+   *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
+   *(unsigned char *)  &__tramp[26] = 0x41; \
+   *(unsigned char *)  &__tramp[27] = 0xff; \
+   *(unsigned char *)  &__tramp[28] = 0xe2; /* jmp %r10 */ \
+ }
+
+/* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
+
+#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+   unsigned int  __fun = (unsigned int)(FUN); \
+   unsigned int  __ctx = (unsigned int)(CTX); \
+   unsigned int  __dis = __fun - (__ctx + 10);  \
+   *(unsigned char*) &__tramp[0] = 0xb8; \
+   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
+   *(unsigned char *)  &__tramp[5] = 0xe9; \
+   *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
+ }
+
+#define FFI_INIT_TRAMPOLINE_THISCALL(TRAMP,FUN,CTX,SIZE) \
+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+   unsigned int  __fun = (unsigned int)(FUN); \
+   unsigned int  __ctx = (unsigned int)(CTX); \
+   unsigned int  __dis = __fun - (__ctx + 49);  \
+   unsigned short __size = (unsigned short)(SIZE); \
+   *(unsigned int *) &__tramp[0] = 0x8324048b;	/* mov (%esp), %eax */ \
+   *(unsigned int *) &__tramp[4] = 0x4c890cec;	/* sub $12, %esp */ \
+   *(unsigned int *) &__tramp[8] = 0x04890424;	/* mov %ecx, 4(%esp) */ \
+   *(unsigned char*) &__tramp[12] = 0x24;	/* mov %eax, (%esp) */ \
+   *(unsigned char*) &__tramp[13] = 0xb8; \
+   *(unsigned int *) &__tramp[14] = __size;	/* mov __size, %eax */ \
+   *(unsigned int *) &__tramp[18] = 0x08244c8d;	/* lea 8(%esp), %ecx */ \
+   *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
+   *(unsigned short*) &__tramp[26] = 0x0b74;	/* jz 1f */ \
+   *(unsigned int *) &__tramp[28] = 0x8908518b;	/* 2b: mov 8(%ecx), %edx */ \
+   *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
+   *(unsigned char*) &__tramp[36] = 0x48;	/* dec %eax */ \
+   *(unsigned short*) &__tramp[37] = 0xf575;	/* jnz 2b ; 1f: */ \
+   *(unsigned char*) &__tramp[39] = 0xb8; \
+   *(unsigned int*)  &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
+   *(unsigned char *)  &__tramp[44] = 0xe8; \
+   *(unsigned int*)  &__tramp[45] = __dis; /* call __fun  */ \
+   *(unsigned char*)  &__tramp[49] = 0xc2; /* ret  */ \
+   *(unsigned short*)  &__tramp[50] = (__size + 8); /* ret (__size + 8)  */ \
+ }
+
+#define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE)  \
+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+   unsigned int  __fun = (unsigned int)(FUN); \
+   unsigned int  __ctx = (unsigned int)(CTX); \
+   unsigned int  __dis = __fun - (__ctx + 10); \
+   unsigned short __size = (unsigned short)(SIZE); \
+   *(unsigned char*) &__tramp[0] = 0xb8; \
+   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
+   *(unsigned char *)  &__tramp[5] = 0xe8; \
+   *(unsigned int*)  &__tramp[6] = __dis; /* call __fun  */ \
+   *(unsigned char *)  &__tramp[10] = 0xc2; \
+   *(unsigned short*)  &__tramp[11] = __size; /* ret __size  */ \
+ }
+
+/* the cif must already be prep'ed */
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+                      ffi_cif* cif,
+                      void (*fun)(ffi_cif*,void*,void**,void*),
+                      void *user_data,
+                      void *codeloc)
+{
+#ifdef X86_WIN64
+#define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
+#define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
+  if (cif->abi == FFI_WIN64) 
+    {
+      int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
+      FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
+                                 &ffi_closure_win64,
+                                 codeloc, mask);
+      /* make sure we can execute here */
+    }
+#else
+  if (cif->abi == FFI_SYSV)
+    {
+      FFI_INIT_TRAMPOLINE (&closure->tramp[0],
+                           &ffi_closure_SYSV,
+                           (void*)codeloc);
+    }
+#ifdef X86_WIN32
+  else if (cif->abi == FFI_THISCALL)
+    {
+      FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0],
+				    &ffi_closure_THISCALL,
+				    (void*)codeloc,
+				    cif->bytes);
+    }
+  else if (cif->abi == FFI_STDCALL)
+    {
+      FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
+                                   &ffi_closure_STDCALL,
+                                   (void*)codeloc, cif->bytes);
+    }
+  else if (cif->abi == FFI_MS_CDECL)
+    {
+      FFI_INIT_TRAMPOLINE (&closure->tramp[0],
+                           &ffi_closure_SYSV,
+                           (void*)codeloc);
+    }
+#endif /* X86_WIN32 */
+#endif /* !X86_WIN64 */
+  else
+    {
+      return FFI_BAD_ABI;
+    }
+    
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+
+/* ------- Native raw API support -------------------------------- */
+
+#if !FFI_NO_RAW_API
+
+ffi_status
+ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
+                          ffi_cif* cif,
+                          void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+                          void *user_data,
+                          void *codeloc)
+{
+  int i;
+
+  if (cif->abi != FFI_SYSV) {
+#ifdef X86_WIN32
+    if (cif->abi != FFI_THISCALL)
+#endif
+    return FFI_BAD_ABI;
+  }
+
+  /* we currently don't support certain kinds of arguments for raw
+     closures.  This should be implemented by a separate assembly
+     language routine, since it would require argument processing,
+     something we don't do now for performance.  */
+
+  for (i = cif->nargs-1; i >= 0; i--)
+    {
+      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
+      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
+    }
+  
+#ifdef X86_WIN32
+  if (cif->abi == FFI_SYSV)
+    {
+#endif
+  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
+                       codeloc);
+#ifdef X86_WIN32
+    }
+  else if (cif->abi == FFI_THISCALL)
+    {
+      FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL,
+				    codeloc, cif->bytes);
+    }
+#endif
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+
+static void 
+ffi_prep_args_raw(char *stack, extended_cif *ecif)
+{
+  memcpy (stack, ecif->avalue, ecif->cif->bytes);
+}
+
+/* we borrow this routine from libffi (it must be changed, though, to
+ * actually call the function passed in the first argument.  as of
+ * libffi-1.20, this is not the case.)
+ */
+
+void
+ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
+{
+  extended_cif ecif;
+  void **avalue = (void **)fake_avalue;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return */
+  /* value address then we need to make one                     */
+
+  if (rvalue == NULL
+      && (cif->flags == FFI_TYPE_STRUCT
+          || cif->flags == FFI_TYPE_MS_STRUCT))
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+    
+  
+  switch (cif->abi) 
+    {
+#ifdef X86_WIN32
+    case FFI_SYSV:
+    case FFI_STDCALL:
+    case FFI_MS_CDECL:
+      ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
+		     ecif.rvalue, fn);
+      break;
+    case FFI_THISCALL:
+    case FFI_FASTCALL:
+      {
+	unsigned int abi = cif->abi;
+	unsigned int i, passed_regs = 0;
+
+	if (cif->flags == FFI_TYPE_STRUCT)
+	  ++passed_regs;
+
+	for (i=0; i < cif->nargs && passed_regs < 2;i++)
+	  {
+	    size_t sz;
+
+	    if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
+	        || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
+	      continue;
+	    sz = (cif->arg_types[i]->size + 3) & ~3;
+	    if (sz == 0 || sz > 4)
+	      continue;
+	    ++passed_regs;
+	  }
+	if (passed_regs < 2 && abi == FFI_FASTCALL)
+	  cif->abi = abi = FFI_THISCALL;
+	if (passed_regs < 1 && abi == FFI_THISCALL)
+	  cif->abi = abi = FFI_STDCALL;
+        ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
+                       ecif.rvalue, fn);
+      }
+      break;
+#else
+    case FFI_SYSV:
+      ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
+                    ecif.rvalue, fn);
+      break;
+#endif
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+#endif
+
+#endif /* !__x86_64__  || X86_WIN64 */
+
diff --git a/third_party/gofrontend/libffi/src/x86/ffi.c b/third_party/gofrontend/libffi/src/x86/ffi.c
index 6338de2..3885e39 100644
--- a/third_party/gofrontend/libffi/src/x86/ffi.c
+++ b/third_party/gofrontend/libffi/src/x86/ffi.c
@@ -28,621 +28,474 @@
    DEALINGS IN THE SOFTWARE.
    ----------------------------------------------------------------------- */
 
-#if !defined(__x86_64__) || defined(_WIN64) || defined(__CYGWIN__)
-
-#ifdef _WIN64
-#include <windows.h>
-#endif
-
+#ifndef __x86_64__
 #include <ffi.h>
 #include <ffi_common.h>
-
 #include <stdlib.h>
+#include "internal.h"
 
-/* ffi_prep_args is called by the assembly routine once stack space
-   has been allocated for the function's arguments */
-
-void ffi_prep_args(char *stack, extended_cif *ecif)
-{
-  register unsigned int i;
-  register void **p_argv;
-  register char *argp;
-  register ffi_type **p_arg;
-#ifdef X86_WIN32
-  size_t p_stack_args[2];
-  void *p_stack_data[2];
-  char *argp2 = stack;
-  int stack_args_count = 0;
-  int cabi = ecif->cif->abi;
-#endif
-
-  argp = stack;
-
-  if ((ecif->cif->flags == FFI_TYPE_STRUCT
-       || ecif->cif->flags == FFI_TYPE_MS_STRUCT)
-#ifdef X86_WIN64
-      && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
-          && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
-#endif
-      )
-    {
-      *(void **) argp = ecif->rvalue;
-#ifdef X86_WIN32
-      /* For fastcall/thiscall this is first register-passed
-         argument.  */
-      if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
-	{
-	  p_stack_args[stack_args_count] = sizeof (void*);
-	  p_stack_data[stack_args_count] = argp;
-	  ++stack_args_count;
-	}
-#endif
-      argp += sizeof(void*);
-    }
-
-  p_argv = ecif->avalue;
-
-  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
-       i != 0;
-       i--, p_arg++)
-    {
-      size_t z;
-
-      /* Align if necessary */
-      if ((sizeof(void*) - 1) & (size_t) argp)
-        argp = (char *) ALIGN(argp, sizeof(void*));
-
-      z = (*p_arg)->size;
-#ifdef X86_WIN64
-      if (z > sizeof(ffi_arg)
-          || ((*p_arg)->type == FFI_TYPE_STRUCT
-              && (z != 1 && z != 2 && z != 4 && z != 8))
-#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
-          || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
-#endif
-          )
-        {
-          z = sizeof(ffi_arg);
-          *(void **)argp = *p_argv;
-        }
-      else if ((*p_arg)->type == FFI_TYPE_FLOAT)
-        {
-          memcpy(argp, *p_argv, z);
-        }
-      else
-#endif
-      if (z < sizeof(ffi_arg))
-        {
-          z = sizeof(ffi_arg);
-          switch ((*p_arg)->type)
-            {
-            case FFI_TYPE_SINT8:
-              *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
-              break;
-
-            case FFI_TYPE_UINT8:
-              *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
-              break;
-
-            case FFI_TYPE_SINT16:
-              *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
-              break;
-
-            case FFI_TYPE_UINT16:
-              *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
-              break;
-
-            case FFI_TYPE_SINT32:
-              *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
-              break;
-
-            case FFI_TYPE_UINT32:
-              *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
-              break;
-
-            case FFI_TYPE_STRUCT:
-              *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
-              break;
-
-            default:
-              FFI_ASSERT(0);
-            }
-        }
-      else
-        {
-          memcpy(argp, *p_argv, z);
-        }
-
-#ifdef X86_WIN32
-    /* For thiscall/fastcall convention register-passed arguments
-       are the first two none-floating-point arguments with a size
-       smaller or equal to sizeof (void*).  */
-    if ((cabi == FFI_THISCALL && stack_args_count < 1)
-        || (cabi == FFI_FASTCALL && stack_args_count < 2))
-      {
-	if (z <= 4
-	    && ((*p_arg)->type != FFI_TYPE_FLOAT
-	        && (*p_arg)->type != FFI_TYPE_STRUCT))
-	  {
-	    p_stack_args[stack_args_count] = z;
-	    p_stack_data[stack_args_count] = argp;
-	    ++stack_args_count;
-	  }
-      }
-#endif
-      p_argv++;
-#ifdef X86_WIN64
-      argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
+/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
+   all further uses in this file will refer to the 80-bit type.  */
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+# if FFI_TYPE_LONGDOUBLE != 4
+#  error FFI_TYPE_LONGDOUBLE out of date
+# endif
 #else
-      argp += z;
+# undef FFI_TYPE_LONGDOUBLE
+# define FFI_TYPE_LONGDOUBLE 4
 #endif
-    }
 
-#ifdef X86_WIN32
-  /* We need to move the register-passed arguments for thiscall/fastcall
-     on top of stack, so that those can be moved to registers ecx/edx by
-     call-handler.  */
-  if (stack_args_count > 0)
-    {
-      size_t zz = (p_stack_args[0] + 3) & ~3;
-      char *h;
-
-      /* Move first argument to top-stack position.  */
-      if (p_stack_data[0] != argp2)
-	{
-	  h = alloca (zz + 1);
-	  memcpy (h, p_stack_data[0], zz);
-	  memmove (argp2 + zz, argp2,
-	           (size_t) ((char *) p_stack_data[0] - (char*)argp2));
-	  memcpy (argp2, h, zz);
-	}
-
-      argp2 += zz;
-      --stack_args_count;
-      if (zz > 4)
-	stack_args_count = 0;
-
-      /* If we have a second argument, then move it on top
-         after the first one.  */
-      if (stack_args_count > 0 && p_stack_data[1] != argp2)
-	{
-	  zz = p_stack_args[1];
-	  zz = (zz + 3) & ~3;
-	  h = alloca (zz + 1);
-	  h = alloca (zz + 1);
-	  memcpy (h, p_stack_data[1], zz);
-	  memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2));
-	  memcpy (argp2, h, zz);
-	}
-    }
+#if defined(__GNUC__) && !defined(__declspec)
+# define __declspec(x)  __attribute__((x))
 #endif
-  return;
-}
 
-/* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+/* Perform machine dependent cif processing.  */
+ffi_status FFI_HIDDEN
+ffi_prep_cif_machdep(ffi_cif *cif)
 {
-  unsigned int i;
-  ffi_type **ptr;
+  size_t bytes = 0;
+  int i, n, flags, cabi = cif->abi;
 
-  /* Set the return type flag */
+  switch (cabi)
+    {
+    case FFI_SYSV:
+    case FFI_STDCALL:
+    case FFI_THISCALL:
+    case FFI_FASTCALL:
+    case FFI_MS_CDECL:
+    case FFI_PASCAL:
+    case FFI_REGISTER:
+      break;
+    default:
+      return FFI_BAD_ABI;
+    }
+
   switch (cif->rtype->type)
     {
     case FFI_TYPE_VOID:
-    case FFI_TYPE_UINT8:
-    case FFI_TYPE_UINT16:
-    case FFI_TYPE_SINT8:
-    case FFI_TYPE_SINT16:
-#ifdef X86_WIN64
-    case FFI_TYPE_UINT32:
-    case FFI_TYPE_SINT32:
-#endif
-    case FFI_TYPE_SINT64:
+      flags = X86_RET_VOID;
+      break;
     case FFI_TYPE_FLOAT:
+      flags = X86_RET_FLOAT;
+      break;
     case FFI_TYPE_DOUBLE:
-#ifndef X86_WIN64
-#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
+      flags = X86_RET_DOUBLE;
+      break;
     case FFI_TYPE_LONGDOUBLE:
-#endif
-#endif
-      cif->flags = (unsigned) cif->rtype->type;
+      flags = X86_RET_LDOUBLE;
       break;
-
-    case FFI_TYPE_UINT64:
-#ifdef X86_WIN64
-    case FFI_TYPE_POINTER:
-#endif
-      cif->flags = FFI_TYPE_SINT64;
+    case FFI_TYPE_UINT8:
+      flags = X86_RET_UINT8;
       break;
-
-    case FFI_TYPE_STRUCT:
-#ifndef X86
-      if (cif->rtype->size == 1)
-        {
-          cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
-        }
-      else if (cif->rtype->size == 2)
-        {
-          cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
-        }
-      else if (cif->rtype->size == 4)
-        {
-#ifdef X86_WIN64
-          cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
-#else
-          cif->flags = FFI_TYPE_INT; /* same as int type */
-#endif
-        }
-      else if (cif->rtype->size == 8)
-        {
-          cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
-        }
-      else
-#endif
-        {
-#ifdef X86_WIN32
-          if (cif->abi == FFI_MS_CDECL)
-            cif->flags = FFI_TYPE_MS_STRUCT;
-          else
-#endif
-            cif->flags = FFI_TYPE_STRUCT;
-          /* allocate space for return value pointer */
-          cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
-        }
+    case FFI_TYPE_UINT16:
+      flags = X86_RET_UINT16;
       break;
-
-    default:
-#ifdef X86_WIN64
-      cif->flags = FFI_TYPE_SINT64;
+    case FFI_TYPE_SINT8:
+      flags = X86_RET_SINT8;
+      break;
+    case FFI_TYPE_SINT16:
+      flags = X86_RET_SINT16;
       break;
     case FFI_TYPE_INT:
-      cif->flags = FFI_TYPE_SINT32;
-#else
-      cif->flags = FFI_TYPE_INT;
-#endif
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_POINTER:
+      flags = X86_RET_INT32;
       break;
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      flags = X86_RET_INT64;
+      break;
+    case FFI_TYPE_STRUCT:
+#ifndef X86
+      /* ??? This should be a different ABI rather than an ifdef.  */
+      if (cif->rtype->size == 1)
+	flags = X86_RET_STRUCT_1B;
+      else if (cif->rtype->size == 2)
+	flags = X86_RET_STRUCT_2B;
+      else if (cif->rtype->size == 4)
+	flags = X86_RET_INT32;
+      else if (cif->rtype->size == 8)
+	flags = X86_RET_INT64;
+      else
+#endif
+	{
+	do_struct:
+	  switch (cabi)
+	    {
+	    case FFI_THISCALL:
+	    case FFI_FASTCALL:
+	    case FFI_STDCALL:
+	    case FFI_MS_CDECL:
+	      flags = X86_RET_STRUCTARG;
+	      break;
+	    default:
+	      flags = X86_RET_STRUCTPOP;
+	      break;
+	    }
+	  /* Allocate space for return value pointer.  */
+	  bytes += ALIGN (sizeof(void*), FFI_SIZEOF_ARG);
+	}
+      break;
+    case FFI_TYPE_COMPLEX:
+      switch (cif->rtype->elements[0]->type)
+	{
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_LONGDOUBLE:
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	  goto do_struct;
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_INT:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+	  flags = X86_RET_INT64;
+	  break;
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+	  flags = X86_RET_INT32;
+	  break;
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT8:
+	  flags = X86_RET_STRUCT_2B;
+	  break;
+	default:
+	  return FFI_BAD_TYPEDEF;
+	}
+      break;
+    default:
+      return FFI_BAD_TYPEDEF;
     }
+  cif->flags = flags;
 
-  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+  for (i = 0, n = cif->nargs; i < n; i++)
     {
-      if (((*ptr)->alignment - 1) & cif->bytes)
-        cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
-      cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
+      ffi_type *t = cif->arg_types[i];
+
+      bytes = ALIGN (bytes, t->alignment);
+      bytes += ALIGN (t->size, FFI_SIZEOF_ARG);
     }
-
-#ifdef X86_WIN64
-  /* ensure space for storing four registers */
-  cif->bytes += 4 * sizeof(ffi_arg);
-#endif
-
-#ifdef X86_DARWIN
-  cif->bytes = (cif->bytes + 15) & ~0xF;
-#endif
+  cif->bytes = ALIGN (bytes, 16);
 
   return FFI_OK;
 }
 
-#ifdef X86_WIN64
-extern int
-ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
-               unsigned, unsigned, unsigned *, void (*fn)(void));
-#elif defined(X86_WIN32)
-extern void
-ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
-               unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
-#else
-extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
-                          unsigned, unsigned, unsigned *, void (*fn)(void));
-#endif
-
-void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+static ffi_arg
+extend_basic_type(void *arg, int type)
 {
-  extended_cif ecif;
-
-  ecif.cif = cif;
-  ecif.avalue = avalue;
-  
-  /* If the return value is a struct and we don't have a return */
-  /* value address then we need to make one                     */
-
-#ifdef X86_WIN64
-  if (rvalue == NULL
-      && cif->flags == FFI_TYPE_STRUCT
-      && cif->rtype->size != 1 && cif->rtype->size != 2
-      && cif->rtype->size != 4 && cif->rtype->size != 8)
+  switch (type)
     {
-      ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
-    }
-#else
-  if (rvalue == NULL
-      && (cif->flags == FFI_TYPE_STRUCT
-          || cif->flags == FFI_TYPE_MS_STRUCT))
-    {
-      ecif.rvalue = alloca(cif->rtype->size);
-    }
-#endif
-  else
-    ecif.rvalue = rvalue;
-    
-  
-  switch (cif->abi) 
-    {
-#ifdef X86_WIN64
-    case FFI_WIN64:
-      ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
-                     cif->flags, ecif.rvalue, fn);
-      break;
-#elif defined(X86_WIN32)
-    case FFI_SYSV:
-    case FFI_STDCALL:
-    case FFI_MS_CDECL:
-      ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
-		     ecif.rvalue, fn);
-      break;
-    case FFI_THISCALL:
-    case FFI_FASTCALL:
-      {
-	unsigned int abi = cif->abi;
-	unsigned int i, passed_regs = 0;
+    case FFI_TYPE_SINT8:
+      return *(SINT8 *)arg;
+    case FFI_TYPE_UINT8:
+      return *(UINT8 *)arg;
+    case FFI_TYPE_SINT16:
+      return *(SINT16 *)arg;
+    case FFI_TYPE_UINT16:
+      return *(UINT16 *)arg;
 
-	if (cif->flags == FFI_TYPE_STRUCT)
-	  ++passed_regs;
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_FLOAT:
+      return *(UINT32 *)arg;
 
-	for (i=0; i < cif->nargs && passed_regs < 2;i++)
-	  {
-	    size_t sz;
-
-	    if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
-	        || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
-	      continue;
-	    sz = (cif->arg_types[i]->size + 3) & ~3;
-	    if (sz == 0 || sz > 4)
-	      continue;
-	    ++passed_regs;
-	  }
-	if (passed_regs < 2 && abi == FFI_FASTCALL)
-	  abi = FFI_THISCALL;
-	if (passed_regs < 1 && abi == FFI_THISCALL)
-	  abi = FFI_STDCALL;
-        ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
-                       ecif.rvalue, fn);
-      }
-      break;
-#else
-    case FFI_SYSV:
-      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
-                    fn);
-      break;
-#endif
     default:
-      FFI_ASSERT(0);
-      break;
+      abort();
     }
 }
 
+struct call_frame
+{
+  void *ebp;		/* 0 */
+  void *retaddr;	/* 4 */
+  void (*fn)(void);	/* 8 */
+  int flags;		/* 12 */
+  void *rvalue;		/* 16 */
+  unsigned regs[3];	/* 20-28 */
+};
+
+struct abi_params
+{
+  int dir;		/* parameter growth direction */
+  int static_chain;	/* the static chain register used by gcc */
+  int nregs;		/* number of register parameters */
+  int regs[3];
+};
+
+static const struct abi_params abi_params[FFI_LAST_ABI] = {
+  [FFI_SYSV] = { 1, R_ECX, 0 },
+  [FFI_THISCALL] = { 1, R_EAX, 1, { R_ECX } },
+  [FFI_FASTCALL] = { 1, R_EAX, 2, { R_ECX, R_EDX } },
+  [FFI_STDCALL] = { 1, R_ECX, 0 },
+  [FFI_PASCAL] = { -1, R_ECX, 0 },
+  /* ??? No defined static chain; gcc does not support REGISTER.  */
+  [FFI_REGISTER] = { -1, R_ECX, 3, { R_EAX, R_EDX, R_ECX } },
+  [FFI_MS_CDECL] = { 1, R_ECX, 0 }
+};
+
+extern void ffi_call_i386(struct call_frame *, char *)
+#if HAVE_FASTCALL
+	__declspec(fastcall)
+#endif
+	FFI_HIDDEN;
+
+static void
+ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
+	      void **avalue, void *closure)
+{
+  size_t rsize, bytes;
+  struct call_frame *frame;
+  char *stack, *argp;
+  ffi_type **arg_types;
+  int flags, cabi, i, n, dir, narg_reg;
+  const struct abi_params *pabi;
+
+  flags = cif->flags;
+  cabi = cif->abi;
+  pabi = &abi_params[cabi];
+  dir = pabi->dir;
+
+  rsize = 0;
+  if (rvalue == NULL)
+    {
+      switch (flags)
+	{
+	case X86_RET_FLOAT:
+	case X86_RET_DOUBLE:
+	case X86_RET_LDOUBLE:
+	case X86_RET_STRUCTPOP:
+	case X86_RET_STRUCTARG:
+	  /* The float cases need to pop the 387 stack.
+	     The struct cases need to pass a valid pointer to the callee.  */
+	  rsize = cif->rtype->size;
+	  break;
+	default:
+	  /* We can pretend that the callee returns nothing.  */
+	  flags = X86_RET_VOID;
+	  break;
+	}
+    }
+
+  bytes = cif->bytes;
+  stack = alloca(bytes + sizeof(*frame) + rsize);
+  argp = (dir < 0 ? stack + bytes : stack);
+  frame = (struct call_frame *)(stack + bytes);
+  if (rsize)
+    rvalue = frame + 1;
+
+  frame->fn = fn;
+  frame->flags = flags;
+  frame->rvalue = rvalue;
+  frame->regs[pabi->static_chain] = (unsigned)closure;
+
+  narg_reg = 0;
+  switch (flags)
+    {
+    case X86_RET_STRUCTARG:
+      /* The pointer is passed as the first argument.  */
+      if (pabi->nregs > 0)
+	{
+	  frame->regs[pabi->regs[0]] = (unsigned)rvalue;
+	  narg_reg = 1;
+	  break;
+	}
+      /* fallthru */
+    case X86_RET_STRUCTPOP:
+      *(void **)argp = rvalue;
+      argp += sizeof(void *);
+      break;
+    }
+
+  arg_types = cif->arg_types;
+  for (i = 0, n = cif->nargs; i < n; i++)
+    {
+      ffi_type *ty = arg_types[i];
+      void *valp = avalue[i];
+      size_t z = ty->size;
+      int t = ty->type;
+
+      if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT)
+        {
+	  ffi_arg val = extend_basic_type (valp, t);
+
+	  if (t != FFI_TYPE_FLOAT && narg_reg < pabi->nregs)
+	    frame->regs[pabi->regs[narg_reg++]] = val;
+	  else if (dir < 0)
+	    {
+	      argp -= 4;
+	      *(ffi_arg *)argp = val;
+	    }
+	  else
+	    {
+	      *(ffi_arg *)argp = val;
+	      argp += 4;
+	    }
+	}
+      else
+	{
+	  size_t za = ALIGN (z, FFI_SIZEOF_ARG);
+	  size_t align = FFI_SIZEOF_ARG;
+
+	  /* Alignment rules for arguments are quite complex.  Vectors and
+	     structures with 16 byte alignment get it.  Note that long double
+	     on Darwin does have 16 byte alignment, and does not get this
+	     alignment if passed directly; a structure with a long double
+	     inside, however, would get 16 byte alignment.  Since libffi does
+	     not support vectors, we need non concern ourselves with other
+	     cases.  */
+	  if (t == FFI_TYPE_STRUCT && ty->alignment >= 16)
+	    align = 16;
+	    
+	  if (dir < 0)
+	    {
+	      /* ??? These reverse argument ABIs are probably too old
+		 to have cared about alignment.  Someone should check.  */
+	      argp -= za;
+	      memcpy (argp, valp, z);
+	    }
+	  else
+	    {
+	      argp = (char *)ALIGN (argp, align);
+	      memcpy (argp, valp, z);
+	      argp += za;
+	    }
+	}
+    }
+  FFI_ASSERT (dir > 0 || argp == stack);
+
+  ffi_call_i386 (frame, stack);
+}
+
+void
+ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, NULL);
+}
+
+void
+ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
+	     void **avalue, void *closure)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, closure);
+}
 
 /** private members **/
 
-/* The following __attribute__((regparm(1))) decorations will have no effect
-   on MSVC - standard cdecl convention applies. */
-static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
-                                         void** args, ffi_cif* cif);
-void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
-     __attribute__ ((regparm(1)));
-unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
-     __attribute__ ((regparm(1)));
-void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
-     __attribute__ ((regparm(1)));
-#ifdef X86_WIN32
-void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
-     __attribute__ ((regparm(1)));
-void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
-     __attribute__ ((regparm(1)));
-void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
-     __attribute__ ((regparm(1)));
-#endif
-#ifdef X86_WIN64
-void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
-#endif
+void FFI_HIDDEN ffi_closure_i386(void);
+void FFI_HIDDEN ffi_closure_STDCALL(void);
+void FFI_HIDDEN ffi_closure_REGISTER(void);
 
-/* This function is jumped to by the trampoline */
-
-#ifdef X86_WIN64
-void * FFI_HIDDEN
-ffi_closure_win64_inner (ffi_closure *closure, void *args) {
-  ffi_cif       *cif;
-  void         **arg_area;
-  void          *result;
-  void          *resp = &result;
-
-  cif         = closure->cif;
-  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
-
-  /* this call will initialize ARG_AREA, such that each
-   * element in that array points to the corresponding 
-   * value on the stack; and if the function returns
-   * a structure, it will change RESP to point to the
-   * structure return address.  */
-
-  ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
-  
-  (closure->fun) (cif, resp, arg_area, closure->user_data);
-
-  /* The result is returned in rax.  This does the right thing for
-     result types except for floats; we have to 'mov xmm0, rax' in the
-     caller to correct this.
-     TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
-  */
-  return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
-}
-
-#else
-unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
-ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
+struct closure_frame
 {
-  /* our various things...  */
-  ffi_cif       *cif;
-  void         **arg_area;
+  unsigned rettemp[4];				/* 0 */
+  unsigned regs[3];				/* 16-24 */
+  ffi_cif *cif;					/* 28 */
+  void (*fun)(ffi_cif*,void*,void**,void*);	/* 32 */
+  void *user_data;				/* 36 */
+};
 
-  cif         = closure->cif;
-  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
-
-  /* this call will initialize ARG_AREA, such that each
-   * element in that array points to the corresponding 
-   * value on the stack; and if the function returns
-   * a structure, it will change RESP to point to the
-   * structure return address.  */
-
-  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
-
-  (closure->fun) (cif, *respp, arg_area, closure->user_data);
-
-  return cif->flags;
-}
-#endif /* !X86_WIN64 */
-
-static void
-ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
-                            ffi_cif *cif)
-{
-  register unsigned int i;
-  register void **p_argv;
-  register char *argp;
-  register ffi_type **p_arg;
-
-  argp = stack;
-
-#ifdef X86_WIN64
-  if (cif->rtype->size > sizeof(ffi_arg)
-      || (cif->flags == FFI_TYPE_STRUCT
-          && (cif->rtype->size != 1 && cif->rtype->size != 2
-              && cif->rtype->size != 4 && cif->rtype->size != 8))) {
-    *rvalue = *(void **) argp;
-    argp += sizeof(void *);
-  }
-#else
-  if ( cif->flags == FFI_TYPE_STRUCT
-       || cif->flags == FFI_TYPE_MS_STRUCT ) {
-    *rvalue = *(void **) argp;
-    argp += sizeof(void *);
-  }
+int FFI_HIDDEN
+#if HAVE_FASTCALL
+__declspec(fastcall)
 #endif
+ffi_closure_inner (struct closure_frame *frame, char *stack)
+{
+  ffi_cif *cif = frame->cif;
+  int cabi, i, n, flags, dir, narg_reg;
+  const struct abi_params *pabi;
+  ffi_type **arg_types;
+  char *argp;
+  void *rvalue;
+  void **avalue;
 
-  p_argv = avalue;
+  cabi = cif->abi;
+  flags = cif->flags;
+  narg_reg = 0;
+  rvalue = frame->rettemp;
+  pabi = &abi_params[cabi];
+  dir = pabi->dir;
+  argp = (dir < 0 ? stack + cif->bytes : stack);
 
-  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
+  switch (flags)
     {
-      size_t z;
-
-      /* Align if necessary */
-      if ((sizeof(void*) - 1) & (size_t) argp) {
-        argp = (char *) ALIGN(argp, sizeof(void*));
-      }
-
-#ifdef X86_WIN64
-      if ((*p_arg)->size > sizeof(ffi_arg)
-          || ((*p_arg)->type == FFI_TYPE_STRUCT
-              && ((*p_arg)->size != 1 && (*p_arg)->size != 2
-                  && (*p_arg)->size != 4 && (*p_arg)->size != 8)))
-        {
-          z = sizeof(void *);
-          *p_argv = *(void **)argp;
-        }
-      else
-#endif
-        {
-          z = (*p_arg)->size;
-          
-          /* because we're little endian, this is what it turns into.   */
-          
-          *p_argv = (void*) argp;
-        }
-          
-      p_argv++;
-#ifdef X86_WIN64
-      argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
-#else
-      argp += z;
-#endif
+    case X86_RET_STRUCTARG:
+      if (pabi->nregs > 0)
+	{
+	  rvalue = (void *)frame->regs[pabi->regs[0]];
+	  narg_reg = 1;
+	  frame->rettemp[0] = (unsigned)rvalue;
+	  break;
+	}
+      /* fallthru */
+    case X86_RET_STRUCTPOP:
+      rvalue = *(void **)argp;
+      argp += sizeof(void *);
+      frame->rettemp[0] = (unsigned)rvalue;
+      break;
     }
-  
-  return;
+
+  n = cif->nargs;
+  avalue = alloca(sizeof(void *) * n);
+
+  arg_types = cif->arg_types;
+  for (i = 0; i < n; ++i)
+    {
+      ffi_type *ty = arg_types[i];
+      size_t z = ty->size;
+      int t = ty->type;
+      void *valp;
+
+      if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT)
+	{
+	  if (t != FFI_TYPE_FLOAT && narg_reg < pabi->nregs)
+	    valp = &frame->regs[pabi->regs[narg_reg++]];
+	  else if (dir < 0)
+	    {
+	      argp -= 4;
+	      valp = argp;
+	    }
+	  else
+	    {
+	      valp = argp;
+	      argp += 4;
+	    }
+	}
+      else
+	{
+	  size_t za = ALIGN (z, FFI_SIZEOF_ARG);
+	  size_t align = FFI_SIZEOF_ARG;
+
+	  /* See the comment in ffi_call_int.  */
+	  if (t == FFI_TYPE_STRUCT && ty->alignment >= 16)
+	    align = 16;
+
+	  if (dir < 0)
+	    {
+	      /* ??? These reverse argument ABIs are probably too old
+		 to have cared about alignment.  Someone should check.  */
+	      argp -= za;
+	      valp = argp;
+	    }
+	  else
+	    {
+	      argp = (char *)ALIGN (argp, align);
+	      valp = argp;
+	      argp += za;
+	    }
+	}
+
+      avalue[i] = valp;
+    }
+
+  frame->fun (cif, rvalue, avalue, frame->user_data);
+
+  if (cabi == FFI_STDCALL)
+    return flags + (cif->bytes << X86_RET_POP_SHIFT);
+  else
+    return flags;
 }
 
-#define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
-{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
-   void*  __fun = (void*)(FUN); \
-   void*  __ctx = (void*)(CTX); \
-   *(unsigned char*) &__tramp[0] = 0x41; \
-   *(unsigned char*) &__tramp[1] = 0xbb; \
-   *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
-   *(unsigned char*) &__tramp[6] = 0x48; \
-   *(unsigned char*) &__tramp[7] = 0xb8; \
-   *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
-   *(unsigned char *)  &__tramp[16] = 0x49; \
-   *(unsigned char *)  &__tramp[17] = 0xba; \
-   *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
-   *(unsigned char *)  &__tramp[26] = 0x41; \
-   *(unsigned char *)  &__tramp[27] = 0xff; \
-   *(unsigned char *)  &__tramp[28] = 0xe2; /* jmp %r10 */ \
- }
-
-/* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
-
-#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
-{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
-   unsigned int  __fun = (unsigned int)(FUN); \
-   unsigned int  __ctx = (unsigned int)(CTX); \
-   unsigned int  __dis = __fun - (__ctx + 10);  \
-   *(unsigned char*) &__tramp[0] = 0xb8; \
-   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
-   *(unsigned char *)  &__tramp[5] = 0xe9; \
-   *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
- }
-
-#define FFI_INIT_TRAMPOLINE_THISCALL(TRAMP,FUN,CTX,SIZE) \
-{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
-   unsigned int  __fun = (unsigned int)(FUN); \
-   unsigned int  __ctx = (unsigned int)(CTX); \
-   unsigned int  __dis = __fun - (__ctx + 49);  \
-   unsigned short __size = (unsigned short)(SIZE); \
-   *(unsigned int *) &__tramp[0] = 0x8324048b;	/* mov (%esp), %eax */ \
-   *(unsigned int *) &__tramp[4] = 0x4c890cec;	/* sub $12, %esp */ \
-   *(unsigned int *) &__tramp[8] = 0x04890424;	/* mov %ecx, 4(%esp) */ \
-   *(unsigned char*) &__tramp[12] = 0x24;	/* mov %eax, (%esp) */ \
-   *(unsigned char*) &__tramp[13] = 0xb8; \
-   *(unsigned int *) &__tramp[14] = __size;	/* mov __size, %eax */ \
-   *(unsigned int *) &__tramp[18] = 0x08244c8d;	/* lea 8(%esp), %ecx */ \
-   *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
-   *(unsigned short*) &__tramp[26] = 0x0b74;	/* jz 1f */ \
-   *(unsigned int *) &__tramp[28] = 0x8908518b;	/* 2b: mov 8(%ecx), %edx */ \
-   *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
-   *(unsigned char*) &__tramp[36] = 0x48;	/* dec %eax */ \
-   *(unsigned short*) &__tramp[37] = 0xf575;	/* jnz 2b ; 1f: */ \
-   *(unsigned char*) &__tramp[39] = 0xb8; \
-   *(unsigned int*)  &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
-   *(unsigned char *)  &__tramp[44] = 0xe8; \
-   *(unsigned int*)  &__tramp[45] = __dis; /* call __fun  */ \
-   *(unsigned char*)  &__tramp[49] = 0xc2; /* ret  */ \
-   *(unsigned short*)  &__tramp[50] = (__size + 8); /* ret (__size + 8)  */ \
- }
-
-#define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE)  \
-{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
-   unsigned int  __fun = (unsigned int)(FUN); \
-   unsigned int  __ctx = (unsigned int)(CTX); \
-   unsigned int  __dis = __fun - (__ctx + 10); \
-   unsigned short __size = (unsigned short)(SIZE); \
-   *(unsigned char*) &__tramp[0] = 0xb8; \
-   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
-   *(unsigned char *)  &__tramp[5] = 0xe8; \
-   *(unsigned int*)  &__tramp[6] = __dis; /* call __fun  */ \
-   *(unsigned char *)  &__tramp[10] = 0xc2; \
-   *(unsigned short*)  &__tramp[11] = __size; /* ret __size  */ \
- }
-
-/* the cif must already be prep'ed */
-
 ffi_status
 ffi_prep_closure_loc (ffi_closure* closure,
                       ffi_cif* cif,
@@ -650,54 +503,76 @@
                       void *user_data,
                       void *codeloc)
 {
-#ifdef X86_WIN64
-#define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
-#define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
-  if (cif->abi == FFI_WIN64) 
+  char *tramp = closure->tramp;
+  void (*dest)(void);
+  int op = 0xb8;  /* movl imm, %eax */
+
+  switch (cif->abi)
     {
-      int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
-      FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
-                                 &ffi_closure_win64,
-                                 codeloc, mask);
-      /* make sure we can execute here */
-    }
-#else
-  if (cif->abi == FFI_SYSV)
-    {
-      FFI_INIT_TRAMPOLINE (&closure->tramp[0],
-                           &ffi_closure_SYSV,
-                           (void*)codeloc);
-    }
-#ifdef X86_WIN32
-  else if (cif->abi == FFI_THISCALL)
-    {
-      FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0],
-				    &ffi_closure_THISCALL,
-				    (void*)codeloc,
-				    cif->bytes);
-    }
-  else if (cif->abi == FFI_STDCALL)
-    {
-      FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
-                                   &ffi_closure_STDCALL,
-                                   (void*)codeloc, cif->bytes);
-    }
-  else if (cif->abi == FFI_MS_CDECL)
-    {
-      FFI_INIT_TRAMPOLINE (&closure->tramp[0],
-                           &ffi_closure_SYSV,
-                           (void*)codeloc);
-    }
-#endif /* X86_WIN32 */
-#endif /* !X86_WIN64 */
-  else
-    {
+    case FFI_SYSV:
+    case FFI_THISCALL:
+    case FFI_FASTCALL:
+    case FFI_MS_CDECL:
+      dest = ffi_closure_i386;
+      break;
+    case FFI_STDCALL:
+    case FFI_PASCAL:
+      dest = ffi_closure_STDCALL;
+      break;
+    case FFI_REGISTER:
+      dest = ffi_closure_REGISTER;
+      op = 0x68;  /* pushl imm */
+    default:
       return FFI_BAD_ABI;
     }
-    
-  closure->cif  = cif;
+
+  /* movl or pushl immediate.  */
+  tramp[0] = op;
+  *(void **)(tramp + 1) = codeloc;
+
+  /* jmp dest */
+  tramp[5] = 0xe9;
+  *(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10);
+
+  closure->cif = cif;
+  closure->fun = fun;
   closure->user_data = user_data;
-  closure->fun  = fun;
+
+  return FFI_OK;
+}
+
+void FFI_HIDDEN ffi_go_closure_EAX(void);
+void FFI_HIDDEN ffi_go_closure_ECX(void);
+void FFI_HIDDEN ffi_go_closure_STDCALL(void);
+
+ffi_status
+ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
+		     void (*fun)(ffi_cif*,void*,void**,void*))
+{
+  void (*dest)(void);
+
+  switch (cif->abi)
+    {
+    case FFI_SYSV:
+    case FFI_MS_CDECL:
+      dest = ffi_go_closure_ECX;
+      break;
+    case FFI_THISCALL:
+    case FFI_FASTCALL:
+      dest = ffi_go_closure_EAX;
+      break;
+    case FFI_STDCALL:
+    case FFI_PASCAL:
+      dest = ffi_go_closure_STDCALL;
+      break;
+    case FFI_REGISTER:
+    default:
+      return FFI_BAD_ABI;
+    }
+
+  closure->tramp = dest;
+  closure->cif = cif;
+  closure->fun = fun;
 
   return FFI_OK;
 }
@@ -706,138 +581,145 @@
 
 #if !FFI_NO_RAW_API
 
+void FFI_HIDDEN ffi_closure_raw_SYSV(void);
+void FFI_HIDDEN ffi_closure_raw_THISCALL(void);
+
 ffi_status
-ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
-                          ffi_cif* cif,
+ffi_prep_raw_closure_loc (ffi_raw_closure *closure,
+                          ffi_cif *cif,
                           void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
                           void *user_data,
                           void *codeloc)
 {
+  char *tramp = closure->tramp;
+  void (*dest)(void);
   int i;
 
-  if (cif->abi != FFI_SYSV) {
-#ifdef X86_WIN32
-    if (cif->abi != FFI_THISCALL)
-#endif
-    return FFI_BAD_ABI;
-  }
-
-  /* we currently don't support certain kinds of arguments for raw
+  /* We currently don't support certain kinds of arguments for raw
      closures.  This should be implemented by a separate assembly
      language routine, since it would require argument processing,
      something we don't do now for performance.  */
-
   for (i = cif->nargs-1; i >= 0; i--)
+    switch (cif->arg_types[i]->type)
+      {
+      case FFI_TYPE_STRUCT:
+      case FFI_TYPE_LONGDOUBLE:
+	return FFI_BAD_TYPEDEF;
+      }
+
+  switch (cif->abi)
     {
-      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
-      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
+    case FFI_THISCALL:
+      dest = ffi_closure_raw_THISCALL;
+      break;
+    case FFI_SYSV:
+      dest = ffi_closure_raw_SYSV;
+      break;
+    default:
+      return FFI_BAD_ABI;
     }
-  
-#ifdef X86_WIN32
-  if (cif->abi == FFI_SYSV)
-    {
-#endif
-  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
-                       codeloc);
-#ifdef X86_WIN32
-    }
-  else if (cif->abi == FFI_THISCALL)
-    {
-      FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL,
-				    codeloc, cif->bytes);
-    }
-#endif
-  closure->cif  = cif;
+
+  /* movl imm, %eax.  */
+  tramp[0] = 0xb8;
+  *(void **)(tramp + 1) = codeloc;
+
+  /* jmp dest */
+  tramp[5] = 0xe9;
+  *(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10);
+
+  closure->cif = cif;
+  closure->fun = fun;
   closure->user_data = user_data;
-  closure->fun  = fun;
 
   return FFI_OK;
 }
 
-static void 
-ffi_prep_args_raw(char *stack, extended_cif *ecif)
-{
-  memcpy (stack, ecif->avalue, ecif->cif->bytes);
-}
-
-/* we borrow this routine from libffi (it must be changed, though, to
- * actually call the function passed in the first argument.  as of
- * libffi-1.20, this is not the case.)
- */
-
 void
-ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
+ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue)
 {
-  extended_cif ecif;
-  void **avalue = (void **)fake_avalue;
+  size_t rsize, bytes;
+  struct call_frame *frame;
+  char *stack, *argp;
+  ffi_type **arg_types;
+  int flags, cabi, i, n, narg_reg;
+  const struct abi_params *pabi;
 
-  ecif.cif = cif;
-  ecif.avalue = avalue;
-  
-  /* If the return value is a struct and we don't have a return */
-  /* value address then we need to make one                     */
+  flags = cif->flags;
+  cabi = cif->abi;
+  pabi = &abi_params[cabi];
 
-  if (rvalue == NULL
-      && (cif->flags == FFI_TYPE_STRUCT
-          || cif->flags == FFI_TYPE_MS_STRUCT))
+  rsize = 0;
+  if (rvalue == NULL)
     {
-      ecif.rvalue = alloca(cif->rtype->size);
+      switch (flags)
+	{
+	case X86_RET_FLOAT:
+	case X86_RET_DOUBLE:
+	case X86_RET_LDOUBLE:
+	case X86_RET_STRUCTPOP:
+	case X86_RET_STRUCTARG:
+	  /* The float cases need to pop the 387 stack.
+	     The struct cases need to pass a valid pointer to the callee.  */
+	  rsize = cif->rtype->size;
+	  break;
+	default:
+	  /* We can pretend that the callee returns nothing.  */
+	  flags = X86_RET_VOID;
+	  break;
+	}
     }
-  else
-    ecif.rvalue = rvalue;
-    
-  
-  switch (cif->abi) 
+
+  bytes = cif->bytes;
+  argp = stack = alloca(bytes + sizeof(*frame) + rsize);
+  frame = (struct call_frame *)(stack + bytes);
+  if (rsize)
+    rvalue = frame + 1;
+
+  narg_reg = 0;
+  switch (flags)
     {
-#ifdef X86_WIN32
-    case FFI_SYSV:
-    case FFI_STDCALL:
-    case FFI_MS_CDECL:
-      ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
-		     ecif.rvalue, fn);
-      break;
-    case FFI_THISCALL:
-    case FFI_FASTCALL:
-      {
-	unsigned int abi = cif->abi;
-	unsigned int i, passed_regs = 0;
-
-	if (cif->flags == FFI_TYPE_STRUCT)
-	  ++passed_regs;
-
-	for (i=0; i < cif->nargs && passed_regs < 2;i++)
-	  {
-	    size_t sz;
-
-	    if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
-	        || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
-	      continue;
-	    sz = (cif->arg_types[i]->size + 3) & ~3;
-	    if (sz == 0 || sz > 4)
-	      continue;
-	    ++passed_regs;
-	  }
-	if (passed_regs < 2 && abi == FFI_FASTCALL)
-	  cif->abi = abi = FFI_THISCALL;
-	if (passed_regs < 1 && abi == FFI_THISCALL)
-	  cif->abi = abi = FFI_STDCALL;
-        ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
-                       ecif.rvalue, fn);
-      }
-      break;
-#else
-    case FFI_SYSV:
-      ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
-                    ecif.rvalue, fn);
-      break;
-#endif
-    default:
-      FFI_ASSERT(0);
+    case X86_RET_STRUCTARG:
+      /* The pointer is passed as the first argument.  */
+      if (pabi->nregs > 0)
+	{
+	  frame->regs[pabi->regs[0]] = (unsigned)rvalue;
+	  narg_reg = 1;
+	  break;
+	}
+      /* fallthru */
+    case X86_RET_STRUCTPOP:
+      *(void **)argp = rvalue;
+      argp += sizeof(void *);
+      bytes -= sizeof(void *);
       break;
     }
+
+  arg_types = cif->arg_types;
+  for (i = 0, n = cif->nargs; narg_reg < pabi->nregs && i < n; i++)
+    {
+      ffi_type *ty = arg_types[i];
+      size_t z = ty->size;
+      int t = ty->type;
+
+      if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT && t != FFI_TYPE_FLOAT)
+	{
+	  ffi_arg val = extend_basic_type (avalue, t);
+	  frame->regs[pabi->regs[narg_reg++]] = val;
+	  z = FFI_SIZEOF_ARG;
+	}
+      else
+	{
+	  memcpy (argp, avalue, z);
+	  z = ALIGN (z, FFI_SIZEOF_ARG);
+	  argp += z;
+	}
+      avalue += z;
+      bytes -= z;
+    }
+  if (i < n)
+    memcpy (argp, avalue, bytes);
+
+  ffi_call_i386 (frame, stack);
 }
-
-#endif
-
-#endif /* !__x86_64__  || X86_WIN64 */
-
+#endif /* !FFI_NO_RAW_API */
+#endif /* !__x86_64__ */
diff --git a/third_party/gofrontend/libffi/src/x86/ffi64.c b/third_party/gofrontend/libffi/src/x86/ffi64.c
index 1daa1c0..131b5e3 100644
--- a/third_party/gofrontend/libffi/src/x86/ffi64.c
+++ b/third_party/gofrontend/libffi/src/x86/ffi64.c
@@ -1,9 +1,10 @@
 /* -----------------------------------------------------------------------
-   ffi64.c - Copyright (c) 20011  Anthony Green
+   ffi64.c - Copyright (c) 2013  The Written Word, Inc.
+             Copyright (c) 2011  Anthony Green
              Copyright (c) 2008, 2010  Red Hat, Inc.
              Copyright (c) 2002, 2007  Bo Thorsen <bo@suse.de>
-             
-   x86-64 Foreign Function Interface 
+
+   x86-64 Foreign Function Interface
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -31,27 +32,44 @@
 
 #include <stdlib.h>
 #include <stdarg.h>
+#include <stdint.h>
+#include "internal64.h"
 
 #ifdef __x86_64__
 
 #define MAX_GPR_REGS 6
 #define MAX_SSE_REGS 8
 
-#ifdef __INTEL_COMPILER
+#if defined(__INTEL_COMPILER)
+#include "xmmintrin.h"
 #define UINT128 __m128
 #else
+#if defined(__SUNPRO_C)
+#include <sunmedia_types.h>
+#define UINT128 __m128i
+#else
 #define UINT128 __int128_t
 #endif
+#endif
+
+union big_int_union
+{
+  UINT32 i32;
+  UINT64 i64;
+  UINT128 i128;
+};
 
 struct register_args
 {
   /* Registers for argument passing.  */
   UINT64 gpr[MAX_GPR_REGS];
-  UINT128 sse[MAX_SSE_REGS];
+  union big_int_union sse[MAX_SSE_REGS];
+  UINT64 rax;	/* ssecount */
+  UINT64 r10;	/* static chain */
 };
 
 extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
-			     void *raddr, void (*fnaddr)(void), unsigned ssecount);
+			     void *raddr, void (*fnaddr)(void)) FFI_HIDDEN;
 
 /* All reference to register classes here is identical to the code in
    gcc/config/i386/i386.c. Do *not* change one without the other.  */
@@ -138,7 +156,7 @@
 
    See the x86-64 PS ABI for details.
 */
-static int
+static size_t
 classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
 		   size_t byte_offset)
 {
@@ -153,8 +171,9 @@
     case FFI_TYPE_UINT64:
     case FFI_TYPE_SINT64:
     case FFI_TYPE_POINTER:
+    do_integer:
       {
-	int size = byte_offset + type->size;
+	size_t size = byte_offset + type->size;
 
 	if (size <= 4)
 	  {
@@ -174,7 +193,7 @@
 	  }
 	else if (size <= 16)
 	  {
-	    classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
+	    classes[0] = classes[1] = X86_64_INTEGER_CLASS;
 	    return 2;
 	  }
 	else
@@ -189,15 +208,17 @@
     case FFI_TYPE_DOUBLE:
       classes[0] = X86_64_SSEDF_CLASS;
       return 1;
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
     case FFI_TYPE_LONGDOUBLE:
       classes[0] = X86_64_X87_CLASS;
       classes[1] = X86_64_X87UP_CLASS;
       return 2;
+#endif
     case FFI_TYPE_STRUCT:
       {
-	const int UNITS_PER_WORD = 8;
-	int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
-	ffi_type **ptr; 
+	const size_t UNITS_PER_WORD = 8;
+	size_t words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+	ffi_type **ptr;
 	int i;
 	enum x86_64_reg_class subclasses[MAX_CLASSES];
 
@@ -212,6 +233,7 @@
 	   signalize memory class, so handle it as special case.  */
 	if (!words)
 	  {
+    case FFI_TYPE_VOID:
 	    classes[0] = X86_64_NO_CLASS;
 	    return 1;
 	  }
@@ -219,7 +241,7 @@
 	/* Merge the fields of structure.  */
 	for (ptr = type->elements; *ptr != NULL; ptr++)
 	  {
-	    int num;
+	    size_t num;
 
 	    byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
 
@@ -228,7 +250,7 @@
 	      return 0;
 	    for (i = 0; i < num; i++)
 	      {
-		int pos = byte_offset / 8;
+		size_t pos = byte_offset / 8;
 		classes[i + pos] =
 		  merge_classes (subclasses[i], classes[i + pos]);
 	      }
@@ -281,22 +303,54 @@
 	  }
 	return words;
       }
+    case FFI_TYPE_COMPLEX:
+      {
+	ffi_type *inner = type->elements[0];
+	switch (inner->type)
+	  {
+	  case FFI_TYPE_INT:
+	  case FFI_TYPE_UINT8:
+	  case FFI_TYPE_SINT8:
+	  case FFI_TYPE_UINT16:
+	  case FFI_TYPE_SINT16:
+	  case FFI_TYPE_UINT32:
+	  case FFI_TYPE_SINT32:
+	  case FFI_TYPE_UINT64:
+	  case FFI_TYPE_SINT64:
+	    goto do_integer;
 
-    default:
-      FFI_ASSERT(0);
+	  case FFI_TYPE_FLOAT:
+	    classes[0] = X86_64_SSE_CLASS;
+	    if (byte_offset % 8)
+	      {
+		classes[1] = X86_64_SSESF_CLASS;
+		return 2;
+	      }
+	    return 1;
+	  case FFI_TYPE_DOUBLE:
+	    classes[0] = classes[1] = X86_64_SSEDF_CLASS;
+	    return 2;
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	  case FFI_TYPE_LONGDOUBLE:
+	    classes[0] = X86_64_COMPLEX_X87_CLASS;
+	    return 1;
+#endif
+	  }
+      }
     }
-  return 0; /* Never reached.  */
+  abort();
 }
 
 /* Examine the argument and return set number of register required in each
    class.  Return zero iff parameter should be passed in memory, otherwise
    the number of registers.  */
 
-static int
+static size_t
 examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES],
 		  _Bool in_return, int *pngpr, int *pnsse)
 {
-  int i, n, ngpr, nsse;
+  size_t n;
+  int i, ngpr, nsse;
 
   n = classify_argument (type, classes, 0);
   if (n == 0)
@@ -337,15 +391,59 @@
 ffi_status
 ffi_prep_cif_machdep (ffi_cif *cif)
 {
-  int gprcount, ssecount, i, avn, n, ngpr, nsse, flags;
+  int gprcount, ssecount, i, avn, ngpr, nsse, flags;
   enum x86_64_reg_class classes[MAX_CLASSES];
-  size_t bytes;
+  size_t bytes, n, rtype_size;
+  ffi_type *rtype;
+
+  if (cif->abi != FFI_UNIX64)
+    return FFI_BAD_ABI;
 
   gprcount = ssecount = 0;
 
-  flags = cif->rtype->type;
-  if (flags != FFI_TYPE_VOID)
+  rtype = cif->rtype;
+  rtype_size = rtype->size;
+  switch (rtype->type)
     {
+    case FFI_TYPE_VOID:
+      flags = UNIX64_RET_VOID;
+      break;
+    case FFI_TYPE_UINT8:
+      flags = UNIX64_RET_UINT8;
+      break;
+    case FFI_TYPE_SINT8:
+      flags = UNIX64_RET_SINT8;
+      break;
+    case FFI_TYPE_UINT16:
+      flags = UNIX64_RET_UINT16;
+      break;
+    case FFI_TYPE_SINT16:
+      flags = UNIX64_RET_SINT16;
+      break;
+    case FFI_TYPE_UINT32:
+      flags = UNIX64_RET_UINT32;
+      break;
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+      flags = UNIX64_RET_SINT32;
+      break;
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      flags = UNIX64_RET_INT64;
+      break;
+    case FFI_TYPE_POINTER:
+      flags = (sizeof(void *) == 4 ? UNIX64_RET_UINT32 : UNIX64_RET_INT64);
+      break;
+    case FFI_TYPE_FLOAT:
+      flags = UNIX64_RET_XMM32;
+      break;
+    case FFI_TYPE_DOUBLE:
+      flags = UNIX64_RET_XMM64;
+      break;
+    case FFI_TYPE_LONGDOUBLE:
+      flags = UNIX64_RET_X87;
+      break;
+    case FFI_TYPE_STRUCT:
       n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
       if (n == 0)
 	{
@@ -353,22 +451,62 @@
 	     memory is the first argument.  Allocate a register for it.  */
 	  gprcount++;
 	  /* We don't have to do anything in asm for the return.  */
-	  flags = FFI_TYPE_VOID;
+	  flags = UNIX64_RET_VOID | UNIX64_FLAG_RET_IN_MEM;
 	}
-      else if (flags == FFI_TYPE_STRUCT)
+      else
 	{
-	  /* Mark which registers the result appears in.  */
 	  _Bool sse0 = SSE_CLASS_P (classes[0]);
-	  _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
-	  if (sse0 && !sse1)
-	    flags |= 1 << 8;
-	  else if (!sse0 && sse1)
-	    flags |= 1 << 9;
-	  else if (sse0 && sse1)
-	    flags |= 1 << 10;
-	  /* Mark the true size of the structure.  */
-	  flags |= cif->rtype->size << 12;
+
+	  if (rtype_size == 4 && sse0)
+	    flags = UNIX64_RET_XMM32;
+	  else if (rtype_size == 8)
+	    flags = sse0 ? UNIX64_RET_XMM64 : UNIX64_RET_INT64;
+	  else
+	    {
+	      _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
+	      if (sse0 && sse1)
+		flags = UNIX64_RET_ST_XMM0_XMM1;
+	      else if (sse0)
+		flags = UNIX64_RET_ST_XMM0_RAX;
+	      else if (sse1)
+		flags = UNIX64_RET_ST_RAX_XMM0;
+	      else
+		flags = UNIX64_RET_ST_RAX_RDX;
+	      flags |= rtype_size << UNIX64_SIZE_SHIFT;
+	    }
 	}
+      break;
+    case FFI_TYPE_COMPLEX:
+      switch (rtype->elements[0]->type)
+	{
+	case FFI_TYPE_UINT8:
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_INT:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	  flags = UNIX64_RET_ST_RAX_RDX | (rtype_size << UNIX64_SIZE_SHIFT);
+	  break;
+	case FFI_TYPE_FLOAT:
+	  flags = UNIX64_RET_XMM64;
+	  break;
+	case FFI_TYPE_DOUBLE:
+	  flags = UNIX64_RET_ST_XMM0_XMM1 | (16 << UNIX64_SIZE_SHIFT);
+	  break;
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+	  flags = UNIX64_RET_X87_2;
+	  break;
+#endif
+	default:
+	  return FFI_BAD_TYPEDEF;
+	}
+      break;
+    default:
+      return FFI_BAD_TYPEDEF;
     }
 
   /* Go over all arguments and determine the way they should be passed.
@@ -395,44 +533,50 @@
 	}
     }
   if (ssecount)
-    flags |= 1 << 11;
+    flags |= UNIX64_FLAG_XMM_ARGS;
+
   cif->flags = flags;
   cif->bytes = ALIGN (bytes, 8);
 
   return FFI_OK;
 }
 
-void
-ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+static void
+ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
+	      void **avalue, void *closure)
 {
   enum x86_64_reg_class classes[MAX_CLASSES];
   char *stack, *argp;
   ffi_type **arg_types;
-  int gprcount, ssecount, ngpr, nsse, i, avn;
-  _Bool ret_in_memory;
+  int gprcount, ssecount, ngpr, nsse, i, avn, flags;
   struct register_args *reg_args;
 
   /* Can't call 32-bit mode from 64-bit mode.  */
   FFI_ASSERT (cif->abi == FFI_UNIX64);
 
   /* If the return value is a struct and we don't have a return value
-     address then we need to make one.  Note the setting of flags to
-     VOID above in ffi_prep_cif_machdep.  */
-  ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
-		   && (cif->flags & 0xff) == FFI_TYPE_VOID);
-  if (rvalue == NULL && ret_in_memory)
-    rvalue = alloca (cif->rtype->size);
+     address then we need to make one.  Otherwise we can ignore it.  */
+  flags = cif->flags;
+  if (rvalue == NULL)
+    {
+      if (flags & UNIX64_FLAG_RET_IN_MEM)
+	rvalue = alloca (cif->rtype->size);
+      else
+	flags = UNIX64_RET_VOID;
+    }
 
   /* Allocate the space for the arguments, plus 4 words of temp space.  */
   stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
   reg_args = (struct register_args *) stack;
   argp = stack + sizeof (struct register_args);
 
+  reg_args->r10 = (uintptr_t) closure;
+
   gprcount = ssecount = 0;
 
   /* If the return value is passed in memory, add the pointer as the
      first integer argument.  */
-  if (ret_in_memory)
+  if (flags & UNIX64_FLAG_RET_IN_MEM)
     reg_args->gpr[gprcount++] = (unsigned long) rvalue;
 
   avn = cif->nargs;
@@ -440,8 +584,7 @@
 
   for (i = 0; i < avn; ++i)
     {
-      size_t size = arg_types[i]->size;
-      int n;
+      size_t n, size = arg_types[i]->size;
 
       n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
       if (n == 0
@@ -469,18 +612,38 @@
 	    {
 	      switch (classes[j])
 		{
+		case X86_64_NO_CLASS:
+		case X86_64_SSEUP_CLASS:
+		  break;
 		case X86_64_INTEGER_CLASS:
 		case X86_64_INTEGERSI_CLASS:
-		  reg_args->gpr[gprcount] = 0;
-		  memcpy (&reg_args->gpr[gprcount], a, size < 8 ? size : 8);
+		  /* Sign-extend integer arguments passed in general
+		     purpose registers, to cope with the fact that
+		     LLVM incorrectly assumes that this will be done
+		     (the x86-64 PS ABI does not specify this). */
+		  switch (arg_types[i]->type)
+		    {
+		    case FFI_TYPE_SINT8:
+		      reg_args->gpr[gprcount] = (SINT64) *((SINT8 *) a);
+		      break;
+		    case FFI_TYPE_SINT16:
+		      reg_args->gpr[gprcount] = (SINT64) *((SINT16 *) a);
+		      break;
+		    case FFI_TYPE_SINT32:
+		      reg_args->gpr[gprcount] = (SINT64) *((SINT32 *) a);
+		      break;
+		    default:
+		      reg_args->gpr[gprcount] = 0;
+		      memcpy (&reg_args->gpr[gprcount], a, size);
+		    }
 		  gprcount++;
 		  break;
 		case X86_64_SSE_CLASS:
 		case X86_64_SSEDF_CLASS:
-		  reg_args->sse[ssecount++] = *(UINT64 *) a;
+		  reg_args->sse[ssecount++].i64 = *(UINT64 *) a;
 		  break;
 		case X86_64_SSESF_CLASS:
-		  reg_args->sse[ssecount++] = *(UINT32 *) a;
+		  reg_args->sse[ssecount++].i32 = *(UINT32 *) a;
 		  break;
 		default:
 		  abort();
@@ -488,13 +651,27 @@
 	    }
 	}
     }
+  reg_args->rax = ssecount;
 
   ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),
-		   cif->flags, rvalue, fn, ssecount);
+		   flags, rvalue, fn);
 }
 
+void
+ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, NULL);
+}
 
-extern void ffi_closure_unix64(void);
+void
+ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
+	     void **avalue, void *closure)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, closure);
+}
+
+extern void ffi_closure_unix64(void) FFI_HIDDEN;
+extern void ffi_closure_unix64_sse(void) FFI_HIDDEN;
 
 ffi_status
 ffi_prep_closure_loc (ffi_closure* closure,
@@ -503,29 +680,27 @@
 		      void *user_data,
 		      void *codeloc)
 {
-  volatile unsigned short *tramp;
+  static const unsigned char trampoline[16] = {
+    /* leaq  -0x7(%rip),%r10   # 0x0  */
+    0x4c, 0x8d, 0x15, 0xf9, 0xff, 0xff, 0xff,
+    /* jmpq  *0x3(%rip)        # 0x10 */
+    0xff, 0x25, 0x03, 0x00, 0x00, 0x00,
+    /* nopl  (%rax) */
+    0x0f, 0x1f, 0x00
+  };
+  void (*dest)(void);
+  char *tramp = closure->tramp;
 
-  /* Sanity check on the cif ABI.  */
-  {
-    int abi = cif->abi;
-    if (UNLIKELY (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI)))
-      return FFI_BAD_ABI;
-  }
+  if (cif->abi != FFI_UNIX64)
+    return FFI_BAD_ABI;
 
-  tramp = (volatile unsigned short *) &closure->tramp[0];
+  if (cif->flags & UNIX64_FLAG_XMM_ARGS)
+    dest = ffi_closure_unix64_sse;
+  else
+    dest = ffi_closure_unix64;
 
-  tramp[0] = 0xbb49;		/* mov <code>, %r11	*/
-  *((unsigned long long * volatile) &tramp[1])
-    = (unsigned long) ffi_closure_unix64;
-  tramp[5] = 0xba49;		/* mov <data>, %r10	*/
-  *((unsigned long long * volatile) &tramp[6])
-    = (unsigned long) codeloc;
-
-  /* Set the carry bit iff the function uses any sse registers.
-     This is clc or stc, together with the first byte of the jmp.  */
-  tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
-
-  tramp[11] = 0xe3ff;			/* jmp *%r11    */
+  memcpy (tramp, trampoline, sizeof(trampoline));
+  *(UINT64 *)(tramp + 16) = (uintptr_t)dest;
 
   closure->cif = cif;
   closure->fun = fun;
@@ -534,53 +709,40 @@
   return FFI_OK;
 }
 
-int
-ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
-			 struct register_args *reg_args, char *argp)
+int FFI_HIDDEN
+ffi_closure_unix64_inner(ffi_cif *cif,
+			 void (*fun)(ffi_cif*, void*, void**, void*),
+			 void *user_data,
+			 void *rvalue,
+			 struct register_args *reg_args,
+			 char *argp)
 {
-  ffi_cif *cif;
   void **avalue;
   ffi_type **arg_types;
   long i, avn;
   int gprcount, ssecount, ngpr, nsse;
-  int ret;
-
-  cif = closure->cif;
-  avalue = alloca(cif->nargs * sizeof(void *));
-  gprcount = ssecount = 0;
-
-  ret = cif->rtype->type;
-  if (ret != FFI_TYPE_VOID)
-    {
-      enum x86_64_reg_class classes[MAX_CLASSES];
-      int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
-      if (n == 0)
-	{
-	  /* The return value goes in memory.  Arrange for the closure
-	     return value to go directly back to the original caller.  */
-	  rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++];
-	  /* We don't have to do anything in asm for the return.  */
-	  ret = FFI_TYPE_VOID;
-	}
-      else if (ret == FFI_TYPE_STRUCT && n == 2)
-	{
-	  /* Mark which register the second word of the structure goes in.  */
-	  _Bool sse0 = SSE_CLASS_P (classes[0]);
-	  _Bool sse1 = SSE_CLASS_P (classes[1]);
-	  if (!sse0 && sse1)
-	    ret |= 1 << 8;
-	  else if (sse0 && !sse1)
-	    ret |= 1 << 9;
-	}
-    }
+  int flags;
 
   avn = cif->nargs;
+  flags = cif->flags;
+  avalue = alloca(avn * sizeof(void *));
+  gprcount = ssecount = 0;
+
+  if (flags & UNIX64_FLAG_RET_IN_MEM)
+    {
+      /* On return, %rax will contain the address that was passed
+	 by the caller in %rdi.  */
+      void *r = (void *)(uintptr_t)reg_args->gpr[gprcount++];
+      *(void **)rvalue = r;
+      rvalue = r;
+      flags = (sizeof(void *) == 4 ? UNIX64_RET_UINT32 : UNIX64_RET_INT64);
+    }
+
   arg_types = cif->arg_types;
-  
   for (i = 0; i < avn; ++i)
     {
       enum x86_64_reg_class classes[MAX_CLASSES];
-      int n;
+      size_t n;
 
       n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
       if (n == 0
@@ -634,10 +796,29 @@
     }
 
   /* Invoke the closure.  */
-  closure->fun (cif, rvalue, avalue, closure->user_data);
+  fun (cif, rvalue, avalue, user_data);
 
   /* Tell assembly how to perform return type promotions.  */
-  return ret;
+  return flags;
+}
+
+extern void ffi_go_closure_unix64(void) FFI_HIDDEN;
+extern void ffi_go_closure_unix64_sse(void) FFI_HIDDEN;
+
+ffi_status
+ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
+		     void (*fun)(ffi_cif*, void*, void**, void*))
+{
+  if (cif->abi != FFI_UNIX64)
+    return FFI_BAD_ABI;
+
+  closure->tramp = (cif->flags & UNIX64_FLAG_XMM_ARGS
+		    ? ffi_go_closure_unix64_sse
+		    : ffi_go_closure_unix64);
+  closure->cif = cif;
+  closure->fun = fun;
+
+  return FFI_OK;
 }
 
 #endif /* __x86_64__ */
diff --git a/third_party/gofrontend/libffi/src/x86/ffitarget.h b/third_party/gofrontend/libffi/src/x86/ffitarget.h
index 46f294c..8c1dcac 100644
--- a/third_party/gofrontend/libffi/src/x86/ffitarget.h
+++ b/third_party/gofrontend/libffi/src/x86/ffitarget.h
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------*-C-*-
-   ffitarget.h - Copyright (c) 2012  Anthony Green
+   ffitarget.h - Copyright (c) 2012, 2014  Anthony Green
                  Copyright (c) 1996-2003, 2010  Red Hat, Inc.
                  Copyright (C) 2008  Free Software Foundation, Inc.
 
@@ -49,6 +49,11 @@
 #define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */
 #endif
 
+#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
+#ifndef _MSC_VER
+#define FFI_TARGET_HAS_COMPLEX_TYPE
+#endif
+
 /* ---- Generic type definitions ----------------------------------------- */
 
 #ifndef LIBFFI_ASM
@@ -73,37 +78,40 @@
 #endif
 
 typedef enum ffi_abi {
+#if defined(X86_WIN64)
   FFI_FIRST_ABI = 0,
-
-  /* ---- Intel x86 Win32 ---------- */
-#ifdef X86_WIN32
-  FFI_SYSV,
-  FFI_STDCALL,
-  FFI_THISCALL,
-  FFI_FASTCALL,
-  FFI_MS_CDECL,
-  FFI_LAST_ABI,
-#ifdef _MSC_VER
-  FFI_DEFAULT_ABI = FFI_MS_CDECL
-#else
-  FFI_DEFAULT_ABI = FFI_SYSV
-#endif
-
-#elif defined(X86_WIN64)
   FFI_WIN64,
   FFI_LAST_ABI,
   FFI_DEFAULT_ABI = FFI_WIN64
 
-#else
-  /* ---- Intel x86 and AMD x86-64 - */
-  FFI_SYSV,
-  FFI_UNIX64,   /* Unix variants all use the same ABI for x86-64  */
+#elif defined(X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
+  FFI_FIRST_ABI = 1,
+  FFI_UNIX64,
   FFI_LAST_ABI,
-#if defined(__i386__) || defined(__i386)
-  FFI_DEFAULT_ABI = FFI_SYSV
-#else
   FFI_DEFAULT_ABI = FFI_UNIX64
-#endif
+
+#elif defined(X86_WIN32)
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV      = 1,
+  FFI_STDCALL   = 2,
+  FFI_THISCALL  = 3,
+  FFI_FASTCALL  = 4,
+  FFI_MS_CDECL  = 5,
+  FFI_PASCAL    = 6,
+  FFI_REGISTER  = 7,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_MS_CDECL
+#else
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV      = 1,
+  FFI_THISCALL  = 3,
+  FFI_FASTCALL  = 4,
+  FFI_STDCALL   = 5,
+  FFI_PASCAL    = 6,
+  FFI_REGISTER  = 7,
+  FFI_MS_CDECL  = 8,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_SYSV
 #endif
 } ffi_abi;
 #endif
@@ -111,29 +119,20 @@
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
+#define FFI_GO_CLOSURES 1
+
 #define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1)
 #define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2)
 #define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3)
 #define FFI_TYPE_MS_STRUCT       (FFI_TYPE_LAST + 4)
 
-#if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
-#define FFI_TRAMPOLINE_SIZE 24
-#define FFI_NATIVE_RAW_API 0
+#if defined (X86_64) || defined(X86_WIN64) \
+    || (defined (__x86_64__) && defined (X86_DARWIN))
+# define FFI_TRAMPOLINE_SIZE 24
+# define FFI_NATIVE_RAW_API 0
 #else
-#ifdef X86_WIN32
-#define FFI_TRAMPOLINE_SIZE 52
-#else
-#ifdef X86_WIN64
-#define FFI_TRAMPOLINE_SIZE 29
-#define FFI_NATIVE_RAW_API 0
-#define FFI_NO_RAW_API 1
-#else
-#define FFI_TRAMPOLINE_SIZE 10
-#endif
-#endif
-#ifndef X86_WIN64
-#define FFI_NATIVE_RAW_API 1	/* x86 has native raw api support */
-#endif
+# define FFI_TRAMPOLINE_SIZE 12
+# define FFI_NATIVE_RAW_API 1  /* x86 has native raw api support */
 #endif
 
 #endif
diff --git a/third_party/gofrontend/libffi/src/x86/ffiw64.c b/third_party/gofrontend/libffi/src/x86/ffiw64.c
new file mode 100644
index 0000000..8a33a6c
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/ffiw64.c
@@ -0,0 +1,281 @@
+/* -----------------------------------------------------------------------
+   ffiw64.c - Copyright (c) 2014 Red Hat, Inc.
+
+   x86 win64 Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#ifdef X86_WIN64
+
+struct win64_call_frame
+{
+  UINT64 rbp;		/* 0 */
+  UINT64 retaddr;	/* 8 */
+  UINT64 fn;		/* 16 */
+  UINT64 flags;		/* 24 */
+  UINT64 rvalue;	/* 32 */
+};
+
+extern void ffi_call_win64 (void *stack, struct win64_call_frame *,
+			    void *closure) FFI_HIDDEN;
+
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  int flags, n;
+
+  if (cif->abi != FFI_WIN64)
+    return FFI_BAD_ABI;
+
+  flags = cif->rtype->type;
+  switch (flags)
+    {
+    default:
+      break;
+    case FFI_TYPE_LONGDOUBLE:
+      flags = FFI_TYPE_STRUCT;
+      break;
+    case FFI_TYPE_COMPLEX:
+      flags = FFI_TYPE_STRUCT;
+      /* FALLTHRU */
+    case FFI_TYPE_STRUCT:
+      switch (cif->rtype->size)
+	{
+	case 8:
+	  flags = FFI_TYPE_UINT64;
+	  break;
+	case 4:
+	  flags = FFI_TYPE_SMALL_STRUCT_4B;
+	  break;
+	case 2:
+	  flags = FFI_TYPE_SMALL_STRUCT_2B;
+	  break;
+	case 1:
+	  flags = FFI_TYPE_SMALL_STRUCT_1B;
+	  break;
+	}
+      break;
+    }
+  cif->flags = flags;
+
+  /* Each argument either fits in a register, an 8 byte slot, or is
+     passed by reference with the pointer in the 8 byte slot.  */
+  n = cif->nargs;
+  n += (flags == FFI_TYPE_STRUCT);
+  if (n < 4)
+    n = 4;
+  cif->bytes = n * 8;
+
+  return FFI_OK;
+}
+
+static void
+ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
+	      void **avalue, void *closure)
+{
+  int i, j, n, flags;
+  UINT64 *stack;
+  size_t rsize;
+  struct win64_call_frame *frame;
+
+  FFI_ASSERT(cif->abi == FFI_WIN64);
+
+  flags = cif->flags;
+  rsize = 0;
+
+  /* If we have no return value for a structure, we need to create one.
+     Otherwise we can ignore the return type entirely.  */
+  if (rvalue == NULL)
+    {
+      if (flags == FFI_TYPE_STRUCT)
+	rsize = cif->rtype->size;
+      else
+	flags = FFI_TYPE_VOID;
+    }
+
+  stack = alloca(cif->bytes + sizeof(struct win64_call_frame) + rsize);
+  frame = (struct win64_call_frame *)((char *)stack + cif->bytes);
+  if (rsize)
+    rvalue = frame + 1;
+
+  frame->fn = (uintptr_t)fn;
+  frame->flags = flags;
+  frame->rvalue = (uintptr_t)rvalue;
+
+  j = 0;
+  if (flags == FFI_TYPE_STRUCT)
+    {
+      stack[0] = (uintptr_t)rvalue;
+      j = 1;
+    }
+
+  for (i = 0, n = cif->nargs; i < n; ++i, ++j)
+    {
+      switch (cif->arg_types[i]->size)
+	{
+	case 8:
+	  stack[j] = *(UINT64 *)avalue[i];
+	  break;
+	case 4:
+	  stack[j] = *(UINT32 *)avalue[i];
+	  break;
+	case 2:
+	  stack[j] = *(UINT16 *)avalue[i];
+	  break;
+	case 1:
+	  stack[j] = *(UINT8 *)avalue[i];
+	  break;
+	default:
+	  stack[j] = (uintptr_t)avalue[i];
+	  break;
+	}
+    }
+
+  ffi_call_win64 (stack, frame, closure);
+}
+
+void
+ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, NULL);
+}
+
+void
+ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
+	     void **avalue, void *closure)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, closure);
+}
+
+
+extern void ffi_closure_win64(void) FFI_HIDDEN;
+extern void ffi_go_closure_win64(void) FFI_HIDDEN;
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+		      ffi_cif* cif,
+		      void (*fun)(ffi_cif*, void*, void**, void*),
+		      void *user_data,
+		      void *codeloc)
+{
+  static const unsigned char trampoline[16] = {
+    /* leaq  -0x7(%rip),%r10   # 0x0  */
+    0x4c, 0x8d, 0x15, 0xf9, 0xff, 0xff, 0xff,
+    /* jmpq  *0x3(%rip)        # 0x10 */
+    0xff, 0x25, 0x03, 0x00, 0x00, 0x00,
+    /* nopl  (%rax) */
+    0x0f, 0x1f, 0x00
+  };
+  unsigned char *tramp = closure->tramp;
+
+  if (cif->abi != FFI_WIN64)
+    return FFI_BAD_ABI;
+
+  memcpy (tramp, trampoline, sizeof(trampoline));
+  *(UINT64 *)(tramp + 16) = (uintptr_t)ffi_closure_win64;
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  return FFI_OK;
+}
+
+ffi_status
+ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
+		     void (*fun)(ffi_cif*, void*, void**, void*))
+{
+  if (cif->abi != FFI_WIN64)
+    return FFI_BAD_ABI;
+
+  closure->tramp = ffi_go_closure_win64;
+  closure->cif = cif;
+  closure->fun = fun;
+
+  return FFI_OK;
+}
+
+struct win64_closure_frame
+{
+  UINT64 rvalue[2];
+  UINT64 fargs[4];
+  UINT64 retaddr;
+  UINT64 args[];
+};
+
+int FFI_HIDDEN
+ffi_closure_win64_inner(ffi_cif *cif,
+			void (*fun)(ffi_cif*, void*, void**, void*),
+			void *user_data,
+			struct win64_closure_frame *frame)
+{
+  void **avalue;
+  void *rvalue;
+  int i, n, nreg, flags;
+
+  avalue = alloca(cif->nargs * sizeof(void *));
+  rvalue = frame->rvalue;
+  nreg = 0;
+
+  /* When returning a structure, the address is in the first argument.
+     We must also be prepared to return the same address in eax, so
+     install that address in the frame and pretend we return a pointer.  */
+  flags = cif->flags;
+  if (flags == FFI_TYPE_STRUCT)
+    {
+      rvalue = (void *)(uintptr_t)frame->args[0];
+      frame->rvalue[0] = frame->args[0];
+      nreg = 1;
+    }
+
+  for (i = 0, n = cif->nargs; i < n; ++i, ++nreg)
+    {
+      size_t size = cif->arg_types[i]->size;
+      size_t type = cif->arg_types[i]->type;
+      void *a;
+
+      if (type == FFI_TYPE_DOUBLE || type == FFI_TYPE_FLOAT)
+	{
+	  if (nreg < 4)
+	    a = &frame->fargs[nreg];
+	  else
+	    a = &frame->args[nreg];
+	}
+      else if (size == 1 || size == 2 || size == 4 || size == 8)
+	a = &frame->args[nreg];
+      else
+	a = (void *)(uintptr_t)frame->args[nreg];
+
+      avalue[i] = a;
+    }
+
+  /* Invoke the closure.  */
+  fun (cif, rvalue, avalue, user_data);
+  return flags;
+}
+
+#endif /* X86_WIN64 */
diff --git a/third_party/gofrontend/libffi/src/x86/freebsd.S b/third_party/gofrontend/libffi/src/x86/freebsd.S
deleted file mode 100644
index afde513..0000000
--- a/third_party/gofrontend/libffi/src/x86/freebsd.S
+++ /dev/null
@@ -1,458 +0,0 @@
-/* -----------------------------------------------------------------------
-   freebsd.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005  Red Hat, Inc.
-	       Copyright (c) 2008  Björn König
-	
-   X86 Foreign Function Interface for FreeBSD
-
-   Permission is hereby granted, free of charge, to any person obtaining
-   a copy of this software and associated documentation files (the
-   ``Software''), to deal in the Software without restriction, including
-   without limitation the rights to use, copy, modify, merge, publish,
-   distribute, sublicense, and/or sell copies of the Software, and to
-   permit persons to whom the Software is furnished to do so, subject to
-   the following conditions:
-
-   The above copyright notice and this permission notice shall be included
-   in all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-   DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------ */
-
-#ifndef __x86_64__
-
-#define LIBFFI_ASM	
-#include <fficonfig.h>
-#include <ffi.h>
-
-.text
-
-.globl ffi_prep_args
-
-	.align 4
-.globl ffi_call_SYSV
-        .type    ffi_call_SYSV,@function
-
-ffi_call_SYSV:
-.LFB1:
-        pushl %ebp
-.LCFI0:
-        movl  %esp,%ebp
-.LCFI1:
-	/* Make room for all of the new args.  */
-	movl  16(%ebp),%ecx
-	subl  %ecx,%esp
-
-	movl  %esp,%eax
-
-	/* Place all of the ffi_prep_args in position  */
-	pushl 12(%ebp)
-	pushl %eax
-	call  *8(%ebp)
-
-	/* Return stack to previous state and call the function  */
-	addl  $8,%esp	
-
-	call  *28(%ebp)
-
-	/* Load %ecx with the return type code  */
-	movl  20(%ebp),%ecx	
-
-	/* Protect %esi.  We're going to pop it in the epilogue.  */
-	pushl %esi
-
-	/* If the return value pointer is NULL, assume no return value.  */
-	cmpl  $0,24(%ebp)
-	jne  0f
-
-	/* Even if there is no space for the return value, we are 
-	   obliged to handle floating-point values.  */
-	cmpl  $FFI_TYPE_FLOAT,%ecx
-	jne   noretval
-	fstp  %st(0)
-
-        jmp   epilogue
-
-0:
-	call  1f
-
-.Lstore_table:
-	.long	noretval-.Lstore_table	/* FFI_TYPE_VOID */
-	.long	retint-.Lstore_table	/* FFI_TYPE_INT */
-	.long	retfloat-.Lstore_table	/* FFI_TYPE_FLOAT */
-	.long	retdouble-.Lstore_table	/* FFI_TYPE_DOUBLE */
-	.long	retlongdouble-.Lstore_table	/* FFI_TYPE_LONGDOUBLE */
-	.long	retuint8-.Lstore_table	/* FFI_TYPE_UINT8 */
-	.long	retsint8-.Lstore_table	/* FFI_TYPE_SINT8 */
-	.long	retuint16-.Lstore_table	/* FFI_TYPE_UINT16 */
-	.long	retsint16-.Lstore_table	/* FFI_TYPE_SINT16 */
-	.long	retint-.Lstore_table	/* FFI_TYPE_UINT32 */
-	.long	retint-.Lstore_table	/* FFI_TYPE_SINT32 */
-	.long	retint64-.Lstore_table	/* FFI_TYPE_UINT64 */
-	.long	retint64-.Lstore_table	/* FFI_TYPE_SINT64 */
-	.long	retstruct-.Lstore_table	/* FFI_TYPE_STRUCT */
-	.long	retint-.Lstore_table	/* FFI_TYPE_POINTER */
-	.long   retstruct1b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_1B */
-	.long   retstruct2b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_2B */
-
-1:
-	pop  %esi
-	add  (%esi, %ecx, 4), %esi
-	jmp  *%esi
-
-	/* Sign/zero extend as appropriate.  */
-retsint8:
-	movsbl  %al, %eax
-	jmp  retint
-
-retsint16:
-	movswl  %ax, %eax
-	jmp  retint
-
-retuint8:
-	movzbl  %al, %eax
-	jmp  retint
-
-retuint16:
-	movzwl  %ax, %eax
-	jmp  retint
-
-retfloat:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	fstps (%ecx)
-	jmp   epilogue
-
-retdouble:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	fstpl (%ecx)
-	jmp   epilogue
-
-retlongdouble:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	fstpt (%ecx)
-	jmp   epilogue
-	
-retint64:	
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	movl  %eax,0(%ecx)
-	movl  %edx,4(%ecx)
-	jmp   epilogue
-	
-retstruct1b:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx
-	movb  %al,0(%ecx)
-	jmp   epilogue
-
-retstruct2b:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx
-	movw  %ax,0(%ecx)
-	jmp   epilogue
-
-retint:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	movl  %eax,0(%ecx)
-
-retstruct:
-	/* Nothing to do!  */
-
-noretval:
-epilogue:
-        popl %esi
-        movl %ebp,%esp
-        popl %ebp
-        ret
-.LFE1:
-.ffi_call_SYSV_end:
-        .size    ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
-
-	.align	4
-FFI_HIDDEN (ffi_closure_SYSV)
-.globl ffi_closure_SYSV
-	.type	ffi_closure_SYSV, @function
-
-ffi_closure_SYSV:
-.LFB2:
-	pushl	%ebp
-.LCFI2:
-	movl	%esp, %ebp
-.LCFI3:
-	subl	$40, %esp
-	leal	-24(%ebp), %edx
-	movl	%edx, -12(%ebp)	/* resp */
-	leal	8(%ebp), %edx
-	movl	%edx, 4(%esp)	/* args = __builtin_dwarf_cfa () */
-	leal	-12(%ebp), %edx
-	movl	%edx, (%esp)	/* &resp */
-#if defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE || !defined __PIC__
-	call	ffi_closure_SYSV_inner
-#else
-	movl	%ebx, 8(%esp)
-.LCFI7:
-	call	1f
-1:	popl	%ebx
-	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
-	call	ffi_closure_SYSV_inner@PLT
-	movl	8(%esp), %ebx
-#endif
-	movl	-12(%ebp), %ecx
-	cmpl	$FFI_TYPE_INT, %eax
-	je	.Lcls_retint
-
-	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
-	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
-	cmpl	$FFI_TYPE_UINT64, %eax
-	jge	0f
-	cmpl	$FFI_TYPE_UINT8, %eax
-	jge	.Lcls_retint
-	
-0:	cmpl	$FFI_TYPE_FLOAT, %eax
-	je	.Lcls_retfloat
-	cmpl	$FFI_TYPE_DOUBLE, %eax
-	je	.Lcls_retdouble
-	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
-	je	.Lcls_retldouble
-	cmpl	$FFI_TYPE_SINT64, %eax
-	je	.Lcls_retllong
-	cmpl	$FFI_TYPE_SMALL_STRUCT_1B, %eax
-	je	.Lcls_retstruct1b
-	cmpl	$FFI_TYPE_SMALL_STRUCT_2B, %eax
-	je	.Lcls_retstruct2b
-	cmpl	$FFI_TYPE_STRUCT, %eax
-	je	.Lcls_retstruct
-.Lcls_epilogue:
-	movl	%ebp, %esp
-	popl	%ebp
-	ret
-.Lcls_retint:
-	movl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-.Lcls_retfloat:
-	flds	(%ecx)
-	jmp	.Lcls_epilogue
-.Lcls_retdouble:
-	fldl	(%ecx)
-	jmp	.Lcls_epilogue
-.Lcls_retldouble:
-	fldt	(%ecx)
-	jmp	.Lcls_epilogue
-.Lcls_retllong:
-	movl	(%ecx), %eax
-	movl	4(%ecx), %edx
-	jmp	.Lcls_epilogue
-.Lcls_retstruct1b:
-	movsbl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-.Lcls_retstruct2b:
-	movswl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-.Lcls_retstruct:
-	movl	%ebp, %esp
-	popl	%ebp
-	ret	$4
-.LFE2:
-	.size	ffi_closure_SYSV, .-ffi_closure_SYSV
-
-#if !FFI_NO_RAW_API
-
-#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
-#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
-#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
-#define CIF_FLAGS_OFFSET 20
-
-	.align	4
-FFI_HIDDEN (ffi_closure_raw_SYSV)
-.globl ffi_closure_raw_SYSV
-	.type	ffi_closure_raw_SYSV, @function
-
-ffi_closure_raw_SYSV:
-.LFB3:
-	pushl	%ebp
-.LCFI4:
-	movl	%esp, %ebp
-.LCFI5:
-	pushl	%esi
-.LCFI6:
-	subl	$36, %esp
-	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
-	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
-	movl	%edx, 12(%esp)	/* user_data */
-	leal	8(%ebp), %edx	/* __builtin_dwarf_cfa () */
-	movl	%edx, 8(%esp)	/* raw_args */
-	leal	-24(%ebp), %edx
-	movl	%edx, 4(%esp)	/* &res */
-	movl	%esi, (%esp)	/* cif */
-	call	*RAW_CLOSURE_FUN_OFFSET(%eax)		 /* closure->fun */
-	movl	CIF_FLAGS_OFFSET(%esi), %eax		 /* rtype */
-	cmpl	$FFI_TYPE_INT, %eax
-	je	.Lrcls_retint
-
-	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
-	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
-	cmpl	$FFI_TYPE_UINT64, %eax
-	jge	0f
-	cmpl	$FFI_TYPE_UINT8, %eax
-	jge	.Lrcls_retint
-0:
-	cmpl	$FFI_TYPE_FLOAT, %eax
-	je	.Lrcls_retfloat
-	cmpl	$FFI_TYPE_DOUBLE, %eax
-	je	.Lrcls_retdouble
-	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
-	je	.Lrcls_retldouble
-	cmpl	$FFI_TYPE_SINT64, %eax
-	je	.Lrcls_retllong
-.Lrcls_epilogue:
-	addl	$36, %esp
-	popl	%esi
-	popl	%ebp
-	ret
-.Lrcls_retint:
-	movl	-24(%ebp), %eax
-	jmp	.Lrcls_epilogue
-.Lrcls_retfloat:
-	flds	-24(%ebp)
-	jmp	.Lrcls_epilogue
-.Lrcls_retdouble:
-	fldl	-24(%ebp)
-	jmp	.Lrcls_epilogue
-.Lrcls_retldouble:
-	fldt	-24(%ebp)
-	jmp	.Lrcls_epilogue
-.Lrcls_retllong:
-	movl	-24(%ebp), %eax
-	movl	-20(%ebp), %edx
-	jmp	.Lrcls_epilogue
-.LFE3:
-	.size	ffi_closure_raw_SYSV, .-ffi_closure_raw_SYSV
-#endif
-
-	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
-.Lframe1:
-	.long	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
-.LSCIE1:
-	.long	0x0	/* CIE Identifier Tag */
-	.byte	0x1	/* CIE Version */
-#ifdef __PIC__
-	.ascii "zR\0"	/* CIE Augmentation */
-#else
-	.ascii "\0"	/* CIE Augmentation */
-#endif
-	.byte	0x1	/* .uleb128 0x1; CIE Code Alignment Factor */
-	.byte	0x7c	/* .sleb128 -4; CIE Data Alignment Factor */
-	.byte	0x8	/* CIE RA Column */
-#ifdef __PIC__
-	.byte	0x1	/* .uleb128 0x1; Augmentation size */
-	.byte	0x1b	/* FDE Encoding (pcrel sdata4) */
-#endif
-	.byte	0xc	/* DW_CFA_def_cfa */
-	.byte	0x4	/* .uleb128 0x4 */
-	.byte	0x4	/* .uleb128 0x4 */
-	.byte	0x88	/* DW_CFA_offset, column 0x8 */
-	.byte	0x1	/* .uleb128 0x1 */
-	.align 4
-.LECIE1:
-.LSFDE1:
-	.long	.LEFDE1-.LASFDE1	/* FDE Length */
-.LASFDE1:
-	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
-#ifdef __PIC__
-	.long	.LFB1-.	/* FDE initial location */
-#else
-	.long	.LFB1	/* FDE initial location */
-#endif
-	.long	.LFE1-.LFB1	/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI0-.LFB1
-	.byte	0xe	/* DW_CFA_def_cfa_offset */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 */
-	.byte	0x2	/* .uleb128 0x2 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI1-.LCFI0
-	.byte	0xd	/* DW_CFA_def_cfa_register */
-	.byte	0x5	/* .uleb128 0x5 */
-	.align 4
-.LEFDE1:
-.LSFDE2:
-	.long	.LEFDE2-.LASFDE2	/* FDE Length */
-.LASFDE2:
-	.long	.LASFDE2-.Lframe1	/* FDE CIE offset */
-#ifdef __PIC__
-	.long	.LFB2-.	/* FDE initial location */
-#else
-	.long	.LFB2
-#endif
-	.long	.LFE2-.LFB2	/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI2-.LFB2
-	.byte	0xe	/* DW_CFA_def_cfa_offset */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 */
-	.byte	0x2	/* .uleb128 0x2 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI3-.LCFI2
-	.byte	0xd	/* DW_CFA_def_cfa_register */
-	.byte	0x5	/* .uleb128 0x5 */
-#if !defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE && defined __PIC__
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI7-.LCFI3
-	.byte	0x83	/* DW_CFA_offset, column 0x3 */
-	.byte	0xa	/* .uleb128 0xa */
-#endif
-	.align 4
-.LEFDE2:
-
-#if !FFI_NO_RAW_API
-
-.LSFDE3:
-	.long	.LEFDE3-.LASFDE3	/* FDE Length */
-.LASFDE3:
-	.long	.LASFDE3-.Lframe1	/* FDE CIE offset */
-#ifdef __PIC__
-	.long	.LFB3-.	/* FDE initial location */
-#else
-	.long	.LFB3
-#endif
-	.long	.LFE3-.LFB3	/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI4-.LFB3
-	.byte	0xe	/* DW_CFA_def_cfa_offset */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 */
-	.byte	0x2	/* .uleb128 0x2 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI5-.LCFI4
-	.byte	0xd	/* DW_CFA_def_cfa_register */
-	.byte	0x5	/* .uleb128 0x5 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI6-.LCFI5
-	.byte	0x86	/* DW_CFA_offset, column 0x6 */
-	.byte	0x3	/* .uleb128 0x3 */
-	.align 4
-.LEFDE3:
-
-#endif
-
-#endif /* ifndef __x86_64__ */
diff --git a/third_party/gofrontend/libffi/src/x86/internal.h b/third_party/gofrontend/libffi/src/x86/internal.h
new file mode 100644
index 0000000..09771ba
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/internal.h
@@ -0,0 +1,29 @@
+#define X86_RET_FLOAT		0
+#define X86_RET_DOUBLE		1
+#define X86_RET_LDOUBLE		2
+#define X86_RET_SINT8		3
+#define X86_RET_SINT16		4
+#define X86_RET_UINT8		5
+#define X86_RET_UINT16		6
+#define X86_RET_INT64		7
+#define X86_RET_INT32		8
+#define X86_RET_VOID		9
+#define X86_RET_STRUCTPOP	10
+#define X86_RET_STRUCTARG       11
+#define X86_RET_STRUCT_1B	12
+#define X86_RET_STRUCT_2B	13
+#define X86_RET_UNUSED14	14
+#define X86_RET_UNUSED15	15
+
+#define X86_RET_TYPE_MASK	15
+#define X86_RET_POP_SHIFT	4
+
+#define R_EAX	0
+#define R_EDX	1
+#define R_ECX	2
+
+#ifdef __PCC__
+# define HAVE_FASTCALL 0
+#else
+# define HAVE_FASTCALL 1
+#endif
diff --git a/third_party/gofrontend/libffi/src/x86/internal64.h b/third_party/gofrontend/libffi/src/x86/internal64.h
new file mode 100644
index 0000000..512e955
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/x86/internal64.h
@@ -0,0 +1,22 @@
+#define UNIX64_RET_VOID		0
+#define UNIX64_RET_UINT8	1
+#define UNIX64_RET_UINT16	2
+#define UNIX64_RET_UINT32	3
+#define UNIX64_RET_SINT8	4
+#define UNIX64_RET_SINT16	5
+#define UNIX64_RET_SINT32	6
+#define UNIX64_RET_INT64	7
+#define UNIX64_RET_XMM32	8
+#define UNIX64_RET_XMM64	9
+#define UNIX64_RET_X87		10
+#define UNIX64_RET_X87_2	11
+#define UNIX64_RET_ST_XMM0_RAX	12
+#define UNIX64_RET_ST_RAX_XMM0	13
+#define UNIX64_RET_ST_XMM0_XMM1	14
+#define UNIX64_RET_ST_RAX_RDX	15
+
+#define UNIX64_RET_LAST		15
+
+#define UNIX64_FLAG_RET_IN_MEM	(1 << 10)
+#define UNIX64_FLAG_XMM_ARGS	(1 << 11)
+#define UNIX64_SIZE_SHIFT	12
diff --git a/third_party/gofrontend/libffi/src/x86/sysv.S b/third_party/gofrontend/libffi/src/x86/sysv.S
index f108dd8..ebbea5d 100644
--- a/third_party/gofrontend/libffi/src/x86/sysv.S
+++ b/third_party/gofrontend/libffi/src/x86/sysv.S
@@ -1,5 +1,6 @@
 /* -----------------------------------------------------------------------
-   sysv.S - Copyright (c) 1996, 1998, 2001-2003, 2005, 2008, 2010  Red Hat, Inc.
+   sysv.S - Copyright (c) 2013  The Written Word, Inc.
+	  - Copyright (c) 1996,1998,2001-2003,2005,2008,2010  Red Hat, Inc.
    
    X86 Foreign Function Interface 
 
@@ -29,437 +30,1006 @@
 #define LIBFFI_ASM	
 #include <fficonfig.h>
 #include <ffi.h>
+#include "internal.h"
 
-.text
-
-.globl ffi_prep_args
-
-	.align 4
-.globl ffi_call_SYSV
-        .type    ffi_call_SYSV,@function
-
-ffi_call_SYSV:
-.LFB1:
-        pushl %ebp
-.LCFI0:
-        movl  %esp,%ebp
-.LCFI1:
-	/* Make room for all of the new args.  */
-	movl  16(%ebp),%ecx
-	subl  %ecx,%esp
-
-        /* Align the stack pointer to 16-bytes */
-        andl  $0xfffffff0, %esp
-
-	movl  %esp,%eax
-
-	/* Place all of the ffi_prep_args in position  */
-	pushl 12(%ebp)
-	pushl %eax
-	call  *8(%ebp)
-
-	/* Return stack to previous state and call the function  */
-	addl  $8,%esp	
-
-	call  *28(%ebp)
-
-	/* Load %ecx with the return type code  */
-	movl  20(%ebp),%ecx	
-
-	/* Protect %esi.  We're going to pop it in the epilogue.  */
-	pushl %esi
-
-	/* If the return value pointer is NULL, assume no return value.  */
-	cmpl  $0,24(%ebp)
-	jne  0f
-
-	/* Even if there is no space for the return value, we are 
-	   obliged to handle floating-point values.  */
-	cmpl  $FFI_TYPE_FLOAT,%ecx
-	jne   noretval
-	fstp  %st(0)
-
-        jmp   epilogue
-
-0:
-	call  1f
-
-.Lstore_table:
-	.long	noretval-.Lstore_table	/* FFI_TYPE_VOID */
-	.long	retint-.Lstore_table	/* FFI_TYPE_INT */
-	.long	retfloat-.Lstore_table	/* FFI_TYPE_FLOAT */
-	.long	retdouble-.Lstore_table	/* FFI_TYPE_DOUBLE */
-	.long	retlongdouble-.Lstore_table	/* FFI_TYPE_LONGDOUBLE */
-	.long	retuint8-.Lstore_table	/* FFI_TYPE_UINT8 */
-	.long	retsint8-.Lstore_table	/* FFI_TYPE_SINT8 */
-	.long	retuint16-.Lstore_table	/* FFI_TYPE_UINT16 */
-	.long	retsint16-.Lstore_table	/* FFI_TYPE_SINT16 */
-	.long	retint-.Lstore_table	/* FFI_TYPE_UINT32 */
-	.long	retint-.Lstore_table	/* FFI_TYPE_SINT32 */
-	.long	retint64-.Lstore_table	/* FFI_TYPE_UINT64 */
-	.long	retint64-.Lstore_table	/* FFI_TYPE_SINT64 */
-	.long	retstruct-.Lstore_table	/* FFI_TYPE_STRUCT */
-	.long	retint-.Lstore_table	/* FFI_TYPE_POINTER */
-
-1:
-	pop  %esi
-	add  (%esi, %ecx, 4), %esi
-	jmp  *%esi
-
-	/* Sign/zero extend as appropriate.  */
-retsint8:
-	movsbl  %al, %eax
-	jmp  retint
-
-retsint16:
-	movswl  %ax, %eax
-	jmp  retint
-
-retuint8:
-	movzbl  %al, %eax
-	jmp  retint
-
-retuint16:
-	movzwl  %ax, %eax
-	jmp  retint
-
-retfloat:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	fstps (%ecx)
-	jmp   epilogue
-
-retdouble:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	fstpl (%ecx)
-	jmp   epilogue
-
-retlongdouble:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	fstpt (%ecx)
-	jmp   epilogue
-	
-retint64:	
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	movl  %eax,0(%ecx)
-	movl  %edx,4(%ecx)
-	jmp   epilogue
-	
-retint:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	movl  %eax,0(%ecx)
-
-retstruct:
-	/* Nothing to do!  */
-
-noretval:
-epilogue:
-        popl %esi
-        movl %ebp,%esp
-        popl %ebp
-        ret
-.LFE1:
-.ffi_call_SYSV_end:
-        .size    ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
-
-	.align	4
-FFI_HIDDEN (ffi_closure_SYSV)
-.globl ffi_closure_SYSV
-	.type	ffi_closure_SYSV, @function
-
-ffi_closure_SYSV:
-.LFB2:
-	pushl	%ebp
-.LCFI2:
-	movl	%esp, %ebp
-.LCFI3:
-	subl	$40, %esp
-	leal	-24(%ebp), %edx
-	movl	%edx, -12(%ebp)	/* resp */
-	leal	8(%ebp), %edx
-	movl	%edx, 4(%esp)	/* args = __builtin_dwarf_cfa () */
-	leal	-12(%ebp), %edx
-	movl	%edx, (%esp)	/* &resp */
-#if defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE || !defined __PIC__
-	call	ffi_closure_SYSV_inner
+#define C2(X, Y)  X ## Y
+#define C1(X, Y)  C2(X, Y)
+#ifdef __USER_LABEL_PREFIX__
+# define C(X)     C1(__USER_LABEL_PREFIX__, X)
 #else
-	movl	%ebx, 8(%esp)
-.LCFI7:
-	call	1f
-1:	popl	%ebx
-	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
-	call	ffi_closure_SYSV_inner@PLT
-	movl	8(%esp), %ebx
+# define C(X)     X
 #endif
-	movl	-12(%ebp), %ecx
-	cmpl	$FFI_TYPE_INT, %eax
-	je	.Lcls_retint
 
-	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
-	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
-	cmpl	$FFI_TYPE_UINT64, %eax
-	jge	0f
-	cmpl	$FFI_TYPE_UINT8, %eax
-	jge	.Lcls_retint
-	
-0:	cmpl	$FFI_TYPE_FLOAT, %eax
-	je	.Lcls_retfloat
-	cmpl	$FFI_TYPE_DOUBLE, %eax
-	je	.Lcls_retdouble
-	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
-	je	.Lcls_retldouble
-	cmpl	$FFI_TYPE_SINT64, %eax
-	je	.Lcls_retllong
-	cmpl	$FFI_TYPE_STRUCT, %eax
-	je	.Lcls_retstruct
-.Lcls_epilogue:
+#ifdef X86_DARWIN
+# define L(X)     C1(L, X)
+#else
+# define L(X)     C1(.L, X)
+#endif
+
+#ifdef __ELF__
+# define ENDF(X)  .type	X,@function; .size X, . - X
+#else
+# define ENDF(X)
+#endif
+
+/* Handle win32 fastcall name mangling.  */
+#ifdef X86_WIN32
+# define ffi_call_i386		@ffi_call_i386@8
+# define ffi_closure_inner	@ffi_closure_inner@8
+#else
+# define ffi_call_i386		C(ffi_call_i386)
+# define ffi_closure_inner	C(ffi_closure_inner)
+#endif
+
+/* This macro allows the safe creation of jump tables without an
+   actual table.  The entry points into the table are all 8 bytes.
+   The use of ORG asserts that we're at the correct location.  */
+/* ??? The clang assembler doesn't handle .org with symbolic expressions.  */
+#if defined(__clang__) || defined(__APPLE__)
+# define E(BASE, X)	.balign 8
+#else
+# define E(BASE, X)	.balign 8; .org BASE + X * 8
+#endif
+
+	.text
+	.balign	16
+	.globl	ffi_call_i386
+	FFI_HIDDEN(ffi_call_i386)
+
+/* This is declared as
+
+   void ffi_call_i386(struct call_frame *frame, char *argp)
+        __attribute__((fastcall));
+
+   Thus the arguments are present in
+
+        ecx: frame
+        edx: argp
+*/
+
+ffi_call_i386:
+L(UW0):
+	# cfi_startproc
+#if !HAVE_FASTCALL
+	movl	4(%esp), %ecx
+	movl	8(%esp), %edx
+#endif
+	movl	(%esp), %eax		/* move the return address */
+	movl	%ebp, (%ecx)		/* store %ebp into local frame */
+	movl	%eax, 4(%ecx)		/* store retaddr into local frame */
+
+	/* New stack frame based off ebp.  This is a itty bit of unwind
+	   trickery in that the CFA *has* changed.  There is no easy way
+	   to describe it correctly on entry to the function.  Fortunately,
+	   it doesn't matter too much since at all points we can correctly
+	   unwind back to ffi_call.  Note that the location to which we
+	   moved the return address is (the new) CFA-4, so from the
+	   perspective of the unwind info, it hasn't moved.  */
+	movl	%ecx, %ebp
+L(UW1):
+	# cfi_def_cfa(%ebp, 8)
+	# cfi_rel_offset(%ebp, 0)
+
+	movl	%edx, %esp		/* set outgoing argument stack */
+	movl	20+R_EAX*4(%ebp), %eax	/* set register arguments */
+	movl	20+R_EDX*4(%ebp), %edx
+	movl	20+R_ECX*4(%ebp), %ecx
+
+	call	*8(%ebp)
+
+	movl	12(%ebp), %ecx		/* load return type code */
+	movl	%ebx, 8(%ebp)		/* preserve %ebx */
+L(UW2):
+	# cfi_rel_offset(%ebx, 8)
+
+	andl	$X86_RET_TYPE_MASK, %ecx
+#ifdef __PIC__
+	call	C(__x86.get_pc_thunk.bx)
+L(pc1):
+	leal	L(store_table)-L(pc1)(%ebx, %ecx, 8), %ebx
+#else
+	leal	L(store_table)(,%ecx, 8), %ebx
+#endif
+	movl	16(%ebp), %ecx		/* load result address */
+	jmp	*%ebx
+
+	.balign	8
+L(store_table):
+E(L(store_table), X86_RET_FLOAT)
+	fstps	(%ecx)
+	jmp	L(e1)
+E(L(store_table), X86_RET_DOUBLE)
+	fstpl	(%ecx)
+	jmp	L(e1)
+E(L(store_table), X86_RET_LDOUBLE)
+	fstpt	(%ecx)
+	jmp	L(e1)
+E(L(store_table), X86_RET_SINT8)
+	movsbl	%al, %eax
+	mov	%eax, (%ecx)
+	jmp	L(e1)
+E(L(store_table), X86_RET_SINT16)
+	movswl	%ax, %eax
+	mov	%eax, (%ecx)
+	jmp	L(e1)
+E(L(store_table), X86_RET_UINT8)
+	movzbl	%al, %eax
+	mov	%eax, (%ecx)
+	jmp	L(e1)
+E(L(store_table), X86_RET_UINT16)
+	movzwl	%ax, %eax
+	mov	%eax, (%ecx)
+	jmp	L(e1)
+E(L(store_table), X86_RET_INT64)
+	movl	%edx, 4(%ecx)
+	/* fallthru */
+E(L(store_table), X86_RET_INT32)
+	movl	%eax, (%ecx)
+	/* fallthru */
+E(L(store_table), X86_RET_VOID)
+L(e1):
+	movl	8(%ebp), %ebx
 	movl	%ebp, %esp
 	popl	%ebp
+L(UW3):
+	# cfi_remember_state
+	# cfi_def_cfa(%esp, 4)
+	# cfi_restore(%ebx)
+	# cfi_restore(%ebp)
 	ret
-.Lcls_retint:
-	movl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-.Lcls_retfloat:
-	flds	(%ecx)
-	jmp	.Lcls_epilogue
-.Lcls_retdouble:
-	fldl	(%ecx)
-	jmp	.Lcls_epilogue
-.Lcls_retldouble:
-	fldt	(%ecx)
-	jmp	.Lcls_epilogue
-.Lcls_retllong:
-	movl	(%ecx), %eax
-	movl	4(%ecx), %edx
-	jmp	.Lcls_epilogue
-.Lcls_retstruct:
-	movl	%ebp, %esp
-	popl	%ebp
-	ret	$4
-.LFE2:
-	.size	ffi_closure_SYSV, .-ffi_closure_SYSV
+L(UW4):
+	# cfi_restore_state
 
-#if !FFI_NO_RAW_API
+E(L(store_table), X86_RET_STRUCTPOP)
+	jmp	L(e1)
+E(L(store_table), X86_RET_STRUCTARG)
+	jmp	L(e1)
+E(L(store_table), X86_RET_STRUCT_1B)
+	movb	%al, (%ecx)
+	jmp	L(e1)
+E(L(store_table), X86_RET_STRUCT_2B)
+	movw	%ax, (%ecx)
+	jmp	L(e1)
 
-/* Precalculate for e.g. the Solaris 10/x86 assembler.  */
-#if FFI_TRAMPOLINE_SIZE == 10
-#define RAW_CLOSURE_CIF_OFFSET 12
-#define RAW_CLOSURE_FUN_OFFSET 16
-#define RAW_CLOSURE_USER_DATA_OFFSET 20
-#elif FFI_TRAMPOLINE_SIZE == 24
-#define RAW_CLOSURE_CIF_OFFSET 24
-#define RAW_CLOSURE_FUN_OFFSET 28
-#define RAW_CLOSURE_USER_DATA_OFFSET 32
+	/* Fill out the table so that bad values are predictable.  */
+E(L(store_table), X86_RET_UNUSED14)
+	ud2
+E(L(store_table), X86_RET_UNUSED15)
+	ud2
+
+L(UW5):
+	# cfi_endproc
+ENDF(ffi_call_i386)
+
+/* The inner helper is declared as
+
+   void ffi_closure_inner(struct closure_frame *frame, char *argp)
+	__attribute_((fastcall))
+
+   Thus the arguments are placed in
+
+	ecx:	frame
+	edx:	argp
+*/
+
+/* Macros to help setting up the closure_data structure.  */
+
+#if HAVE_FASTCALL
+# define closure_FS	(40 + 4)
+# define closure_CF	0
 #else
-#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
-#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
-#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
-#endif
-#define CIF_FLAGS_OFFSET 20
-
-	.align	4
-FFI_HIDDEN (ffi_closure_raw_SYSV)
-.globl ffi_closure_raw_SYSV
-	.type	ffi_closure_raw_SYSV, @function
-
-ffi_closure_raw_SYSV:
-.LFB3:
-	pushl	%ebp
-.LCFI4:
-	movl	%esp, %ebp
-.LCFI5:
-	pushl	%esi
-.LCFI6:
-	subl	$36, %esp
-	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
-	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
-	movl	%edx, 12(%esp)	/* user_data */
-	leal	8(%ebp), %edx	/* __builtin_dwarf_cfa () */
-	movl	%edx, 8(%esp)	/* raw_args */
-	leal	-24(%ebp), %edx
-	movl	%edx, 4(%esp)	/* &res */
-	movl	%esi, (%esp)	/* cif */
-	call	*RAW_CLOSURE_FUN_OFFSET(%eax)		 /* closure->fun */
-	movl	CIF_FLAGS_OFFSET(%esi), %eax		 /* rtype */
-	cmpl	$FFI_TYPE_INT, %eax
-	je	.Lrcls_retint
-
-	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
-	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
-	cmpl	$FFI_TYPE_UINT64, %eax
-	jge	0f
-	cmpl	$FFI_TYPE_UINT8, %eax
-	jge	.Lrcls_retint
-0:
-	cmpl	$FFI_TYPE_FLOAT, %eax
-	je	.Lrcls_retfloat
-	cmpl	$FFI_TYPE_DOUBLE, %eax
-	je	.Lrcls_retdouble
-	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
-	je	.Lrcls_retldouble
-	cmpl	$FFI_TYPE_SINT64, %eax
-	je	.Lrcls_retllong
-.Lrcls_epilogue:
-	addl	$36, %esp
-	popl	%esi
-	popl	%ebp
-	ret
-.Lrcls_retint:
-	movl	-24(%ebp), %eax
-	jmp	.Lrcls_epilogue
-.Lrcls_retfloat:
-	flds	-24(%ebp)
-	jmp	.Lrcls_epilogue
-.Lrcls_retdouble:
-	fldl	-24(%ebp)
-	jmp	.Lrcls_epilogue
-.Lrcls_retldouble:
-	fldt	-24(%ebp)
-	jmp	.Lrcls_epilogue
-.Lrcls_retllong:
-	movl	-24(%ebp), %eax
-	movl	-20(%ebp), %edx
-	jmp	.Lrcls_epilogue
-.LFE3:
-	.size	ffi_closure_raw_SYSV, .-ffi_closure_raw_SYSV
+# define closure_FS	(8 + 40 + 12)
+# define closure_CF	8
 #endif
 
-#if defined __PIC__
-# if defined __sun__ && defined __svr4__
-/* 32-bit Solaris 2/x86 uses datarel encoding for PIC.  GNU ld before 2.22
-   doesn't correctly sort .eh_frame_hdr with mixed encodings, so match this.  */
-#  define FDE_ENCODING		0x30	/* datarel */
-#  define FDE_ENCODE(X)		X@GOTOFF
+#define FFI_CLOSURE_SAVE_REGS		\
+	movl	%eax, closure_CF+16+R_EAX*4(%esp);	\
+	movl	%edx, closure_CF+16+R_EDX*4(%esp);	\
+	movl	%ecx, closure_CF+16+R_ECX*4(%esp)
+
+#define FFI_CLOSURE_COPY_TRAMP_DATA					\
+	movl	FFI_TRAMPOLINE_SIZE(%eax), %edx;	/* copy cif */	\
+	movl	FFI_TRAMPOLINE_SIZE+4(%eax), %ecx;	/* copy fun */	\
+	movl	FFI_TRAMPOLINE_SIZE+8(%eax), %eax;	/* copy user_data */ \
+	movl	%edx, closure_CF+28(%esp);				\
+	movl	%ecx, closure_CF+32(%esp);				\
+	movl	%eax, closure_CF+36(%esp)
+
+#if HAVE_FASTCALL
+# define FFI_CLOSURE_PREP_CALL						\
+	movl	%esp, %ecx;			/* load closure_data */	\
+	leal	closure_FS+4(%esp), %edx;	/* load incoming stack */
+#else
+# define FFI_CLOSURE_PREP_CALL						\
+	leal	closure_CF(%esp), %ecx;		/* load closure_data */	\
+	leal	closure_FS+4(%esp), %edx;	/* load incoming stack */ \
+	movl	%ecx, (%esp);						\
+	movl	%edx, 4(%esp)
+#endif
+
+#define FFI_CLOSURE_CALL_INNER(UWN) \
+	call	ffi_closure_inner
+
+#define FFI_CLOSURE_MASK_AND_JUMP(N, UW)				\
+	andl	$X86_RET_TYPE_MASK, %eax;				\
+	leal	L(C1(load_table,N))(, %eax, 8), %edx;			\
+	movl	closure_CF(%esp), %eax;		/* optimiztic load */	\
+	jmp	*%edx
+
+#ifdef __PIC__
+# if defined X86_DARWIN || defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+#  undef FFI_CLOSURE_MASK_AND_JUMP
+#  define FFI_CLOSURE_MASK_AND_JUMP(N, UW)				\
+	andl	$X86_RET_TYPE_MASK, %eax;				\
+	call	C(__x86.get_pc_thunk.dx);				\
+L(C1(pc,N)):								\
+	leal	L(C1(load_table,N))-L(C1(pc,N))(%edx, %eax, 8), %edx;	\
+	movl	closure_CF(%esp), %eax;		/* optimiztic load */	\
+	jmp	*%edx
 # else
-#  define FDE_ENCODING		0x1b	/* pcrel sdata4 */
-#  if defined HAVE_AS_X86_PCREL
-#   define FDE_ENCODE(X)	X-.
-#  else
-#   define FDE_ENCODE(X)	X@rel
-#  endif
-# endif
-#else
-# define FDE_ENCODING		0	/* absolute */
-# define FDE_ENCODE(X)		X
-#endif
+#  define FFI_CLOSURE_CALL_INNER_SAVE_EBX
+#  undef FFI_CLOSURE_CALL_INNER
+#  define FFI_CLOSURE_CALL_INNER(UWN)					\
+	movl	%ebx, 40(%esp);			/* save ebx */		\
+L(C1(UW,UWN)):								\
+	# cfi_rel_offset(%ebx, 40);					\
+	call	C(__x86.get_pc_thunk.bx);	/* load got register */	\
+	addl	$C(_GLOBAL_OFFSET_TABLE_), %ebx;			\
+	call	ffi_closure_inner@PLT
+#  undef FFI_CLOSURE_MASK_AND_JUMP
+#  define FFI_CLOSURE_MASK_AND_JUMP(N, UWN)				\
+	andl	$X86_RET_TYPE_MASK, %eax;				\
+	leal	L(C1(load_table,N))@GOTOFF(%ebx, %eax, 8), %edx;	\
+	movl	40(%esp), %ebx;			/* restore ebx */	\
+L(C1(UW,UWN)):								\
+	# cfi_restore(%ebx);						\
+	movl	closure_CF(%esp), %eax;		/* optimiztic load */	\
+	jmp	*%edx
+# endif /* DARWIN || HIDDEN */
+#endif /* __PIC__ */
 
-	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
-.Lframe1:
-	.long	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
-.LSCIE1:
-	.long	0x0	/* CIE Identifier Tag */
-	.byte	0x1	/* CIE Version */
-#ifdef HAVE_AS_ASCII_PSEUDO_OP
-#ifdef __PIC__
-	.ascii "zR\0"	/* CIE Augmentation */
-#else
-	.ascii "\0"	/* CIE Augmentation */
-#endif
-#elif defined HAVE_AS_STRING_PSEUDO_OP
-#ifdef __PIC__
-	.string "zR"	/* CIE Augmentation */
-#else
-	.string ""	/* CIE Augmentation */
-#endif
-#else
-#error missing .ascii/.string
-#endif
-	.byte	0x1	/* .uleb128 0x1; CIE Code Alignment Factor */
-	.byte	0x7c	/* .sleb128 -4; CIE Data Alignment Factor */
-	.byte	0x8	/* CIE RA Column */
-#ifdef __PIC__
-	.byte	0x1	/* .uleb128 0x1; Augmentation size */
-	.byte	FDE_ENCODING
-#endif
-	.byte	0xc	/* DW_CFA_def_cfa */
-	.byte	0x4	/* .uleb128 0x4 */
-	.byte	0x4	/* .uleb128 0x4 */
-	.byte	0x88	/* DW_CFA_offset, column 0x8 */
-	.byte	0x1	/* .uleb128 0x1 */
-	.align 4
-.LECIE1:
-.LSFDE1:
-	.long	.LEFDE1-.LASFDE1	/* FDE Length */
-.LASFDE1:
-	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
-	.long	FDE_ENCODE(.LFB1)	/* FDE initial location */
-	.long	.LFE1-.LFB1		/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI0-.LFB1
-	.byte	0xe	/* DW_CFA_def_cfa_offset */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 */
-	.byte	0x2	/* .uleb128 0x2 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI1-.LCFI0
-	.byte	0xd	/* DW_CFA_def_cfa_register */
-	.byte	0x5	/* .uleb128 0x5 */
-	.align 4
-.LEFDE1:
-.LSFDE2:
-	.long	.LEFDE2-.LASFDE2	/* FDE Length */
-.LASFDE2:
-	.long	.LASFDE2-.Lframe1	/* FDE CIE offset */
-	.long	FDE_ENCODE(.LFB2)	/* FDE initial location */
-	.long	.LFE2-.LFB2		/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI2-.LFB2
-	.byte	0xe	/* DW_CFA_def_cfa_offset */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 */
-	.byte	0x2	/* .uleb128 0x2 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI3-.LCFI2
-	.byte	0xd	/* DW_CFA_def_cfa_register */
-	.byte	0x5	/* .uleb128 0x5 */
-#if !defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE && defined __PIC__
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI7-.LCFI3
-	.byte	0x83	/* DW_CFA_offset, column 0x3 */
-	.byte	0xa	/* .uleb128 0xa */
-#endif
-	.align 4
-.LEFDE2:
+	.balign	16
+	.globl	C(ffi_go_closure_EAX)
+	FFI_HIDDEN(C(ffi_go_closure_EAX))
+C(ffi_go_closure_EAX):
+L(UW6):
+	# cfi_startproc
+	subl	$closure_FS, %esp
+L(UW7):
+	# cfi_def_cfa_offset(closure_FS + 4)
+	FFI_CLOSURE_SAVE_REGS
+	movl	4(%eax), %edx			/* copy cif */
+	movl	8(%eax), %ecx			/* copy fun */
+	movl	%edx, closure_CF+28(%esp)
+	movl	%ecx, closure_CF+32(%esp)
+	movl	%eax, closure_CF+36(%esp)	/* closure is user_data */
+	jmp	L(do_closure_i386)
+L(UW8):
+	# cfi_endproc
+ENDF(C(ffi_go_closure_EAX))
+
+	.balign	16
+	.globl	C(ffi_go_closure_ECX)
+	FFI_HIDDEN(C(ffi_go_closure_ECX))
+C(ffi_go_closure_ECX):
+L(UW9):
+	# cfi_startproc
+	subl	$closure_FS, %esp
+L(UW10):
+	# cfi_def_cfa_offset(closure_FS + 4)
+	FFI_CLOSURE_SAVE_REGS
+	movl	4(%ecx), %edx			/* copy cif */
+	movl	8(%ecx), %eax			/* copy fun */
+	movl	%edx, closure_CF+28(%esp)
+	movl	%eax, closure_CF+32(%esp)
+	movl	%ecx, closure_CF+36(%esp)	/* closure is user_data */
+	jmp	L(do_closure_i386)
+L(UW11):
+	# cfi_endproc
+ENDF(C(ffi_go_closure_ECX))
+
+/* The closure entry points are reached from the ffi_closure trampoline.
+   On entry, %eax contains the address of the ffi_closure.  */
+
+	.balign	16
+	.globl	C(ffi_closure_i386)
+	FFI_HIDDEN(C(ffi_closure_i386))
+
+C(ffi_closure_i386):
+L(UW12):
+	# cfi_startproc
+	subl	$closure_FS, %esp
+L(UW13):
+	# cfi_def_cfa_offset(closure_FS + 4)
+
+	FFI_CLOSURE_SAVE_REGS
+	FFI_CLOSURE_COPY_TRAMP_DATA
+
+	/* Entry point from preceeding Go closures.  */
+L(do_closure_i386):
+
+	FFI_CLOSURE_PREP_CALL
+	FFI_CLOSURE_CALL_INNER(14)
+	FFI_CLOSURE_MASK_AND_JUMP(2, 15)
+
+	.balign	8
+L(load_table2):
+E(L(load_table2), X86_RET_FLOAT)
+	flds	closure_CF(%esp)
+	jmp	L(e2)
+E(L(load_table2), X86_RET_DOUBLE)
+	fldl	closure_CF(%esp)
+	jmp	L(e2)
+E(L(load_table2), X86_RET_LDOUBLE)
+	fldt	closure_CF(%esp)
+	jmp	L(e2)
+E(L(load_table2), X86_RET_SINT8)
+	movsbl	%al, %eax
+	jmp	L(e2)
+E(L(load_table2), X86_RET_SINT16)
+	movswl	%ax, %eax
+	jmp	L(e2)
+E(L(load_table2), X86_RET_UINT8)
+	movzbl	%al, %eax
+	jmp	L(e2)
+E(L(load_table2), X86_RET_UINT16)
+	movzwl	%ax, %eax
+	jmp	L(e2)
+E(L(load_table2), X86_RET_INT64)
+	movl	closure_CF+4(%esp), %edx
+	jmp	L(e2)
+E(L(load_table2), X86_RET_INT32)
+	nop
+	/* fallthru */
+E(L(load_table2), X86_RET_VOID)
+L(e2):
+	addl	$closure_FS, %esp
+L(UW16):
+	# cfi_adjust_cfa_offset(-closure_FS)
+	ret
+L(UW17):
+	# cfi_adjust_cfa_offset(closure_FS)
+E(L(load_table2), X86_RET_STRUCTPOP)
+	addl	$closure_FS, %esp
+L(UW18):
+	# cfi_adjust_cfa_offset(-closure_FS)
+	ret	$4
+L(UW19):
+	# cfi_adjust_cfa_offset(closure_FS)
+E(L(load_table2), X86_RET_STRUCTARG)
+	jmp	L(e2)
+E(L(load_table2), X86_RET_STRUCT_1B)
+	movzbl	%al, %eax
+	jmp	L(e2)
+E(L(load_table2), X86_RET_STRUCT_2B)
+	movzwl	%ax, %eax
+	jmp	L(e2)
+
+	/* Fill out the table so that bad values are predictable.  */
+E(L(load_table2), X86_RET_UNUSED14)
+	ud2
+E(L(load_table2), X86_RET_UNUSED15)
+	ud2
+
+L(UW20):
+	# cfi_endproc
+ENDF(C(ffi_closure_i386))
+
+	.balign	16
+	.globl	C(ffi_go_closure_STDCALL)
+	FFI_HIDDEN(C(ffi_go_closure_STDCALL))
+C(ffi_go_closure_STDCALL):
+L(UW21):
+	# cfi_startproc
+	subl	$closure_FS, %esp
+L(UW22):
+	# cfi_def_cfa_offset(closure_FS + 4)
+	FFI_CLOSURE_SAVE_REGS
+	movl	4(%ecx), %edx			/* copy cif */
+	movl	8(%ecx), %eax			/* copy fun */
+	movl	%edx, closure_CF+28(%esp)
+	movl	%eax, closure_CF+32(%esp)
+	movl	%ecx, closure_CF+36(%esp)	/* closure is user_data */
+	jmp	L(do_closure_STDCALL)
+L(UW23):
+	# cfi_endproc
+ENDF(C(ffi_go_closure_STDCALL))
+
+/* For REGISTER, we have no available parameter registers, and so we
+   enter here having pushed the closure onto the stack.  */
+
+	.balign	16
+	.globl	C(ffi_closure_REGISTER)
+	FFI_HIDDEN(C(ffi_closure_REGISTER))
+C(ffi_closure_REGISTER):
+L(UW24):
+	# cfi_startproc
+	# cfi_def_cfa(%esp, 8)
+	# cfi_offset(%eip, -8)
+	subl	$closure_FS-4, %esp
+L(UW25):
+	# cfi_def_cfa_offset(closure_FS + 4)
+	FFI_CLOSURE_SAVE_REGS
+	movl	closure_FS-4(%esp), %ecx	/* load retaddr */
+	movl	closure_FS(%esp), %eax		/* load closure */
+	movl	%ecx, closure_FS(%esp)		/* move retaddr */
+	jmp	L(do_closure_REGISTER)
+L(UW26):
+	# cfi_endproc
+ENDF(C(ffi_closure_REGISTER))
+
+/* For STDCALL (and others), we need to pop N bytes of arguments off
+   the stack following the closure.  The amount needing to be popped
+   is returned to us from ffi_closure_inner.  */
+
+	.balign	16
+	.globl	C(ffi_closure_STDCALL)
+	FFI_HIDDEN(C(ffi_closure_STDCALL))
+C(ffi_closure_STDCALL):
+L(UW27):
+	# cfi_startproc
+	subl	$closure_FS, %esp
+L(UW28):
+	# cfi_def_cfa_offset(closure_FS + 4)
+
+	FFI_CLOSURE_SAVE_REGS
+
+	/* Entry point from ffi_closure_REGISTER.  */
+L(do_closure_REGISTER):
+
+	FFI_CLOSURE_COPY_TRAMP_DATA
+
+	/* Entry point from preceeding Go closure.  */
+L(do_closure_STDCALL):
+
+	FFI_CLOSURE_PREP_CALL
+	FFI_CLOSURE_CALL_INNER(29)
+
+	movl	%eax, %ecx
+	shrl	$X86_RET_POP_SHIFT, %ecx	/* isolate pop count */
+	leal	closure_FS(%esp, %ecx), %ecx	/* compute popped esp */
+	movl	closure_FS(%esp), %edx		/* move return address */
+	movl	%edx, (%ecx)
+
+	/* From this point on, the value of %esp upon return is %ecx+4,
+	   and we've copied the return address to %ecx to make return easy.
+	   There's no point in representing this in the unwind info, as
+	   there is always a window between the mov and the ret which
+	   will be wrong from one point of view or another.  */
+
+	FFI_CLOSURE_MASK_AND_JUMP(3, 30)
+
+	.balign	8
+L(load_table3):
+E(L(load_table3), X86_RET_FLOAT)
+	flds    closure_CF(%esp)
+	movl    %ecx, %esp
+	ret
+E(L(load_table3), X86_RET_DOUBLE)
+	fldl    closure_CF(%esp)
+	movl    %ecx, %esp
+	ret
+E(L(load_table3), X86_RET_LDOUBLE)
+	fldt    closure_CF(%esp)
+	movl    %ecx, %esp
+	ret
+E(L(load_table3), X86_RET_SINT8)
+	movsbl  %al, %eax
+	movl    %ecx, %esp
+	ret
+E(L(load_table3), X86_RET_SINT16)
+	movswl  %ax, %eax
+	movl    %ecx, %esp
+	ret
+E(L(load_table3), X86_RET_UINT8)
+	movzbl  %al, %eax
+	movl    %ecx, %esp
+	ret
+E(L(load_table3), X86_RET_UINT16)
+	movzwl  %ax, %eax
+	movl    %ecx, %esp
+	ret
+E(L(load_table3), X86_RET_INT64)
+	movl	closure_CF+4(%esp), %edx
+	movl    %ecx, %esp
+	ret
+E(L(load_table3), X86_RET_INT32)
+	movl    %ecx, %esp
+	ret
+E(L(load_table3), X86_RET_VOID)
+	movl    %ecx, %esp
+	ret
+E(L(load_table3), X86_RET_STRUCTPOP)
+	movl    %ecx, %esp
+	ret
+E(L(load_table3), X86_RET_STRUCTARG)
+	movl	%ecx, %esp
+	ret
+E(L(load_table3), X86_RET_STRUCT_1B)
+	movzbl	%al, %eax
+	movl	%ecx, %esp
+	ret
+E(L(load_table3), X86_RET_STRUCT_2B)
+	movzwl	%ax, %eax
+	movl	%ecx, %esp
+	ret
+
+	/* Fill out the table so that bad values are predictable.  */
+E(L(load_table3), X86_RET_UNUSED14)
+	ud2
+E(L(load_table3), X86_RET_UNUSED15)
+	ud2
+
+L(UW31):
+	# cfi_endproc
+ENDF(C(ffi_closure_STDCALL))
 
 #if !FFI_NO_RAW_API
 
-.LSFDE3:
-	.long	.LEFDE3-.LASFDE3	/* FDE Length */
-.LASFDE3:
-	.long	.LASFDE3-.Lframe1	/* FDE CIE offset */
-	.long	FDE_ENCODE(.LFB3)	/* FDE initial location */
-	.long	.LFE3-.LFB3		/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI4-.LFB3
-	.byte	0xe	/* DW_CFA_def_cfa_offset */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 */
-	.byte	0x2	/* .uleb128 0x2 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI5-.LCFI4
-	.byte	0xd	/* DW_CFA_def_cfa_register */
-	.byte	0x5	/* .uleb128 0x5 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI6-.LCFI5
-	.byte	0x86	/* DW_CFA_offset, column 0x6 */
-	.byte	0x3	/* .uleb128 0x3 */
-	.align 4
-.LEFDE3:
+#define raw_closure_S_FS	(16+16+12)
 
+	.balign	16
+	.globl	C(ffi_closure_raw_SYSV)
+	FFI_HIDDEN(C(ffi_closure_raw_SYSV))
+C(ffi_closure_raw_SYSV):
+L(UW32):
+	# cfi_startproc
+	subl	$raw_closure_S_FS, %esp
+L(UW33):
+	# cfi_def_cfa_offset(raw_closure_S_FS + 4)
+	movl	%ebx, raw_closure_S_FS-4(%esp)
+L(UW34):
+	# cfi_rel_offset(%ebx, raw_closure_S_FS-4)
+
+	movl	FFI_TRAMPOLINE_SIZE+8(%eax), %edx	/* load cl->user_data */
+	movl	%edx, 12(%esp)
+	leal	raw_closure_S_FS+4(%esp), %edx		/* load raw_args */
+	movl	%edx, 8(%esp)
+	leal	16(%esp), %edx				/* load &res */
+	movl	%edx, 4(%esp)
+	movl	FFI_TRAMPOLINE_SIZE(%eax), %ebx		/* load cl->cif */
+	movl	%ebx, (%esp)
+	call	*FFI_TRAMPOLINE_SIZE+4(%eax)		/* call cl->fun */
+
+	movl	20(%ebx), %eax				/* load cif->flags */
+	andl	$X86_RET_TYPE_MASK, %eax
+#ifdef __PIC__
+	call	C(__x86.get_pc_thunk.bx)
+L(pc4):
+	leal	L(load_table4)-L(pc4)(%ebx, %eax, 8), %ecx
+#else
+	leal	L(load_table4)(,%eax, 8), %ecx
 #endif
+	movl	raw_closure_S_FS-4(%esp), %ebx
+L(UW35):
+	# cfi_restore(%ebx)
+	movl	16(%esp), %eax				/* Optimistic load */
+	jmp	*%ecx
+
+	.balign	8
+L(load_table4):
+E(L(load_table4), X86_RET_FLOAT)
+	flds	16(%esp)
+	jmp	L(e4)
+E(L(load_table4), X86_RET_DOUBLE)
+	fldl	16(%esp)
+	jmp	L(e4)
+E(L(load_table4), X86_RET_LDOUBLE)
+	fldt	16(%esp)
+	jmp	L(e4)
+E(L(load_table4), X86_RET_SINT8)
+	movsbl	%al, %eax
+	jmp	L(e4)
+E(L(load_table4), X86_RET_SINT16)
+	movswl	%ax, %eax
+	jmp	L(e4)
+E(L(load_table4), X86_RET_UINT8)
+	movzbl	%al, %eax
+	jmp	L(e4)
+E(L(load_table4), X86_RET_UINT16)
+	movzwl	%ax, %eax
+	jmp	L(e4)
+E(L(load_table4), X86_RET_INT64)
+	movl	16+4(%esp), %edx
+	jmp	L(e4)
+E(L(load_table4), X86_RET_INT32)
+	nop
+	/* fallthru */
+E(L(load_table4), X86_RET_VOID)
+L(e4):
+	addl	$raw_closure_S_FS, %esp
+L(UW36):
+	# cfi_adjust_cfa_offset(-raw_closure_S_FS)
+	ret
+L(UW37):
+	# cfi_adjust_cfa_offset(raw_closure_S_FS)
+E(L(load_table4), X86_RET_STRUCTPOP)
+	addl	$raw_closure_S_FS, %esp
+L(UW38):
+	# cfi_adjust_cfa_offset(-raw_closure_S_FS)
+	ret	$4
+L(UW39):
+	# cfi_adjust_cfa_offset(raw_closure_S_FS)
+E(L(load_table4), X86_RET_STRUCTARG)
+	jmp	L(e4)
+E(L(load_table4), X86_RET_STRUCT_1B)
+	movzbl	%al, %eax
+	jmp	L(e4)
+E(L(load_table4), X86_RET_STRUCT_2B)
+	movzwl	%ax, %eax
+	jmp	L(e4)
+
+	/* Fill out the table so that bad values are predictable.  */
+E(L(load_table4), X86_RET_UNUSED14)
+	ud2
+E(L(load_table4), X86_RET_UNUSED15)
+	ud2
+
+L(UW40):
+	# cfi_endproc
+ENDF(C(ffi_closure_raw_SYSV))
+
+#define raw_closure_T_FS	(16+16+8)
+
+	.balign	16
+	.globl	C(ffi_closure_raw_THISCALL)
+	FFI_HIDDEN(C(ffi_closure_raw_THISCALL))
+C(ffi_closure_raw_THISCALL):
+L(UW41):
+	# cfi_startproc
+	/* Rearrange the stack such that %ecx is the first argument.
+	   This means moving the return address.  */
+	popl	%edx
+L(UW42):
+	# cfi_def_cfa_offset(0)
+	# cfi_register(%eip, %edx)
+	pushl	%ecx
+L(UW43):
+	# cfi_adjust_cfa_offset(4)
+	pushl	%edx
+L(UW44):
+	# cfi_adjust_cfa_offset(4)
+	# cfi_rel_offset(%eip, 0)
+	subl	$raw_closure_T_FS, %esp
+L(UW45):
+	# cfi_adjust_cfa_offset(raw_closure_T_FS)
+	movl	%ebx, raw_closure_T_FS-4(%esp)
+L(UW46):
+	# cfi_rel_offset(%ebx, raw_closure_T_FS-4)
+
+	movl	FFI_TRAMPOLINE_SIZE+8(%eax), %edx	/* load cl->user_data */
+	movl	%edx, 12(%esp)
+	leal	raw_closure_T_FS+4(%esp), %edx		/* load raw_args */
+	movl	%edx, 8(%esp)
+	leal	16(%esp), %edx				/* load &res */
+	movl	%edx, 4(%esp)
+	movl	FFI_TRAMPOLINE_SIZE(%eax), %ebx		/* load cl->cif */
+	movl	%ebx, (%esp)
+	call	*FFI_TRAMPOLINE_SIZE+4(%eax)		/* call cl->fun */
+
+	movl	20(%ebx), %eax				/* load cif->flags */
+	andl	$X86_RET_TYPE_MASK, %eax
+#ifdef __PIC__
+	call	C(__x86.get_pc_thunk.bx)
+L(pc5):
+	leal	L(load_table5)-L(pc5)(%ebx, %eax, 8), %ecx
+#else
+	leal	L(load_table5)(,%eax, 8), %ecx
+#endif
+	movl	raw_closure_T_FS-4(%esp), %ebx
+L(UW47):
+	# cfi_restore(%ebx)
+	movl	16(%esp), %eax				/* Optimistic load */
+	jmp	*%ecx
+
+	.balign	8
+L(load_table5):
+E(L(load_table5), X86_RET_FLOAT)
+	flds	16(%esp)
+	jmp	L(e5)
+E(L(load_table5), X86_RET_DOUBLE)
+	fldl	16(%esp)
+	jmp	L(e5)
+E(L(load_table5), X86_RET_LDOUBLE)
+	fldt	16(%esp)
+	jmp	L(e5)
+E(L(load_table5), X86_RET_SINT8)
+	movsbl	%al, %eax
+	jmp	L(e5)
+E(L(load_table5), X86_RET_SINT16)
+	movswl	%ax, %eax
+	jmp	L(e5)
+E(L(load_table5), X86_RET_UINT8)
+	movzbl	%al, %eax
+	jmp	L(e5)
+E(L(load_table5), X86_RET_UINT16)
+	movzwl	%ax, %eax
+	jmp	L(e5)
+E(L(load_table5), X86_RET_INT64)
+	movl	16+4(%esp), %edx
+	jmp	L(e5)
+E(L(load_table5), X86_RET_INT32)
+	nop
+	/* fallthru */
+E(L(load_table5), X86_RET_VOID)
+L(e5):
+	addl	$raw_closure_T_FS, %esp
+L(UW48):
+	# cfi_adjust_cfa_offset(-raw_closure_T_FS)
+	/* Remove the extra %ecx argument we pushed.  */
+	ret	$4
+L(UW49):
+	# cfi_adjust_cfa_offset(raw_closure_T_FS)
+E(L(load_table5), X86_RET_STRUCTPOP)
+	addl	$raw_closure_T_FS, %esp
+L(UW50):
+	# cfi_adjust_cfa_offset(-raw_closure_T_FS)
+	ret	$8
+L(UW51):
+	# cfi_adjust_cfa_offset(raw_closure_T_FS)
+E(L(load_table5), X86_RET_STRUCTARG)
+	jmp	L(e5)
+E(L(load_table5), X86_RET_STRUCT_1B)
+	movzbl	%al, %eax
+	jmp	L(e5)
+E(L(load_table5), X86_RET_STRUCT_2B)
+	movzwl	%ax, %eax
+	jmp	L(e5)
+
+	/* Fill out the table so that bad values are predictable.  */
+E(L(load_table5), X86_RET_UNUSED14)
+	ud2
+E(L(load_table5), X86_RET_UNUSED15)
+	ud2
+
+L(UW52):
+	# cfi_endproc
+ENDF(C(ffi_closure_raw_THISCALL))
+
+#endif /* !FFI_NO_RAW_API */
+
+#ifdef X86_DARWIN
+# define COMDAT(X)							\
+        .section __TEXT,__textcoal_nt,coalesced,pure_instructions;	\
+        .weak_definition X;						\
+        .private_extern X
+#elif defined __ELF__
+# define COMDAT(X)							\
+	.section .text.X,"axG",@progbits,X,comdat;			\
+	.globl	X;							\
+	FFI_HIDDEN(X)
+#else
+# define COMDAT(X)
+#endif
+
+#if defined(__PIC__)
+	COMDAT(C(__x86.get_pc_thunk.bx))
+C(__x86.get_pc_thunk.bx):
+	movl	(%esp), %ebx
+	ret
+ENDF(C(__x86.get_pc_thunk.bx))
+# if defined X86_DARWIN || defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+	COMDAT(C(__x86.get_pc_thunk.dx))
+C(__x86.get_pc_thunk.dx):
+	movl	(%esp), %edx
+	ret
+ENDF(C(__x86.get_pc_thunk.dx))
+#endif /* DARWIN || HIDDEN */
+#endif /* __PIC__ */
+
+/* Sadly, OSX cctools-as doesn't understand .cfi directives at all.  */
+
+#ifdef __APPLE__
+.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EHFrame0:
+#elif defined(HAVE_AS_X86_64_UNWIND_SECTION_TYPE)
+.section .eh_frame,"a",@unwind
+#else
+.section .eh_frame,"a",@progbits
+#endif
+
+#ifdef HAVE_AS_X86_PCREL
+# define PCREL(X)	X - .
+#else
+# define PCREL(X)	X@rel
+#endif
+
+/* Simplify advancing between labels.  Assume DW_CFA_advance_loc1 fits.  */
+#define ADV(N, P)	.byte 2, L(N)-L(P)
+
+	.balign 4
+L(CIE):
+	.set	L(set0),L(ECIE)-L(SCIE)
+	.long	L(set0)			/* CIE Length */
+L(SCIE):
+	.long	0			/* CIE Identifier Tag */
+	.byte	1			/* CIE Version */
+	.ascii	"zR\0"			/* CIE Augmentation */
+	.byte	1			/* CIE Code Alignment Factor */
+	.byte	0x7c			/* CIE Data Alignment Factor */
+	.byte	0x8			/* CIE RA Column */
+	.byte	1			/* Augmentation size */
+	.byte	0x1b			/* FDE Encoding (pcrel sdata4) */
+	.byte	0xc, 4, 4		/* DW_CFA_def_cfa, %esp offset 4 */
+	.byte	0x80+8, 1		/* DW_CFA_offset, %eip offset 1*-4 */
+	.balign 4
+L(ECIE):
+
+	.set	L(set1),L(EFDE1)-L(SFDE1)
+	.long	L(set1)			/* FDE Length */
+L(SFDE1):
+	.long	L(SFDE1)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW0))		/* Initial location */
+	.long	L(UW5)-L(UW0)		/* Address range */
+	.byte	0			/* Augmentation size */
+	ADV(UW1, UW0)
+	.byte	0xc, 5, 8		/* DW_CFA_def_cfa, %ebp 8 */
+	.byte	0x80+5, 2		/* DW_CFA_offset, %ebp 2*-4 */
+	ADV(UW2, UW1)
+	.byte	0x80+3, 0		/* DW_CFA_offset, %ebx 0*-4 */
+	ADV(UW3, UW2)
+	.byte	0xa			/* DW_CFA_remember_state */
+	.byte	0xc, 4, 4		/* DW_CFA_def_cfa, %esp 4 */
+	.byte	0xc0+3			/* DW_CFA_restore, %ebx */
+	.byte	0xc0+5			/* DW_CFA_restore, %ebp */
+	ADV(UW4, UW3)
+	.byte	0xb			/* DW_CFA_restore_state */
+	.balign	4
+L(EFDE1):
+
+	.set	L(set2),L(EFDE2)-L(SFDE2)
+	.long	L(set2)			/* FDE Length */
+L(SFDE2):
+	.long	L(SFDE2)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW6))		/* Initial location */
+	.long	L(UW8)-L(UW6)		/* Address range */
+	.byte	0			/* Augmentation size */
+	ADV(UW7, UW6)
+	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
+	.balign	4
+L(EFDE2):
+
+	.set	L(set3),L(EFDE3)-L(SFDE3)
+	.long	L(set3)			/* FDE Length */
+L(SFDE3):
+	.long	L(SFDE3)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW9))		/* Initial location */
+	.long	L(UW11)-L(UW9)		/* Address range */
+	.byte	0			/* Augmentation size */
+	ADV(UW10, UW9)
+	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
+	.balign	4
+L(EFDE3):
+
+	.set	L(set4),L(EFDE4)-L(SFDE4)
+	.long	L(set4)			/* FDE Length */
+L(SFDE4):
+	.long	L(SFDE4)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW12))		/* Initial location */
+	.long	L(UW20)-L(UW12)		/* Address range */
+	.byte	0			/* Augmentation size */
+	ADV(UW13, UW12)
+	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
+#ifdef FFI_CLOSURE_CALL_INNER_SAVE_EBX
+	ADV(UW14, UW13)
+	.byte	0x80+3, (40-(closure_FS+4))/-4  /* DW_CFA_offset %ebx */
+	ADV(UW15, UW14)
+	.byte	0xc0+3			/* DW_CFA_restore %ebx */
+	ADV(UW16, UW15)
+#else
+	ADV(UW16, UW13)
+#endif
+	.byte	0xe, 4			/* DW_CFA_def_cfa_offset */
+	ADV(UW17, UW16)
+	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
+	ADV(UW18, UW17)
+	.byte	0xe, 4			/* DW_CFA_def_cfa_offset */
+	ADV(UW19, UW18)
+	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
+	.balign	4
+L(EFDE4):
+
+	.set	L(set5),L(EFDE5)-L(SFDE5)
+	.long	L(set5)			/* FDE Length */
+L(SFDE5):
+	.long	L(SFDE5)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW21))		/* Initial location */
+	.long	L(UW23)-L(UW21)		/* Address range */
+	.byte	0			/* Augmentation size */
+	ADV(UW22, UW21)
+	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
+	.balign	4
+L(EFDE5):
+
+	.set	L(set6),L(EFDE6)-L(SFDE6)
+	.long	L(set6)			/* FDE Length */
+L(SFDE6):
+	.long	L(SFDE6)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW24))		/* Initial location */
+	.long	L(UW26)-L(UW24)		/* Address range */
+	.byte	0			/* Augmentation size */
+	.byte	0xe, 8			/* DW_CFA_def_cfa_offset */
+	.byte	0x80+8, 2		/* DW_CFA_offset %eip, 2*-4 */
+	ADV(UW25, UW24)
+	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
+	.balign	4
+L(EFDE6):
+
+	.set	L(set7),L(EFDE7)-L(SFDE7)
+	.long	L(set7)			/* FDE Length */
+L(SFDE7):
+	.long	L(SFDE7)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW27))		/* Initial location */
+	.long	L(UW31)-L(UW27)		/* Address range */
+	.byte	0			/* Augmentation size */
+	ADV(UW28, UW27)
+	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
+#ifdef FFI_CLOSURE_CALL_INNER_SAVE_EBX
+	ADV(UW29, UW28)
+	.byte	0x80+3, (40-(closure_FS+4))/-4  /* DW_CFA_offset %ebx */
+	ADV(UW30, UW29)
+	.byte	0xc0+3			/* DW_CFA_restore %ebx */
+#endif
+	.balign	4
+L(EFDE7):
+
+#if !FFI_NO_RAW_API
+	.set	L(set8),L(EFDE8)-L(SFDE8)
+	.long	L(set8)			/* FDE Length */
+L(SFDE8):
+	.long	L(SFDE8)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW32))		/* Initial location */
+	.long	L(UW40)-L(UW32)		/* Address range */
+	.byte	0			/* Augmentation size */
+	ADV(UW33, UW32)
+	.byte	0xe, raw_closure_S_FS+4	/* DW_CFA_def_cfa_offset */
+	ADV(UW34, UW33)
+	.byte	0x80+3, 2		/* DW_CFA_offset %ebx 2*-4 */
+	ADV(UW35, UW34)
+	.byte	0xc0+3			/* DW_CFA_restore %ebx */
+	ADV(UW36, UW35)
+	.byte	0xe, 4			/* DW_CFA_def_cfa_offset */
+	ADV(UW37, UW36)
+	.byte	0xe, raw_closure_S_FS+4	/* DW_CFA_def_cfa_offset */
+	ADV(UW38, UW37)
+	.byte	0xe, 4			/* DW_CFA_def_cfa_offset */
+	ADV(UW39, UW38)
+	.byte	0xe, raw_closure_S_FS+4	/* DW_CFA_def_cfa_offset */
+	.balign	4
+L(EFDE8):
+
+	.set	L(set9),L(EFDE9)-L(SFDE9)
+	.long	L(set9)			/* FDE Length */
+L(SFDE9):
+	.long	L(SFDE9)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW41))		/* Initial location */
+	.long	L(UW52)-L(UW41)		/* Address range */
+	.byte	0			/* Augmentation size */
+	ADV(UW42, UW41)
+	.byte	0xe, 0			/* DW_CFA_def_cfa_offset */
+	.byte	0x9, 8, 2		/* DW_CFA_register %eip, %edx */
+	ADV(UW43, UW42)
+	.byte	0xe, 4			/* DW_CFA_def_cfa_offset */
+	ADV(UW44, UW43)
+	.byte	0xe, 8			/* DW_CFA_def_cfa_offset */
+	.byte	0x80+8, 2		/* DW_CFA_offset %eip 2*-4 */
+	ADV(UW45, UW44)
+	.byte	0xe, raw_closure_T_FS+8	/* DW_CFA_def_cfa_offset */
+	ADV(UW46, UW45)
+	.byte	0x80+3, 3		/* DW_CFA_offset %ebx 3*-4 */
+	ADV(UW47, UW46)
+	.byte	0xc0+3			/* DW_CFA_restore %ebx */
+	ADV(UW48, UW47)
+	.byte	0xe, 8			/* DW_CFA_def_cfa_offset */
+	ADV(UW49, UW48)
+	.byte	0xe, raw_closure_T_FS+8	/* DW_CFA_def_cfa_offset */
+	ADV(UW50, UW49)
+	.byte	0xe, 8			/* DW_CFA_def_cfa_offset */
+	ADV(UW51, UW50)
+	.byte	0xe, raw_closure_T_FS+8	/* DW_CFA_def_cfa_offset */
+	.balign	4
+L(EFDE9):
+#endif /* !FFI_NO_RAW_API */
 
 #endif /* ifndef __x86_64__ */
 
diff --git a/third_party/gofrontend/libffi/src/x86/unix64.S b/third_party/gofrontend/libffi/src/x86/unix64.S
index 7a6619a..f9f9163 100644
--- a/third_party/gofrontend/libffi/src/x86/unix64.S
+++ b/third_party/gofrontend/libffi/src/x86/unix64.S
@@ -1,6 +1,7 @@
 /* -----------------------------------------------------------------------
-   unix64.S - Copyright (c) 2002  Bo Thorsen <bo@suse.de>
-	      Copyright (c) 2008  Red Hat, Inc
+   unix64.S - Copyright (c) 2013  The Written Word, Inc.
+	    - Copyright (c) 2008  Red Hat, Inc
+	    - Copyright (c) 2002  Bo Thorsen <bo@suse.de>
 
    x86-64 Foreign Function Interface 
 
@@ -29,8 +30,41 @@
 #define LIBFFI_ASM	
 #include <fficonfig.h>
 #include <ffi.h>
+#include "internal64.h"
 
-.text
+	.text
+
+#define C2(X, Y)  X ## Y
+#define C1(X, Y)  C2(X, Y)
+#ifdef __USER_LABEL_PREFIX__
+# define C(X)     C1(__USER_LABEL_PREFIX__, X)
+#else
+# define C(X)     X
+#endif
+
+#ifdef __APPLE__
+# define L(X)     C1(L, X)
+#else
+# define L(X)     C1(.L, X)
+#endif
+
+#ifdef __ELF__
+# define PLT(X)	  X@PLT
+# define ENDF(X)  .type	X,@function; .size X, . - X
+#else
+# define PLT(X)	  X
+# define ENDF(X)
+#endif
+
+/* This macro allows the safe creation of jump tables without an
+   actual table.  The entry points into the table are all 8 bytes.
+   The use of ORG asserts that we're at the correct location.  */
+/* ??? The clang assembler doesn't handle .org with symbolic expressions.  */
+#if defined(__clang__) || defined(__APPLE__)
+# define E(BASE, X)	.balign 8
+#else
+# define E(BASE, X)	.balign 8; .org BASE + X * 8
+#endif
 
 /* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
 	            void *raddr, void (*fnaddr)(void));
@@ -39,12 +73,12 @@
    for this function.  This has been allocated by ffi_call.  We also
    deallocate some of the stack that has been alloca'd.  */
 
-	.align	2
-	.globl	ffi_call_unix64
-	.type	ffi_call_unix64,@function
+	.balign	8
+	.globl	C(ffi_call_unix64)
+	FFI_HIDDEN(C(ffi_call_unix64))
 
-ffi_call_unix64:
-.LUW0:
+C(ffi_call_unix64):
+L(UW0):
 	movq	(%rsp), %r10		/* Load return address.  */
 	leaq	(%rdi, %rsi), %rax	/* Find local stack base.  */
 	movq	%rdx, (%rax)		/* Save flags.  */
@@ -52,24 +86,37 @@
 	movq	%rbp, 16(%rax)		/* Save old frame pointer.  */
 	movq	%r10, 24(%rax)		/* Relocate return address.  */
 	movq	%rax, %rbp		/* Finalize local stack frame.  */
-.LUW1:
+
+	/* New stack frame based off rbp.  This is a itty bit of unwind
+	   trickery in that the CFA *has* changed.  There is no easy way
+	   to describe it correctly on entry to the function.  Fortunately,
+	   it doesn't matter too much since at all points we can correctly
+	   unwind back to ffi_call.  Note that the location to which we
+	   moved the return address is (the new) CFA-8, so from the
+	   perspective of the unwind info, it hasn't moved.  */
+L(UW1):
+	/* cfi_def_cfa(%rbp, 32) */
+	/* cfi_rel_offset(%rbp, 16) */
+
 	movq	%rdi, %r10		/* Save a copy of the register area. */
 	movq	%r8, %r11		/* Save a copy of the target fn.  */
 	movl	%r9d, %eax		/* Set number of SSE registers.  */
 
 	/* Load up all argument registers.  */
 	movq	(%r10), %rdi
-	movq	8(%r10), %rsi
-	movq	16(%r10), %rdx
-	movq	24(%r10), %rcx
-	movq	32(%r10), %r8
-	movq	40(%r10), %r9
+	movq	0x08(%r10), %rsi
+	movq	0x10(%r10), %rdx
+	movq	0x18(%r10), %rcx
+	movq	0x20(%r10), %r8
+	movq	0x28(%r10), %r9
+	movl	0xb0(%r10), %eax
 	testl	%eax, %eax
-	jnz	.Lload_sse
-.Lret_from_load_sse:
+	jnz	L(load_sse)
+L(ret_from_load_sse):
 
-	/* Deallocate the reg arg area.  */
-	leaq	176(%r10), %rsp
+	/* Deallocate the reg arg area, except for r10, then load via pop.  */
+	leaq	0xb8(%r10), %rsp
+	popq	%r10
 
 	/* Call the user function.  */
 	call	*%r11
@@ -80,347 +127,420 @@
 	movq	0(%rbp), %rcx		/* Reload flags.  */
 	movq	8(%rbp), %rdi		/* Reload raddr.  */
 	movq	16(%rbp), %rbp		/* Reload old frame pointer.  */
-.LUW2:
+L(UW2):
+	/* cfi_remember_state */
+	/* cfi_def_cfa(%rsp, 8) */
+	/* cfi_restore(%rbp) */
 
 	/* The first byte of the flags contains the FFI_TYPE.  */
+	cmpb	$UNIX64_RET_LAST, %cl
 	movzbl	%cl, %r10d
-	leaq	.Lstore_table(%rip), %r11
-	movslq	(%r11, %r10, 4), %r10
-	addq	%r11, %r10
+	leaq	L(store_table)(%rip), %r11
+	ja	L(sa)
+	leaq	(%r11, %r10, 8), %r10
+
+	/* Prep for the structure cases: scratch area in redzone.  */
+	leaq	-20(%rsp), %rsi
 	jmp	*%r10
 
-.Lstore_table:
-	.long	.Lst_void-.Lstore_table		/* FFI_TYPE_VOID */
-	.long	.Lst_sint32-.Lstore_table	/* FFI_TYPE_INT */
-	.long	.Lst_float-.Lstore_table	/* FFI_TYPE_FLOAT */
-	.long	.Lst_double-.Lstore_table	/* FFI_TYPE_DOUBLE */
-	.long	.Lst_ldouble-.Lstore_table	/* FFI_TYPE_LONGDOUBLE */
-	.long	.Lst_uint8-.Lstore_table	/* FFI_TYPE_UINT8 */
-	.long	.Lst_sint8-.Lstore_table	/* FFI_TYPE_SINT8 */
-	.long	.Lst_uint16-.Lstore_table	/* FFI_TYPE_UINT16 */
-	.long	.Lst_sint16-.Lstore_table	/* FFI_TYPE_SINT16 */
-	.long	.Lst_uint32-.Lstore_table	/* FFI_TYPE_UINT32 */
-	.long	.Lst_sint32-.Lstore_table	/* FFI_TYPE_SINT32 */
-	.long	.Lst_int64-.Lstore_table	/* FFI_TYPE_UINT64 */
-	.long	.Lst_int64-.Lstore_table	/* FFI_TYPE_SINT64 */
-	.long	.Lst_struct-.Lstore_table	/* FFI_TYPE_STRUCT */
-	.long	.Lst_int64-.Lstore_table	/* FFI_TYPE_POINTER */
-
-	.align 2
-.Lst_void:
+	.balign	8
+L(store_table):
+E(L(store_table), UNIX64_RET_VOID)
 	ret
-	.align 2
-
-.Lst_uint8:
-	movzbq	%al, %rax
+E(L(store_table), UNIX64_RET_UINT8)
+	movzbl	%al, %eax
 	movq	%rax, (%rdi)
 	ret
-	.align 2
-.Lst_sint8:
+E(L(store_table), UNIX64_RET_UINT16)
+	movzwl	%ax, %eax
+	movq	%rax, (%rdi)
+	ret
+E(L(store_table), UNIX64_RET_UINT32)
+	movl	%eax, %eax
+	movq	%rax, (%rdi)
+	ret
+E(L(store_table), UNIX64_RET_SINT8)
 	movsbq	%al, %rax
 	movq	%rax, (%rdi)
 	ret
-	.align 2
-.Lst_uint16:
-	movzwq	%ax, %rax
-	movq	%rax, (%rdi)
-	.align 2
-.Lst_sint16:
+E(L(store_table), UNIX64_RET_SINT16)
 	movswq	%ax, %rax
 	movq	%rax, (%rdi)
 	ret
-	.align 2
-.Lst_uint32:
-	movl	%eax, %eax
-	movq	%rax, (%rdi)
-	.align 2
-.Lst_sint32:
+E(L(store_table), UNIX64_RET_SINT32)
 	cltq
 	movq	%rax, (%rdi)
 	ret
-	.align 2
-.Lst_int64:
+E(L(store_table), UNIX64_RET_INT64)
 	movq	%rax, (%rdi)
 	ret
-
-	.align 2
-.Lst_float:
-	movss	%xmm0, (%rdi)
+E(L(store_table), UNIX64_RET_XMM32)
+	movd	%xmm0, (%rdi)
 	ret
-	.align 2
-.Lst_double:
-	movsd	%xmm0, (%rdi)
+E(L(store_table), UNIX64_RET_XMM64)
+	movq	%xmm0, (%rdi)
 	ret
-.Lst_ldouble:
+E(L(store_table), UNIX64_RET_X87)
 	fstpt	(%rdi)
 	ret
-
-	.align 2
-.Lst_struct:
-	leaq	-20(%rsp), %rsi		/* Scratch area in redzone.  */
-
-	/* We have to locate the values now, and since we don't want to
-	   write too much data into the user's return value, we spill the
-	   value to a 16 byte scratch area first.  Bits 8, 9, and 10
-	   control where the values are located.  Only one of the three
-	   bits will be set; see ffi_prep_cif_machdep for the pattern.  */
-	movd	%xmm0, %r10
-	movd	%xmm1, %r11
-	testl	$0x100, %ecx
-	cmovnz	%rax, %rdx
-	cmovnz	%r10, %rax
-	testl	$0x200, %ecx
-	cmovnz	%r10, %rdx
-	testl	$0x400, %ecx
-	cmovnz	%r10, %rax
-	cmovnz	%r11, %rdx
-	movq	%rax, (%rsi)
+E(L(store_table), UNIX64_RET_X87_2)
+	fstpt	(%rdi)
+	fstpt	16(%rdi)
+	ret
+E(L(store_table), UNIX64_RET_ST_XMM0_RAX)
+	movq	%rax, 8(%rsi)
+	jmp	L(s3)
+E(L(store_table), UNIX64_RET_ST_RAX_XMM0)
+	movq	%xmm0, 8(%rsi)
+	jmp	L(s2)
+E(L(store_table), UNIX64_RET_ST_XMM0_XMM1)
+	movq	%xmm1, 8(%rsi)
+	jmp	L(s3)
+E(L(store_table), UNIX64_RET_ST_RAX_RDX)
 	movq	%rdx, 8(%rsi)
-
-	/* Bits 12-31 contain the true size of the structure.  Copy from
-	   the scratch area to the true destination.  */
-	shrl	$12, %ecx
+L(s2):
+	movq	%rax, (%rsi)
+	shrl	$UNIX64_SIZE_SHIFT, %ecx
 	rep movsb
 	ret
+	.balign 8
+L(s3):
+	movq	%xmm0, (%rsi)
+	shrl	$UNIX64_SIZE_SHIFT, %ecx
+	rep movsb
+	ret
+
+L(sa):	call	PLT(C(abort))
 
 	/* Many times we can avoid loading any SSE registers at all.
 	   It's not worth an indirect jump to load the exact set of
 	   SSE registers needed; zero or all is a good compromise.  */
-	.align 2
-.LUW3:
-.Lload_sse:
-	movdqa	48(%r10), %xmm0
-	movdqa	64(%r10), %xmm1
-	movdqa	80(%r10), %xmm2
-	movdqa	96(%r10), %xmm3
-	movdqa	112(%r10), %xmm4
-	movdqa	128(%r10), %xmm5
-	movdqa	144(%r10), %xmm6
-	movdqa	160(%r10), %xmm7
-	jmp	.Lret_from_load_sse
+	.balign 2
+L(UW3):
+	/* cfi_restore_state */
+L(load_sse):
+	movdqa	0x30(%r10), %xmm0
+	movdqa	0x40(%r10), %xmm1
+	movdqa	0x50(%r10), %xmm2
+	movdqa	0x60(%r10), %xmm3
+	movdqa	0x70(%r10), %xmm4
+	movdqa	0x80(%r10), %xmm5
+	movdqa	0x90(%r10), %xmm6
+	movdqa	0xa0(%r10), %xmm7
+	jmp	L(ret_from_load_sse)
 
-.LUW4:
-	.size    ffi_call_unix64,.-ffi_call_unix64
+L(UW4):
+ENDF(C(ffi_call_unix64))
 
-	.align	2
-	.globl ffi_closure_unix64
-	.type	ffi_closure_unix64,@function
+/* 6 general registers, 8 vector registers,
+   32 bytes of rvalue, 8 bytes of alignment.  */
+#define ffi_closure_OFS_G	0
+#define ffi_closure_OFS_V	(6*8)
+#define ffi_closure_OFS_RVALUE	(ffi_closure_OFS_V + 8*16)
+#define ffi_closure_FS		(ffi_closure_OFS_RVALUE + 32 + 8)
 
-ffi_closure_unix64:
-.LUW5:
-	/* The carry flag is set by the trampoline iff SSE registers
-	   are used.  Don't clobber it before the branch instruction.  */
-	leaq    -200(%rsp), %rsp
-.LUW6:
-	movq	%rdi, (%rsp)
-	movq    %rsi, 8(%rsp)
-	movq    %rdx, 16(%rsp)
-	movq    %rcx, 24(%rsp)
-	movq    %r8, 32(%rsp)
-	movq    %r9, 40(%rsp)
-	jc      .Lsave_sse
-.Lret_from_save_sse:
+/* The location of rvalue within the red zone after deallocating the frame.  */
+#define ffi_closure_RED_RVALUE	(ffi_closure_OFS_RVALUE - ffi_closure_FS)
 
-	movq	%r10, %rdi
-	leaq	176(%rsp), %rsi
-	movq	%rsp, %rdx
-	leaq	208(%rsp), %rcx
-	call	ffi_closure_unix64_inner@PLT
+	.balign	2
+	.globl	C(ffi_closure_unix64_sse)
+	FFI_HIDDEN(C(ffi_closure_unix64_sse))
+
+C(ffi_closure_unix64_sse):
+L(UW5):
+	subq	$ffi_closure_FS, %rsp
+L(UW6):
+	/* cfi_adjust_cfa_offset(ffi_closure_FS) */
+
+	movdqa	%xmm0, ffi_closure_OFS_V+0x00(%rsp)
+	movdqa	%xmm1, ffi_closure_OFS_V+0x10(%rsp)
+	movdqa	%xmm2, ffi_closure_OFS_V+0x20(%rsp)
+	movdqa	%xmm3, ffi_closure_OFS_V+0x30(%rsp)
+	movdqa	%xmm4, ffi_closure_OFS_V+0x40(%rsp)
+	movdqa	%xmm5, ffi_closure_OFS_V+0x50(%rsp)
+	movdqa	%xmm6, ffi_closure_OFS_V+0x60(%rsp)
+	movdqa	%xmm7, ffi_closure_OFS_V+0x70(%rsp)
+	jmp	L(sse_entry1)
+
+L(UW7):
+ENDF(C(ffi_closure_unix64_sse))
+
+	.balign	2
+	.globl	C(ffi_closure_unix64)
+	FFI_HIDDEN(C(ffi_closure_unix64))
+
+C(ffi_closure_unix64):
+L(UW8):
+	subq	$ffi_closure_FS, %rsp
+L(UW9):
+	/* cfi_adjust_cfa_offset(ffi_closure_FS) */
+L(sse_entry1):
+	movq	%rdi, ffi_closure_OFS_G+0x00(%rsp)
+	movq    %rsi, ffi_closure_OFS_G+0x08(%rsp)
+	movq    %rdx, ffi_closure_OFS_G+0x10(%rsp)
+	movq    %rcx, ffi_closure_OFS_G+0x18(%rsp)
+	movq    %r8,  ffi_closure_OFS_G+0x20(%rsp)
+	movq    %r9,  ffi_closure_OFS_G+0x28(%rsp)
+
+#ifdef __ILP32__
+	movl	FFI_TRAMPOLINE_SIZE(%r10), %edi		/* Load cif */
+	movl	FFI_TRAMPOLINE_SIZE+4(%r10), %esi	/* Load fun */
+	movl	FFI_TRAMPOLINE_SIZE+8(%r10), %edx	/* Load user_data */
+#else
+	movq	FFI_TRAMPOLINE_SIZE(%r10), %rdi		/* Load cif */
+	movq	FFI_TRAMPOLINE_SIZE+8(%r10), %rsi	/* Load fun */
+	movq	FFI_TRAMPOLINE_SIZE+16(%r10), %rdx	/* Load user_data */
+#endif
+L(do_closure):
+	leaq	ffi_closure_OFS_RVALUE(%rsp), %rcx	/* Load rvalue */
+	movq	%rsp, %r8				/* Load reg_args */
+	leaq	ffi_closure_FS+8(%rsp), %r9		/* Load argp */
+	call	C(ffi_closure_unix64_inner)
 
 	/* Deallocate stack frame early; return value is now in redzone.  */
-	addq	$200, %rsp
-.LUW7:
+	addq	$ffi_closure_FS, %rsp
+L(UW10):
+	/* cfi_adjust_cfa_offset(-ffi_closure_FS) */
 
 	/* The first byte of the return value contains the FFI_TYPE.  */
+	cmpb	$UNIX64_RET_LAST, %al
 	movzbl	%al, %r10d
-	leaq	.Lload_table(%rip), %r11
-	movslq	(%r11, %r10, 4), %r10
-	addq	%r11, %r10
+	leaq	L(load_table)(%rip), %r11
+	ja	L(la)
+	leaq	(%r11, %r10, 8), %r10
+	leaq	ffi_closure_RED_RVALUE(%rsp), %rsi
 	jmp	*%r10
 
-.Lload_table:
-	.long	.Lld_void-.Lload_table		/* FFI_TYPE_VOID */
-	.long	.Lld_int32-.Lload_table		/* FFI_TYPE_INT */
-	.long	.Lld_float-.Lload_table		/* FFI_TYPE_FLOAT */
-	.long	.Lld_double-.Lload_table	/* FFI_TYPE_DOUBLE */
-	.long	.Lld_ldouble-.Lload_table	/* FFI_TYPE_LONGDOUBLE */
-	.long	.Lld_int8-.Lload_table		/* FFI_TYPE_UINT8 */
-	.long	.Lld_int8-.Lload_table		/* FFI_TYPE_SINT8 */
-	.long	.Lld_int16-.Lload_table		/* FFI_TYPE_UINT16 */
-	.long	.Lld_int16-.Lload_table		/* FFI_TYPE_SINT16 */
-	.long	.Lld_int32-.Lload_table		/* FFI_TYPE_UINT32 */
-	.long	.Lld_int32-.Lload_table		/* FFI_TYPE_SINT32 */
-	.long	.Lld_int64-.Lload_table		/* FFI_TYPE_UINT64 */
-	.long	.Lld_int64-.Lload_table		/* FFI_TYPE_SINT64 */
-	.long	.Lld_struct-.Lload_table	/* FFI_TYPE_STRUCT */
-	.long	.Lld_int64-.Lload_table		/* FFI_TYPE_POINTER */
-
-	.align 2
-.Lld_void:
+	.balign	8
+L(load_table):
+E(L(load_table), UNIX64_RET_VOID)
+	ret
+E(L(load_table), UNIX64_RET_UINT8)
+	movzbl	(%rsi), %eax
+	ret
+E(L(load_table), UNIX64_RET_UINT16)
+	movzwl	(%rsi), %eax
+	ret
+E(L(load_table), UNIX64_RET_UINT32)
+	movl	(%rsi), %eax
+	ret
+E(L(load_table), UNIX64_RET_SINT8)
+	movsbl	(%rsi), %eax
+	ret
+E(L(load_table), UNIX64_RET_SINT16)
+	movswl	(%rsi), %eax
+	ret
+E(L(load_table), UNIX64_RET_SINT32)
+	movl	(%rsi), %eax
+	ret
+E(L(load_table), UNIX64_RET_INT64)
+	movq	(%rsi), %rax
+	ret
+E(L(load_table), UNIX64_RET_XMM32)
+	movd	(%rsi), %xmm0
+	ret
+E(L(load_table), UNIX64_RET_XMM64)
+	movq	(%rsi), %xmm0
+	ret
+E(L(load_table), UNIX64_RET_X87)
+	fldt	(%rsi)
+	ret
+E(L(load_table), UNIX64_RET_X87_2)
+	fldt	16(%rsi)
+	fldt	(%rsi)
+	ret
+E(L(load_table), UNIX64_RET_ST_XMM0_RAX)
+	movq	8(%rsi), %rax
+	jmp	L(l3)
+E(L(load_table), UNIX64_RET_ST_RAX_XMM0)
+	movq	8(%rsi), %xmm0
+	jmp	L(l2)
+E(L(load_table), UNIX64_RET_ST_XMM0_XMM1)
+	movq	8(%rsi), %xmm1
+	jmp	L(l3)
+E(L(load_table), UNIX64_RET_ST_RAX_RDX)
+	movq	8(%rsi), %rdx
+L(l2):
+	movq	(%rsi), %rax
+	ret
+	.balign	8
+L(l3):
+	movq	(%rsi), %xmm0
 	ret
 
-	.align 2
-.Lld_int8:
-	movzbl	-24(%rsp), %eax
-	ret
-	.align 2
-.Lld_int16:
-	movzwl	-24(%rsp), %eax
-	ret
-	.align 2
-.Lld_int32:
-	movl	-24(%rsp), %eax
-	ret
-	.align 2
-.Lld_int64:
-	movq	-24(%rsp), %rax
-	ret
+L(la):	call	PLT(C(abort))
 
-	.align 2
-.Lld_float:
-	movss	-24(%rsp), %xmm0
-	ret
-	.align 2
-.Lld_double:
-	movsd	-24(%rsp), %xmm0
-	ret
-	.align 2
-.Lld_ldouble:
-	fldt	-24(%rsp)
-	ret
+L(UW11):
+ENDF(C(ffi_closure_unix64))
 
-	.align 2
-.Lld_struct:
-	/* There are four possibilities here, %rax/%rdx, %xmm0/%rax,
-	   %rax/%xmm0, %xmm0/%xmm1.  We collapse two by always loading
-	   both rdx and xmm1 with the second word.  For the remaining,
-	   bit 8 set means xmm0 gets the second word, and bit 9 means
-	   that rax gets the second word.  */
-	movq	-24(%rsp), %rcx
-	movq	-16(%rsp), %rdx
-	movq	-16(%rsp), %xmm1
-	testl	$0x100, %eax
-	cmovnz	%rdx, %rcx
-	movd	%rcx, %xmm0
-	testl	$0x200, %eax
-	movq	-24(%rsp), %rax
-	cmovnz	%rdx, %rax
-	ret
+	.balign	2
+	.globl	C(ffi_go_closure_unix64_sse)
+	FFI_HIDDEN(C(ffi_go_closure_unix64_sse))
 
-	/* See the comment above .Lload_sse; the same logic applies here.  */
-	.align 2
-.LUW8:
-.Lsave_sse:
-	movdqa	%xmm0, 48(%rsp)
-	movdqa	%xmm1, 64(%rsp)
-	movdqa	%xmm2, 80(%rsp)
-	movdqa	%xmm3, 96(%rsp)
-	movdqa	%xmm4, 112(%rsp)
-	movdqa	%xmm5, 128(%rsp)
-	movdqa	%xmm6, 144(%rsp)
-	movdqa	%xmm7, 160(%rsp)
-	jmp	.Lret_from_save_sse
+C(ffi_go_closure_unix64_sse):
+L(UW12):
+	subq	$ffi_closure_FS, %rsp
+L(UW13):
+	/* cfi_adjust_cfa_offset(ffi_closure_FS) */
 
-.LUW9:
-	.size	ffi_closure_unix64,.-ffi_closure_unix64
+	movdqa	%xmm0, ffi_closure_OFS_V+0x00(%rsp)
+	movdqa	%xmm1, ffi_closure_OFS_V+0x10(%rsp)
+	movdqa	%xmm2, ffi_closure_OFS_V+0x20(%rsp)
+	movdqa	%xmm3, ffi_closure_OFS_V+0x30(%rsp)
+	movdqa	%xmm4, ffi_closure_OFS_V+0x40(%rsp)
+	movdqa	%xmm5, ffi_closure_OFS_V+0x50(%rsp)
+	movdqa	%xmm6, ffi_closure_OFS_V+0x60(%rsp)
+	movdqa	%xmm7, ffi_closure_OFS_V+0x70(%rsp)
+	jmp	L(sse_entry2)
 
-#ifdef HAVE_AS_X86_64_UNWIND_SECTION_TYPE
-	.section	.eh_frame,"a",@unwind
+L(UW14):
+ENDF(C(ffi_go_closure_unix64_sse))
+
+	.balign	2
+	.globl	C(ffi_go_closure_unix64)
+	FFI_HIDDEN(C(ffi_go_closure_unix64))
+
+C(ffi_go_closure_unix64):
+L(UW15):
+	subq	$ffi_closure_FS, %rsp
+L(UW16):
+	/* cfi_adjust_cfa_offset(ffi_closure_FS) */
+L(sse_entry2):
+	movq	%rdi, ffi_closure_OFS_G+0x00(%rsp)
+	movq    %rsi, ffi_closure_OFS_G+0x08(%rsp)
+	movq    %rdx, ffi_closure_OFS_G+0x10(%rsp)
+	movq    %rcx, ffi_closure_OFS_G+0x18(%rsp)
+	movq    %r8,  ffi_closure_OFS_G+0x20(%rsp)
+	movq    %r9,  ffi_closure_OFS_G+0x28(%rsp)
+
+#ifdef __ILP32__
+	movl	4(%r10), %edi		/* Load cif */
+	movl	8(%r10), %esi		/* Load fun */
+	movl	%r10d, %edx		/* Load closure (user_data) */
 #else
-	.section	.eh_frame,"a",@progbits
+	movq	8(%r10), %rdi		/* Load cif */
+	movq	16(%r10), %rsi		/* Load fun */
+	movq	%r10, %rdx		/* Load closure (user_data) */
 #endif
-.Lframe1:
-	.long	.LECIE1-.LSCIE1		/* CIE Length */
-.LSCIE1:
+	jmp	L(do_closure)
+
+L(UW17):
+ENDF(C(ffi_go_closure_unix64))
+
+/* Sadly, OSX cctools-as doesn't understand .cfi directives at all.  */
+
+#ifdef __APPLE__
+.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EHFrame0:
+#elif defined(HAVE_AS_X86_64_UNWIND_SECTION_TYPE)
+.section .eh_frame,"a",@unwind
+#else
+.section .eh_frame,"a",@progbits
+#endif
+
+#ifdef HAVE_AS_X86_PCREL
+# define PCREL(X)	X - .
+#else
+# define PCREL(X)	X@rel
+#endif
+
+/* Simplify advancing between labels.  Assume DW_CFA_advance_loc1 fits.  */
+#define ADV(N, P)	.byte 2, L(N)-L(P)
+
+	.balign 8
+L(CIE):
+	.set	L(set0),L(ECIE)-L(SCIE)
+	.long	L(set0)			/* CIE Length */
+L(SCIE):
 	.long	0			/* CIE Identifier Tag */
 	.byte	1			/* CIE Version */
-	.ascii "zR\0"			/* CIE Augmentation */
-	.uleb128 1			/* CIE Code Alignment Factor */
-	.sleb128 -8			/* CIE Data Alignment Factor */
+	.ascii	"zR\0"			/* CIE Augmentation */
+	.byte	1			/* CIE Code Alignment Factor */
+	.byte	0x78			/* CIE Data Alignment Factor */
 	.byte	0x10			/* CIE RA Column */
-	.uleb128 1			/* Augmentation size */
+	.byte	1			/* Augmentation size */
 	.byte	0x1b			/* FDE Encoding (pcrel sdata4) */
-	.byte	0xc			/* DW_CFA_def_cfa, %rsp offset 8 */
-	.uleb128 7
-	.uleb128 8
-	.byte	0x80+16			/* DW_CFA_offset, %rip offset 1*-8 */
-	.uleb128 1
-	.align 8
-.LECIE1:
-.LSFDE1:
-	.long	.LEFDE1-.LASFDE1	/* FDE Length */
-.LASFDE1:
-	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
-#if HAVE_AS_X86_PCREL
-	.long	.LUW0-.			/* FDE initial location */
-#else
-	.long	.LUW0@rel
-#endif
-	.long	.LUW4-.LUW0		/* FDE address range */
-	.uleb128 0x0			/* Augmentation size */
+	.byte	0xc, 7, 8		/* DW_CFA_def_cfa, %rsp offset 8 */
+	.byte	0x80+16, 1		/* DW_CFA_offset, %rip offset 1*-8 */
+	.balign 8
+L(ECIE):
 
-	.byte	0x4			/* DW_CFA_advance_loc4 */
-	.long	.LUW1-.LUW0
-
-	/* New stack frame based off rbp.  This is a itty bit of unwind
-	   trickery in that the CFA *has* changed.  There is no easy way
-	   to describe it correctly on entry to the function.  Fortunately,
-	   it doesn't matter too much since at all points we can correctly
-	   unwind back to ffi_call.  Note that the location to which we
-	   moved the return address is (the new) CFA-8, so from the
-	   perspective of the unwind info, it hasn't moved.  */
-	.byte	0xc			/* DW_CFA_def_cfa, %rbp offset 32 */
-	.uleb128 6
-	.uleb128 32
-	.byte	0x80+6			/* DW_CFA_offset, %rbp offset 2*-8 */
-	.uleb128 2
+	.set	L(set1),L(EFDE1)-L(SFDE1)
+	.long	L(set1)			/* FDE Length */
+L(SFDE1):
+	.long	L(SFDE1)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW0))		/* Initial location */
+	.long	L(UW4)-L(UW0)		/* Address range */
+	.byte	0			/* Augmentation size */
+	ADV(UW1, UW0)
+	.byte	0xc, 6, 32		/* DW_CFA_def_cfa, %rbp 32 */
+	.byte	0x80+6, 2		/* DW_CFA_offset, %rbp 2*-8 */
+	ADV(UW2, UW1)
 	.byte	0xa			/* DW_CFA_remember_state */
-
-	.byte	0x4			/* DW_CFA_advance_loc4 */
-	.long	.LUW2-.LUW1
-	.byte	0xc			/* DW_CFA_def_cfa, %rsp offset 8 */
-	.uleb128 7
-	.uleb128 8
+	.byte	0xc, 7, 8		/* DW_CFA_def_cfa, %rsp 8 */
 	.byte	0xc0+6			/* DW_CFA_restore, %rbp */
-
-	.byte	0x4			/* DW_CFA_advance_loc4 */
-	.long	.LUW3-.LUW2
+	ADV(UW3, UW2)
 	.byte	0xb			/* DW_CFA_restore_state */
+	.balign	8
+L(EFDE1):
 
-	.align 8
-.LEFDE1:
-.LSFDE3:
-	.long	.LEFDE3-.LASFDE3	/* FDE Length */
-.LASFDE3:
-	.long	.LASFDE3-.Lframe1	/* FDE CIE offset */
-#if HAVE_AS_X86_PCREL
-	.long	.LUW5-.			/* FDE initial location */
-#else
-	.long	.LUW5@rel
+	.set	L(set2),L(EFDE2)-L(SFDE2)
+	.long	L(set2)			/* FDE Length */
+L(SFDE2):
+	.long	L(SFDE2)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW5))		/* Initial location */
+	.long	L(UW7)-L(UW5)		/* Address range */
+	.byte	0			/* Augmentation size */
+	ADV(UW6, UW5)
+	.byte	0xe			/* DW_CFA_def_cfa_offset */
+	.byte	ffi_closure_FS + 8, 1	/* uleb128, assuming 128 <= FS < 255 */
+	.balign	8
+L(EFDE2):
+
+	.set	L(set3),L(EFDE3)-L(SFDE3)
+	.long	L(set3)			/* FDE Length */
+L(SFDE3):
+	.long	L(SFDE3)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW8))		/* Initial location */
+	.long	L(UW11)-L(UW8)		/* Address range */
+	.byte	0			/* Augmentation size */
+	ADV(UW9, UW8)
+	.byte	0xe			/* DW_CFA_def_cfa_offset */
+	.byte	ffi_closure_FS + 8, 1	/* uleb128, assuming 128 <= FS < 255 */
+	ADV(UW10, UW9)
+	.byte	0xe, 8			/* DW_CFA_def_cfa_offset 8 */
+L(EFDE3):
+
+	.set	L(set4),L(EFDE4)-L(SFDE4)
+	.long	L(set4)			/* FDE Length */
+L(SFDE4):
+	.long	L(SFDE4)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW12))		/* Initial location */
+	.long	L(UW14)-L(UW12)		/* Address range */
+	.byte	0			/* Augmentation size */
+	ADV(UW13, UW12)
+	.byte	0xe			/* DW_CFA_def_cfa_offset */
+	.byte	ffi_closure_FS + 8, 1	/* uleb128, assuming 128 <= FS < 255 */
+	.balign	8
+L(EFDE4):
+
+	.set	L(set5),L(EFDE5)-L(SFDE5)
+	.long	L(set5)			/* FDE Length */
+L(SFDE5):
+	.long	L(SFDE5)-L(CIE)		/* FDE CIE offset */
+	.long	PCREL(L(UW15))		/* Initial location */
+	.long	L(UW17)-L(UW15)		/* Address range */
+	.byte	0			/* Augmentation size */
+	ADV(UW16, UW15)
+	.byte	0xe			/* DW_CFA_def_cfa_offset */
+	.byte	ffi_closure_FS + 8, 1	/* uleb128, assuming 128 <= FS < 255 */
+	.balign	8
+L(EFDE5):
+#ifdef __APPLE__
+	.subsections_via_symbols
 #endif
-	.long	.LUW9-.LUW5		/* FDE address range */
-	.uleb128 0x0			/* Augmentation size */
-
-	.byte	0x4			/* DW_CFA_advance_loc4 */
-	.long	.LUW6-.LUW5
-	.byte	0xe			/* DW_CFA_def_cfa_offset */
-	.uleb128 208
-	.byte	0xa			/* DW_CFA_remember_state */
-
-	.byte	0x4			/* DW_CFA_advance_loc4 */
-	.long	.LUW7-.LUW6
-	.byte	0xe			/* DW_CFA_def_cfa_offset */
-	.uleb128 8
-
-	.byte	0x4			/* DW_CFA_advance_loc4 */
-	.long	.LUW8-.LUW7
-	.byte	0xb			/* DW_CFA_restore_state */
-
-	.align 8
-.LEFDE3:
 
 #endif /* __x86_64__ */
-
 #if defined __ELF__ && defined __linux__
 	.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/third_party/gofrontend/libffi/src/x86/win32.S b/third_party/gofrontend/libffi/src/x86/win32.S
deleted file mode 100644
index 24b7bbd..0000000
--- a/third_party/gofrontend/libffi/src/x86/win32.S
+++ /dev/null
@@ -1,1201 +0,0 @@
-/* -----------------------------------------------------------------------
-   win32.S - Copyright (c) 1996, 1998, 2001, 2002, 2009  Red Hat, Inc.
-	     Copyright (c) 2001  John Beniton
-	     Copyright (c) 2002  Ranjit Mathew
-	     Copyright (c) 2009  Daniel Witte
-			
- 
-   X86 Foreign Function Interface
- 
-   Permission is hereby granted, free of charge, to any person obtaining
-   a copy of this software and associated documentation files (the
-   ``Software''), to deal in the Software without restriction, including
-   without limitation the rights to use, copy, modify, merge, publish,
-   distribute, sublicense, and/or sell copies of the Software, and to
-   permit persons to whom the Software is furnished to do so, subject to
-   the following conditions:
- 
-   The above copyright notice and this permission notice shall be included
-   in all copies or substantial portions of the Software.
- 
-   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-   DEALINGS IN THE SOFTWARE.
-   -----------------------------------------------------------------------
-   */
- 
-#define LIBFFI_ASM
-#include <fficonfig.h>
-#include <ffi.h>
-
-#ifdef _MSC_VER
-
-.386
-.MODEL FLAT, C
-
-EXTRN ffi_closure_SYSV_inner:NEAR
-
-_TEXT SEGMENT
-
-ffi_call_win32 PROC NEAR,
-    ffi_prep_args : NEAR PTR DWORD,
-    ecif          : NEAR PTR DWORD,
-    cif_abi       : DWORD,
-    cif_bytes     : DWORD,
-    cif_flags     : DWORD,
-    rvalue        : NEAR PTR DWORD,
-    fn            : NEAR PTR DWORD
-
-        ;; Make room for all of the new args.
-        mov  ecx, cif_bytes
-        sub  esp, ecx
-
-        mov  eax, esp
-
-        ;; Place all of the ffi_prep_args in position
-        push ecif
-        push eax
-        call ffi_prep_args
-
-        ;; Return stack to previous state and call the function
-        add  esp, 8
-
-	;; Handle thiscall and fastcall
-	cmp cif_abi, 3 ;; FFI_THISCALL
-	jz do_thiscall
-	cmp cif_abi, 4 ;; FFI_FASTCALL
-	jnz do_stdcall
-	mov ecx, DWORD PTR [esp]
-	mov edx, DWORD PTR [esp+4]
-	add esp, 8
-	jmp do_stdcall
-do_thiscall:
-	mov ecx, DWORD PTR [esp]
-	add esp, 4
-do_stdcall:
-        call fn
-
-        ;; cdecl:   we restore esp in the epilogue, so there's no need to
-        ;;          remove the space we pushed for the args.
-        ;; stdcall: the callee has already cleaned the stack.
-
-        ;; Load ecx with the return type code
-        mov  ecx, cif_flags
-
-        ;; If the return value pointer is NULL, assume no return value.
-        cmp  rvalue, 0
-        jne  ca_jumptable
-
-        ;; Even if there is no space for the return value, we are
-        ;; obliged to handle floating-point values.
-        cmp  ecx, FFI_TYPE_FLOAT
-        jne  ca_epilogue
-        fstp st(0)
-
-        jmp  ca_epilogue
-
-ca_jumptable:
-        jmp  [ca_jumpdata + 4 * ecx]
-ca_jumpdata:
-        ;; Do not insert anything here between label and jump table.
-        dd offset ca_epilogue       ;; FFI_TYPE_VOID
-        dd offset ca_retint         ;; FFI_TYPE_INT
-        dd offset ca_retfloat       ;; FFI_TYPE_FLOAT
-        dd offset ca_retdouble      ;; FFI_TYPE_DOUBLE
-        dd offset ca_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
-        dd offset ca_retuint8       ;; FFI_TYPE_UINT8
-        dd offset ca_retsint8       ;; FFI_TYPE_SINT8
-        dd offset ca_retuint16      ;; FFI_TYPE_UINT16
-        dd offset ca_retsint16      ;; FFI_TYPE_SINT16
-        dd offset ca_retint         ;; FFI_TYPE_UINT32
-        dd offset ca_retint         ;; FFI_TYPE_SINT32
-        dd offset ca_retint64       ;; FFI_TYPE_UINT64
-        dd offset ca_retint64       ;; FFI_TYPE_SINT64
-        dd offset ca_epilogue       ;; FFI_TYPE_STRUCT
-        dd offset ca_retint         ;; FFI_TYPE_POINTER
-        dd offset ca_retstruct1b    ;; FFI_TYPE_SMALL_STRUCT_1B
-        dd offset ca_retstruct2b    ;; FFI_TYPE_SMALL_STRUCT_2B
-        dd offset ca_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
-        dd offset ca_epilogue       ;; FFI_TYPE_MS_STRUCT
-
-        /* Sign/zero extend as appropriate.  */
-ca_retuint8:
-        movzx eax, al
-        jmp   ca_retint
-
-ca_retsint8:
-        movsx eax, al
-        jmp   ca_retint
-
-ca_retuint16:
-        movzx eax, ax
-        jmp   ca_retint
-
-ca_retsint16:
-        movsx eax, ax
-        jmp   ca_retint
-
-ca_retint:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        mov   [ecx + 0], eax
-        jmp   ca_epilogue
-
-ca_retint64:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        mov   [ecx + 0], eax
-        mov   [ecx + 4], edx
-        jmp   ca_epilogue
-
-ca_retfloat:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        fstp  DWORD PTR [ecx]
-        jmp   ca_epilogue
-
-ca_retdouble:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        fstp  QWORD PTR [ecx]
-        jmp   ca_epilogue
-
-ca_retlongdouble:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        fstp  TBYTE PTR [ecx]
-        jmp   ca_epilogue
-
-ca_retstruct1b:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        mov   [ecx + 0], al
-        jmp   ca_epilogue
-
-ca_retstruct2b:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        mov   [ecx + 0], ax
-        jmp   ca_epilogue
-
-ca_epilogue:
-        ;; Epilogue code is autogenerated.
-        ret
-ffi_call_win32 ENDP
-
-ffi_closure_THISCALL PROC NEAR FORCEFRAME
-	sub	esp, 40
-	lea	edx, [ebp -24]
-	mov	[ebp - 12], edx	/* resp */
-	lea	edx, [ebp + 12]  /* account for stub return address on stack */
-	jmp	stub
-ffi_closure_THISCALL ENDP
-
-ffi_closure_SYSV PROC NEAR FORCEFRAME
-    ;; the ffi_closure ctx is passed in eax by the trampoline.
-
-        sub  esp, 40
-        lea  edx, [ebp - 24]
-        mov  [ebp - 12], edx         ;; resp
-        lea  edx, [ebp + 8]
-stub::
-        mov  [esp + 8], edx          ;; args
-        lea  edx, [ebp - 12]
-        mov  [esp + 4], edx          ;; &resp
-        mov  [esp], eax              ;; closure
-        call ffi_closure_SYSV_inner
-        mov  ecx, [ebp - 12]
-
-cs_jumptable:
-        jmp  [cs_jumpdata + 4 * eax]
-cs_jumpdata:
-        ;; Do not insert anything here between the label and jump table.
-        dd offset cs_epilogue       ;; FFI_TYPE_VOID
-        dd offset cs_retint         ;; FFI_TYPE_INT
-        dd offset cs_retfloat       ;; FFI_TYPE_FLOAT
-        dd offset cs_retdouble      ;; FFI_TYPE_DOUBLE
-        dd offset cs_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
-        dd offset cs_retuint8       ;; FFI_TYPE_UINT8
-        dd offset cs_retsint8       ;; FFI_TYPE_SINT8
-        dd offset cs_retuint16      ;; FFI_TYPE_UINT16
-        dd offset cs_retsint16      ;; FFI_TYPE_SINT16
-        dd offset cs_retint         ;; FFI_TYPE_UINT32
-        dd offset cs_retint         ;; FFI_TYPE_SINT32
-        dd offset cs_retint64       ;; FFI_TYPE_UINT64
-        dd offset cs_retint64       ;; FFI_TYPE_SINT64
-        dd offset cs_retstruct      ;; FFI_TYPE_STRUCT
-        dd offset cs_retint         ;; FFI_TYPE_POINTER
-        dd offset cs_retsint8       ;; FFI_TYPE_SMALL_STRUCT_1B
-        dd offset cs_retsint16      ;; FFI_TYPE_SMALL_STRUCT_2B
-        dd offset cs_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
-        dd offset cs_retmsstruct    ;; FFI_TYPE_MS_STRUCT
-
-cs_retuint8:
-        movzx eax, BYTE PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retsint8:
-        movsx eax, BYTE PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retuint16:
-        movzx eax, WORD PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retsint16:
-        movsx eax, WORD PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retint:
-        mov   eax, [ecx]
-        jmp   cs_epilogue
-
-cs_retint64:
-        mov   eax, [ecx + 0]
-        mov   edx, [ecx + 4]
-        jmp   cs_epilogue
-
-cs_retfloat:
-        fld   DWORD PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retdouble:
-        fld   QWORD PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retlongdouble:
-        fld   TBYTE PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retstruct:
-        ;; Caller expects us to pop struct return value pointer hidden arg.
-        ;; Epilogue code is autogenerated.
-        ret	4
-
-cs_retmsstruct:
-        ;; Caller expects us to return a pointer to the real return value.
-        mov   eax, ecx
-        ;; Caller doesn't expects us to pop struct return value pointer hidden arg.
-        jmp   cs_epilogue
-
-cs_epilogue:
-        ;; Epilogue code is autogenerated.
-        ret
-ffi_closure_SYSV ENDP
-
-#if !FFI_NO_RAW_API
-
-#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3)
-#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
-#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
-#define CIF_FLAGS_OFFSET 20
-
-ffi_closure_raw_THISCALL PROC NEAR USES esi FORCEFRAME
-	sub esp, 36
-	mov  esi, [eax + RAW_CLOSURE_CIF_OFFSET]        ;; closure->cif
-	mov  edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET]  ;; closure->user_data
-	mov [esp + 12], edx
-	lea edx, [ebp + 12]
-	jmp stubraw
-ffi_closure_raw_THISCALL ENDP
-
-ffi_closure_raw_SYSV PROC NEAR USES esi FORCEFRAME
-    ;; the ffi_closure ctx is passed in eax by the trampoline.
-
-        sub  esp, 40
-        mov  esi, [eax + RAW_CLOSURE_CIF_OFFSET]        ;; closure->cif
-        mov  edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET]  ;; closure->user_data
-        mov  [esp + 12], edx                            ;; user_data
-        lea  edx, [ebp + 8]
-stubraw::
-        mov  [esp + 8], edx                             ;; raw_args
-        lea  edx, [ebp - 24]
-        mov  [esp + 4], edx                             ;; &res
-        mov  [esp], esi                                 ;; cif
-        call DWORD PTR [eax + RAW_CLOSURE_FUN_OFFSET]   ;; closure->fun
-        mov  eax, [esi + CIF_FLAGS_OFFSET]              ;; cif->flags
-        lea  ecx, [ebp - 24]
-
-cr_jumptable:
-        jmp  [cr_jumpdata + 4 * eax]
-cr_jumpdata:
-        ;; Do not insert anything here between the label and jump table.
-        dd offset cr_epilogue       ;; FFI_TYPE_VOID
-        dd offset cr_retint         ;; FFI_TYPE_INT
-        dd offset cr_retfloat       ;; FFI_TYPE_FLOAT
-        dd offset cr_retdouble      ;; FFI_TYPE_DOUBLE
-        dd offset cr_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
-        dd offset cr_retuint8       ;; FFI_TYPE_UINT8
-        dd offset cr_retsint8       ;; FFI_TYPE_SINT8
-        dd offset cr_retuint16      ;; FFI_TYPE_UINT16
-        dd offset cr_retsint16      ;; FFI_TYPE_SINT16
-        dd offset cr_retint         ;; FFI_TYPE_UINT32
-        dd offset cr_retint         ;; FFI_TYPE_SINT32
-        dd offset cr_retint64       ;; FFI_TYPE_UINT64
-        dd offset cr_retint64       ;; FFI_TYPE_SINT64
-        dd offset cr_epilogue       ;; FFI_TYPE_STRUCT
-        dd offset cr_retint         ;; FFI_TYPE_POINTER
-        dd offset cr_retsint8       ;; FFI_TYPE_SMALL_STRUCT_1B
-        dd offset cr_retsint16      ;; FFI_TYPE_SMALL_STRUCT_2B
-        dd offset cr_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
-        dd offset cr_epilogue       ;; FFI_TYPE_MS_STRUCT
-
-cr_retuint8:
-        movzx eax, BYTE PTR [ecx]
-        jmp   cr_epilogue
-
-cr_retsint8:
-        movsx eax, BYTE PTR [ecx]
-        jmp   cr_epilogue
-
-cr_retuint16:
-        movzx eax, WORD PTR [ecx]
-        jmp   cr_epilogue
-
-cr_retsint16:
-        movsx eax, WORD PTR [ecx]
-        jmp   cr_epilogue
-
-cr_retint:
-        mov   eax, [ecx]
-        jmp   cr_epilogue
-
-cr_retint64:
-        mov   eax, [ecx + 0]
-        mov   edx, [ecx + 4]
-        jmp   cr_epilogue
-
-cr_retfloat:
-        fld   DWORD PTR [ecx]
-        jmp   cr_epilogue
-
-cr_retdouble:
-        fld   QWORD PTR [ecx]
-        jmp   cr_epilogue
-
-cr_retlongdouble:
-        fld   TBYTE PTR [ecx]
-        jmp   cr_epilogue
-
-cr_epilogue:
-        ;; Epilogue code is autogenerated.
-        ret
-ffi_closure_raw_SYSV ENDP
-
-#endif /* !FFI_NO_RAW_API */
-
-ffi_closure_STDCALL PROC NEAR FORCEFRAME
-    ;; the ffi_closure ctx is passed in eax by the trampoline.
-
-        sub  esp, 40
-        lea  edx, [ebp - 24]
-        mov  [ebp - 12], edx         ;; resp
-        lea  edx, [ebp + 12]         ;; account for stub return address on stack
-        mov  [esp + 8], edx          ;; args
-        lea  edx, [ebp - 12]
-        mov  [esp + 4], edx          ;; &resp
-        mov  [esp], eax              ;; closure
-        call ffi_closure_SYSV_inner
-        mov  ecx, [ebp - 12]
-
-cd_jumptable:
-        jmp  [cd_jumpdata + 4 * eax]
-cd_jumpdata:
-        ;; Do not insert anything here between the label and jump table.
-        dd offset cd_epilogue       ;; FFI_TYPE_VOID
-        dd offset cd_retint         ;; FFI_TYPE_INT
-        dd offset cd_retfloat       ;; FFI_TYPE_FLOAT
-        dd offset cd_retdouble      ;; FFI_TYPE_DOUBLE
-        dd offset cd_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
-        dd offset cd_retuint8       ;; FFI_TYPE_UINT8
-        dd offset cd_retsint8       ;; FFI_TYPE_SINT8
-        dd offset cd_retuint16      ;; FFI_TYPE_UINT16
-        dd offset cd_retsint16      ;; FFI_TYPE_SINT16
-        dd offset cd_retint         ;; FFI_TYPE_UINT32
-        dd offset cd_retint         ;; FFI_TYPE_SINT32
-        dd offset cd_retint64       ;; FFI_TYPE_UINT64
-        dd offset cd_retint64       ;; FFI_TYPE_SINT64
-        dd offset cd_epilogue       ;; FFI_TYPE_STRUCT
-        dd offset cd_retint         ;; FFI_TYPE_POINTER
-        dd offset cd_retsint8       ;; FFI_TYPE_SMALL_STRUCT_1B
-        dd offset cd_retsint16      ;; FFI_TYPE_SMALL_STRUCT_2B
-        dd offset cd_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
-
-cd_retuint8:
-        movzx eax, BYTE PTR [ecx]
-        jmp   cd_epilogue
-
-cd_retsint8:
-        movsx eax, BYTE PTR [ecx]
-        jmp   cd_epilogue
-
-cd_retuint16:
-        movzx eax, WORD PTR [ecx]
-        jmp   cd_epilogue
-
-cd_retsint16:
-        movsx eax, WORD PTR [ecx]
-        jmp   cd_epilogue
-
-cd_retint:
-        mov   eax, [ecx]
-        jmp   cd_epilogue
-
-cd_retint64:
-        mov   eax, [ecx + 0]
-        mov   edx, [ecx + 4]
-        jmp   cd_epilogue
-
-cd_retfloat:
-        fld   DWORD PTR [ecx]
-        jmp   cd_epilogue
-
-cd_retdouble:
-        fld   QWORD PTR [ecx]
-        jmp   cd_epilogue
-
-cd_retlongdouble:
-        fld   TBYTE PTR [ecx]
-        jmp   cd_epilogue
-
-cd_epilogue:
-        ;; Epilogue code is autogenerated.
-        ret
-ffi_closure_STDCALL ENDP
-
-_TEXT ENDS
-END
-
-#else
-
-	.text
- 
-        # This assumes we are using gas.
-        .balign 16
-	.globl	_ffi_call_win32
-#ifndef __OS2__
-	.def	_ffi_call_win32;	.scl	2;	.type	32;	.endef
-#endif
-_ffi_call_win32:
-.LFB1:
-        pushl %ebp
-.LCFI0:
-        movl  %esp,%ebp
-.LCFI1:
-        # Make room for all of the new args.
-        movl  20(%ebp),%ecx                                                     
-        subl  %ecx,%esp
- 
-        movl  %esp,%eax
- 
-        # Place all of the ffi_prep_args in position
-        pushl 12(%ebp)
-        pushl %eax
-        call  *8(%ebp)
- 
-        # Return stack to previous state and call the function
-        addl  $8,%esp
-
-	# Handle fastcall and thiscall
-	cmpl $3, 16(%ebp)  # FFI_THISCALL
-	jz .do_thiscall
-	cmpl $4, 16(%ebp) # FFI_FASTCALL
-	jnz .do_fncall
-	movl (%esp), %ecx
-	movl 4(%esp), %edx
-	addl $8, %esp
-	jmp .do_fncall
-.do_thiscall:
-	movl (%esp), %ecx
-	addl $4, %esp
-
-.do_fncall:
-	 
-        # FIXME: Align the stack to a 128-bit boundary to avoid
-        # potential performance hits.
-
-        call  *32(%ebp)
- 
-        # stdcall functions pop arguments off the stack themselves
-
-        # Load %ecx with the return type code
-        movl  24(%ebp),%ecx
- 
-        # If the return value pointer is NULL, assume no return value.
-        cmpl  $0,28(%ebp)
-        jne   0f
- 
-        # Even if there is no space for the return value, we are
-        # obliged to handle floating-point values.
-        cmpl  $FFI_TYPE_FLOAT,%ecx
-        jne   .Lnoretval
-        fstp  %st(0)
- 
-        jmp   .Lepilogue
-
-0:
-	call	1f
-	# Do not insert anything here between the call and the jump table.
-.Lstore_table:
-	.long	.Lnoretval		/* FFI_TYPE_VOID */
-	.long	.Lretint		/* FFI_TYPE_INT */
-	.long	.Lretfloat		/* FFI_TYPE_FLOAT */
-	.long	.Lretdouble		/* FFI_TYPE_DOUBLE */
-	.long	.Lretlongdouble		/* FFI_TYPE_LONGDOUBLE */
-	.long	.Lretuint8		/* FFI_TYPE_UINT8 */
-	.long	.Lretsint8		/* FFI_TYPE_SINT8 */
-	.long	.Lretuint16		/* FFI_TYPE_UINT16 */
-	.long	.Lretsint16		/* FFI_TYPE_SINT16 */
-	.long	.Lretint		/* FFI_TYPE_UINT32 */
-	.long	.Lretint		/* FFI_TYPE_SINT32 */
-	.long	.Lretint64		/* FFI_TYPE_UINT64 */
-	.long	.Lretint64		/* FFI_TYPE_SINT64 */
-	.long	.Lretstruct		/* FFI_TYPE_STRUCT */
-	.long	.Lretint		/* FFI_TYPE_POINTER */
-	.long	.Lretstruct1b		/* FFI_TYPE_SMALL_STRUCT_1B */
-	.long	.Lretstruct2b		/* FFI_TYPE_SMALL_STRUCT_2B */
-	.long	.Lretstruct4b		/* FFI_TYPE_SMALL_STRUCT_4B */
-	.long	.Lretstruct		/* FFI_TYPE_MS_STRUCT */
-1:
-	add	%ecx, %ecx
-	add	%ecx, %ecx
-	add	(%esp),%ecx
-	add	$4, %esp
-	jmp	*(%ecx)
-
-	/* Sign/zero extend as appropriate.  */
-.Lretsint8:
-	movsbl	%al, %eax
-	jmp	.Lretint
-
-.Lretsint16:
-	movswl	%ax, %eax
-	jmp	.Lretint
-
-.Lretuint8:
-	movzbl	%al, %eax
-	jmp	.Lretint
-
-.Lretuint16:
-	movzwl	%ax, %eax
-	jmp	.Lretint
-
-.Lretint:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        movl  %eax,0(%ecx)
-        jmp   .Lepilogue
- 
-.Lretfloat:
-         # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        fstps (%ecx)
-        jmp   .Lepilogue
- 
-.Lretdouble:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        fstpl (%ecx)
-        jmp   .Lepilogue
- 
-.Lretlongdouble:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        fstpt (%ecx)
-        jmp   .Lepilogue
- 
-.Lretint64:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        movl  %eax,0(%ecx)
-        movl  %edx,4(%ecx)
-	jmp   .Lepilogue
-
-.Lretstruct1b:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        movb  %al,0(%ecx)
-        jmp   .Lepilogue
- 
-.Lretstruct2b:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        movw  %ax,0(%ecx)
-        jmp   .Lepilogue
-
-.Lretstruct4b:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        movl  %eax,0(%ecx)
-        jmp   .Lepilogue
-
-.Lretstruct:
-        # Nothing to do!
- 
-.Lnoretval:
-.Lepilogue:
-        movl %ebp,%esp
-        popl %ebp
-        ret
-.ffi_call_win32_end:
-        .balign 16
-	.globl	_ffi_closure_THISCALL
-#ifndef __OS2__
-	.def	_ffi_closure_THISCALL;	.scl	2;	.type	32;	.endef
-#endif
-_ffi_closure_THISCALL:
-	pushl	%ebp
-	movl	%esp, %ebp
-	subl	$40, %esp
-	leal	-24(%ebp), %edx
-	movl	%edx, -12(%ebp)	/* resp */
-	leal	12(%ebp), %edx  /* account for stub return address on stack */
-	jmp	.stub
-.LFE1:
-
-        # This assumes we are using gas.
-        .balign 16
-	.globl	_ffi_closure_SYSV
-#ifndef __OS2__
-	.def	_ffi_closure_SYSV;	.scl	2;	.type	32;	.endef
-#endif
-_ffi_closure_SYSV:
-.LFB3:
-	pushl	%ebp
-.LCFI4:
-	movl	%esp, %ebp
-.LCFI5:
-	subl	$40, %esp
-	leal	-24(%ebp), %edx
-	movl	%edx, -12(%ebp)	/* resp */
-	leal	8(%ebp), %edx
-.stub:
-	movl	%edx, 4(%esp)	/* args = __builtin_dwarf_cfa () */
-	leal	-12(%ebp), %edx
-	movl	%edx, (%esp)	/* &resp */
-	call	_ffi_closure_SYSV_inner
-	movl	-12(%ebp), %ecx
-
-0:
-	call	1f
-	# Do not insert anything here between the call and the jump table.
-.Lcls_store_table:
-	.long	.Lcls_noretval		/* FFI_TYPE_VOID */
-	.long	.Lcls_retint		/* FFI_TYPE_INT */
-	.long	.Lcls_retfloat		/* FFI_TYPE_FLOAT */
-	.long	.Lcls_retdouble		/* FFI_TYPE_DOUBLE */
-	.long	.Lcls_retldouble	/* FFI_TYPE_LONGDOUBLE */
-	.long	.Lcls_retuint8		/* FFI_TYPE_UINT8 */
-	.long	.Lcls_retsint8		/* FFI_TYPE_SINT8 */
-	.long	.Lcls_retuint16		/* FFI_TYPE_UINT16 */
-	.long	.Lcls_retsint16		/* FFI_TYPE_SINT16 */
-	.long	.Lcls_retint		/* FFI_TYPE_UINT32 */
-	.long	.Lcls_retint		/* FFI_TYPE_SINT32 */
-	.long	.Lcls_retllong		/* FFI_TYPE_UINT64 */
-	.long	.Lcls_retllong		/* FFI_TYPE_SINT64 */
-	.long	.Lcls_retstruct		/* FFI_TYPE_STRUCT */
-	.long	.Lcls_retint		/* FFI_TYPE_POINTER */
-	.long	.Lcls_retstruct1	/* FFI_TYPE_SMALL_STRUCT_1B */
-	.long	.Lcls_retstruct2	/* FFI_TYPE_SMALL_STRUCT_2B */
-	.long	.Lcls_retstruct4	/* FFI_TYPE_SMALL_STRUCT_4B */
-	.long	.Lcls_retmsstruct	/* FFI_TYPE_MS_STRUCT */
-
-1:
-	add	%eax, %eax
-	add	%eax, %eax
-	add	(%esp),%eax
-	add	$4, %esp
-	jmp	*(%eax)
-
-	/* Sign/zero extend as appropriate.  */
-.Lcls_retsint8:
-	movsbl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-
-.Lcls_retsint16:
-	movswl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-
-.Lcls_retuint8:
-	movzbl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-
-.Lcls_retuint16:
-	movzwl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-
-.Lcls_retint:
-	movl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-
-.Lcls_retfloat:
-	flds	(%ecx)
-	jmp	.Lcls_epilogue
-
-.Lcls_retdouble:
-	fldl	(%ecx)
-	jmp	.Lcls_epilogue
-
-.Lcls_retldouble:
-	fldt	(%ecx)
-	jmp	.Lcls_epilogue
-
-.Lcls_retllong:
-	movl	(%ecx), %eax
-	movl	4(%ecx), %edx
-	jmp	.Lcls_epilogue
-
-.Lcls_retstruct1:
-	movsbl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-
-.Lcls_retstruct2:
-	movswl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-
-.Lcls_retstruct4:
-	movl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-
-.Lcls_retstruct:
-        # Caller expects us to pop struct return value pointer hidden arg.
-	movl	%ebp, %esp
-	popl	%ebp
-	ret	$0x4
-
-.Lcls_retmsstruct:
-	# Caller expects us to return a pointer to the real return value.
-	mov	%ecx, %eax
-	# Caller doesn't expects us to pop struct return value pointer hidden arg.
-	jmp	.Lcls_epilogue
-
-.Lcls_noretval:
-.Lcls_epilogue:
-	movl	%ebp, %esp
-	popl	%ebp
-	ret
-.ffi_closure_SYSV_end:
-.LFE3:
-
-#if !FFI_NO_RAW_API
-
-#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
-#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
-#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
-#define CIF_FLAGS_OFFSET 20
-        .balign 16
-	.globl	_ffi_closure_raw_THISCALL
-#ifndef __OS2__
-	.def	_ffi_closure_raw_THISCALL;	.scl	2;	.type	32;	.endef
-#endif
-_ffi_closure_raw_THISCALL:
-	pushl	%ebp
-	movl	%esp, %ebp
-	pushl	%esi
-	subl	$36, %esp
-	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
-	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
-	movl	%edx, 12(%esp)	/* user_data */
-	leal	12(%ebp), %edx	/* __builtin_dwarf_cfa () */
-	jmp	.stubraw
-        # This assumes we are using gas.
-        .balign 16
-	.globl	_ffi_closure_raw_SYSV
-#ifndef __OS2__
-	.def	_ffi_closure_raw_SYSV;	.scl	2;	.type	32;	.endef
-#endif
-_ffi_closure_raw_SYSV:
-.LFB4:
-	pushl	%ebp
-.LCFI6:
-	movl	%esp, %ebp
-.LCFI7:
-	pushl	%esi
-.LCFI8:
-	subl	$36, %esp
-	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
-	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
-	movl	%edx, 12(%esp)	/* user_data */
-	leal	8(%ebp), %edx	/* __builtin_dwarf_cfa () */
-.stubraw:
-	movl	%edx, 8(%esp)	/* raw_args */
-	leal	-24(%ebp), %edx
-	movl	%edx, 4(%esp)	/* &res */
-	movl	%esi, (%esp)	/* cif */
-	call	*RAW_CLOSURE_FUN_OFFSET(%eax)		 /* closure->fun */
-	movl	CIF_FLAGS_OFFSET(%esi), %eax		 /* rtype */
-0:
-	call	1f
-	# Do not insert anything here between the call and the jump table.
-.Lrcls_store_table:
-	.long	.Lrcls_noretval		/* FFI_TYPE_VOID */
-	.long	.Lrcls_retint		/* FFI_TYPE_INT */
-	.long	.Lrcls_retfloat		/* FFI_TYPE_FLOAT */
-	.long	.Lrcls_retdouble	/* FFI_TYPE_DOUBLE */
-	.long	.Lrcls_retldouble	/* FFI_TYPE_LONGDOUBLE */
-	.long	.Lrcls_retuint8		/* FFI_TYPE_UINT8 */
-	.long	.Lrcls_retsint8		/* FFI_TYPE_SINT8 */
-	.long	.Lrcls_retuint16	/* FFI_TYPE_UINT16 */
-	.long	.Lrcls_retsint16	/* FFI_TYPE_SINT16 */
-	.long	.Lrcls_retint		/* FFI_TYPE_UINT32 */
-	.long	.Lrcls_retint		/* FFI_TYPE_SINT32 */
-	.long	.Lrcls_retllong		/* FFI_TYPE_UINT64 */
-	.long	.Lrcls_retllong		/* FFI_TYPE_SINT64 */
-	.long	.Lrcls_retstruct	/* FFI_TYPE_STRUCT */
-	.long	.Lrcls_retint		/* FFI_TYPE_POINTER */
-	.long	.Lrcls_retstruct1	/* FFI_TYPE_SMALL_STRUCT_1B */
-	.long	.Lrcls_retstruct2	/* FFI_TYPE_SMALL_STRUCT_2B */
-	.long	.Lrcls_retstruct4	/* FFI_TYPE_SMALL_STRUCT_4B */
-	.long	.Lrcls_retstruct	/* FFI_TYPE_MS_STRUCT */
-1:
-	add	%eax, %eax
-	add	%eax, %eax
-	add	(%esp),%eax
-	add	$4, %esp
-	jmp	*(%eax)
-
-	/* Sign/zero extend as appropriate.  */
-.Lrcls_retsint8:
-	movsbl	-24(%ebp), %eax
-	jmp	.Lrcls_epilogue
-
-.Lrcls_retsint16:
-	movswl	-24(%ebp), %eax
-	jmp	.Lrcls_epilogue
-
-.Lrcls_retuint8:
-	movzbl	-24(%ebp), %eax
-	jmp	.Lrcls_epilogue
-
-.Lrcls_retuint16:
-	movzwl	-24(%ebp), %eax
-	jmp	.Lrcls_epilogue
-
-.Lrcls_retint:
-	movl	-24(%ebp), %eax
-	jmp	.Lrcls_epilogue
-
-.Lrcls_retfloat:
-	flds	-24(%ebp)
-	jmp	.Lrcls_epilogue
-
-.Lrcls_retdouble:
-	fldl	-24(%ebp)
-	jmp	.Lrcls_epilogue
-
-.Lrcls_retldouble:
-	fldt	-24(%ebp)
-	jmp	.Lrcls_epilogue
-
-.Lrcls_retllong:
-	movl	-24(%ebp), %eax
-	movl	-20(%ebp), %edx
-	jmp	.Lrcls_epilogue
-
-.Lrcls_retstruct1:
-	movsbl	-24(%ebp), %eax
-	jmp	.Lrcls_epilogue
-
-.Lrcls_retstruct2:
-	movswl	-24(%ebp), %eax
-	jmp	.Lrcls_epilogue
-
-.Lrcls_retstruct4:
-	movl	-24(%ebp), %eax
-	jmp	.Lrcls_epilogue
-
-.Lrcls_retstruct:
-	# Nothing to do!
-
-.Lrcls_noretval:
-.Lrcls_epilogue:
-	addl	$36, %esp
-	popl	%esi
-	popl	%ebp
-	ret
-.ffi_closure_raw_SYSV_end:
-.LFE4:
-
-#endif /* !FFI_NO_RAW_API */
-
-        # This assumes we are using gas.
-	.balign	16
-	.globl	_ffi_closure_STDCALL
-#ifndef __OS2__
-	.def	_ffi_closure_STDCALL;	.scl	2;	.type	32;	.endef
-#endif
-_ffi_closure_STDCALL:
-.LFB5:
-	pushl	%ebp
-.LCFI9:
-	movl	%esp, %ebp
-.LCFI10:
-	subl	$40, %esp
-	leal	-24(%ebp), %edx
-	movl	%edx, -12(%ebp)	/* resp */
-	leal	12(%ebp), %edx  /* account for stub return address on stack */
-	movl	%edx, 4(%esp)	/* args */
-	leal	-12(%ebp), %edx
-	movl	%edx, (%esp)	/* &resp */
-	call	_ffi_closure_SYSV_inner
-	movl	-12(%ebp), %ecx
-0:
-	call	1f
-	# Do not insert anything here between the call and the jump table.
-.Lscls_store_table:
-	.long	.Lscls_noretval		/* FFI_TYPE_VOID */
-	.long	.Lscls_retint		/* FFI_TYPE_INT */
-	.long	.Lscls_retfloat		/* FFI_TYPE_FLOAT */
-	.long	.Lscls_retdouble	/* FFI_TYPE_DOUBLE */
-	.long	.Lscls_retldouble	/* FFI_TYPE_LONGDOUBLE */
-	.long	.Lscls_retuint8		/* FFI_TYPE_UINT8 */
-	.long	.Lscls_retsint8		/* FFI_TYPE_SINT8 */
-	.long	.Lscls_retuint16	/* FFI_TYPE_UINT16 */
-	.long	.Lscls_retsint16	/* FFI_TYPE_SINT16 */
-	.long	.Lscls_retint		/* FFI_TYPE_UINT32 */
-	.long	.Lscls_retint		/* FFI_TYPE_SINT32 */
-	.long	.Lscls_retllong		/* FFI_TYPE_UINT64 */
-	.long	.Lscls_retllong		/* FFI_TYPE_SINT64 */
-	.long	.Lscls_retstruct	/* FFI_TYPE_STRUCT */
-	.long	.Lscls_retint		/* FFI_TYPE_POINTER */
-	.long	.Lscls_retstruct1	/* FFI_TYPE_SMALL_STRUCT_1B */
-	.long	.Lscls_retstruct2	/* FFI_TYPE_SMALL_STRUCT_2B */
-	.long	.Lscls_retstruct4	/* FFI_TYPE_SMALL_STRUCT_4B */
-1:
-	add	%eax, %eax
-	add	%eax, %eax
-	add	(%esp),%eax
-	add	$4, %esp
-	jmp	*(%eax)
-
-	/* Sign/zero extend as appropriate.  */
-.Lscls_retsint8:
-	movsbl	(%ecx), %eax
-	jmp	.Lscls_epilogue
-
-.Lscls_retsint16:
-	movswl	(%ecx), %eax
-	jmp	.Lscls_epilogue
-
-.Lscls_retuint8:
-	movzbl	(%ecx), %eax
-	jmp	.Lscls_epilogue
-
-.Lscls_retuint16:
-	movzwl	(%ecx), %eax
-	jmp	.Lscls_epilogue
-
-.Lscls_retint:
-	movl	(%ecx), %eax
-	jmp	.Lscls_epilogue
-
-.Lscls_retfloat:
-	flds	(%ecx)
-	jmp	.Lscls_epilogue
-
-.Lscls_retdouble:
-	fldl	(%ecx)
-	jmp	.Lscls_epilogue
-
-.Lscls_retldouble:
-	fldt	(%ecx)
-	jmp	.Lscls_epilogue
-
-.Lscls_retllong:
-	movl	(%ecx), %eax
-	movl	4(%ecx), %edx
-	jmp	.Lscls_epilogue
-
-.Lscls_retstruct1:
-	movsbl	(%ecx), %eax
-	jmp	.Lscls_epilogue
-
-.Lscls_retstruct2:
-	movswl	(%ecx), %eax
-	jmp	.Lscls_epilogue
-
-.Lscls_retstruct4:
-	movl	(%ecx), %eax
-	jmp	.Lscls_epilogue
-
-.Lscls_retstruct:
-	# Nothing to do!
-
-.Lscls_noretval:
-.Lscls_epilogue:
-	movl	%ebp, %esp
-	popl	%ebp
-	ret
-.ffi_closure_STDCALL_end:
-.LFE5:
-
-#ifndef __OS2__
-	.section	.eh_frame,"w"
-#endif
-.Lframe1:
-.LSCIE1:
-	.long	.LECIE1-.LASCIE1  /* Length of Common Information Entry */
-.LASCIE1:
-	.long	0x0	/* CIE Identifier Tag */
-	.byte	0x1	/* CIE Version */
-#ifdef __PIC__
-	.ascii "zR\0"	/* CIE Augmentation */
-#else
-	.ascii "\0"	/* CIE Augmentation */
-#endif
-	.byte	0x1	/* .uleb128 0x1; CIE Code Alignment Factor */
-	.byte	0x7c	/* .sleb128 -4; CIE Data Alignment Factor */
-	.byte	0x8	/* CIE RA Column */
-#ifdef __PIC__
-	.byte	0x1	/* .uleb128 0x1; Augmentation size */
-	.byte	0x1b	/* FDE Encoding (pcrel sdata4) */
-#endif
-	.byte	0xc	/* DW_CFA_def_cfa CFA = r4 + 4 = 4(%esp) */
-	.byte	0x4	/* .uleb128 0x4 */
-	.byte	0x4	/* .uleb128 0x4 */
-	.byte	0x88	/* DW_CFA_offset, column 0x8 %eip at CFA + 1 * -4 */
-	.byte	0x1	/* .uleb128 0x1 */
-	.align 4
-.LECIE1:
-
-.LSFDE1:
-	.long	.LEFDE1-.LASFDE1	/* FDE Length */
-.LASFDE1:
-	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
-#if defined __PIC__ && defined HAVE_AS_X86_PCREL
-	.long	.LFB1-.	/* FDE initial location */
-#else
-	.long	.LFB1
-#endif
-	.long	.LFE1-.LFB1	/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	/* DW_CFA_xxx CFI instructions go here.  */
-
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI0-.LFB1
-	.byte	0xe	/* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
-	.byte	0x2	/* .uleb128 0x2 */
-
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI1-.LCFI0
-	.byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
-	.byte	0x5	/* .uleb128 0x5 */
-
-	/* End of DW_CFA_xxx CFI instructions.  */
-	.align 4
-.LEFDE1:
-
-
-.LSFDE3:
-	.long	.LEFDE3-.LASFDE3	/* FDE Length */
-.LASFDE3:
-	.long	.LASFDE3-.Lframe1	/* FDE CIE offset */
-#if defined __PIC__ && defined HAVE_AS_X86_PCREL
-	.long	.LFB3-.	/* FDE initial location */
-#else
-	.long	.LFB3
-#endif
-	.long	.LFE3-.LFB3	/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	/* DW_CFA_xxx CFI instructions go here.  */
-
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI4-.LFB3
-	.byte	0xe	/* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
-	.byte	0x2	/* .uleb128 0x2 */
-
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI5-.LCFI4
-	.byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
-	.byte	0x5	/* .uleb128 0x5 */
-
-	/* End of DW_CFA_xxx CFI instructions.  */
-	.align 4
-.LEFDE3:
-
-#if !FFI_NO_RAW_API
-
-.LSFDE4:
-	.long	.LEFDE4-.LASFDE4	/* FDE Length */
-.LASFDE4:
-	.long	.LASFDE4-.Lframe1	/* FDE CIE offset */
-#if defined __PIC__ && defined HAVE_AS_X86_PCREL
-	.long	.LFB4-.	/* FDE initial location */
-#else
-	.long	.LFB4
-#endif
-	.long	.LFE4-.LFB4	/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	/* DW_CFA_xxx CFI instructions go here.  */
-
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI6-.LFB4
-	.byte	0xe	/* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
-	.byte	0x2	/* .uleb128 0x2 */
-
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI7-.LCFI6
-	.byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
-	.byte	0x5	/* .uleb128 0x5 */
-
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI8-.LCFI7
-	.byte	0x86	/* DW_CFA_offset, column 0x6 %esi at CFA + 3 * -4 */
-	.byte	0x3	/* .uleb128 0x3 */
-
-	/* End of DW_CFA_xxx CFI instructions.  */
-	.align 4
-.LEFDE4:
-
-#endif /* !FFI_NO_RAW_API */
-
-.LSFDE5:
-	.long	.LEFDE5-.LASFDE5	/* FDE Length */
-.LASFDE5:
-	.long	.LASFDE5-.Lframe1	/* FDE CIE offset */
-#if defined __PIC__ && defined HAVE_AS_X86_PCREL
-	.long	.LFB5-.	/* FDE initial location */
-#else
-	.long	.LFB5
-#endif
-	.long	.LFE5-.LFB5	/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	/* DW_CFA_xxx CFI instructions go here.  */
-
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI9-.LFB5
-	.byte	0xe	/* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
-	.byte	0x2	/* .uleb128 0x2 */
-
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI10-.LCFI9
-	.byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
-	.byte	0x5	/* .uleb128 0x5 */
-
-	/* End of DW_CFA_xxx CFI instructions.  */
-	.align 4
-.LEFDE5:
-
-#endif /* !_MSC_VER */
-
diff --git a/third_party/gofrontend/libffi/src/x86/win64.S b/third_party/gofrontend/libffi/src/x86/win64.S
index 687f97c..a5a20b6 100644
--- a/third_party/gofrontend/libffi/src/x86/win64.S
+++ b/third_party/gofrontend/libffi/src/x86/win64.S
@@ -1,264 +1,16 @@
 #define LIBFFI_ASM
 #include <fficonfig.h>
 #include <ffi.h>
+#include <ffi_cfi.h>
 
-/* Constants for ffi_call_win64 */
-#define STACK 0
-#define PREP_ARGS_FN 32
-#define ECIF 40
-#define CIF_BYTES 48
-#define CIF_FLAGS 56
-#define RVALUE 64
-#define FN 72
+#if defined(HAVE_AS_CFI_PSEUDO_OP)
+        .cfi_sections   .debug_frame
+#endif
 
-/* ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *),
-		   extended_cif *ecif, unsigned bytes, unsigned flags,
-		   unsigned *rvalue, void (*fn)());
- */
-
-#ifdef _MSC_VER
-PUBLIC	ffi_call_win64
-
-EXTRN	__chkstk:NEAR
-EXTRN	ffi_closure_win64_inner:NEAR
-
-_TEXT	SEGMENT
-
-;;; ffi_closure_win64 will be called with these registers set:
-;;;    rax points to 'closure'
-;;;    r11 contains a bit mask that specifies which of the
-;;;    first four parameters are float or double
-;;;
-;;; It must move the parameters passed in registers to their stack location,
-;;; call ffi_closure_win64_inner for the actual work, then return the result.
-;;;
-ffi_closure_win64 PROC FRAME
-	;; copy register arguments onto stack
-	test	r11, 1
-	jne	first_is_float
-	mov	QWORD PTR [rsp+8], rcx
-	jmp	second
-first_is_float:
-	movlpd	QWORD PTR [rsp+8], xmm0
-
-second:
-	test	r11, 2
-	jne	second_is_float
-	mov	QWORD PTR [rsp+16], rdx
-	jmp	third
-second_is_float:
-	movlpd	QWORD PTR [rsp+16], xmm1
-
-third:
-	test	r11, 4
-	jne	third_is_float
-	mov	QWORD PTR [rsp+24], r8
-	jmp	fourth
-third_is_float:
-	movlpd	QWORD PTR [rsp+24], xmm2
-
-fourth:
-	test	r11, 8
-	jne	fourth_is_float
-	mov	QWORD PTR [rsp+32], r9
-	jmp	done
-fourth_is_float:
-	movlpd	QWORD PTR [rsp+32], xmm3
-
-done:
-	.ALLOCSTACK 40
-	sub	rsp, 40
-	.ENDPROLOG
-	mov	rcx, rax	; context is first parameter
-	mov	rdx, rsp	; stack is second parameter
-	add	rdx, 48		; point to start of arguments
-	mov	rax, ffi_closure_win64_inner
-	call	rax		; call the real closure function
-	add	rsp, 40
-	movd	xmm0, rax	; If the closure returned a float,
-				; ffi_closure_win64_inner wrote it to rax
-	ret	0
-ffi_closure_win64 ENDP
-
-ffi_call_win64 PROC FRAME
-	;; copy registers onto stack
-	mov	QWORD PTR [rsp+32], r9
-	mov	QWORD PTR [rsp+24], r8
-	mov	QWORD PTR [rsp+16], rdx
-	mov	QWORD PTR [rsp+8], rcx
-	.PUSHREG rbp
-	push	rbp
-	.ALLOCSTACK 48
-	sub	rsp, 48					; 00000030H
-	.SETFRAME rbp, 32
-	lea	rbp, QWORD PTR [rsp+32]
-	.ENDPROLOG
-
-	mov	eax, DWORD PTR CIF_BYTES[rbp]
-	add	rax, 15
-	and	rax, -16
-	call	__chkstk
-	sub	rsp, rax
-	lea	rax, QWORD PTR [rsp+32]
-	mov	QWORD PTR STACK[rbp], rax
-
-	mov	rdx, QWORD PTR ECIF[rbp]
-	mov	rcx, QWORD PTR STACK[rbp]
-	call	QWORD PTR PREP_ARGS_FN[rbp]
-
-	mov	rsp, QWORD PTR STACK[rbp]
-
-	movlpd	xmm3, QWORD PTR [rsp+24]
-	movd	r9, xmm3
-
-	movlpd	xmm2, QWORD PTR [rsp+16]
-	movd	r8, xmm2
-
-	movlpd	xmm1, QWORD PTR [rsp+8]
-	movd	rdx, xmm1
-
-	movlpd	xmm0, QWORD PTR [rsp]
-	movd	rcx, xmm0
-
-	call	QWORD PTR FN[rbp]
-ret_struct4b$:
- 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_4B
- 	jne	ret_struct2b$
-
-	mov	rcx, QWORD PTR RVALUE[rbp]
-	mov	DWORD PTR [rcx], eax
-	jmp	ret_void$
-
-ret_struct2b$:
- 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_2B
- 	jne	ret_struct1b$
-
-	mov	rcx, QWORD PTR RVALUE[rbp]
-	mov	WORD PTR [rcx], ax
-	jmp	ret_void$
-
-ret_struct1b$:
- 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_1B
- 	jne	ret_uint8$
-
-	mov	rcx, QWORD PTR RVALUE[rbp]
-	mov	BYTE PTR [rcx], al
-	jmp	ret_void$
-
-ret_uint8$:
- 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT8
- 	jne	ret_sint8$
-
-	mov	rcx, QWORD PTR RVALUE[rbp]
-	movzx   rax, al
-	mov	QWORD PTR [rcx], rax
-	jmp	ret_void$
-
-ret_sint8$:
- 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT8
- 	jne	ret_uint16$
-
-	mov	rcx, QWORD PTR RVALUE[rbp]
-	movsx   rax, al
-	mov	QWORD PTR [rcx], rax
-	jmp	ret_void$
-
-ret_uint16$:
- 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT16
- 	jne	ret_sint16$
-
-	mov	rcx, QWORD PTR RVALUE[rbp]
-	movzx   rax, ax
-	mov	QWORD PTR [rcx], rax
-	jmp	SHORT ret_void$
-
-ret_sint16$:
- 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT16
- 	jne	ret_uint32$
-
-	mov	rcx, QWORD PTR RVALUE[rbp]
-	movsx   rax, ax
-	mov	QWORD PTR [rcx], rax
-	jmp	SHORT ret_void$
-
-ret_uint32$:
- 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT32
- 	jne	ret_sint32$
-
-	mov	rcx, QWORD PTR RVALUE[rbp]
-	mov     eax, eax
-	mov	QWORD PTR [rcx], rax
-	jmp	SHORT ret_void$
-
-ret_sint32$:
- 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT32
- 	jne	ret_float$
-
-	mov	rcx, QWORD PTR RVALUE[rbp]
-	cdqe
-	mov	QWORD PTR [rcx], rax
-	jmp	SHORT ret_void$
-
-ret_float$:
- 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_FLOAT
- 	jne	SHORT ret_double$
-
- 	mov	rax, QWORD PTR RVALUE[rbp]
- 	movss	DWORD PTR [rax], xmm0
- 	jmp	SHORT ret_void$
-
-ret_double$:
- 	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE
- 	jne	SHORT ret_uint64$
-
- 	mov	rax, QWORD PTR RVALUE[rbp]
- 	movlpd	QWORD PTR [rax], xmm0
- 	jmp	SHORT ret_void$
-
-ret_uint64$:
-  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT64
-  	jne	SHORT ret_sint64$
-
- 	mov	rcx, QWORD PTR RVALUE[rbp]
- 	mov	QWORD PTR [rcx], rax
- 	jmp	SHORT ret_void$
-
-ret_sint64$:
-  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64
-  	jne	SHORT ret_pointer$
-
- 	mov	rcx, QWORD PTR RVALUE[rbp]
- 	mov	QWORD PTR [rcx], rax
- 	jmp	SHORT ret_void$
-
-ret_pointer$:
-  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_POINTER
-  	jne	SHORT ret_int$
-
- 	mov	rcx, QWORD PTR RVALUE[rbp]
- 	mov	QWORD PTR [rcx], rax
- 	jmp	SHORT ret_void$
-
-ret_int$:
-  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_INT
-  	jne	SHORT ret_void$
-
-	mov	rcx, QWORD PTR RVALUE[rbp]
-	cdqe
-	mov	QWORD PTR [rcx], rax
- 	jmp	SHORT ret_void$
-
-ret_void$:
-	xor	rax, rax
-
-	lea	rsp, QWORD PTR [rbp+16]
-	pop	rbp
-	ret	0
-ffi_call_win64 ENDP
-_TEXT	ENDS
-END
-
-#else
+#define arg0	%rcx
+#define arg1	%rdx
+#define arg2	%r8
+#define arg3	%r9
 
 #ifdef SYMBOL_UNDERSCORE
 #define SYMBOL_NAME(name) _##name
@@ -266,255 +18,202 @@
 #define SYMBOL_NAME(name) name
 #endif
 
-.text
+.macro E which
+	.align	8
+	.org	0b + \which * 8
+.endm
 
-.extern SYMBOL_NAME(ffi_closure_win64_inner)
+	.text
 
-# ffi_closure_win64 will be called with these registers set:
-#    rax points to 'closure'
-#    r11 contains a bit mask that specifies which of the
-#    first four parameters are float or double
-#
-# It must move the parameters passed in registers to their stack location,
-# call ffi_closure_win64_inner for the actual work, then return the result.
-#
-	.balign 16
-	.globl SYMBOL_NAME(ffi_closure_win64)
-	.seh_proc SYMBOL_NAME(ffi_closure_win64)
-SYMBOL_NAME(ffi_closure_win64):
-	# copy register arguments onto stack
-	test	$1,%r11
-	jne	.Lfirst_is_float
-	mov	%rcx, 8(%rsp)
-	jmp	.Lsecond
-.Lfirst_is_float:
-	movlpd	%xmm0, 8(%rsp)
+/* ffi_call_win64 (void *stack, struct win64_call_frame *frame, void *r10)
 
-.Lsecond:
-	test	$2, %r11
-	jne	.Lsecond_is_float
-	mov	%rdx, 16(%rsp)
-	jmp	.Lthird
-.Lsecond_is_float:
-	movlpd	%xmm1, 16(%rsp)
+   Bit o trickiness here -- FRAME is the base of the stack frame
+   for this function.  This has been allocated by ffi_call.  We also
+   deallocate some of the stack that has been alloca'd.  */
 
-.Lthird:
-	test	$4, %r11
-	jne	.Lthird_is_float
-	mov	%r8,24(%rsp)
-	jmp	.Lfourth
-.Lthird_is_float:
-	movlpd	%xmm2, 24(%rsp)
+	.align	8
+	.globl	ffi_call_win64
 
-.Lfourth:
-	test	$8, %r11
-	jne	.Lfourth_is_float
-	mov	%r9, 32(%rsp)
-	jmp	.Ldone
-.Lfourth_is_float:
-	movlpd	%xmm3, 32(%rsp)
-
-.Ldone:
-	.seh_stackalloc 40
-	sub	$40, %rsp
+	.seh_proc ffi_call_win64
+ffi_call_win64:
+	cfi_startproc
+	/* Set up the local stack frame and install it in rbp/rsp.  */
+	movq	(%rsp), %rax
+	movq	%rbp, (arg1)
+	movq	%rax, 8(arg1)
+	movq	arg1, %rbp
+	cfi_def_cfa(%rbp, 16)
+	cfi_rel_offset(%rbp, 0)
+	.seh_pushreg %rbp
+	.seh_setframe %rbp, 0
 	.seh_endprologue
-	mov	%rax, %rcx	# context is first parameter
-	mov	%rsp, %rdx	# stack is second parameter
-	add	$48, %rdx	# point to start of arguments
-	leaq	SYMBOL_NAME(ffi_closure_win64_inner)(%rip), %rax
-	callq	*%rax		# call the real closure function
-	add	$40, %rsp
-	movq	%rax, %xmm0	# If the closure returned a float,
-				# ffi_closure_win64_inner wrote it to rax
-	retq
+	movq	arg0, %rsp
+
+	movq	arg2, %r10
+
+	/* Load all slots into both general and xmm registers.  */
+	movq	(%rsp), %rcx
+	movsd	(%rsp), %xmm0
+	movq	8(%rsp), %rdx
+	movsd	8(%rsp), %xmm1
+	movq	16(%rsp), %r8
+	movsd	16(%rsp), %xmm2
+	movq	24(%rsp), %r9
+	movsd	24(%rsp), %xmm3
+
+	call	*16(%rbp)
+
+	movl	24(%rbp), %ecx
+	movq	32(%rbp), %r8
+	leaq	0f(%rip), %r10
+	cmpl	$FFI_TYPE_SMALL_STRUCT_4B, %ecx
+	leaq	(%r10, %rcx, 8), %r10
+	ja	99f
+	jmp	*%r10
+
+/* Below, we're space constrained most of the time.  Thus we eschew the
+   modern "mov, pop, ret" sequence (5 bytes) for "leave, ret" (2 bytes).  */
+.macro epilogue
+	leaveq
+	cfi_remember_state
+	cfi_def_cfa(%rsp, 8)
+	cfi_restore(%rbp)
+	ret
+	cfi_restore_state
+.endm
+
+	.align	8
+0:
+E FFI_TYPE_VOID
+	epilogue
+E FFI_TYPE_INT
+	movslq	%eax, %rax
+	movq	%rax, (%r8)
+	epilogue
+E FFI_TYPE_FLOAT
+	movss	%xmm0, (%r8)
+	epilogue
+E FFI_TYPE_DOUBLE
+	movsd	%xmm0, (%r8)
+	epilogue
+E FFI_TYPE_LONGDOUBLE
+	call	abort
+E FFI_TYPE_UINT8
+	movzbl	%al, %eax
+	movq	%rax, (%r8)
+	epilogue
+E FFI_TYPE_SINT8
+	movsbq	%al, %rax
+	jmp	98f
+E FFI_TYPE_UINT16
+	movzwl	%ax, %eax
+	movq	%rax, (%r8)
+	epilogue
+E FFI_TYPE_SINT16
+	movswq	%ax, %rax
+	jmp	98f
+E FFI_TYPE_UINT32
+	movl	%eax, %eax
+	movq	%rax, (%r8)
+	epilogue
+E FFI_TYPE_SINT32
+	movslq	%eax, %rax
+	movq	%rax, (%r8)
+	epilogue
+E FFI_TYPE_UINT64
+98:	movq	%rax, (%r8)
+	epilogue
+E FFI_TYPE_SINT64
+	movq	%rax, (%r8)
+	epilogue
+E FFI_TYPE_STRUCT
+	epilogue
+E FFI_TYPE_POINTER
+	movq	%rax, (%r8)
+	epilogue
+E FFI_TYPE_COMPLEX
+	call	abort
+E FFI_TYPE_SMALL_STRUCT_1B
+	movb	%al, (%r8)
+	epilogue
+E FFI_TYPE_SMALL_STRUCT_2B
+	movw	%ax, (%r8)
+	epilogue
+E FFI_TYPE_SMALL_STRUCT_4B
+	movl	%eax, (%r8)
+	epilogue
+
+	.align	8
+99:	call	abort
+
+.purgem epilogue
+
+	cfi_endproc
 	.seh_endproc
 
-	.balign 16
-	.globl	SYMBOL_NAME(ffi_call_win64)
-	.seh_proc SYMBOL_NAME(ffi_call_win64)
-SYMBOL_NAME(ffi_call_win64):
-	# copy registers onto stack
-	mov	%r9,32(%rsp)
-	mov	%r8,24(%rsp)
-	mov	%rdx,16(%rsp)
-	mov	%rcx,8(%rsp)
-	.seh_pushreg rbp
-	push	%rbp
-	.seh_stackalloc 48
-	sub	$48,%rsp
-	.seh_setframe rbp, 32
-	lea	32(%rsp),%rbp
+
+/* 32 bytes of outgoing register stack space, 8 bytes of alignment,
+   16 bytes of result, 32 bytes of xmm registers.  */
+#define ffi_clo_FS	(32+8+16+32)
+#define ffi_clo_OFF_R	(32+8)
+#define ffi_clo_OFF_X	(32+8+16)
+
+	.align	8
+	.globl	ffi_go_closure_win64
+
+	.seh_proc ffi_go_closure_win64
+ffi_go_closure_win64:
+	cfi_startproc
+	/* Save all integer arguments into the incoming reg stack space.  */
+	movq	arg0, 8(%rsp)
+	movq	arg1, 16(%rsp)
+	movq	arg2, 24(%rsp)
+	movq	arg3, 32(%rsp)
+
+	movq	8(%r10), arg0			/* load cif */
+	movq	16(%r10), arg1			/* load fun */
+	movq	%r10, arg2			/* closure is user_data */
+	jmp	0f
+	cfi_endproc
+	.seh_endproc
+
+	.align	8
+	.globl	ffi_closure_win64
+
+	.seh_proc ffi_closure_win64
+ffi_closure_win64:
+	cfi_startproc
+	/* Save all integer arguments into the incoming reg stack space.  */
+	movq	arg0, 8(%rsp)
+	movq	arg1, 16(%rsp)
+	movq	arg2, 24(%rsp)
+	movq	arg3, 32(%rsp)
+
+	movq	FFI_TRAMPOLINE_SIZE(%r10), arg0		/* load cif */
+	movq	FFI_TRAMPOLINE_SIZE+8(%r10), arg1	/* load fun */
+	movq	FFI_TRAMPOLINE_SIZE+16(%r10), arg2	/* load user_data */
+0:
+	subq	$ffi_clo_FS, %rsp
+	cfi_adjust_cfa_offset(ffi_clo_FS)
+	.seh_stackalloc ffi_clo_FS
 	.seh_endprologue
 
-	mov	CIF_BYTES(%rbp),%eax
-	add	$15, %rax
-	and	$-16, %rax
-	cmpq	$0x1000, %rax
-	jb	Lch_done
-Lch_probe:
-	subq	$0x1000,%rsp
-	orl	$0x0, (%rsp)
-	subq	$0x1000,%rax
-	cmpq	$0x1000,%rax
-	ja	Lch_probe
-Lch_done:
-	subq	%rax, %rsp
-	orl	$0x0, (%rsp)
-	lea	32(%rsp), %rax
-	mov	%rax, STACK(%rbp)
+	/* Save all sse arguments into the stack frame.  */
+	movsd	%xmm0, ffi_clo_OFF_X(%rsp)
+	movsd	%xmm1, ffi_clo_OFF_X+8(%rsp)
+	movsd	%xmm2, ffi_clo_OFF_X+16(%rsp)
+	movsd	%xmm3, ffi_clo_OFF_X+24(%rsp)
 
-	mov	ECIF(%rbp), %rdx
-	mov	STACK(%rbp), %rcx
-	callq	*PREP_ARGS_FN(%rbp)
+	leaq	ffi_clo_OFF_R(%rsp), arg3
+	call	ffi_closure_win64_inner
 
-	mov	STACK(%rbp), %rsp
+	/* Load the result into both possible result registers.  */
+	movq    ffi_clo_OFF_R(%rsp), %rax
+	movsd   ffi_clo_OFF_R(%rsp), %xmm0
 
-	movlpd	24(%rsp), %xmm3
-	movd	%xmm3, %r9
+	addq	$ffi_clo_FS, %rsp
+	cfi_adjust_cfa_offset(-ffi_clo_FS)
+	ret
 
-	movlpd	16(%rsp), %xmm2
-	movd	%xmm2, %r8
-
-	movlpd	8(%rsp), %xmm1
-	movd	%xmm1, %rdx
-
-	movlpd	(%rsp), %xmm0
-	movd	%xmm0, %rcx
-
-	callq	*FN(%rbp)
-.Lret_struct4b:
- 	cmpl	$FFI_TYPE_SMALL_STRUCT_4B, CIF_FLAGS(%rbp)
- 	jne .Lret_struct2b
-
-	mov	RVALUE(%rbp), %rcx
-	mov	%eax, (%rcx)
-	jmp	.Lret_void
-
-.Lret_struct2b:
-	cmpl	$FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp)
-	jne .Lret_struct1b
-
-	mov	RVALUE(%rbp), %rcx
-	mov	%ax, (%rcx)
-	jmp .Lret_void
-
-.Lret_struct1b:
-	cmpl	$FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp)
-	jne .Lret_uint8
-
-	mov	RVALUE(%rbp), %rcx
-	mov	%al, (%rcx)
-	jmp .Lret_void
-
-.Lret_uint8:
-	cmpl	$FFI_TYPE_UINT8, CIF_FLAGS(%rbp)
-	jne .Lret_sint8
-
-	mov     RVALUE(%rbp), %rcx
-	movzbq  %al, %rax
-	movq    %rax, (%rcx)
-	jmp .Lret_void
-
-.Lret_sint8:
-	cmpl	$FFI_TYPE_SINT8, CIF_FLAGS(%rbp)
-	jne .Lret_uint16
-
-	mov     RVALUE(%rbp), %rcx
-	movsbq  %al, %rax
-	movq    %rax, (%rcx)
-	jmp .Lret_void
-
-.Lret_uint16:
-	cmpl	$FFI_TYPE_UINT16, CIF_FLAGS(%rbp)
-	jne .Lret_sint16
-
-	mov     RVALUE(%rbp), %rcx
-	movzwq  %ax, %rax
-	movq    %rax, (%rcx)
-	jmp .Lret_void
-
-.Lret_sint16:
-	cmpl	$FFI_TYPE_SINT16, CIF_FLAGS(%rbp)
-	jne .Lret_uint32
-
-	mov     RVALUE(%rbp), %rcx
-	movswq  %ax, %rax
-	movq    %rax, (%rcx)
-	jmp .Lret_void
-
-.Lret_uint32:
-	cmpl	$FFI_TYPE_UINT32, CIF_FLAGS(%rbp)
-	jne .Lret_sint32
-
-	mov     RVALUE(%rbp), %rcx
-	movl    %eax, %eax
-	movq    %rax, (%rcx)
-	jmp .Lret_void
-
-.Lret_sint32:
- 	cmpl	$FFI_TYPE_SINT32, CIF_FLAGS(%rbp)
- 	jne	.Lret_float
-
-	mov	RVALUE(%rbp), %rcx
-	cltq
-	movq	%rax, (%rcx)
-	jmp	.Lret_void
-
-.Lret_float:
- 	cmpl	$FFI_TYPE_FLOAT, CIF_FLAGS(%rbp)
- 	jne	.Lret_double
-
- 	mov	RVALUE(%rbp), %rax
- 	movss	%xmm0, (%rax)
- 	jmp	.Lret_void
-
-.Lret_double:
- 	cmpl	$FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp)
- 	jne	.Lret_uint64
-
- 	mov	RVALUE(%rbp), %rax
- 	movlpd	%xmm0, (%rax)
- 	jmp	.Lret_void
-
-.Lret_uint64:
-  	cmpl	$FFI_TYPE_UINT64, CIF_FLAGS(%rbp)
- 	jne	.Lret_sint64
-
- 	mov	RVALUE(%rbp), %rcx
- 	mov	%rax, (%rcx)
- 	jmp	.Lret_void
-
-.Lret_sint64:
-  	cmpl	$FFI_TYPE_SINT64, CIF_FLAGS(%rbp)
-  	jne	.Lret_pointer
-
- 	mov	RVALUE(%rbp), %rcx
- 	mov	%rax, (%rcx)
- 	jmp	.Lret_void
-
-.Lret_pointer:
-  	cmpl	$FFI_TYPE_POINTER, CIF_FLAGS(%rbp)
-  	jne	.Lret_int
-
- 	mov	RVALUE(%rbp), %rcx
- 	mov	%rax, (%rcx)
- 	jmp	.Lret_void
-
-.Lret_int:
-  	cmpl	$FFI_TYPE_INT, CIF_FLAGS(%rbp)
-  	jne	.Lret_void
-
-	mov	RVALUE(%rbp), %rcx
-	cltq
-	movq	%rax, (%rcx)
-	jmp	.Lret_void
-
-.Lret_void:
-	xor	%rax, %rax
-
-	lea	16(%rbp), %rsp
-	pop	%rbp
-	retq
+	cfi_endproc
 	.seh_endproc
-#endif /* !_MSC_VER */
-
diff --git a/third_party/gofrontend/libffi/src/xtensa/ffi.c b/third_party/gofrontend/libffi/src/xtensa/ffi.c
new file mode 100644
index 0000000..fd94daf
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/xtensa/ffi.c
@@ -0,0 +1,298 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2013 Tensilica, Inc.
+
+   XTENSA Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+/*
+                                 |----------------------------------------|
+                                 |                                        |
+    on entry to ffi_call ---->   |----------------------------------------|
+                                 | caller stack frame for registers a0-a3 |
+                                 |----------------------------------------|
+                                 |                                        |
+                                 |         additional arguments           |
+    entry of the function --->   |----------------------------------------|
+                                 |    copy of function arguments a2-a7    |
+                                 | -  -  -  -  -  -  -  -  -  -  -  -  -  |
+                                 |                                        |
+
+    The area below the entry line becomes the new stack frame for the function.
+
+*/
+
+
+#define FFI_TYPE_STRUCT_REGS FFI_TYPE_LAST
+
+
+extern void ffi_call_SYSV(void *rvalue, unsigned rsize, unsigned flags,
+			  void(*fn)(void), unsigned nbytes, extended_cif*);
+extern void ffi_closure_SYSV(void) FFI_HIDDEN;
+
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  switch(cif->rtype->type) {
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_UINT16:
+      cif->flags = cif->rtype->type;
+      break;
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+      cif->flags = FFI_TYPE_UINT32;
+      break;
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      cif->flags = FFI_TYPE_UINT64; // cif->rtype->type;
+      break;
+    case FFI_TYPE_STRUCT:
+      cif->flags = FFI_TYPE_STRUCT; //_REGS;
+      /* Up to 16 bytes are returned in registers */
+      if (cif->rtype->size > 4 * 4) {
+        /* returned structure is referenced by a register; use 8 bytes
+           (including 4 bytes for potential additional alignment) */
+        cif->flags = FFI_TYPE_STRUCT;	
+        cif->bytes += 8;
+      }
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_UINT32;
+      break;
+  }
+
+  /* Round the stack up to a full 4 register frame, just in case
+     (we use this size in movsp). This way, it's also a  multiple of
+     8 bytes for 64-bit arguments.  */
+  cif->bytes = ALIGN(cif->bytes, 16);
+
+  return FFI_OK;
+}
+
+void ffi_prep_args(extended_cif *ecif, unsigned char* stack)
+{
+  unsigned int i;
+  unsigned long *addr;
+  ffi_type **ptr;
+
+  union {
+    void **v;
+    char **c;
+    signed char **sc;
+    unsigned char **uc;
+    signed short **ss;
+    unsigned short **us;
+    unsigned int **i;
+    long long **ll;
+    float **f;
+    double **d;
+  } p_argv;
+
+  /* Verify that everything is aligned up properly */
+  FFI_ASSERT (((unsigned long) stack & 0x7) == 0);
+
+  p_argv.v = ecif->avalue;
+  addr = (unsigned long*)stack;
+
+  /* structures with a size greater than 16 bytes are passed in memory */
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 16)
+  {
+    *addr++ = (unsigned long)ecif->rvalue;
+  }
+
+  for (i = ecif->cif->nargs, ptr = ecif->cif->arg_types;
+       i > 0;
+       i--, ptr++, p_argv.v++)
+  {
+    switch ((*ptr)->type)
+    {
+      case FFI_TYPE_SINT8:
+        *addr++ = **p_argv.sc;
+        break;
+      case FFI_TYPE_UINT8:
+        *addr++ = **p_argv.uc;
+        break;
+      case FFI_TYPE_SINT16:
+        *addr++ = **p_argv.ss;
+        break;
+      case FFI_TYPE_UINT16:
+        *addr++ = **p_argv.us;
+        break;
+      case FFI_TYPE_FLOAT:
+      case FFI_TYPE_INT:
+      case FFI_TYPE_UINT32:
+      case FFI_TYPE_SINT32:
+      case FFI_TYPE_POINTER:
+        *addr++ = **p_argv.i;
+        break;
+      case FFI_TYPE_DOUBLE:
+      case FFI_TYPE_UINT64:
+      case FFI_TYPE_SINT64:
+        if (((unsigned long)addr & 4) != 0)
+          addr++;
+        *(unsigned long long*)addr = **p_argv.ll;
+	addr += sizeof(unsigned long long) / sizeof (addr);
+        break;
+
+      case FFI_TYPE_STRUCT:
+      {
+        unsigned long offs;
+        unsigned long size;
+
+        if (((unsigned long)addr & 4) != 0 && (*ptr)->alignment > 4)
+          addr++;
+
+        offs = (unsigned long) addr - (unsigned long) stack;
+        size = (*ptr)->size;
+
+        /* Entire structure must fit the argument registers or referenced */
+        if (offs < FFI_REGISTER_NARGS * 4
+            && offs + size > FFI_REGISTER_NARGS * 4)
+          addr = (unsigned long*) (stack + FFI_REGISTER_NARGS * 4);
+
+        memcpy((char*) addr, *p_argv.c, size);
+        addr += (size + 3) / 4;
+        break;
+      }
+
+      default:
+        FFI_ASSERT(0);
+    }
+  }
+}
+
+
+void ffi_call(ffi_cif* cif, void(*fn)(void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+  unsigned long rsize = cif->rtype->size;
+  int flags = cif->flags;
+  void *alloc = NULL;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* Note that for structures that are returned in registers (size <= 16 bytes)
+     we allocate a temporary buffer and use memcpy to copy it to the final 
+     destination. The reason is that the target address might be misaligned or
+     the length not a multiple of 4 bytes. Handling all those cases would be
+     very complex.  */
+
+  if (flags == FFI_TYPE_STRUCT && (rsize <= 16 || rvalue == NULL))
+  {
+    alloc = alloca(ALIGN(rsize, 4));
+    ecif.rvalue = alloc;
+  }
+  else
+  {
+    ecif.rvalue = rvalue;
+  }
+
+  if (cif->abi != FFI_SYSV)
+    FFI_ASSERT(0);
+
+  ffi_call_SYSV (ecif.rvalue, rsize, cif->flags, fn, cif->bytes, &ecif);
+
+  if (alloc != NULL && rvalue != NULL)
+    memcpy(rvalue, alloc, rsize);
+}
+
+extern void ffi_trampoline();
+extern void ffi_cacheflush(void* start, void* end);
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure* closure,
+                      ffi_cif* cif,
+                      void (*fun)(ffi_cif*, void*, void**, void*),
+                      void *user_data,
+                      void *codeloc)
+{
+  /* copye trampoline to stack and patch 'ffi_closure_SYSV' pointer */
+  memcpy(closure->tramp, ffi_trampoline, FFI_TRAMPOLINE_SIZE);
+  *(unsigned int*)(&closure->tramp[8]) = (unsigned int)ffi_closure_SYSV;
+
+  // Do we have this function?
+  // __builtin___clear_cache(closer->tramp, closer->tramp + FFI_TRAMPOLINE_SIZE)
+  ffi_cacheflush(closure->tramp, closure->tramp + FFI_TRAMPOLINE_SIZE);
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+  return FFI_OK; 
+}
+
+
+long FFI_HIDDEN
+ffi_closure_SYSV_inner(ffi_closure *closure, void **values, void *rvalue)
+{
+  ffi_cif *cif;
+  ffi_type **arg_types;
+  void **avalue;
+  int i, areg;
+
+  cif = closure->cif;
+  if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+  areg = 0;
+
+  int rtype = cif->rtype->type;
+  if (rtype == FFI_TYPE_STRUCT && cif->rtype->size > 4 * 4)
+  {
+    rvalue = *values;
+    areg++;
+  }
+
+  cif = closure->cif; 
+  arg_types = cif->arg_types;
+  avalue = alloca(cif->nargs * sizeof(void *));
+
+  for (i = 0; i < cif->nargs; i++)
+  {
+    if (arg_types[i]->alignment == 8 && (areg & 1) != 0)
+      areg++;
+
+    // skip the entry 16,a1 framework, add 16 bytes (4 registers)
+    if (areg == FFI_REGISTER_NARGS)
+      areg += 4;
+
+    if (arg_types[i]->type == FFI_TYPE_STRUCT)
+    {
+      int numregs = ((arg_types[i]->size + 3) & ~3) / 4;
+      if (areg < FFI_REGISTER_NARGS && areg + numregs > FFI_REGISTER_NARGS)
+        areg = FFI_REGISTER_NARGS + 4;
+    }
+
+    avalue[i] = &values[areg];
+    areg += (arg_types[i]->size + 3) / 4;
+  }
+
+  (closure->fun)(cif, rvalue, avalue, closure->user_data);
+
+  return rtype;
+}
diff --git a/third_party/gofrontend/libffi/src/xtensa/ffitarget.h b/third_party/gofrontend/libffi/src/xtensa/ffitarget.h
new file mode 100644
index 0000000..0ba728b
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/xtensa/ffitarget.h
@@ -0,0 +1,53 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2013 Tensilica, Inc.
+   Target configuration macros for XTENSA.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long	ffi_arg;
+typedef signed long	ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_LAST_ABI,
+  FFI_DEFAULT_ABI = FFI_SYSV
+} ffi_abi;
+#endif
+
+#define FFI_REGISTER_NARGS	6
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+#define FFI_TRAMPOLINE_SIZE 24
+
+#endif
diff --git a/third_party/gofrontend/libffi/src/xtensa/sysv.S b/third_party/gofrontend/libffi/src/xtensa/sysv.S
new file mode 100644
index 0000000..64e6a09
--- /dev/null
+++ b/third_party/gofrontend/libffi/src/xtensa/sysv.S
@@ -0,0 +1,253 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2013 Tensilica, Inc.
+   
+   XTENSA Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+#define ENTRY(name) .text; .globl name; .type  name,@function; .align 4; name:
+#define END(name) .size name , . - name
+
+/* Assert that the table below is in sync with ffi.h.  */
+
+#if	   FFI_TYPE_UINT8 != 5          \
+        || FFI_TYPE_SINT8 != 6          \
+        || FFI_TYPE_UINT16 != 7         \
+        || FFI_TYPE_SINT16 != 8         \
+        || FFI_TYPE_UINT32 != 9         \
+        || FFI_TYPE_SINT32 != 10        \
+        || FFI_TYPE_UINT64 != 11
+#error "xtensa/sysv.S out of sync with ffi.h"
+#endif
+
+
+/* ffi_call_SYSV (rvalue, rbytes, flags, (*fnaddr)(), bytes, ecif)
+      void *rvalue;            a2
+      unsigned long rbytes;    a3
+      unsigned flags;          a4
+      void (*fnaddr)();        a5
+      unsigned long bytes;     a6
+      extended_cif* ecif)      a7
+*/
+
+ENTRY(ffi_call_SYSV)
+
+	entry	a1, 32              # 32 byte frame for using call8 below
+
+	mov	a10, a7             # a10(->arg0): ecif
+	sub	a11, a1, a6         # a11(->arg1): stack pointer
+	mov	a7, a1              # fp
+	movsp	a1, a11             # set new sp = old_sp - bytes
+
+	movi	a8, ffi_prep_args
+	callx8	a8                  # ffi_prep_args(ecif, stack)
+
+	# prepare to move stack pointer back up to 6 arguments
+	# note that 'bytes' is already aligned
+
+	movi	a10, 6*4 
+	sub	a11, a6, a10
+	movgez	a6, a10, a11
+	add	a6, a1, a6
+
+	
+	# we can pass up to 6 arguments in registers
+	# for simplicity, just load 6 arguments
+	# (the stack size is at least 32 bytes, so no risk to cross boundaries)
+
+	l32i	a10, a1, 0
+	l32i	a11, a1, 4
+	l32i	a12, a1, 8
+	l32i	a13, a1, 12
+	l32i	a14, a1, 16
+	l32i	a15, a1, 20
+
+	# move stack pointer
+
+	movsp	a1, a6
+
+	callx8	a5                  # (*fn)(args...)
+
+	# Handle return value(s)
+
+	beqz	a2, .Lexit
+
+	movi	a5, FFI_TYPE_STRUCT
+	bne	a4, a5, .Lstore
+	movi	a5, 16
+	blt	a5, a3, .Lexit
+
+	s32i	a10, a2, 0
+	blti	a3, 5, .Lexit
+	addi	a3, a3, -1
+	s32i	a11, a2, 4
+	blti	a3, 8, .Lexit
+	s32i	a12, a2, 8
+	blti	a3, 12, .Lexit
+	s32i	a13, a2, 12
+
+.Lexit:	retw
+
+.Lstore:
+	addi	a4, a4, -FFI_TYPE_UINT8
+	bgei	a4, 7, .Lexit	# should never happen
+	movi	a6, store_calls
+	add	a4, a4, a4
+	addx4	a6, a4, a6	# store_table + idx * 8
+	jx	a6
+
+	.align	8
+store_calls:
+	# UINT8
+	s8i	a10, a2, 0
+	retw
+
+	# SINT8
+	.align	8
+	s8i	a10, a2, 0
+	retw
+
+	# UINT16
+	.align	8
+	s16i	a10, a2, 0
+	retw
+
+	# SINT16
+	.align	8
+	s16i	a10, a2, 0
+	retw
+
+	# UINT32
+	.align	8
+	s32i	a10, a2, 0
+	retw
+
+	# SINT32
+	.align	8
+	s32i	a10, a2, 0
+	retw
+
+	# UINT64
+	.align	8
+	s32i	a10, a2, 0
+	s32i	a11, a2, 4
+	retw
+
+END(ffi_call_SYSV)
+
+
+/*
+ * void ffi_cacheflush (unsigned long start, unsigned long end)
+ */
+
+#define EXTRA_ARGS_SIZE	24
+
+ENTRY(ffi_cacheflush)
+
+	entry	a1, 16
+
+1:	dhwbi	a2, 0
+	ihi	a2, 0
+	addi	a2, a2, 4
+	blt	a2, a3, 1b
+
+	retw
+
+END(ffi_cacheflush)
+
+/* ffi_trampoline is copied to the stack */
+
+ENTRY(ffi_trampoline)
+
+	entry	a1, 16 + (FFI_REGISTER_NARGS * 4) + (4 * 4)   # [ 0]
+	j	2f                                # [ 3]
+	.align	4                                 # [ 6]
+1:	.long	0                                 # [ 8]
+2:	l32r	a15, 1b                           # [12]
+	_mov 	a14, a0                           # [15]
+	callx0	a15                               # [18]
+                                                  # [21]
+END(ffi_trampoline)
+
+/*
+ * ffi_closure()
+ *
+ * a0:  closure + 21
+ * a14: return address (a0)
+ */
+
+ENTRY(ffi_closure_SYSV)
+
+	/* intentionally omitting entry here */
+
+	# restore return address (a0) and move pointer to closure to a10
+	addi	a10, a0, -21
+	mov	a0, a14
+
+	# allow up to 4 arguments as return values
+	addi	a11, a1, 4 * 4
+
+	# save up to 6 arguments to stack (allocated by entry below)
+	s32i	a2, a11,  0
+	s32i	a3, a11,  4
+	s32i	a4, a11,  8
+	s32i	a5, a11, 12
+	s32i	a6, a11, 16
+	s32i	a7, a11, 20
+
+	movi	a8, ffi_closure_SYSV_inner
+	mov	a12, a1
+	callx8	a8			# .._inner(*closure, **avalue, *rvalue)
+
+	# load up to four return arguments
+	l32i	a2, a1,  0
+	l32i	a3, a1,  4
+	l32i	a4, a1,  8
+	l32i	a5, a1, 12
+
+	# (sign-)extend return value
+	movi	a11, FFI_TYPE_UINT8
+	bne	a10, a11, 1f
+	extui	a2, a2, 0, 8
+	retw
+
+1:	movi	a11, FFI_TYPE_SINT8
+	bne	a10, a11, 1f
+	sext	a2, a2, 7
+	retw
+
+1:	movi	a11, FFI_TYPE_UINT16
+	bne	a10, a11, 1f
+	extui	a2, a2, 0, 16
+	retw
+
+1:	movi	a11, FFI_TYPE_SINT16
+	bne	a10, a11, 1f
+	sext	a2, a2, 15
+
+1:	retw
+
+END(ffi_closure_SYSV)
diff --git a/third_party/gofrontend/libffi/testsuite/Makefile.am b/third_party/gofrontend/libffi/testsuite/Makefile.am
index 146fdf9..209e897 100644
--- a/third_party/gofrontend/libffi/testsuite/Makefile.am
+++ b/third_party/gofrontend/libffi/testsuite/Makefile.am
@@ -4,8 +4,8 @@
 
 # Setup the testing framework, if you have one
 EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \
-            echo $(top_builddir)/../expect/expect ; \
-          else echo expect ; fi`
+	    echo $(top_builddir)/../expect/expect ; \
+	  else echo expect ; fi`
 
 RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \
 	       echo $(top_srcdir)/../dejagnu/runtest ; \
@@ -15,71 +15,80 @@
 
 CLEANFILES = *.exe core* *.log *.sum
 
-EXTRA_DIST = config/default.exp libffi.call/cls_19byte.c \
-libffi.call/cls_align_longdouble_split.c libffi.call/closure_loc_fn0.c \
-libffi.call/cls_schar.c libffi.call/closure_fn1.c \
-libffi.call/many2_win32.c libffi.call/return_ul.c \
-libffi.call/cls_align_double.c libffi.call/return_fl2.c \
-libffi.call/cls_1_1byte.c libffi.call/cls_64byte.c \
-libffi.call/nested_struct7.c libffi.call/cls_align_sint32.c \
-libffi.call/nested_struct2.c libffi.call/ffitest.h \
-libffi.call/nested_struct4.c libffi.call/cls_multi_ushort.c \
-libffi.call/struct3.c libffi.call/cls_3byte1.c \
-libffi.call/cls_16byte.c libffi.call/struct8.c \
-libffi.call/nested_struct8.c libffi.call/cls_multi_sshort.c \
-libffi.call/cls_3byte2.c libffi.call/fastthis2_win32.c \
-libffi.call/cls_pointer.c libffi.call/err_bad_typedef.c \
-libffi.call/cls_4_1byte.c libffi.call/cls_9byte2.c \
-libffi.call/cls_multi_schar.c libffi.call/stret_medium2.c \
-libffi.call/cls_5_1_byte.c libffi.call/call.exp \
-libffi.call/cls_double.c libffi.call/cls_align_sint16.c \
-libffi.call/cls_uint.c libffi.call/return_ll1.c \
-libffi.call/nested_struct3.c libffi.call/cls_20byte1.c \
-libffi.call/closure_fn4.c libffi.call/cls_uchar.c \
-libffi.call/struct2.c libffi.call/cls_7byte.c libffi.call/strlen.c \
-libffi.call/many.c libffi.call/testclosure.c libffi.call/return_fl.c \
-libffi.call/struct5.c libffi.call/cls_12byte.c \
-libffi.call/cls_multi_sshortchar.c \
-libffi.call/cls_align_longdouble_split2.c libffi.call/return_dbl2.c \
-libffi.call/return_fl3.c libffi.call/stret_medium.c \
-libffi.call/nested_struct6.c libffi.call/a.out \
-libffi.call/closure_fn3.c libffi.call/float3.c libffi.call/many2.c \
-libffi.call/closure_stdcall.c libffi.call/cls_align_uint16.c \
-libffi.call/cls_9byte1.c libffi.call/closure_fn6.c \
-libffi.call/cls_double_va.c libffi.call/cls_align_pointer.c \
-libffi.call/cls_align_longdouble.c libffi.call/closure_fn2.c \
-libffi.call/cls_sshort.c libffi.call/many_win32.c \
-libffi.call/nested_struct.c libffi.call/cls_20byte.c \
-libffi.call/cls_longdouble.c libffi.call/cls_multi_uchar.c \
-libffi.call/return_uc.c libffi.call/closure_thiscall.c \
-libffi.call/cls_18byte.c libffi.call/cls_8byte.c \
-libffi.call/promotion.c libffi.call/struct1_win32.c \
-libffi.call/return_dbl.c libffi.call/cls_24byte.c \
-libffi.call/struct4.c libffi.call/cls_6byte.c \
-libffi.call/cls_align_uint32.c libffi.call/float.c \
-libffi.call/float1.c libffi.call/float_va.c libffi.call/negint.c \
-libffi.call/return_dbl1.c libffi.call/cls_3_1byte.c \
-libffi.call/cls_align_float.c libffi.call/return_fl1.c \
-libffi.call/nested_struct10.c libffi.call/nested_struct5.c \
-libffi.call/fastthis1_win32.c libffi.call/cls_align_sint64.c \
-libffi.call/stret_large2.c libffi.call/return_sl.c \
-libffi.call/closure_fn0.c libffi.call/cls_5byte.c \
-libffi.call/cls_2byte.c libffi.call/float2.c \
-libffi.call/cls_dbls_struct.c libffi.call/cls_sint.c \
-libffi.call/stret_large.c libffi.call/cls_ulonglong.c \
-libffi.call/cls_ushort.c libffi.call/nested_struct1.c \
-libffi.call/err_bad_abi.c libffi.call/cls_longdouble_va.c \
-libffi.call/cls_float.c libffi.call/cls_pointer_stack.c \
-libffi.call/pyobjc-tc.c libffi.call/cls_multi_ushortchar.c \
-libffi.call/struct1.c libffi.call/nested_struct9.c \
-libffi.call/huge_struct.c libffi.call/problem1.c libffi.call/float4.c \
-libffi.call/fastthis3_win32.c libffi.call/return_ldl.c \
-libffi.call/strlen2_win32.c libffi.call/closure_fn5.c \
-libffi.call/struct2_win32.c libffi.call/struct6.c \
-libffi.call/return_ll.c libffi.call/struct9.c libffi.call/return_sc.c \
-libffi.call/struct7.c libffi.call/cls_align_uint64.c \
-libffi.call/cls_4byte.c libffi.call/strlen_win32.c \
-libffi.call/cls_6_1_byte.c libffi.call/cls_7_1_byte.c \
-libffi.special/unwindtest.cc libffi.special/special.exp \
-libffi.special/unwindtest_ffi_call.cc libffi.special/ffitestcxx.h \
-lib/wrapper.exp lib/target-libpath.exp lib/libffi.exp
+EXTRA_DIST = config/default.exp libffi.call/cls_19byte.c		\
+libffi.call/cls_align_longdouble_split.c				\
+libffi.call/closure_loc_fn0.c libffi.call/cls_schar.c			\
+libffi.call/closure_fn1.c \
+libffi.call/return_ul.c libffi.call/cls_align_double.c			\
+libffi.call/return_fl2.c libffi.call/cls_1_1byte.c			\
+libffi.call/cls_64byte.c libffi.call/nested_struct7.c			\
+libffi.call/cls_align_sint32.c libffi.call/nested_struct2.c		\
+libffi.call/ffitest.h libffi.call/nested_struct4.c			\
+libffi.call/cls_multi_ushort.c libffi.call/struct3.c			\
+libffi.call/cls_3byte1.c libffi.call/cls_16byte.c			\
+libffi.call/struct8.c libffi.call/nested_struct8.c			\
+libffi.call/cls_multi_sshort.c libffi.call/cls_3byte2.c			\
+libffi.call/cls_pointer.c			\
+libffi.call/err_bad_typedef.c libffi.call/cls_4_1byte.c			\
+libffi.call/cls_9byte2.c libffi.call/cls_multi_schar.c			\
+libffi.call/stret_medium2.c libffi.call/cls_5_1_byte.c			\
+libffi.call/call.exp libffi.call/cls_double.c				\
+libffi.call/cls_align_sint16.c libffi.call/cls_uint.c			\
+libffi.call/return_ll1.c libffi.call/nested_struct3.c			\
+libffi.call/cls_20byte1.c libffi.call/closure_fn4.c			\
+libffi.call/cls_uchar.c libffi.call/struct2.c libffi.call/cls_7byte.c	\
+libffi.call/strlen.c libffi.call/many.c libffi.call/testclosure.c	\
+libffi.call/return_fl.c libffi.call/struct5.c				\
+libffi.call/cls_12byte.c libffi.call/cls_multi_sshortchar.c		\
+libffi.call/cls_align_longdouble_split2.c libffi.call/return_dbl2.c	\
+libffi.call/return_fl3.c libffi.call/stret_medium.c			\
+libffi.call/nested_struct6.c libffi.call/closure_fn3.c			\
+libffi.call/float3.c libffi.call/many2.c				\
+libffi.call/closure_simple.c libffi.call/cls_align_uint16.c		\
+libffi.call/cls_9byte1.c libffi.call/closure_fn6.c			\
+libffi.call/cls_double_va.c libffi.call/cls_align_pointer.c		\
+libffi.call/cls_align_longdouble.c libffi.call/closure_fn2.c		\
+libffi.call/cls_sshort.c \
+libffi.call/nested_struct.c libffi.call/cls_20byte.c			\
+libffi.call/cls_longdouble.c libffi.call/cls_multi_uchar.c		\
+libffi.call/return_uc.c \
+libffi.call/cls_18byte.c libffi.call/cls_8byte.c			\
+libffi.call/promotion.c \
+libffi.call/return_dbl.c libffi.call/cls_24byte.c			\
+libffi.call/struct4.c libffi.call/cls_6byte.c				\
+libffi.call/cls_align_uint32.c libffi.call/float.c			\
+libffi.call/float1.c libffi.call/float_va.c libffi.call/negint.c	\
+libffi.call/return_dbl1.c libffi.call/cls_3_1byte.c			\
+libffi.call/cls_align_float.c libffi.call/return_fl1.c			\
+libffi.call/nested_struct10.c libffi.call/nested_struct5.c		\
+libffi.call/cls_align_sint64.c		\
+libffi.call/stret_large2.c libffi.call/return_sl.c			\
+libffi.call/closure_fn0.c libffi.call/cls_5byte.c			\
+libffi.call/cls_2byte.c libffi.call/float2.c				\
+libffi.call/cls_dbls_struct.c libffi.call/cls_sint.c			\
+libffi.call/stret_large.c libffi.call/cls_ulonglong.c			\
+libffi.call/cls_ushort.c libffi.call/nested_struct1.c			\
+libffi.call/err_bad_abi.c libffi.call/cls_longdouble_va.c		\
+libffi.call/cls_float.c libffi.call/cls_pointer_stack.c		\
+libffi.call/pyobjc-tc.c libffi.call/cls_multi_ushortchar.c		\
+libffi.call/struct1.c libffi.call/nested_struct9.c			\
+libffi.call/huge_struct.c libffi.call/problem1.c			\
+libffi.call/float4.c \
+libffi.call/return_ldl.c \
+libffi.call/closure_fn5.c \
+libffi.call/struct6.c libffi.call/return_ll.c libffi.call/struct9.c	\
+libffi.call/return_sc.c libffi.call/struct7.c				\
+libffi.call/cls_align_uint64.c libffi.call/cls_4byte.c			\
+libffi.call/cls_6_1_byte.c			\
+libffi.call/cls_7_1_byte.c libffi.call/unwindtest.cc			\
+libffi.call/unwindtest_ffi_call.cc	\
+lib/wrapper.exp lib/target-libpath.exp	\
+lib/libffi.exp libffi.call/cls_struct_va1.c				\
+libffi.call/cls_uchar_va.c libffi.call/cls_uint_va.c			\
+libffi.call/cls_ulong_va.c libffi.call/cls_ushort_va.c			\
+libffi.call/nested_struct11.c libffi.call/uninitialized.c		\
+libffi.call/va_1.c libffi.call/va_struct1.c libffi.call/va_struct2.c	\
+libffi.call/va_struct3.c \
+libffi.call/strlen2.c \
+libffi.call/strlen3.c \
+libffi.call/strlen4.c
diff --git a/third_party/gofrontend/libffi/testsuite/Makefile.in b/third_party/gofrontend/libffi/testsuite/Makefile.in
index 808d4cb..cbfe35b 100644
--- a/third_party/gofrontend/libffi/testsuite/Makefile.in
+++ b/third_party/gofrontend/libffi/testsuite/Makefile.in
@@ -74,6 +74,10 @@
 CFLAGS = @CFLAGS@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -126,12 +130,14 @@
 STRIP = @STRIP@
 TARGET = @TARGET@
 TARGETDIR = @TARGETDIR@
+TARGET_OBJ = @TARGET_OBJ@
 VERSION = @VERSION@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
 abs_top_srcdir = @abs_top_srcdir@
 ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
 am__include = @am__include@
 am__leading_dot = @am__leading_dot@
@@ -189,82 +195,91 @@
 
 # Setup the testing framework, if you have one
 EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \
-            echo $(top_builddir)/../expect/expect ; \
-          else echo expect ; fi`
+	    echo $(top_builddir)/../expect/expect ; \
+	  else echo expect ; fi`
 
 RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \
 	       echo $(top_srcdir)/../dejagnu/runtest ; \
 	    else echo runtest; fi`
 
 CLEANFILES = *.exe core* *.log *.sum
-EXTRA_DIST = config/default.exp libffi.call/cls_19byte.c \
-libffi.call/cls_align_longdouble_split.c libffi.call/closure_loc_fn0.c \
-libffi.call/cls_schar.c libffi.call/closure_fn1.c \
-libffi.call/many2_win32.c libffi.call/return_ul.c \
-libffi.call/cls_align_double.c libffi.call/return_fl2.c \
-libffi.call/cls_1_1byte.c libffi.call/cls_64byte.c \
-libffi.call/nested_struct7.c libffi.call/cls_align_sint32.c \
-libffi.call/nested_struct2.c libffi.call/ffitest.h \
-libffi.call/nested_struct4.c libffi.call/cls_multi_ushort.c \
-libffi.call/struct3.c libffi.call/cls_3byte1.c \
-libffi.call/cls_16byte.c libffi.call/struct8.c \
-libffi.call/nested_struct8.c libffi.call/cls_multi_sshort.c \
-libffi.call/cls_3byte2.c libffi.call/fastthis2_win32.c \
-libffi.call/cls_pointer.c libffi.call/err_bad_typedef.c \
-libffi.call/cls_4_1byte.c libffi.call/cls_9byte2.c \
-libffi.call/cls_multi_schar.c libffi.call/stret_medium2.c \
-libffi.call/cls_5_1_byte.c libffi.call/call.exp \
-libffi.call/cls_double.c libffi.call/cls_align_sint16.c \
-libffi.call/cls_uint.c libffi.call/return_ll1.c \
-libffi.call/nested_struct3.c libffi.call/cls_20byte1.c \
-libffi.call/closure_fn4.c libffi.call/cls_uchar.c \
-libffi.call/struct2.c libffi.call/cls_7byte.c libffi.call/strlen.c \
-libffi.call/many.c libffi.call/testclosure.c libffi.call/return_fl.c \
-libffi.call/struct5.c libffi.call/cls_12byte.c \
-libffi.call/cls_multi_sshortchar.c \
-libffi.call/cls_align_longdouble_split2.c libffi.call/return_dbl2.c \
-libffi.call/return_fl3.c libffi.call/stret_medium.c \
-libffi.call/nested_struct6.c libffi.call/a.out \
-libffi.call/closure_fn3.c libffi.call/float3.c libffi.call/many2.c \
-libffi.call/closure_stdcall.c libffi.call/cls_align_uint16.c \
-libffi.call/cls_9byte1.c libffi.call/closure_fn6.c \
-libffi.call/cls_double_va.c libffi.call/cls_align_pointer.c \
-libffi.call/cls_align_longdouble.c libffi.call/closure_fn2.c \
-libffi.call/cls_sshort.c libffi.call/many_win32.c \
-libffi.call/nested_struct.c libffi.call/cls_20byte.c \
-libffi.call/cls_longdouble.c libffi.call/cls_multi_uchar.c \
-libffi.call/return_uc.c libffi.call/closure_thiscall.c \
-libffi.call/cls_18byte.c libffi.call/cls_8byte.c \
-libffi.call/promotion.c libffi.call/struct1_win32.c \
-libffi.call/return_dbl.c libffi.call/cls_24byte.c \
-libffi.call/struct4.c libffi.call/cls_6byte.c \
-libffi.call/cls_align_uint32.c libffi.call/float.c \
-libffi.call/float1.c libffi.call/float_va.c libffi.call/negint.c \
-libffi.call/return_dbl1.c libffi.call/cls_3_1byte.c \
-libffi.call/cls_align_float.c libffi.call/return_fl1.c \
-libffi.call/nested_struct10.c libffi.call/nested_struct5.c \
-libffi.call/fastthis1_win32.c libffi.call/cls_align_sint64.c \
-libffi.call/stret_large2.c libffi.call/return_sl.c \
-libffi.call/closure_fn0.c libffi.call/cls_5byte.c \
-libffi.call/cls_2byte.c libffi.call/float2.c \
-libffi.call/cls_dbls_struct.c libffi.call/cls_sint.c \
-libffi.call/stret_large.c libffi.call/cls_ulonglong.c \
-libffi.call/cls_ushort.c libffi.call/nested_struct1.c \
-libffi.call/err_bad_abi.c libffi.call/cls_longdouble_va.c \
-libffi.call/cls_float.c libffi.call/cls_pointer_stack.c \
-libffi.call/pyobjc-tc.c libffi.call/cls_multi_ushortchar.c \
-libffi.call/struct1.c libffi.call/nested_struct9.c \
-libffi.call/huge_struct.c libffi.call/problem1.c libffi.call/float4.c \
-libffi.call/fastthis3_win32.c libffi.call/return_ldl.c \
-libffi.call/strlen2_win32.c libffi.call/closure_fn5.c \
-libffi.call/struct2_win32.c libffi.call/struct6.c \
-libffi.call/return_ll.c libffi.call/struct9.c libffi.call/return_sc.c \
-libffi.call/struct7.c libffi.call/cls_align_uint64.c \
-libffi.call/cls_4byte.c libffi.call/strlen_win32.c \
-libffi.call/cls_6_1_byte.c libffi.call/cls_7_1_byte.c \
-libffi.special/unwindtest.cc libffi.special/special.exp \
-libffi.special/unwindtest_ffi_call.cc libffi.special/ffitestcxx.h \
-lib/wrapper.exp lib/target-libpath.exp lib/libffi.exp
+EXTRA_DIST = config/default.exp libffi.call/cls_19byte.c		\
+libffi.call/cls_align_longdouble_split.c				\
+libffi.call/closure_loc_fn0.c libffi.call/cls_schar.c			\
+libffi.call/closure_fn1.c \
+libffi.call/return_ul.c libffi.call/cls_align_double.c			\
+libffi.call/return_fl2.c libffi.call/cls_1_1byte.c			\
+libffi.call/cls_64byte.c libffi.call/nested_struct7.c			\
+libffi.call/cls_align_sint32.c libffi.call/nested_struct2.c		\
+libffi.call/ffitest.h libffi.call/nested_struct4.c			\
+libffi.call/cls_multi_ushort.c libffi.call/struct3.c			\
+libffi.call/cls_3byte1.c libffi.call/cls_16byte.c			\
+libffi.call/struct8.c libffi.call/nested_struct8.c			\
+libffi.call/cls_multi_sshort.c libffi.call/cls_3byte2.c			\
+libffi.call/cls_pointer.c			\
+libffi.call/err_bad_typedef.c libffi.call/cls_4_1byte.c			\
+libffi.call/cls_9byte2.c libffi.call/cls_multi_schar.c			\
+libffi.call/stret_medium2.c libffi.call/cls_5_1_byte.c			\
+libffi.call/call.exp libffi.call/cls_double.c				\
+libffi.call/cls_align_sint16.c libffi.call/cls_uint.c			\
+libffi.call/return_ll1.c libffi.call/nested_struct3.c			\
+libffi.call/cls_20byte1.c libffi.call/closure_fn4.c			\
+libffi.call/cls_uchar.c libffi.call/struct2.c libffi.call/cls_7byte.c	\
+libffi.call/strlen.c libffi.call/many.c libffi.call/testclosure.c	\
+libffi.call/return_fl.c libffi.call/struct5.c				\
+libffi.call/cls_12byte.c libffi.call/cls_multi_sshortchar.c		\
+libffi.call/cls_align_longdouble_split2.c libffi.call/return_dbl2.c	\
+libffi.call/return_fl3.c libffi.call/stret_medium.c			\
+libffi.call/nested_struct6.c libffi.call/closure_fn3.c			\
+libffi.call/float3.c libffi.call/many2.c				\
+libffi.call/closure_simple.c libffi.call/cls_align_uint16.c		\
+libffi.call/cls_9byte1.c libffi.call/closure_fn6.c			\
+libffi.call/cls_double_va.c libffi.call/cls_align_pointer.c		\
+libffi.call/cls_align_longdouble.c libffi.call/closure_fn2.c		\
+libffi.call/cls_sshort.c \
+libffi.call/nested_struct.c libffi.call/cls_20byte.c			\
+libffi.call/cls_longdouble.c libffi.call/cls_multi_uchar.c		\
+libffi.call/return_uc.c \
+libffi.call/cls_18byte.c libffi.call/cls_8byte.c			\
+libffi.call/promotion.c \
+libffi.call/return_dbl.c libffi.call/cls_24byte.c			\
+libffi.call/struct4.c libffi.call/cls_6byte.c				\
+libffi.call/cls_align_uint32.c libffi.call/float.c			\
+libffi.call/float1.c libffi.call/float_va.c libffi.call/negint.c	\
+libffi.call/return_dbl1.c libffi.call/cls_3_1byte.c			\
+libffi.call/cls_align_float.c libffi.call/return_fl1.c			\
+libffi.call/nested_struct10.c libffi.call/nested_struct5.c		\
+libffi.call/cls_align_sint64.c		\
+libffi.call/stret_large2.c libffi.call/return_sl.c			\
+libffi.call/closure_fn0.c libffi.call/cls_5byte.c			\
+libffi.call/cls_2byte.c libffi.call/float2.c				\
+libffi.call/cls_dbls_struct.c libffi.call/cls_sint.c			\
+libffi.call/stret_large.c libffi.call/cls_ulonglong.c			\
+libffi.call/cls_ushort.c libffi.call/nested_struct1.c			\
+libffi.call/err_bad_abi.c libffi.call/cls_longdouble_va.c		\
+libffi.call/cls_float.c libffi.call/cls_pointer_stack.c		\
+libffi.call/pyobjc-tc.c libffi.call/cls_multi_ushortchar.c		\
+libffi.call/struct1.c libffi.call/nested_struct9.c			\
+libffi.call/huge_struct.c libffi.call/problem1.c			\
+libffi.call/float4.c \
+libffi.call/return_ldl.c \
+libffi.call/closure_fn5.c \
+libffi.call/struct6.c libffi.call/return_ll.c libffi.call/struct9.c	\
+libffi.call/return_sc.c libffi.call/struct7.c				\
+libffi.call/cls_align_uint64.c libffi.call/cls_4byte.c			\
+libffi.call/cls_6_1_byte.c			\
+libffi.call/cls_7_1_byte.c libffi.call/unwindtest.cc			\
+libffi.call/unwindtest_ffi_call.cc	\
+lib/wrapper.exp lib/target-libpath.exp	\
+lib/libffi.exp libffi.call/cls_struct_va1.c				\
+libffi.call/cls_uchar_va.c libffi.call/cls_uint_va.c			\
+libffi.call/cls_ulong_va.c libffi.call/cls_ushort_va.c			\
+libffi.call/nested_struct11.c libffi.call/uninitialized.c		\
+libffi.call/va_1.c libffi.call/va_struct1.c libffi.call/va_struct2.c	\
+libffi.call/va_struct3.c \
+libffi.call/strlen2.c \
+libffi.call/strlen3.c \
+libffi.call/strlen4.c
 
 all: all-am
 
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_simple.c b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_simple.c
new file mode 100644
index 0000000..5a4e728
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_simple.c
@@ -0,0 +1,55 @@
+/* Area:	closure_call
+   Purpose:	Check simple closure handling with all ABIs
+   Limitations:	none.
+   PR:		none.
+   Originator:	<twalljava@dev.java.net> */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void
+closure_test(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(int *)args[0] + (int)(*(int *)args[1])
+    + (int)(*(int *)args[2])  + (int)(*(int *)args[3])
+    + (int)(intptr_t)userdata;
+
+  printf("%d %d %d %d: %d\n",
+	 (int)*(int *)args[0], (int)(*(int *)args[1]),
+	 (int)(*(int *)args[2]), (int)(*(int *)args[3]),
+         (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (ABI_ATTR *closure_test_type0)(int, int, int, int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+
+  cl_arg_types[0] = &ffi_type_uint;
+  cl_arg_types[1] = &ffi_type_uint;
+  cl_arg_types[2] = &ffi_type_uint;
+  cl_arg_types[3] = &ffi_type_uint;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 4,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+  res = (*(closure_test_type0)code)(0, 1, 2, 3);
+  /* { dg-output "0 1 2 3: 9" } */
+
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 9" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_stdcall.c b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_stdcall.c
deleted file mode 100644
index 1407f02..0000000
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_stdcall.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Area:	closure_call (stdcall convention)
-   Purpose:	Check handling when caller expects stdcall callee
-   Limitations:	none.
-   PR:		none.
-   Originator:	<twalljava@dev.java.net> */
-
-/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
-#include "ffitest.h"
-
-static void
-closure_test_stdcall(ffi_cif* cif __UNUSED__, void* resp, void** args,
-		 void* userdata)
-{
-  *(ffi_arg*)resp =
-    (int)*(int *)args[0] + (int)(*(int *)args[1])
-    + (int)(*(int *)args[2])  + (int)(*(int *)args[3])
-    + (int)(intptr_t)userdata;
-
-  printf("%d %d %d %d: %d\n",
-	 (int)*(int *)args[0], (int)(*(int *)args[1]),
-	 (int)(*(int *)args[2]), (int)(*(int *)args[3]),
-         (int)*(ffi_arg *)resp);
-
-}
-
-typedef int (__stdcall *closure_test_type0)(int, int, int, int);
-
-int main (void)
-{
-  ffi_cif cif;
-  void *code;
-  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
-  ffi_type * cl_arg_types[17];
-  int res;
-  void* sp_pre;
-  void* sp_post;
-  char buf[1024];
-
-  cl_arg_types[0] = &ffi_type_uint;
-  cl_arg_types[1] = &ffi_type_uint;
-  cl_arg_types[2] = &ffi_type_uint;
-  cl_arg_types[3] = &ffi_type_uint;
-  cl_arg_types[4] = NULL;
-
-  /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 4,
-		     &ffi_type_sint, cl_arg_types) == FFI_OK);
-
-  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_stdcall,
-                             (void *) 3 /* userdata */, code) == FFI_OK);
-
-#ifdef _MSC_VER
-  __asm { mov sp_pre, esp }
-#else
-  asm volatile (" movl %%esp,%0" : "=g" (sp_pre));
-#endif
-  res = (*(closure_test_type0)code)(0, 1, 2, 3);
-#ifdef _MSC_VER
-  __asm { mov sp_post, esp }
-#else
-  asm volatile (" movl %%esp,%0" : "=g" (sp_post));
-#endif
-  /* { dg-output "0 1 2 3: 9" } */
-
-  printf("res: %d\n",res);
-  /* { dg-output "\nres: 9" } */
-
-  sprintf(buf, "mismatch: pre=%p vs post=%p", sp_pre, sp_post);
-  printf("stack pointer %s\n", (sp_pre == sp_post ? "match" : buf));
-  /* { dg-output "\nstack pointer match" } */
-  exit(0);
-}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_thiscall.c b/third_party/gofrontend/libffi/testsuite/libffi.call/closure_thiscall.c
deleted file mode 100644
index 0f93649..0000000
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/closure_thiscall.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Area:	closure_call (thiscall convention)
-   Purpose:	Check handling when caller expects thiscall callee
-   Limitations:	none.
-   PR:		none.
-   Originator:	<ktietz@redhat.com> */
-
-/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
-#include "ffitest.h"
-
-static void
-closure_test_thiscall(ffi_cif* cif __UNUSED__, void* resp, void** args,
-		      void* userdata)
-{
-  *(ffi_arg*)resp =
-    (int)*(int *)args[0] + (int)(*(int *)args[1])
-    + (int)(*(int *)args[2])  + (int)(*(int *)args[3])
-    + (int)(intptr_t)userdata;
-
-  printf("%d %d %d %d: %d\n",
-	 (int)*(int *)args[0], (int)(*(int *)args[1]),
-	 (int)(*(int *)args[2]), (int)(*(int *)args[3]),
-         (int)*(ffi_arg *)resp);
-
-}
-
-typedef int (__thiscall *closure_test_type0)(int, int, int, int);
-
-int main (void)
-{
-  ffi_cif cif;
-  void *code;
-  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
-  ffi_type * cl_arg_types[17];
-  int res;
-  void* sp_pre;
-  void* sp_post;
-  char buf[1024];
-
-  cl_arg_types[0] = &ffi_type_uint;
-  cl_arg_types[1] = &ffi_type_uint;
-  cl_arg_types[2] = &ffi_type_uint;
-  cl_arg_types[3] = &ffi_type_uint;
-  cl_arg_types[4] = NULL;
-
-  /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_THISCALL, 4,
-		     &ffi_type_sint, cl_arg_types) == FFI_OK);
-
-  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_thiscall,
-                             (void *) 3 /* userdata */, code) == FFI_OK);
-
-#ifdef _MSC_VER
-  __asm { mov sp_pre, esp }
-#else
-  asm volatile (" movl %%esp,%0" : "=g" (sp_pre));
-#endif
-  res = (*(closure_test_type0)code)(0, 1, 2, 3);
-#ifdef _MSC_VER
-  __asm { mov sp_post, esp }
-#else
-  asm volatile (" movl %%esp,%0" : "=g" (sp_post));
-#endif
-  /* { dg-output "0 1 2 3: 9" } */
-
-  printf("res: %d\n",res);
-  /* { dg-output "\nres: 9" } */
-
-  sprintf(buf, "mismatch: pre=%p vs post=%p", sp_pre, sp_post);
-  printf("stack pointer %s\n", (sp_pre == sp_post ? "match" : buf));
-  /* { dg-output "\nstack pointer match" } */
-  exit(0);
-}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split.c
index 15f9365..cc1c43b 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split.c
@@ -4,10 +4,8 @@
    PR:		none.
    Originator:	<hos@tamanegi.org> 20031203	 */
 
-/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
 /* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
 /* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
-/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
 
 #include "ffitest.h"
 
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c
index ca1c356..5d3bec0 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c
@@ -5,10 +5,8 @@
 	Originator:		Blake Chaffin	6/18/2007
 */
 
-/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
 /* { dg-do run { xfail strongarm*-*-* } } */
 /* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
-/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
 
 #include "ffitest.h"
 
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_longdouble.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_longdouble.c
index e6bac1f..d24e72e 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_longdouble.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_longdouble.c
@@ -4,10 +4,10 @@
    PR:			none.
    Originator:	Blake Chaffin	*/
 
-/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
-/* { dg-do run { xfail arm*-*-* strongarm*-*-* xscale*-*-* } } */
+/* This test is known to PASS on armv7l-unknown-linux-gnueabihf, so I have
+   remove the xfail for arm*-*-* below, until we know more.  */
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
 /* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
-/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
 
 #include "ffitest.h"
 
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_many_mixed_args.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_many_mixed_args.c
new file mode 100644
index 0000000..7fd6c82
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_many_mixed_args.c
@@ -0,0 +1,70 @@
+/* Area:	closure_call
+   Purpose:	Check closures called with many args of mixed types
+   Limitations:	none.
+   PR:		none.
+   Originator:	<david.schneider@picle.org> */
+
+/* { dg-do run } */
+#include "ffitest.h"
+#include <float.h>
+#include <math.h>
+
+#define NARGS 16
+
+static void cls_ret_double_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			      void* userdata __UNUSED__)
+{
+  int i;
+  double r = 0;
+  double t;
+  for(i = 0; i < NARGS; i++)
+    {
+    if(i == 4 || i == 9 || i == 11 || i == 13 || i == 15)
+      {
+      t = *(long int *)args[i];
+      CHECK(t == i+1);
+      }
+    else
+      {
+      t = *(double *)args[i];
+      CHECK(fabs(t - ((i+1) * 0.1)) < FLT_EPSILON);
+      }
+    r += t;
+    }
+  *(double *)resp = r;
+}
+typedef double (*cls_ret_double)(double, double, double, double, long int,
+double, double, double, double, long int, double, long int, double, long int,
+double, long int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[NARGS];
+  double res;
+  int i;
+  double expected = 64.9;
+
+  for(i = 0; i < NARGS; i++)
+    {
+    if(i == 4 || i == 9 || i == 11 || i == 13 || i == 15)
+      cl_arg_types[i] = &ffi_type_slong;
+    else
+      cl_arg_types[i] = &ffi_type_double;
+    }
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NARGS,
+		     &ffi_type_double, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_double_fn, NULL, code) == FFI_OK);
+
+  res = (((cls_ret_double)code))(0.1, 0.2, 0.3, 0.4, 5, 0.6, 0.7, 0.8, 0.9, 10,
+                                 1.1, 12, 1.3, 14, 1.5, 16);
+  if (fabs(res - expected) < FLT_EPSILON)
+    exit(0);
+  else
+    abort();
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_many_mixed_float_double.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_many_mixed_float_double.c
new file mode 100644
index 0000000..62b0697
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_many_mixed_float_double.c
@@ -0,0 +1,55 @@
+/* Area:	closure_call
+   Purpose:	Check register allocation for closure calls with many float and double arguments
+   Limitations:	none.
+   PR:		none.
+   Originator:	<david.schneider@picle.org> */
+
+/* { dg-do run } */
+#include "ffitest.h"
+#include <float.h>
+#include <math.h>
+
+#define NARGS 16
+
+static void cls_mixed_float_double_fn(ffi_cif* cif , void* ret, void** args,
+			      void* userdata __UNUSED__)
+{
+    double r = 0;
+    unsigned int i;
+    double t;
+    for(i=0; i < cif->nargs; i++)
+    {
+        if(cif->arg_types[i] == &ffi_type_double) {
+				t = *(((double**)(args))[i]);
+        } else {
+				t = *(((float**)(args))[i]);
+        }
+        r += t;
+    }
+    *((double*)ret) = r;
+}
+typedef double (*cls_mixed)(double, float, double, double, double, double, double, float, float, double, float, float);
+
+int main (void)
+{
+    ffi_cif cif;
+    ffi_closure *closure;
+	void* code;
+    ffi_type *argtypes[12] = {&ffi_type_double, &ffi_type_float, &ffi_type_double,
+                          &ffi_type_double, &ffi_type_double, &ffi_type_double,
+                          &ffi_type_double, &ffi_type_float, &ffi_type_float,
+                          &ffi_type_double, &ffi_type_float, &ffi_type_float};
+
+
+    closure = ffi_closure_alloc(sizeof(ffi_closure), (void**)&code);
+    if(closure ==NULL)
+		abort();
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 12, &ffi_type_double, argtypes) == FFI_OK);
+	CHECK(ffi_prep_closure_loc(closure, &cif, cls_mixed_float_double_fn, NULL,  code) == FFI_OK);
+    double ret = ((cls_mixed)code)(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2);
+    ffi_closure_free(closure);
+	if(fabs(ret - 7.8) < FLT_EPSILON)
+		exit(0);
+	else
+		abort();
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer.c
index cf03993..d82a87a 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer.c
@@ -35,7 +35,7 @@
         void *code;
 	ffi_closure*	pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
 	void*			args[3];
-//	ffi_type		cls_pointer_type;
+	/*	ffi_type		cls_pointer_type; */
 	ffi_type*		arg_types[3];
 
 /*	cls_pointer_type.size = sizeof(void*);
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer_stack.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer_stack.c
index e31139e..1f1d915 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer_stack.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_pointer_stack.c
@@ -98,7 +98,7 @@
         void *code;
 	ffi_closure*	pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
 	void*			args[3];
-//	ffi_type		cls_pointer_type;
+	/*	ffi_type		cls_pointer_type; */
 	ffi_type*		arg_types[3];
 
 /*	cls_pointer_type.size = sizeof(void*);
@@ -125,18 +125,18 @@
 	ffi_call(&cif, FFI_FN(cls_pointer_fn1), &res, args);
 
 	printf("res: 0x%08x\n", (unsigned int) res);
-	// { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" }
-	// { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" }
-	// { dg-output "\nres: 0x8bf258bd" }
+	/* { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" } */
+	/* { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" } */
+	/* { dg-output "\nres: 0x8bf258bd" } */
 
 	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_pointer_gn, NULL, code) == FFI_OK);
 
 	res = (ffi_arg)(uintptr_t)((void*(*)(void*, void*))(code))(arg1, arg2);
 
 	printf("res: 0x%08x\n", (unsigned int) res);
-	// { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" }
-	// { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" }
-	// { dg-output "\nres: 0x8bf258bd" }
+	/* { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" } */
+	/* { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" } */
+	/* { dg-output "\nres: 0x8bf258bd" } */
 
 	exit(0);
 }
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_struct_va1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_struct_va1.c
index 7262d63..6d1fdae 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_struct_va1.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_struct_va1.c
@@ -106,9 +106,9 @@
   CHECK(ffi_prep_closure_loc(pcl, &cif, test_fn, NULL, code) == FFI_OK);
 
   res = ((int (*)(int, ...))(code))(si, s1, l1, s2);
-  // { dg-output "4 5 6 10 11 12 13 14 20 21" }
+  /* { dg-output "4 5 6 10 11 12 13 14 20 21" } */
   printf("res: %d\n", (int) res);
-  // { dg-output "\nres: 42" }
+  /* { dg-output "\nres: 42" } */
 
   exit(0);
 }
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ulonglong.c b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ulonglong.c
index 235ab44..62f2cae 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ulonglong.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/cls_ulonglong.c
@@ -11,7 +11,7 @@
 static void cls_ret_ulonglong_fn(ffi_cif* cif __UNUSED__, void* resp,
 				 void** args, void* userdata __UNUSED__)
 {
-  *(unsigned long long *)resp=  *(unsigned long long *)args[0];
+  *(unsigned long long *)resp= 0xfffffffffffffffLL ^ *(unsigned long long *)args[0];
 
   printf("%" PRIuLL ": %" PRIuLL "\n",*(unsigned long long *)args[0],
 	 *(unsigned long long *)(resp));
@@ -34,14 +34,14 @@
 		     &ffi_type_uint64, cl_arg_types) == FFI_OK);
   CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_ulonglong_fn, NULL, code)  == FFI_OK);
   res = (*((cls_ret_ulonglong)code))(214LL);
-  /* { dg-output "214: 214" } */
+  /* { dg-output "214: 1152921504606846761" } */
   printf("res: %" PRIdLL "\n", res);
-  /* { dg-output "\nres: 214" } */
+  /* { dg-output "\nres: 1152921504606846761" } */
 
   res = (*((cls_ret_ulonglong)code))(9223372035854775808LL);
-  /* { dg-output "\n9223372035854775808: 9223372035854775808" } */
+  /* { dg-output "\n9223372035854775808: 8070450533247928831" } */
   printf("res: %" PRIdLL "\n", res);
-  /* { dg-output "\nres: 9223372035854775808" } */
+  /* { dg-output "\nres: 8070450533247928831" } */
 
   exit(0);
 }
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/ffitest.h b/third_party/gofrontend/libffi/testsuite/libffi.call/ffitest.h
index d81d4da..15d5e44 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/ffitest.h
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/ffitest.h
@@ -15,22 +15,25 @@
 
 #define MAX_ARGS 256
 
-#define CHECK(x) !(x) ? abort() : 0
+#define CHECK(x) (void)(!(x) ? (abort(), 1) : 0)
 
-/* Define __UNUSED__ that also other compilers than gcc can run the tests.  */
+/* Define macros so that compilers other than gcc can run the tests.  */
 #undef __UNUSED__
 #if defined(__GNUC__)
 #define __UNUSED__ __attribute__((__unused__))
+#define __STDCALL__ __attribute__((stdcall))
+#define __THISCALL__ __attribute__((thiscall))
+#define __FASTCALL__ __attribute__((fastcall))
 #else
 #define __UNUSED__
+#define __STDCALL__ __stdcall
+#define __THISCALL__ __thiscall
+#define __FASTCALL__ __fastcall
 #endif
 
-/* Define __FASTCALL__ so that other compilers than gcc can run the tests.  */
-#undef __FASTCALL__
-#if defined _MSC_VER
-#define __FASTCALL__ __fastcall
-#else
-#define __FASTCALL__ __attribute__((fastcall))
+#ifndef ABI_NUM
+#define ABI_NUM FFI_DEFAULT_ABI
+#define ABI_ATTR
 #endif
 
 /* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
@@ -127,44 +130,6 @@
 #define PRId64 "I64d"
 #endif
 
-#ifdef USING_MMAP
-static inline void *
-allocate_mmap (size_t size)
-{
-  void *page;
-#if defined (HAVE_MMAP_DEV_ZERO)
-  static int dev_zero_fd = -1;
-#endif
-
-#ifdef HAVE_MMAP_DEV_ZERO
-  if (dev_zero_fd == -1)
-    {
-      dev_zero_fd = open ("/dev/zero", O_RDONLY);
-      if (dev_zero_fd == -1)
-	{
-	  perror ("open /dev/zero: %m");
-	  exit (1);
-	}
-    }
-#endif
-
-
-#ifdef HAVE_MMAP_ANON
-  page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
-	       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-#endif
-#ifdef HAVE_MMAP_DEV_ZERO
-  page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
-	       MAP_PRIVATE, dev_zero_fd, 0);
-#endif
-
-  if (page == (void *) MAP_FAILED)
-    {
-      perror ("virtual memory exhausted");
-      exit (1);
-    }
-
-  return page;
-}
-
+#ifndef PRIuPTR
+#define PRIuPTR "u"
 #endif
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/float1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/float1.c
index 991d059..c48493c 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/float1.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/float1.c
@@ -8,6 +8,8 @@
 #include "ffitest.h"
 #include "float.h"
 
+#include <math.h>
+
 typedef union
 {
   double d;
@@ -47,7 +49,7 @@
 
   /* These are not always the same!! Check for a reasonable delta */
 
-  CHECK(result[0].d - dblit(f) < DBL_EPSILON);
+  CHECK(fabs(result[0].d - dblit(f)) < DBL_EPSILON);
 
   /* Check the canary.  */
   for (i = 0; i < sizeof (double); ++i)
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/float2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/float2.c
index a0b296c..20a8c40 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/float2.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/float2.c
@@ -3,13 +3,13 @@
    Limitations:	none.
    PR:		none.
    Originator:	From the original ffitest.c  */
-
-/* { dg-excess-errors "fails" { target x86_64-*-mingw* x86_64-*-cygwin* } } */
-/* { dg-do run { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-do run } */
 
 #include "ffitest.h"
 #include "float.h"
 
+#include <math.h>
+
 static long double ldblit(float f)
 {
   return (long double) (((long double) f)/ (long double) 3.0);
@@ -49,7 +49,7 @@
 #endif
 
   /* These are not always the same!! Check for a reasonable delta */
-  if (ld - ldblit(f) < LDBL_EPSILON)
+  if (fabsl(ld - ldblit(f)) < LDBL_EPSILON)
     puts("long double return value tests ok!");
   else
     CHECK(0);
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/float3.c b/third_party/gofrontend/libffi/testsuite/libffi.call/float3.c
index 76bd5f2..bab3206 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/float3.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/float3.c
@@ -9,6 +9,8 @@
 #include "ffitest.h"
 #include "float.h"
 
+#include <math.h>
+
 static double floating_1(float a, double b, long double c)
 {
   return (double) a + b + (double) c;
@@ -49,7 +51,7 @@
 
   ffi_call(&cif, FFI_FN(floating_1), &rd, values);
 
-  CHECK(rd - floating_1(f, d, ld) < DBL_EPSILON);
+  CHECK(fabs(rd - floating_1(f, d, ld)) < DBL_EPSILON);
 
   args[0] = &ffi_type_longdouble;
   values[0] = &ld;
@@ -66,7 +68,7 @@
 
   ffi_call(&cif, FFI_FN(floating_2), &rd, values);
 
-  CHECK(rd - floating_2(ld, d, f) < DBL_EPSILON);
+  CHECK(fabs(rd - floating_2(ld, d, f)) < DBL_EPSILON);
 
   exit (0);
 }
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/float_va.c b/third_party/gofrontend/libffi/testsuite/libffi.call/float_va.c
index aae158e..5acff91 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/float_va.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/float_va.c
@@ -56,9 +56,9 @@
    * different. */
   /* Call it statically and then via ffi */
   resfp=float_va_fn(0,2.0);
-  // { dg-output "0: 2.0 : total: 2.0" }
+  /* { dg-output "0: 2.0 : total: 2.0" } */
   printf("compiled: %.1f\n", resfp);
-  // { dg-output "\ncompiled: 2.0" }
+  /* { dg-output "\ncompiled: 2.0" } */
 
   arg_types[0] = &ffi_type_uint;
   arg_types[1] = &ffi_type_double;
@@ -71,16 +71,16 @@
   values[0] = &firstarg;
   values[1] = &doubles[0];
   ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
-  // { dg-output "\n0: 2.0 : total: 2.0" }
+  /* { dg-output "\n0: 2.0 : total: 2.0" } */
   printf("ffi: %.1f\n", resfp);
-  // { dg-output "\nffi: 2.0" }
+  /* { dg-output "\nffi: 2.0" } */
 
   /* Second test, float_va_fn(2,2.0,3.0,4.0), now with variadic params */
   /* Call it statically and then via ffi */
   resfp=float_va_fn(2,2.0,3.0,4.0);
-  // { dg-output "\n2: 2.0 : 0:3.0  1:4.0  total: 11.0" }
+  /* { dg-output "\n2: 2.0 : 0:3.0  1:4.0  total: 11.0" } */
   printf("compiled: %.1f\n", resfp);
-  // { dg-output "\ncompiled: 11.0" }
+  /* { dg-output "\ncompiled: 11.0" } */
 
   arg_types[0] = &ffi_type_uint;
   arg_types[1] = &ffi_type_double;
@@ -99,9 +99,9 @@
   values[2] = &doubles[1];
   values[3] = &doubles[2];
   ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
-  // { dg-output "\n2: 2.0 : 0:3.0  1:4.0  total: 11.0" }
+  /* { dg-output "\n2: 2.0 : 0:3.0  1:4.0  total: 11.0" } */
   printf("ffi: %.1f\n", resfp);
-  // { dg-output "\nffi: 11.0" }
+  /* { dg-output "\nffi: 11.0" } */
 
   exit(0);
 }
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/huge_struct.c b/third_party/gofrontend/libffi/testsuite/libffi.call/huge_struct.c
index 380fedf..187c42c 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/huge_struct.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/huge_struct.c
@@ -5,10 +5,9 @@
 	Originator:		Blake Chaffin	6/18/2007
 */
 
-/* { dg-excess-errors "" { target x86_64-*-mingw* x86_64-*-cygwin* } } */
 /* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
 /* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
-/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-options -Wformat=0 { target moxie*-*-elf } } */
 
 #include "ffitest.h"
 
@@ -295,7 +294,7 @@
 	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 50, &ret_struct_type, argTypes) == FFI_OK);
 
 	ffi_call(&cif, FFI_FN(test_large_fn), &retVal, argValues);
-	// { dg-output "1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
+	/* { dg-output "1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" } */
 	printf("res: %" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
 		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
 		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
@@ -308,7 +307,7 @@
 	       retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, (unsigned long)retVal.jj,
 		retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
 	       retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, (unsigned long)retVal.vv, retVal.ww, retVal.xx);
-	// { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
+	/* { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" } */
 
 	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_large_fn, NULL, code) == FFI_OK);
 
@@ -323,7 +322,7 @@
 		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
 		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
 		ui8, si8);
-	// { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
+	/* { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" } */
 	printf("res: %" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
 		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
 		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
@@ -336,7 +335,7 @@
 	       retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, (unsigned long)retVal.jj,
 		retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
 	       retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, (unsigned long)retVal.vv, retVal.ww, retVal.xx);
-	// { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
+	/* { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" } */
 
     return 0;
 }
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/many.c b/third_party/gofrontend/libffi/testsuite/libffi.call/many.c
index 4869ba9..336968c 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/many.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/many.c
@@ -7,21 +7,11 @@
 /* { dg-do run } */
 #include "ffitest.h"
 
+#include <stdlib.h>
 #include <float.h>
+#include <math.h>
 
-static float many(float f1,
-		  float f2,
-		  float f3,
-		  float f4,
-		  float f5,
-		  float f6,
-		  float f7,
-		  float f8,
-		  float f9,
-		  float f10,
-		  float f11,
-		  float f12,
-		  float f13)
+static float ABI_ATTR many(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13)
 {
 #if 0
   printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
@@ -30,7 +20,7 @@
 	 (double) f11, (double) f12, (double) f13);
 #endif
 
-  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+  return f1+f2+f3+f4+f5+f6+f7+f8+f9+f10+f11+f12+f13;
 }
 
 int main (void)
@@ -50,7 +40,7 @@
     }
 
     /* Initialize the cif */
-    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, 
+    CHECK(ffi_prep_cif(&cif, ABI_NUM, 13,
 		       &ffi_type_float, args) == FFI_OK);
 
     ffi_call(&cif, FFI_FN(many), &f, values);
@@ -62,7 +52,7 @@
 	       fa[8], fa[9],
 	       fa[10],fa[11],fa[12]);
 
-    if (f - ff < FLT_EPSILON)
+    if (fabs(f - ff) < FLT_EPSILON)
       exit(0);
     else
       abort();
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/many2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/many2.c
index 1077159..1c85746 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/many2.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/many2.c
@@ -12,14 +12,17 @@
 
 typedef unsigned char u8;
 
-__attribute__((noinline)) uint8_t
+#ifdef __GNUC__
+__attribute__((noinline))
+#endif
+uint8_t
 foo (uint8_t a, uint8_t b, uint8_t c, uint8_t d,
      uint8_t e, uint8_t f, uint8_t g)
 {
   return a + b + c + d + e + f + g;
 }
 
-uint8_t
+uint8_t ABI_ATTR
 bar (uint8_t a, uint8_t b, uint8_t c, uint8_t d,
      uint8_t e, uint8_t f, uint8_t g)
 {
@@ -39,7 +42,7 @@
   for (i = 0; i < NARGS; ++i)
     ffitypes[i] = &ffi_type_uint8;
 
-  CHECK (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, NARGS,
+  CHECK (ffi_prep_cif (&cif, ABI_NUM, NARGS,
 		       &ffi_type_uint8, ffitypes) == FFI_OK);
 
   for (i = 0; i < NARGS; ++i)
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/many2_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/many2_win32.c
deleted file mode 100644
index 4adbe4d..0000000
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/many2_win32.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Area:	ffi_call
-   Purpose:	Check stdcall many call on X86_WIN32 systems.
-   Limitations:	none.
-   PR:		none.
-   Originator:	From the original ffitest.c  */
-
-/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
-
-#include "ffitest.h"
-#include <float.h>
-
-static float __attribute__((fastcall)) fastcall_many(float f1,
-						   float f2,
-						   float f3,
-						   float f4,
-						   float f5,
-						   float f6,
-						   float f7,
-						   float f8,
-						   float f9,
-						   float f10,
-						   float f11,
-						   float f12,
-						   float f13)
-{
-  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
-}
-
-int main (void)
-{
-  ffi_cif cif;
-  ffi_type *args[13];
-  void *values[13];
-  float fa[13];
-  float f, ff;
-  unsigned long ul;
-
-  for (ul = 0; ul < 13; ul++)
-    {
-      args[ul] = &ffi_type_float;
-      values[ul] = &fa[ul];
-	fa[ul] = (float) ul;
-    }
-
-  /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 13,
-		     &ffi_type_float, args) == FFI_OK);
-
-  ff =  fastcall_many(fa[0], fa[1],
-		     fa[2], fa[3],
-		     fa[4], fa[5],
-		     fa[6], fa[7],
-		     fa[8], fa[9],
-		     fa[10], fa[11], fa[12]);
-
-  ffi_call(&cif, FFI_FN(fastcall_many), &f, values);
-
-  if (f - ff < FLT_EPSILON)
-    printf("fastcall many arg tests ok!\n");
-  else
-    CHECK(0);
-  exit(0);
-}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/many_double.c b/third_party/gofrontend/libffi/testsuite/libffi.call/many_double.c
new file mode 100644
index 0000000..4ef8c8a
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/many_double.c
@@ -0,0 +1,70 @@
+/* Area:	ffi_call
+   Purpose:	Check return value double, with many arguments
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+#include <stdlib.h>
+#include <float.h>
+#include <math.h>
+
+static double many(double f1,
+		  double f2,
+		  double f3,
+		  double f4,
+		  double f5,
+		  double f6,
+		  double f7,
+		  double f8,
+		  double f9,
+		  double f10,
+		  double f11,
+		  double f12,
+		  double f13)
+{
+#if 0
+  printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
+	 (double) f1, (double) f2, (double) f3, (double) f4, (double) f5, 
+	 (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
+	 (double) f11, (double) f12, (double) f13);
+#endif
+
+  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[13];
+  void *values[13];
+  double fa[13];
+  double f, ff;
+  int i;
+
+  for (i = 0; i < 13; i++)
+    {
+      args[i] = &ffi_type_double;
+      values[i] = &fa[i];
+      fa[i] = (double) i;
+    }
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, 
+		       &ffi_type_double, args) == FFI_OK);
+
+    ffi_call(&cif, FFI_FN(many), &f, values);
+
+    ff =  many(fa[0], fa[1],
+	       fa[2], fa[3],
+	       fa[4], fa[5],
+	       fa[6], fa[7],
+	       fa[8], fa[9],
+	       fa[10],fa[11],fa[12]);
+    if (fabs(f - ff) < FLT_EPSILON)
+      exit(0);
+    else
+      abort();
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/many_mixed.c b/third_party/gofrontend/libffi/testsuite/libffi.call/many_mixed.c
new file mode 100644
index 0000000..85ec36e
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/many_mixed.c
@@ -0,0 +1,78 @@
+/* Area:	ffi_call
+   Purpose:	Check return value double, with many arguments
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+#include <stdlib.h>
+#include <float.h>
+#include <math.h>
+
+static double many(double f1,
+		  double f2,
+		  long int i1,
+		  double f3,
+		  double f4,
+		  long int i2,
+		  double f5,
+		  double f6,
+		  long int i3,
+		  double f7,
+		  double f8,
+		  long int i4,
+		  double f9,
+		  double f10,
+		  long int i5,
+		  double f11,
+		  double f12,
+		  long int i6,
+		  double f13)
+{
+  return ((double) (i1 + i2 + i3 + i4 + i5 + i6) + (f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[19];
+  void *values[19];
+  double fa[19];
+  long int la[19];
+  double f, ff;
+  int i;
+
+  for (i = 0; i < 19; i++)
+    {
+	  if( (i - 2) % 3 == 0) {
+	    args[i] = &ffi_type_slong;
+	    la[i] = (long int) i;
+	    values[i] = &la[i];
+	  }
+	  else {
+	    args[i] = &ffi_type_double;
+	    fa[i] = (double) i;
+	    values[i] = &fa[i];
+	  }
+    }
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 19,
+		       &ffi_type_double, args) == FFI_OK);
+
+    ffi_call(&cif, FFI_FN(many), &f, values);
+
+    ff =  many(fa[0], fa[1], la[2],
+               fa[3], fa[4], la[5],
+               fa[6], fa[7], la[8],
+               fa[9], fa[10], la[11],
+               fa[12], fa[13], la[14],
+               fa[15], fa[16], la[17],
+               fa[18]);
+    if (fabs(f - ff) < FLT_EPSILON)
+      exit(0);
+    else
+      abort();
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/many_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/many_win32.c
deleted file mode 100644
index 1b26332..0000000
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/many_win32.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Area:	ffi_call
-   Purpose:	Check stdcall many call on X86_WIN32 systems.
-   Limitations:	none.
-   PR:		none.
-   Originator:	From the original ffitest.c  */
-
-/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
-
-#include "ffitest.h"
-#include <float.h>
-
-static float __attribute__((stdcall)) stdcall_many(float f1,
-						   float f2,
-						   float f3,
-						   float f4,
-						   float f5,
-						   float f6,
-						   float f7,
-						   float f8,
-						   float f9,
-						   float f10,
-						   float f11,
-						   float f12,
-						   float f13)
-{
-  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
-}
-
-int main (void)
-{
-  ffi_cif cif;
-  ffi_type *args[13];
-  void *values[13];
-  float fa[13];
-  float f, ff;
-  unsigned long ul;
-
-  for (ul = 0; ul < 13; ul++)
-    {
-      args[ul] = &ffi_type_float;
-      values[ul] = &fa[ul];
-	fa[ul] = (float) ul;
-    }
-
-  /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 13,
-		     &ffi_type_float, args) == FFI_OK);
-
-  ff =  stdcall_many(fa[0], fa[1],
-		     fa[2], fa[3],
-		     fa[4], fa[5],
-		     fa[6], fa[7],
-		     fa[8], fa[9],
-		     fa[10], fa[11], fa[12]);
-
-  ffi_call(&cif, FFI_FN(stdcall_many), &f, values);
-
-  if (f - ff < FLT_EPSILON)
-    printf("stdcall many arg tests ok!\n");
-  else
-    CHECK(0);
-  exit(0);
-}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/negint.c b/third_party/gofrontend/libffi/testsuite/libffi.call/negint.c
index 3168113..6e2f26f 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/negint.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/negint.c
@@ -5,7 +5,6 @@
    Originator:	From the original ffitest.c  */
 
 /* { dg-do run } */
-/* { dg-options -O2 } */
 
 #include "ffitest.h"
 
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct1.c
index 1087f7b..477a6b9 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct1.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct1.c
@@ -156,6 +156,6 @@
   CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
   CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
   CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
-  //  CHECK( 1 == 0);
+  /*  CHECK( 1 == 0); */
   exit(0);
 }
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct11.c b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct11.c
index fce6948..3510493 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct11.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/nested_struct11.c
@@ -1,7 +1,7 @@
 /* Area:	ffi_call, closure_call
    Purpose:	Check parameter passing with nested structs
 		of a single type.  This tests the special cases
-		for homogenous floating-point aggregates in the
+		for homogeneous floating-point aggregates in the
 		AArch64 PCS.
    Limitations:	none.
    PR:		none.
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_dbl.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_dbl.c
index 1aab403..fd07e50 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/return_dbl.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_dbl.c
@@ -9,6 +9,7 @@
 
 static double return_dbl(double dbl)
 {
+  printf ("%f\n", dbl);
   return 2 * dbl;
 }
 int main (void)
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_ldl.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_ldl.c
index 5c2fe65..52a92fe 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/return_ldl.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_ldl.c
@@ -3,8 +3,8 @@
    Limitations:	none.
    PR:		none.
    Originator:	<andreast@gcc.gnu.org> 20071113  */
+/* { dg-do run } */
 
-/* { dg-do run { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
 #include "ffitest.h"
 
 static long double return_ldl(long double ldl)
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/return_uc.c b/third_party/gofrontend/libffi/testsuite/libffi.call/return_uc.c
index 07c45de..6fe5546 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/return_uc.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/return_uc.c
@@ -32,7 +32,7 @@
        uc < (unsigned char) '\xff'; uc++)
     {
       ffi_call(&cif, FFI_FN(return_uc), &rint, values);
-      CHECK(rint == (signed int) uc);
+      CHECK((unsigned char)rint == uc);
     }
   exit(0);
 }
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large.c b/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large.c
index f32938c..71c2469 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large.c
@@ -9,8 +9,8 @@
 /* { dg-do run { xfail strongarm*-*-* xscale*-*-*  } } */
 #include "ffitest.h"
 
-// 13 FPRs: 104 bytes
-// 14 FPRs: 112 bytes
+/* 13 FPRs: 104 bytes */
+/* 14 FPRs: 112 bytes */
 
 typedef struct struct_108byte {
 	double a;
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large2.c
index 3b0ef9a..d9c750e 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large2.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/stret_large2.c
@@ -9,8 +9,8 @@
 /* { dg-do run { xfail strongarm*-*-* xscale*-*-*  } } */
 #include "ffitest.h"
 
-// 13 FPRs: 104 bytes
-// 14 FPRs: 112 bytes
+/* 13 FPRs: 104 bytes */
+/* 14 FPRs: 112 bytes */
 
 typedef struct struct_116byte {
 	double a;
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/strlen.c b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen.c
index 3de45de..35b70ea 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/strlen.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen.c
@@ -7,7 +7,7 @@
 /* { dg-do run } */
 #include "ffitest.h"
 
-static size_t my_strlen(char *s)
+static size_t ABI_ATTR my_strlen(char *s)
 {
   return (strlen(s));
 }
@@ -24,7 +24,7 @@
   values[0] = (void*) &s;
   
   /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1,
 		     &ffi_type_sint, args) == FFI_OK);
   
   s = "a";
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis1_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen2.c
similarity index 60%
rename from third_party/gofrontend/libffi/testsuite/libffi.call/fastthis1_win32.c
rename to third_party/gofrontend/libffi/testsuite/libffi.call/strlen2.c
index cbc4724..96282bc 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis1_win32.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen2.c
@@ -1,14 +1,14 @@
 /* Area:	ffi_call
-   Purpose:	Check fastcall fct call on X86_WIN32 systems.
+   Purpose:	Check strlen function call with additional arguments.
    Limitations:	none.
    PR:		none.
    Originator:	From the original ffitest.c  */
 
-/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+/* { dg-do run } */
 
 #include "ffitest.h"
 
-static size_t __FASTCALL__ my_fastcall_f(char *s, float a)
+static size_t ABI_ATTR my_f(char *s, float a)
 {
   return (size_t) ((int) strlen(s) + (int) a);
 }
@@ -27,24 +27,23 @@
   values[1] = (void*) &v2;
   
   /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 2,
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 2,
 		       &ffi_type_sint, args) == FFI_OK);
   
   s = "a";
   v2 = 0.0;
-  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
   CHECK(rint == 1);
   
   s = "1234567";
   v2 = -1.0;
-  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
   CHECK(rint == 6);
   
   s = "1234567890123456789012345";
   v2 = 1.0;
-  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
   CHECK(rint == 26);
   
-  printf("fastcall fct1 tests passed\n");
   exit(0);
 }
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/strlen2_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen2_win32.c
deleted file mode 100644
index 0d81061..0000000
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/strlen2_win32.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Area:	ffi_call
-   Purpose:	Check fastcall strlen call on X86_WIN32 systems.
-   Limitations:	none.
-   PR:		none.
-   Originator:	From the original ffitest.c  */
-
-/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
-
-#include "ffitest.h"
-
-static size_t __FASTCALL__ my_fastcall_strlen(char *s)
-{
-  return (strlen(s));
-}
-
-int main (void)
-{
-  ffi_cif cif;
-  ffi_type *args[MAX_ARGS];
-  void *values[MAX_ARGS];
-  ffi_arg rint;
-  char *s;
-  args[0] = &ffi_type_pointer;
-  values[0] = (void*) &s;
-  
-  /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 1,
-		       &ffi_type_sint, args) == FFI_OK);
-  
-  s = "a";
-  ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values);
-  CHECK(rint == 1);
-  
-  s = "1234567";
-  ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values);
-  CHECK(rint == 7);
-  
-  s = "1234567890123456789012345";
-  ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values);
-  CHECK(rint == 25);
-  
-  printf("fastcall strlen tests passed\n");
-  exit(0);
-}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis2_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen3.c
similarity index 60%
rename from third_party/gofrontend/libffi/testsuite/libffi.call/fastthis2_win32.c
rename to third_party/gofrontend/libffi/testsuite/libffi.call/strlen3.c
index 7bdd0e1..beba86e 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis2_win32.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen3.c
@@ -1,14 +1,14 @@
 /* Area:	ffi_call
-   Purpose:	Check fastcall fct call on X86_WIN32 systems.
+   Purpose:	Check strlen function call with additional arguments.
    Limitations:	none.
    PR:		none.
    Originator:	From the original ffitest.c  */
 
-/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+/* { dg-do run } */
 
 #include "ffitest.h"
 
-static size_t __FASTCALL__ my_fastcall_f(float a, char *s)
+static size_t ABI_ATTR my_f(float a, char *s)
 {
   return (size_t) ((int) strlen(s) + (int) a);
 }
@@ -27,24 +27,23 @@
   values[0] = (void*) &v2;
   
   /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 2,
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 2,
 		       &ffi_type_sint, args) == FFI_OK);
   
   s = "a";
   v2 = 0.0;
-  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
   CHECK(rint == 1);
   
   s = "1234567";
   v2 = -1.0;
-  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
   CHECK(rint == 6);
   
   s = "1234567890123456789012345";
   v2 = 1.0;
-  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
   CHECK(rint == 26);
   
-  printf("fastcall fct2 tests passed\n");
   exit(0);
 }
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis3_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen4.c
similarity index 63%
rename from third_party/gofrontend/libffi/testsuite/libffi.call/fastthis3_win32.c
rename to third_party/gofrontend/libffi/testsuite/libffi.call/strlen4.c
index b5d606d..d5d42b4 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/fastthis3_win32.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen4.c
@@ -1,14 +1,14 @@
 /* Area:	ffi_call
-   Purpose:	Check fastcall f call on X86_WIN32 systems.
+   Purpose:	Check strlen function call with additional arguments.
    Limitations:	none.
    PR:		none.
    Originator:	From the original ffitest.c  */
 
-/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+/* { dg-do run } */
 
 #include "ffitest.h"
 
-static size_t __FASTCALL__ my_fastcall_f(float a, char *s, int i)
+static size_t ABI_ATTR my_f(float a, char *s, int i)
 {
   return (size_t) ((int) strlen(s) + (int) a + i);
 }
@@ -30,27 +30,26 @@
   values[0] = (void*) &v2;
   
   /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 3,
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 3,
 		       &ffi_type_sint, args) == FFI_OK);
   
   s = "a";
   v1 = 1;
   v2 = 0.0;
-  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
   CHECK(rint == 2);
   
   s = "1234567";
   v2 = -1.0;
   v1 = -2;
-  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
   CHECK(rint == 4);
   
   s = "1234567890123456789012345";
   v2 = 1.0;
   v1 = 2;
-  ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
   CHECK(rint == 28);
   
-  printf("fastcall fct3 tests passed\n");
   exit(0);
 }
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/strlen_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/strlen_win32.c
deleted file mode 100644
index 6fbcc87..0000000
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/strlen_win32.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Area:	ffi_call
-   Purpose:	Check stdcall strlen call on X86_WIN32 systems.
-   Limitations:	none.
-   PR:		none.
-   Originator:	From the original ffitest.c  */
-
-/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
-
-#include "ffitest.h"
-
-static size_t __attribute__((stdcall)) my_stdcall_strlen(char *s)
-{
-  return (strlen(s));
-}
-
-int main (void)
-{
-  ffi_cif cif;
-  ffi_type *args[MAX_ARGS];
-  void *values[MAX_ARGS];
-  ffi_arg rint;
-  char *s;
-  args[0] = &ffi_type_pointer;
-  values[0] = (void*) &s;
-  
-  /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 1,
-		       &ffi_type_sint, args) == FFI_OK);
-  
-  s = "a";
-  ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
-  CHECK(rint == 1);
-  
-  s = "1234567";
-  ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
-  CHECK(rint == 7);
-  
-  s = "1234567890123456789012345";
-  ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
-  CHECK(rint == 25);
-  
-  printf("stdcall strlen tests passed\n");
-  exit(0);
-}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct1.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct1.c
index bfc23f6..c13e23f 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/struct1.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct1.c
@@ -14,7 +14,7 @@
   unsigned int ui;
 } test_structure_1;
 
-static test_structure_1 struct1(test_structure_1 ts)
+static test_structure_1 ABI_ATTR struct1(test_structure_1 ts)
 {
   ts.uc++;
   ts.d--;
@@ -50,7 +50,7 @@
   values[0] = &ts1_arg;
   
   /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1,
 		     &ts1_type, args) == FFI_OK);
   
   ts1_arg.uc = '\x01';
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct1_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct1_win32.c
deleted file mode 100644
index b756f5a..0000000
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/struct1_win32.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Area:	ffi_call
-   Purpose:	Check structures with fastcall/thiscall convention.
-   Limitations:	none.
-   PR:		none.
-   Originator:	From the original ffitest.c  */
-
-/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
-#include "ffitest.h"
-
-typedef struct
-{
-  unsigned char uc;
-  double d;
-  unsigned int ui;
-} test_structure_1;
-
-static test_structure_1 __FASTCALL__ struct1(test_structure_1 ts)
-{
-  ts.uc++;
-  ts.d--;
-  ts.ui++;
-
-  return ts;
-}
-
-int main (void)
-{
-  ffi_cif cif;
-  ffi_type *args[MAX_ARGS];
-  void *values[MAX_ARGS];
-  ffi_type ts1_type;
-  ffi_type *ts1_type_elements[4];
-
-  test_structure_1 ts1_arg;
-
-  /* This is a hack to get a properly aligned result buffer */
-  test_structure_1 *ts1_result =
-    (test_structure_1 *) malloc (sizeof(test_structure_1));
-
-  ts1_type.size = 0;
-  ts1_type.alignment = 0;
-  ts1_type.type = FFI_TYPE_STRUCT;
-  ts1_type.elements = ts1_type_elements;
-  ts1_type_elements[0] = &ffi_type_uchar;
-  ts1_type_elements[1] = &ffi_type_double;
-  ts1_type_elements[2] = &ffi_type_uint;
-  ts1_type_elements[3] = NULL;
-  
-  args[0] = &ts1_type;
-  values[0] = &ts1_arg;
-  
-  /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 1, 
-		     &ts1_type, args) == FFI_OK);
-  
-  ts1_arg.uc = '\x01';
-  ts1_arg.d = 3.14159;
-  ts1_arg.ui = 555;
-
-  ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
-  
-  CHECK(ts1_result->ui == 556);
-  CHECK(ts1_result->d == 3.14159 - 1);
- 
-  free (ts1_result);
-  exit(0);
-}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct2.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct2.c
index d85385e..5077a5e 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/struct2.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct2.c
@@ -13,7 +13,7 @@
   double d2;
 } test_structure_2;
 
-static test_structure_2 struct2(test_structure_2 ts)
+static test_structure_2 ABI_ATTR struct2(test_structure_2 ts)
 {
   ts.d1--;
   ts.d2--;
@@ -46,7 +46,7 @@
   values[0] = &ts2_arg;
   
   /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts2_type, args) == FFI_OK);
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts2_type, args) == FFI_OK);
   
   ts2_arg.d1 = 5.55;
   ts2_arg.d2 = 6.66;
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct2_win32.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct2_win32.c
deleted file mode 100644
index 5d02285..0000000
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/struct2_win32.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Area:	ffi_call
-   Purpose:	Check structures in fastcall/stdcall function
-   Limitations:	none.
-   PR:		none.
-   Originator:	From the original ffitest.c  */
-
-/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
-#include "ffitest.h"
-
-typedef struct
-{
-  double d1;
-  double d2;
-} test_structure_2;
-
-static test_structure_2 __FASTCALL__ struct2(test_structure_2 ts)
-{
-  ts.d1--;
-  ts.d2--;
-
-  return ts;
-}
-
-int main (void)
-{
-  ffi_cif cif;
-  ffi_type *args[MAX_ARGS];
-  void *values[MAX_ARGS];
-  test_structure_2 ts2_arg;
-  ffi_type ts2_type;
-  ffi_type *ts2_type_elements[3];
-
-  /* This is a hack to get a properly aligned result buffer */
-  test_structure_2 *ts2_result =
-    (test_structure_2 *) malloc (sizeof(test_structure_2));
-
-  ts2_type.size = 0;
-  ts2_type.alignment = 0;
-  ts2_type.type = FFI_TYPE_STRUCT;
-  ts2_type.elements = ts2_type_elements;
-  ts2_type_elements[0] = &ffi_type_double;
-  ts2_type_elements[1] = &ffi_type_double;
-  ts2_type_elements[2] = NULL;
-
-  args[0] = &ts2_type;
-  values[0] = &ts2_arg;
-  
-  /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 1, &ts2_type, args) == FFI_OK);
-  
-  ts2_arg.d1 = 5.55;
-  ts2_arg.d2 = 6.66;
-  
-  printf ("%g\n", ts2_arg.d1);
-  printf ("%g\n", ts2_arg.d2);
-  
-  ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
-  
-  printf ("%g\n", ts2_result->d1);
-  printf ("%g\n", ts2_result->d2);
-  
-  CHECK(ts2_result->d1 == 5.55 - 1);
-  CHECK(ts2_result->d2 == 6.66 - 1);
-  
-  free (ts2_result);
-  exit(0);
-}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct3.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct3.c
index de883c2..7eba0ea 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/struct3.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct3.c
@@ -12,7 +12,7 @@
   int si;
 } test_structure_3;
 
-static test_structure_3 struct3(test_structure_3 ts)
+static test_structure_3 ABI_ATTR struct3(test_structure_3 ts)
 {
   ts.si = -(ts.si*2);
 
@@ -43,7 +43,7 @@
   values[0] = &ts3_arg;
   
   /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1,
 		     &ts3_type, args) == FFI_OK);
   
   ts3_arg.si = -123;
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct4.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct4.c
index 48e0349..66a9551 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/struct4.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct4.c
@@ -14,7 +14,7 @@
   unsigned ui3;
 } test_structure_4;
 
-static test_structure_4 struct4(test_structure_4 ts)
+static test_structure_4 ABI_ATTR struct4(test_structure_4 ts)
 {
   ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
 
@@ -48,7 +48,7 @@
   values[0] = &ts4_arg;
   
   /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts4_type, args) == FFI_OK);
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts4_type, args) == FFI_OK);
   
   ts4_arg.ui1 = 2;
   ts4_arg.ui2 = 3;
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct5.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct5.c
index 28b1f0c..23e2a3f 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/struct5.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct5.c
@@ -12,7 +12,7 @@
   char c2;
 } test_structure_5;
 
-static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
+static test_structure_5 ABI_ATTR struct5(test_structure_5 ts1, test_structure_5 ts2)
 {
   ts1.c1 += ts2.c1;
   ts1.c2 -= ts2.c2;
@@ -48,7 +48,7 @@
   values[1] = &ts5_arg2;
   
   /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ts5_type, args) == FFI_OK);
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 2, &ts5_type, args) == FFI_OK);
   
   ts5_arg1.c1 = 2;
   ts5_arg1.c2 = 6;
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct6.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct6.c
index 0e26746..173c66e 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/struct6.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct6.c
@@ -12,7 +12,7 @@
   double d;
 } test_structure_6;
 
-static test_structure_6 struct6 (test_structure_6 ts)
+static test_structure_6 ABI_ATTR struct6 (test_structure_6 ts)
 {
   ts.f += 1;
   ts.d += 1;
@@ -46,7 +46,7 @@
   values[0] = &ts6_arg;
 
   /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts6_type, args) == FFI_OK);
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts6_type, args) == FFI_OK);
   
   ts6_arg.f = 5.55f;
   ts6_arg.d = 6.66;
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct7.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct7.c
index 8f2bbfd..badc7e0 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/struct7.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct7.c
@@ -13,7 +13,7 @@
   double d;
 } test_structure_7;
 
-static test_structure_7 struct7 (test_structure_7 ts)
+static test_structure_7 ABI_ATTR struct7 (test_structure_7 ts)
 {
   ts.f1 += 1;
   ts.f2 += 1;
@@ -49,7 +49,7 @@
   values[0] = &ts7_arg;
   
   /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts7_type, args) == FFI_OK);
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts7_type, args) == FFI_OK);
   
   ts7_arg.f1 = 5.55f;
   ts7_arg.f2 = 55.5f;
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct8.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct8.c
index 266e1f0..ef204ec 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/struct8.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct8.c
@@ -14,7 +14,7 @@
   float f4;
 } test_structure_8;
 
-static test_structure_8 struct8 (test_structure_8 ts)
+static test_structure_8 ABI_ATTR struct8 (test_structure_8 ts)
 {
   ts.f1 += 1;
   ts.f2 += 1;
@@ -52,7 +52,7 @@
   values[0] = &ts8_arg;
   
   /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts8_type, args) == FFI_OK);
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts8_type, args) == FFI_OK);
   
   ts8_arg.f1 = 5.55f;
   ts8_arg.f2 = 55.5f;
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.call/struct9.c b/third_party/gofrontend/libffi/testsuite/libffi.call/struct9.c
index efeb716..4a13b81 100644
--- a/third_party/gofrontend/libffi/testsuite/libffi.call/struct9.c
+++ b/third_party/gofrontend/libffi/testsuite/libffi.call/struct9.c
@@ -13,7 +13,7 @@
   int i;
 } test_structure_9;
 
-static test_structure_9 struct9 (test_structure_9 ts)
+static test_structure_9 ABI_ATTR struct9 (test_structure_9 ts)
 {
   ts.f += 1;
   ts.i += 1;
@@ -47,7 +47,7 @@
   values[0] = &ts9_arg;
   
   /* Initialize the cif */
-  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts9_type, args) == FFI_OK);
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts9_type, args) == FFI_OK);
   
   ts9_arg.f = 5.55f;
   ts9_arg.i = 5;
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_align_complex.inc b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_align_complex.inc
new file mode 100644
index 0000000..4a812ed
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_align_complex.inc
@@ -0,0 +1,91 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <complex.h>
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  _Complex T_C_TYPE b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(
+	struct cls_struct_align a1, struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %f,%fi %d %d %f,%fi %d: %d %f,%fi %d\n",
+	 a1.a, T_CONV creal (a1.b), T_CONV cimag (a1.b), a1.c,
+	 a2.a, T_CONV creal (a2.b), T_CONV cimag (a2.b), a2.c,
+	 result.a, T_CONV creal (result.b), T_CONV cimag (result.b), result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_c[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* c_arg_types[5];
+
+  struct cls_struct_align g_c = { 12, 4951 + 7 * I, 127 };
+  struct cls_struct_align f_c = { 1, 9320 + 1 * I, 13 };
+  struct cls_struct_align res_c;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &T_FFI_TYPE;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  c_arg_types[0] = &cls_struct_type;
+  c_arg_types[1] = &cls_struct_type;
+  c_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     c_arg_types) == FFI_OK);
+
+  args_c[0] = &g_c;
+  args_c[1] = &f_c;
+  args_c[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_c, args_c);
+  /* { dg-output "12 4951,7i 127 1 9320,1i 13: 13 14271,8i 140" } */
+  printf("res: %d %f,%fi %d\n",
+	 res_c.a, T_CONV  creal (res_c.b), T_CONV  cimag (res_c.b), res_c.c);
+  /* { dg-output "\nres: 13 14271,8i 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_c = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_c, f_c);
+  /* { dg-output "\n12 4951,7i 127 1 9320,1i 13: 13 14271,8i 140" } */
+  printf("res: %d %f,%fi %d\n",
+	 res_c.a, T_CONV  creal (res_c.b), T_CONV  cimag (res_c.b), res_c.c);
+  /* { dg-output "\nres: 13 14271,8i 140" } */
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_align_complex_double.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_align_complex_double.c
new file mode 100644
index 0000000..0dff23a
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_align_complex_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "cls_align_complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_align_complex_float.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_align_complex_float.c
new file mode 100644
index 0000000..0affbd0
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_align_complex_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "cls_align_complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_align_complex_longdouble.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_align_complex_longdouble.c
new file mode 100644
index 0000000..7889ba8
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_align_complex_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "cls_align_complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex.inc b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex.inc
new file mode 100644
index 0000000..f937404
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex.inc
@@ -0,0 +1,42 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <complex.h>
+
+static void cls_ret_complex_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			      void* userdata __UNUSED__)
+ {
+   _Complex T_C_TYPE *pa;
+   _Complex T_C_TYPE *pr;
+   pa = (_Complex T_C_TYPE *)args[0];
+   pr = (_Complex T_C_TYPE *)resp;
+   *pr = *pa;
+
+   printf("%.6f,%.6fi: %.6f,%.6fi\n",
+	  T_CONV creal (*pa), T_CONV cimag (*pa),
+	  T_CONV creal (*pr), T_CONV cimag (*pr));
+ }
+typedef _Complex T_C_TYPE (*cls_ret_complex)(_Complex T_C_TYPE);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  _Complex T_C_TYPE res;
+
+  cl_arg_types[0] = &T_FFI_TYPE;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &T_FFI_TYPE, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_complex_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_complex)code))(0.125 + 128.0 * I);
+  printf("res: %.6f,%.6fi\n", T_CONV creal (res), T_CONV cimag (res));
+  CHECK (res == (0.125 + 128.0 * I));
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_double.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_double.c
new file mode 100644
index 0000000..05e3534
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_double.c
@@ -0,0 +1,10 @@
+/* Area:	closure_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "cls_complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_float.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_float.c
new file mode 100644
index 0000000..5df7849
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_float.c
@@ -0,0 +1,10 @@
+/* Area:	closure_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "cls_complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_longdouble.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_longdouble.c
new file mode 100644
index 0000000..2b1c320
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	closure_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "cls_complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_struct.inc b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_struct.inc
new file mode 100644
index 0000000..df8708d
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_struct.inc
@@ -0,0 +1,71 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <complex.h>
+
+typedef struct Cs {
+  _Complex T_C_TYPE x;
+  _Complex T_C_TYPE y;
+} Cs;
+
+Cs gc;
+
+void
+closure_test_fn(Cs p)
+{
+  printf("%.1f,%.1fi %.1f,%.1fi\n",
+	 T_CONV creal (p.x), T_CONV cimag (p.x),
+	 T_CONV creal (p.y), T_CONV cimag (p.y));
+  gc = p;
+}
+
+void
+closure_test_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
+		void** args, void* userdata __UNUSED__)
+{
+  closure_test_fn(*(Cs*)args[0]);
+}
+
+int main(int argc __UNUSED__, char** argv __UNUSED__)
+{
+  ffi_cif cif;
+
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type *cl_arg_types[1];
+
+  ffi_type ts1_type;
+  ffi_type* ts1_type_elements[4];
+
+  Cs arg = { 1.0 + 11.0 * I, 2.0 + 22.0 * I};
+
+  ts1_type.size = 0;
+  ts1_type.alignment = 0;
+  ts1_type.type = FFI_TYPE_STRUCT;
+  ts1_type.elements = ts1_type_elements;
+
+  ts1_type_elements[0] = &T_FFI_TYPE;
+  ts1_type_elements[1] = &T_FFI_TYPE;
+  ts1_type_elements[2] = NULL;
+
+  cl_arg_types[0] = &ts1_type;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_void, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_gn, NULL, code) == FFI_OK);
+
+  gc.x = 0.0 + 0.0 * I;
+  gc.y = 0.0 + 0.0 * I;
+  ((void*(*)(Cs))(code))(arg);
+  /* { dg-output "1.0,11.0i 2.0,22.0i\n" } */
+  CHECK (gc.x == arg.x && gc.y == arg.y);
+
+  gc.x = 0.0 + 0.0 * I;
+  gc.y = 0.0 + 0.0 * I;
+  closure_test_fn(arg);
+  /* { dg-output "1.0,11.0i 2.0,22.0i\n" } */
+  CHECK (gc.x == arg.x && gc.y == arg.y);
+
+  return 0;
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_struct_double.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_struct_double.c
new file mode 100644
index 0000000..ec71346
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_struct_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check complex arguments in structs.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "cls_complex_struct.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_struct_float.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_struct_float.c
new file mode 100644
index 0000000..96fdf75
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_struct_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check complex arguments in structs.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "cls_complex_struct.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_struct_longdouble.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_struct_longdouble.c
new file mode 100644
index 0000000..005b467
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_struct_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check complex arguments in structs.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "cls_complex_struct.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_va.inc b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_va.inc
new file mode 100644
index 0000000..8a3e15f
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_va.inc
@@ -0,0 +1,80 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <complex.h>
+
+static _Complex T_C_TYPE gComplexValue1 = 1 + 2 * I;
+static _Complex T_C_TYPE gComplexValue2 = 3 + 4 * I;
+
+static int cls_variadic(const char *format, ...)
+{
+  va_list ap;
+  _Complex T_C_TYPE p1, p2;
+
+  va_start (ap, format);
+  p1 = va_arg (ap, _Complex T_C_TYPE);
+  p2 = va_arg (ap, _Complex T_C_TYPE);
+  va_end (ap);
+
+  return printf(format, T_CONV creal (p1), T_CONV cimag (p1),
+		T_CONV creal (p2), T_CONV cimag (p2));
+}
+
+static void
+cls_complex_va_fn(ffi_cif* cif __UNUSED__, void* resp,
+		  void** args, void* userdata __UNUSED__)
+{
+  char*	format = *(char**)args[0];
+  gComplexValue1 = *(_Complex T_C_TYPE*)args[1];
+  gComplexValue2 = *(_Complex T_C_TYPE*)args[2];
+
+  *(ffi_arg*)resp =
+    printf(format,
+	   T_CONV creal (gComplexValue1), T_CONV cimag (gComplexValue1),
+	   T_CONV creal (gComplexValue2), T_CONV cimag (gComplexValue2));
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args[4];
+  ffi_type* arg_types[4];
+  char *format = "%.1f,%.1fi %.1f,%.1fi\n";
+
+  _Complex T_C_TYPE complexArg1 = 1.0 + 22.0 *I;
+  _Complex T_C_TYPE complexArg2 = 333.0 + 4444.0 *I;
+  ffi_arg res = 0;
+
+  arg_types[0] = &ffi_type_pointer;
+  arg_types[1] = &T_FFI_TYPE;
+  arg_types[2] = &T_FFI_TYPE;
+  arg_types[3] = NULL;
+
+  /* This printf call is variadic */
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 3, &ffi_type_sint,
+			 arg_types) == FFI_OK);
+
+  args[0] = &format;
+  args[1] = &complexArg1;
+  args[2] = &complexArg2;
+  args[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_variadic), &res, args);
+  printf("res: %d\n", (int) res);
+  CHECK (res == 24);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_complex_va_fn, NULL, code)
+	== FFI_OK);
+
+  res = ((int(*)(char *, ...))(code))(format, complexArg1, complexArg2);
+  CHECK (gComplexValue1 == complexArg1);
+  CHECK (gComplexValue2 == complexArg2);
+  printf("res: %d\n", (int) res);
+  CHECK (res == 24);
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_va_double.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_va_double.c
new file mode 100644
index 0000000..879ccf3
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_va_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Test complex' passed in variable argument lists.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "cls_complex_va.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_va_float.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_va_float.c
new file mode 100644
index 0000000..2b17826
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_va_float.c
@@ -0,0 +1,16 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Test complex' passed in variable argument lists.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+/* Alpha splits _Complex into two arguments.  It's illegal to pass
+   float through varargs, so _Complex float goes badly.  In sort of
+   gets passed as _Complex double, but the compiler doesn't agree
+   with itself on this issue.  */
+/* { dg-do run { xfail alpha*-*-* } } */
+
+#include "complex_defs_float.inc"
+#include "cls_complex_va.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_va_longdouble.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_va_longdouble.c
new file mode 100644
index 0000000..6eca965
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/cls_complex_va_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Test complex' passed in variable argument lists.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "cls_complex_va.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/complex.inc b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex.inc
new file mode 100644
index 0000000..515ae3e
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex.inc
@@ -0,0 +1,51 @@
+/* -*-c-*-*/
+#include "ffitest.h"
+#include <complex.h>
+
+static _Complex T_C_TYPE f_complex(_Complex T_C_TYPE c, int x, int *py)
+{
+  c = -(2 * creal (c)) + (cimag (c) + 1)* I;
+  *py += x;
+
+  return c;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+
+  _Complex T_C_TYPE tc_arg;
+  _Complex T_C_TYPE tc_result;
+  int tc_int_arg_x;
+  int tc_y;
+  int *tc_ptr_arg_y = &tc_y;
+
+  args[0] = &T_FFI_TYPE;
+  args[1] = &ffi_type_sint;
+  args[2] = &ffi_type_pointer;
+  values[0] = &tc_arg;
+  values[1] = &tc_int_arg_x;
+  values[2] = &tc_ptr_arg_y;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+		     &T_FFI_TYPE, args) == FFI_OK);
+
+  tc_arg = 1 + 7 * I;
+  tc_int_arg_x = 1234;
+  tc_y = 9876;
+  ffi_call(&cif, FFI_FN(f_complex), &tc_result, values);
+
+  printf ("%f,%fi %f,%fi, x %d 1234, y %d 11110\n",
+	  T_CONV creal (tc_result), T_CONV cimag (tc_result),
+	  T_CONV creal (2.0), T_CONV creal (8.0), tc_int_arg_x, tc_y);
+
+  CHECK (creal (tc_result) == -2);
+  CHECK (cimag (tc_result) == 8);
+  CHECK (tc_int_arg_x == 1234);
+  CHECK (*tc_ptr_arg_y == 11110);
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_defs_double.inc b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_defs_double.inc
new file mode 100644
index 0000000..3583e16
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_defs_double.inc
@@ -0,0 +1,7 @@
+/* -*-c-*- */
+/* Complex base type.  */
+#define T_FFI_TYPE ffi_type_complex_double
+/* C type corresponding to the base type.  */
+#define T_C_TYPE double
+/* C cast for a value of type T_C_TYPE that is passed to printf.  */
+#define T_CONV
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_defs_float.inc b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_defs_float.inc
new file mode 100644
index 0000000..bbd9375
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_defs_float.inc
@@ -0,0 +1,7 @@
+/* -*-c-*- */
+/* Complex base type.  */
+#define T_FFI_TYPE ffi_type_complex_float
+/* C type corresponding to the base type.  */
+#define T_C_TYPE float
+/* C cast for a value of type T_C_TYPE that is passed to printf.  */
+#define T_CONV (double)
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_defs_longdouble.inc b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_defs_longdouble.inc
new file mode 100644
index 0000000..14b9f24
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_defs_longdouble.inc
@@ -0,0 +1,7 @@
+/* -*-c-*- */
+/* Complex base type.  */
+#define T_FFI_TYPE ffi_type_complex_longdouble
+/* C type corresponding to the base type.  */
+#define T_C_TYPE long double
+/* C cast for a value of type T_C_TYPE that is passed to printf.  */
+#define T_CONV
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_double.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_double.c
new file mode 100644
index 0000000..8a3297b
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check complex types.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_float.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_float.c
new file mode 100644
index 0000000..5044ebb
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check complex types.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_int.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_int.c
new file mode 100644
index 0000000..bac3190
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_int.c
@@ -0,0 +1,86 @@
+/* Area:	ffi_call
+   Purpose:	Check non-standard complex types.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+#include "ffi.h"
+#include <complex.h>
+
+_Complex int f_complex(_Complex int c, int x, int *py)
+{
+  __real__ c = -2 * __real__ c;
+  __imag__ c = __imag__ c + 1;
+  *py += x;
+  return c;
+}
+
+/*
+ * This macro can be used to define new complex type descriptors
+ * in a platform independent way.
+ *
+ * name: Name of the new descriptor is ffi_type_complex_<name>.
+ * type: The C base type of the complex type.
+ */
+#define FFI_COMPLEX_TYPEDEF(name, type, ffitype)	     \
+  static ffi_type *ffi_elements_complex_##name [2] = {	     \
+    (ffi_type *)(&ffitype), NULL			     \
+  };							     \
+  struct struct_align_complex_##name {			     \
+    char c;						     \
+    _Complex type x;					     \
+  };							     \
+  ffi_type ffi_type_complex_##name = {		     \
+    sizeof(_Complex type),				     \
+    offsetof(struct struct_align_complex_##name, x),	     \
+    FFI_TYPE_COMPLEX,					     \
+    (ffi_type **)ffi_elements_complex_##name		     \
+  }
+
+/* Define new complex type descriptors using the macro: */
+/* ffi_type_complex_sint */
+FFI_COMPLEX_TYPEDEF(sint, int, ffi_type_sint);
+/* ffi_type_complex_uchar */
+FFI_COMPLEX_TYPEDEF(uchar, unsigned char, ffi_type_uint8);
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+
+  _Complex int tc_arg;
+  _Complex int tc_result;
+  int tc_int_arg_x;
+  int tc_y;
+  int *tc_ptr_arg_y = &tc_y;
+
+  args[0] = &ffi_type_complex_sint;
+  args[1] = &ffi_type_sint;
+  args[2] = &ffi_type_pointer;
+  values[0] = &tc_arg;
+  values[1] = &tc_int_arg_x;
+  values[2] = &tc_ptr_arg_y;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &ffi_type_complex_sint, args)
+	== FFI_OK);
+
+  tc_arg = 1 + 7 * I;
+  tc_int_arg_x = 1234;
+  tc_y = 9876;
+  ffi_call(&cif, FFI_FN(f_complex), &tc_result, values);
+
+  printf ("%d,%di %d,%di, x %d 1234, y %d 11110\n",
+	  (int)tc_result, (int)(tc_result * -I), 2, 8, tc_int_arg_x, tc_y);
+  /* dg-output "-2,8i 2,8i, x 1234 1234, y 11110 11110" */
+  CHECK (creal (tc_result) == -2);
+  CHECK (cimag (tc_result) == 8);
+  CHECK (tc_int_arg_x == 1234);
+  CHECK (*tc_ptr_arg_y == 11110);
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_longdouble.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_longdouble.c
new file mode 100644
index 0000000..7e78366
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/complex_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check complex types.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/ffitest.h b/third_party/gofrontend/libffi/testsuite/libffi.complex/ffitest.h
new file mode 100644
index 0000000..d27d362
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/ffitest.h
@@ -0,0 +1 @@
+#include "../libffi.call/ffitest.h"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/many_complex.inc b/third_party/gofrontend/libffi/testsuite/libffi.complex/many_complex.inc
new file mode 100644
index 0000000..e37a774
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/many_complex.inc
@@ -0,0 +1,78 @@
+/* -*-c-*- */
+#include "ffitest.h"
+
+#include <stdlib.h>
+#include <complex.h>
+
+static _Complex T_C_TYPE many(_Complex T_C_TYPE c1,
+			      _Complex T_C_TYPE c2,
+			      _Complex T_C_TYPE c3,
+			      _Complex T_C_TYPE c4,
+			      _Complex T_C_TYPE c5,
+			      _Complex T_C_TYPE c6,
+			      _Complex T_C_TYPE c7,
+			      _Complex T_C_TYPE c8,
+			      _Complex T_C_TYPE c9,
+			      _Complex T_C_TYPE c10,
+			      _Complex T_C_TYPE c11,
+			      _Complex T_C_TYPE c12,
+			      _Complex T_C_TYPE c13)
+{
+  printf("0 :%f,%fi\n"
+	 "1 :%f,%fi\n"
+	 "2 :%f,%fi\n"
+	 "3 :%f,%fi\n"
+	 "4 :%f,%fi\n"
+	 "5 :%f,%fi\n"
+	 "6 :%f,%fi\n"
+	 "7 :%f,%fi\n"
+	 "8 :%f,%fi\n"
+	 "9 :%f,%fi\n"
+	 "10:%f,%fi\n"
+	 "11:%f,%fi\n"
+	 "12:%f,%fi\n",
+	 T_CONV creal (c1), T_CONV cimag (c1),
+	 T_CONV creal (c2), T_CONV cimag (c2),
+	 T_CONV creal (c3), T_CONV cimag (c3),
+	 T_CONV creal (c4), T_CONV cimag (c4),
+	 T_CONV creal (c5), T_CONV cimag (c5),
+	 T_CONV creal (c6), T_CONV cimag (c6),
+	 T_CONV creal (c7), T_CONV cimag (c7),
+	 T_CONV creal (c8), T_CONV cimag (c8),
+	 T_CONV creal (c9), T_CONV cimag (c9),
+	 T_CONV creal (c10), T_CONV cimag (c10),
+	 T_CONV creal (c11), T_CONV cimag (c11),
+	 T_CONV creal (c12), T_CONV cimag (c12),
+	 T_CONV creal (c13), T_CONV cimag (c13));
+
+  return (c1+c2-c3-c4+c5+c6+c7-c8-c9-c10-c11+c12+c13);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[13];
+  void *values[13];
+  _Complex T_C_TYPE ca[13];
+  _Complex T_C_TYPE c, cc;
+  int i;
+
+  for (i = 0; i < 13; i++)
+    {
+      args[i] = &T_FFI_TYPE;
+      values[i] = &ca[i];
+      ca[i] = i + (-20 - i) * I;
+    }
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, &T_FFI_TYPE, args) == FFI_OK);
+
+    ffi_call(&cif, FFI_FN(many), &c, values);
+
+    cc =  many(ca[0], ca[1], ca[2], ca[3], ca[4], ca[5], ca[6], ca[7], ca[8],
+	       ca[9], ca[10], ca[11], ca[12]);
+    CHECK(creal (cc) == creal (c));
+    CHECK(cimag (cc) == cimag (c));
+
+    exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/many_complex_double.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/many_complex_double.c
new file mode 100644
index 0000000..3fd53c3
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/many_complex_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex, with many arguments
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "many_complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/many_complex_float.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/many_complex_float.c
new file mode 100644
index 0000000..c43d21c
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/many_complex_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex, with many arguments
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "many_complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/many_complex_longdouble.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/many_complex_longdouble.c
new file mode 100644
index 0000000..dbab723
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/many_complex_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex, with many arguments
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "many_complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex.inc b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex.inc
new file mode 100644
index 0000000..8bf0c1f
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex.inc
@@ -0,0 +1,37 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <complex.h>
+
+static _Complex T_C_TYPE return_c(_Complex T_C_TYPE c)
+{
+  printf ("%f,%fi\n", T_CONV creal (c), T_CONV cimag (c));
+  return 2 * c;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  _Complex T_C_TYPE c, rc, rc2;
+  T_C_TYPE cr, ci;
+
+  args[0] = &T_FFI_TYPE;
+  values[0] = &c;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &T_FFI_TYPE, args) == FFI_OK);
+
+  for (cr = -127.0; cr <  127; cr++)
+    {
+      ci = 1000.0 - cr;
+      c = cr + ci * I;
+      ffi_call(&cif, FFI_FN(return_c), &rc, values);
+      rc2 = return_c(c);
+      printf ("%f,%fi vs %f,%fi\n",
+	      T_CONV creal (rc), T_CONV cimag (rc),
+	      T_CONV creal (rc2), T_CONV cimag (rc2));
+      CHECK(rc == 2 * c);
+    }
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex1.inc b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex1.inc
new file mode 100644
index 0000000..7cecc0f
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex1.inc
@@ -0,0 +1,41 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <complex.h>
+
+static _Complex T_C_TYPE return_c(_Complex T_C_TYPE c1, float fl2, unsigned int in3, _Complex T_C_TYPE c4)
+{
+  return c1 + fl2 + in3 + c4;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  _Complex T_C_TYPE c1, c4, rc, rc2;
+  float fl2;
+  unsigned int in3;
+  args[0] = &T_FFI_TYPE;
+  args[1] = &ffi_type_float;
+  args[2] = &ffi_type_uint;
+  args[3] = &T_FFI_TYPE;
+  values[0] = &c1;
+  values[1] = &fl2;
+  values[2] = &in3;
+  values[3] = &c4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &T_FFI_TYPE, args) == FFI_OK);
+  c1 = 127.0 + 255.0 * I;
+  fl2 = 128.0;
+  in3 = 255;
+  c4 = 512.7 + 1024.1 * I;
+
+  ffi_call(&cif, FFI_FN(return_c), &rc, values);
+  rc2 = return_c(c1, fl2, in3, c4);
+  printf ("%f,%fi vs %f,%fi\n",
+	  T_CONV creal (rc), T_CONV cimag (rc),
+	  T_CONV creal (rc2), T_CONV cimag (rc2));
+  CHECK(rc == rc2);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex1_double.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex1_double.c
new file mode 100644
index 0000000..727410d
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex1_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "return_complex1.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex1_float.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex1_float.c
new file mode 100644
index 0000000..a2aeada
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex1_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "return_complex1.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex1_longdouble.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex1_longdouble.c
new file mode 100644
index 0000000..103504b
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex1_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "return_complex1.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex2.inc b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex2.inc
new file mode 100644
index 0000000..265170b
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex2.inc
@@ -0,0 +1,44 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <complex.h>
+
+_Complex T_C_TYPE
+return_c(_Complex T_C_TYPE c1, _Complex T_C_TYPE c2,
+	 unsigned int in3, _Complex T_C_TYPE c4)
+{
+  volatile _Complex T_C_TYPE r = c1 + c2 + in3 + c4;
+  return r;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  _Complex T_C_TYPE c1, c2, c4, rc, rc2;
+  unsigned int in3;
+  args[0] = &T_FFI_TYPE;
+  args[1] = &T_FFI_TYPE;
+  args[2] = &ffi_type_uint;
+  args[3] = &T_FFI_TYPE;
+  values[0] = &c1;
+  values[1] = &c2;
+  values[2] = &in3;
+  values[3] = &c4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &T_FFI_TYPE, args) == FFI_OK);
+  c1 = 127.0 + 255.0 * I;
+  c2 = 128.0 + 256.0;
+  in3 = 255;
+  c4 = 512.7 + 1024.1 * I;
+
+  ffi_call(&cif, FFI_FN(return_c), &rc, values);
+  rc2 = return_c(c1, c2, in3, c4);
+  printf ("%f,%fi vs %f,%fi\n",
+	  T_CONV creal (rc), T_CONV cimag (rc),
+	  T_CONV creal (rc2), T_CONV cimag (rc2));
+  CHECK(rc == rc2);
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex2_double.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex2_double.c
new file mode 100644
index 0000000..ab9efac
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex2_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "return_complex2.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex2_float.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex2_float.c
new file mode 100644
index 0000000..d7f22c2
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex2_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "return_complex2.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex2_longdouble.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex2_longdouble.c
new file mode 100644
index 0000000..3edea62
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex2_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "return_complex2.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex_double.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex_double.c
new file mode 100644
index 0000000..e2497cc
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "return_complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex_float.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex_float.c
new file mode 100644
index 0000000..a35528f
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "return_complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex_longdouble.c b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex_longdouble.c
new file mode 100644
index 0000000..142d7be
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.complex/return_complex_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "return_complex.inc"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.go/aa-direct.c b/third_party/gofrontend/libffi/testsuite/libffi.go/aa-direct.c
new file mode 100644
index 0000000..b00c404
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.go/aa-direct.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+
+#include "static-chain.h"
+
+#if defined(__GNUC__) && !defined(__clang__) && defined(STATIC_CHAIN_REG)
+
+#include "ffitest.h"
+
+/* Blatent assumption here that the prologue doesn't clobber the
+   static chain for trivial functions.  If this is not true, don't
+   define STATIC_CHAIN_REG, and we'll test what we can via other tests.  */
+void *doit(void)
+{
+  register void *chain __asm__(STATIC_CHAIN_REG);
+  return chain;
+}
+
+int main()
+{
+  ffi_cif cif;
+  void *result;
+
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 0, &ffi_type_pointer, NULL) == FFI_OK);
+
+  ffi_call_go(&cif, FFI_FN(doit), &result, NULL, &result);
+
+  CHECK(result == &result);
+
+  return 0;
+}
+
+#else /* UNSUPPORTED */
+int main() { return 0; }
+#endif
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.go/closure1.c b/third_party/gofrontend/libffi/testsuite/libffi.go/closure1.c
new file mode 100644
index 0000000..7b34afc
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.go/closure1.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+void doit(ffi_cif *cif, void *rvalue, void **avalue, void *closure)
+{
+  (void)cif;
+  (void)avalue;
+  *(void **)rvalue = closure;
+}
+
+typedef void * (*FN)(void);
+
+int main()
+{
+  ffi_cif cif;
+  ffi_go_closure cl;
+  void *result;
+
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 0, &ffi_type_pointer, NULL) == FFI_OK);
+  CHECK(ffi_prep_go_closure(&cl, &cif, doit) == FFI_OK);
+
+  ffi_call_go(&cif, FFI_FN(*(FN *)&cl), &result, NULL, &cl);
+
+  CHECK(result == &cl);
+
+  exit(0);
+}
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.go/ffitest.h b/third_party/gofrontend/libffi/testsuite/libffi.go/ffitest.h
new file mode 100644
index 0000000..d27d362
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.go/ffitest.h
@@ -0,0 +1 @@
+#include "../libffi.call/ffitest.h"
diff --git a/third_party/gofrontend/libffi/testsuite/libffi.go/static-chain.h b/third_party/gofrontend/libffi/testsuite/libffi.go/static-chain.h
new file mode 100644
index 0000000..3675b40
--- /dev/null
+++ b/third_party/gofrontend/libffi/testsuite/libffi.go/static-chain.h
@@ -0,0 +1,19 @@
+#ifdef __aarch64__
+# define STATIC_CHAIN_REG  "x18"
+#elif defined(__alpha__)
+# define STATIC_CHAIN_REG  "$1"
+#elif defined(__arm__)
+# define STATIC_CHAIN_REG  "ip"
+#elif defined(__sparc__)
+# if defined(__arch64__) || defined(__sparcv9)
+#  define STATIC_CHAIN_REG "g5"
+# else
+#  define STATIC_CHAIN_REG "g2"
+# endif
+#elif defined(__x86_64__)
+# define STATIC_CHAIN_REG  "r10"
+#elif defined(__i386__)
+# ifndef ABI_NUM
+#  define STATIC_CHAIN_REG  "ecx"	/* FFI_DEFAULT_ABI only */
+# endif
+#endif
diff --git a/third_party/gofrontend/libgo/Makefile.am b/third_party/gofrontend/libgo/Makefile.am
index f42220a..6c2af92 100644
--- a/third_party/gofrontend/libgo/Makefile.am
+++ b/third_party/gofrontend/libgo/Makefile.am
@@ -938,44 +938,10 @@
 	go/path/match.go \
 	go/path/path.go
 
-if LIBGO_IS_X86_64
-go_reflect_makefunc_file = \
-	go/reflect/makefuncgo_amd64.go
-go_reflect_makefunc_s_file = \
-	go/reflect/makefunc_amd64.S
-else
-if LIBGO_IS_386
-go_reflect_makefunc_file = \
-	go/reflect/makefuncgo_386.go
-go_reflect_makefunc_s_file = \
-	go/reflect/makefunc_386.S
-else
-if LIBGO_IS_S390
-go_reflect_makefunc_file = \
-	go/reflect/makefuncgo_s390.go
-go_reflect_makefunc_s_file = \
-	go/reflect/makefunc_s390.c
-else
-if LIBGO_IS_S390X
-go_reflect_makefunc_file = \
-	go/reflect/makefuncgo_s390x.go \
-	go/reflect/makefuncgo_s390.go
-go_reflect_makefunc_s_file = \
-	go/reflect/makefunc_s390.c
-else
-go_reflect_makefunc_file =
-go_reflect_makefunc_s_file = \
-	go/reflect/makefunc_dummy.c
-endif
-endif
-endif
-endif
-
 go_reflect_files = \
 	go/reflect/deepequal.go \
 	go/reflect/makefunc.go \
 	go/reflect/makefunc_ffi.go \
-	$(go_reflect_makefunc_file) \
 	go/reflect/type.go \
 	go/reflect/value.go
 go_reflect_makefunc_c_file = \
@@ -1897,7 +1863,6 @@
 	os.lo \
 	path.lo \
 	reflect-go.lo \
-	reflect/makefunc.lo \
 	reflect/makefunc_ffi_c.lo \
 	regexp.lo \
 	runtime-go.lo \
@@ -2316,9 +2281,6 @@
 	$(BUILDPACKAGE)
 reflect/check: $(CHECK_DEPS)
 	@$(CHECK)
-reflect/makefunc.lo: $(go_reflect_makefunc_s_file)
-	@$(MKDIR_P) reflect
-	$(LTCOMPILE) -c -o $@ $<
 reflect/makefunc_ffi_c.lo: $(go_reflect_makefunc_c_file)
 	@$(MKDIR_P) reflect
 	$(LTCOMPILE) -c -o $@ $<
diff --git a/third_party/gofrontend/libgo/Makefile.in b/third_party/gofrontend/libgo/Makefile.in
index 9549ee8..19ca1a5 100644
--- a/third_party/gofrontend/libgo/Makefile.in
+++ b/third_party/gofrontend/libgo/Makefile.in
@@ -141,11 +141,11 @@
 am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \
 	encoding.lo errors.lo expvar.lo flag.lo fmt.lo hash.lo html.lo \
 	image.lo io.lo log.lo math.lo mime.lo net.lo os.lo path.lo \
-	reflect-go.lo reflect/makefunc.lo reflect/makefunc_ffi_c.lo \
-	regexp.lo runtime-go.lo sort.lo strconv.lo strings.lo \
-	strings/index.lo sync.lo syscall.lo syscall/errno.lo \
-	syscall/signame.lo syscall/wait.lo testing.lo time-go.lo \
-	unicode.lo archive/tar.lo archive/zip.lo compress/bzip2.lo \
+	reflect-go.lo reflect/makefunc_ffi_c.lo regexp.lo \
+	runtime-go.lo sort.lo strconv.lo strings.lo strings/index.lo \
+	sync.lo syscall.lo syscall/errno.lo syscall/signame.lo \
+	syscall/wait.lo testing.lo time-go.lo unicode.lo \
+	archive/tar.lo archive/zip.lo compress/bzip2.lo \
 	compress/flate.lo compress/gzip.lo compress/lzw.lo \
 	compress/zlib.lo container/heap.lo container/list.lo \
 	container/ring.lo crypto/aes.lo crypto/cipher.lo crypto/des.lo \
@@ -1125,40 +1125,10 @@
 	go/path/match.go \
 	go/path/path.go
 
-@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_FALSE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file = 
-@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_TRUE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file = \
-@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_TRUE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefuncgo_s390x.go \
-@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_TRUE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefuncgo_s390.go
-
-@LIBGO_IS_386_FALSE@@LIBGO_IS_S390_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file = \
-@LIBGO_IS_386_FALSE@@LIBGO_IS_S390_TRUE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefuncgo_s390.go
-
-@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file = \
-@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefuncgo_386.go
-
-@LIBGO_IS_X86_64_TRUE@go_reflect_makefunc_file = \
-@LIBGO_IS_X86_64_TRUE@	go/reflect/makefuncgo_amd64.go
-
-@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_FALSE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \
-@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_FALSE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefunc_dummy.c
-
-@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_TRUE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \
-@LIBGO_IS_386_FALSE@@LIBGO_IS_S390X_TRUE@@LIBGO_IS_S390_FALSE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefunc_s390.c
-
-@LIBGO_IS_386_FALSE@@LIBGO_IS_S390_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \
-@LIBGO_IS_386_FALSE@@LIBGO_IS_S390_TRUE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefunc_s390.c
-
-@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \
-@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@	go/reflect/makefunc_386.S
-
-@LIBGO_IS_X86_64_TRUE@go_reflect_makefunc_s_file = \
-@LIBGO_IS_X86_64_TRUE@	go/reflect/makefunc_amd64.S
-
 go_reflect_files = \
 	go/reflect/deepequal.go \
 	go/reflect/makefunc.go \
 	go/reflect/makefunc_ffi.go \
-	$(go_reflect_makefunc_file) \
 	go/reflect/type.go \
 	go/reflect/value.go
 
@@ -1963,7 +1933,6 @@
 	os.lo \
 	path.lo \
 	reflect-go.lo \
-	reflect/makefunc.lo \
 	reflect/makefunc_ffi_c.lo \
 	regexp.lo \
 	runtime-go.lo \
@@ -4655,9 +4624,6 @@
 	$(BUILDPACKAGE)
 reflect/check: $(CHECK_DEPS)
 	@$(CHECK)
-reflect/makefunc.lo: $(go_reflect_makefunc_s_file)
-	@$(MKDIR_P) reflect
-	$(LTCOMPILE) -c -o $@ $<
 reflect/makefunc_ffi_c.lo: $(go_reflect_makefunc_c_file)
 	@$(MKDIR_P) reflect
 	$(LTCOMPILE) -c -o $@ $<
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc.go b/third_party/gofrontend/libgo/go/reflect/makefunc.go
index 276be26..7ec277b 100644
--- a/third_party/gofrontend/libgo/go/reflect/makefunc.go
+++ b/third_party/gofrontend/libgo/go/reflect/makefunc.go
@@ -7,25 +7,24 @@
 package reflect
 
 import (
-	"runtime"
 	"unsafe"
 )
 
 // makeFuncImpl is the closure value implementing the function
 // returned by MakeFunc.
 type makeFuncImpl struct {
-	code uintptr
-	typ  *funcType
-	fn   func([]Value) []Value
+	// These first three words are layed out like ffi_go_closure.
+	code    uintptr
+	ffi_cif unsafe.Pointer
+	ffi_fun func(unsafe.Pointer, unsafe.Pointer)
+
+	typ *funcType
+	fn  func([]Value) []Value
 
 	// For gccgo we use the same entry point for functions and for
 	// method values.
 	method int
 	rcvr   Value
-
-	// When using FFI, hold onto the FFI closure for the garbage
-	// collector.
-	ffi *ffiData
 }
 
 // MakeFunc returns a new function of the given Type
@@ -58,37 +57,17 @@
 	t := typ.common()
 	ftyp := (*funcType)(unsafe.Pointer(t))
 
-	var code uintptr
-	var ffi *ffiData
-	switch runtime.GOARCH {
-	case "amd64", "386", "s390", "s390x":
-		// Indirect Go func value (dummy) to obtain actual
-		// code address. (A Go func value is a pointer to a C
-		// function pointer. http://golang.org/s/go11func.)
-		dummy := makeFuncStub
-		code = **(**uintptr)(unsafe.Pointer(&dummy))
-	default:
-		code, ffi = makeFuncFFI(ftyp, fn)
-	}
-
 	impl := &makeFuncImpl{
-		code:   code,
 		typ:    ftyp,
 		fn:     fn,
 		method: -1,
-		ffi:    ffi,
 	}
 
+	makeFuncFFI(ftyp, unsafe.Pointer(impl))
+
 	return Value{t, unsafe.Pointer(&impl), flag(Func) | flagIndir}
 }
 
-// makeFuncStub is an assembly function that is the code half of
-// the function returned from MakeFunc. It expects a *callReflectFunc
-// as its context register, and its job is to invoke callReflect(ctxt, frame)
-// where ctxt is the context register and frame is a pointer to the first
-// word in the passed-in argument frame.
-func makeFuncStub()
-
 // makeMethodValue converts v from the rcvr+method index representation
 // of a method value to an actual method func value, which is
 // basically the receiver value with a special bit set, into a true
@@ -123,16 +102,7 @@
 		rcvr:   rcvr,
 	}
 
-	switch runtime.GOARCH {
-	case "amd64", "386":
-		// Indirect Go func value (dummy) to obtain actual
-		// code address. (A Go func value is a pointer to a C
-		// function pointer. http://golang.org/s/go11func.)
-		dummy := makeFuncStub
-		fv.code = **(**uintptr)(unsafe.Pointer(&dummy))
-	default:
-		fv.code, fv.ffi = makeFuncFFI(ftyp, fv.call)
-	}
+	makeFuncFFI(ftyp, unsafe.Pointer(fv))
 
 	return Value{ft, unsafe.Pointer(&fv), v.flag&flagRO | flag(Func) | flagIndir}
 }
@@ -158,16 +128,7 @@
 		rcvr:   v,
 	}
 
-	switch runtime.GOARCH {
-	case "amd64", "386", "s390", "s390x":
-		// Indirect Go func value (dummy) to obtain actual
-		// code address. (A Go func value is a pointer to a C
-		// function pointer. http://golang.org/s/go11func.)
-		dummy := makeFuncStub
-		impl.code = **(**uintptr)(unsafe.Pointer(&dummy))
-	default:
-		impl.code, impl.ffi = makeFuncFFI(ftyp, impl.call)
-	}
+	makeFuncFFI(ftyp, unsafe.Pointer(impl))
 
 	return Value{t, unsafe.Pointer(&impl), v.flag&flagRO | flag(Func) | flagIndir}
 }
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc_386.S b/third_party/gofrontend/libgo/go/reflect/makefunc_386.S
deleted file mode 100644
index 0e2e764..0000000
--- a/third_party/gofrontend/libgo/go/reflect/makefunc_386.S
+++ /dev/null
@@ -1,230 +0,0 @@
-/* Copyright 2013 The Go Authors. All rights reserved.
-   Use of this source code is governed by a BSD-style
-   license that can be found in the LICENSE file.
-
-   MakeFunc 386 assembly code.  */
-
-#include "config.h"
-
-	.globl reflect.makeFuncStub
-
-#ifdef __ELF__
-	.type reflect.makeFuncStub,@function
-#endif
-
-reflect.makeFuncStub:
-.LFB1:
-
-	/* Go does not provide any equivalent to the regparm function
-	   attribute, so on Go we do not need to worry about passing
-	   parameters in registers.  We just pass a pointer to the
-	   arguments on the stack.
-	
-	   We do need to pick up the return values, though, so we pass
-	   a pointer to a struct that looks like this.
-	   struct {
-	     esp uint32		// 0x0
-	     eax uint32		// 0x4
-	     st0 float64	// 0x8
-	     sr  bool		// 0x10
-	     sf  bool		// 0x11
-	   }
-	   The sr field is set by the function to a non-zero value if
-	   the function takes a struct hidden pointer that must be
-	   popped off the stack.  */
-
-	pushl	%ebp
-.LCFI0:
-	movl	%esp, %ebp
-.LCFI1:
-	pushl	%ebx		/* In case this is PIC.  */
-	subl	$36, %esp	/* Enough for args and to align stack.  */
-.LCFI2:
-
-#ifdef __PIC__
-	call	__x86.get_pc_thunk.bx
-	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
-#endif
-
-	leal	8(%ebp), %eax	/* Set esp field in struct.  */
-	movl	%eax, -24(%ebp)
-
-	/* For MakeFunc functions that call recover.  */
-	movl	4(%ebp), %eax
-	movl	%eax, (%esp)
-#ifdef __PIC__
-	call	__go_makefunc_can_recover@PLT
-#else
-	call	__go_makefunc_can_recover
-#endif
-
-#ifdef __PIC__
-	call	__go_get_closure@PLT
-#else
-	call	__go_get_closure
-#endif
-
-	movl	%eax, 4(%esp)
-
-	leal	-24(%ebp), %eax
-	movl	%eax, (%esp)
-
-#ifdef __PIC__
-	call	reflect.MakeFuncStubGo@PLT
-#else
-	call	reflect.MakeFuncStubGo
-#endif
-
-	/* MakeFunc functions can no longer call recover.  */
-#ifdef __PIC__
-	call __go_makefunc_returning@PLT
-#else
-	call __go_makefunc_returning
-#endif
-
-	/* Set return registers.  */
-
-	movl	-20(%ebp), %eax
-
-	cmpb	$0, -7(%ebp)
-	je	2f
-
-	fldl	-16(%ebp)
-
-#ifdef __SSE2__
-	/* In case we are compiling with -msseregparm.  This won't work
-	   correctly if only SSE1 is supported, but that seems unlikely.  */
-	movsd	-16(%ebp), %xmm0
-#endif
-
-2:
-	movb	-8(%ebp), %dl
-
-	addl	$36, %esp
-	popl	%ebx
-.LCFI3:
-	popl	%ebp
-.LCFI4:
-
-	testb	%dl,%dl
-	jne	1f
-	ret
-1:
-	ret	$4
-.LFE1:
-#ifdef __ELF__
-	.size	reflect.makeFuncStub, . - reflect.makeFuncStub
-#endif
-
-#ifdef __PIC__
-#ifdef HAVE_AS_COMDAT_GAS
-	.section	.text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
-#else
-	/* Sun as needs a different syntax.  */
-	.section	.text.__x86.get_pc_thunk.bx%__x86.get_pc_thunk.bx,"ax",@progbits
-	.group		__x86.get_pc_thunk.bx,.text.__x86.get_pc_thunk.bx%__x86.get_pc_thunk.bx,#comdat
-#endif
-	.globl	__x86.get_pc_thunk.bx
-	.hidden	__x86.get_pc_thunk.bx
-#ifdef __ELF__
-	.type	__x86.get_pc_thunk.bx, @function
-#endif
-__x86.get_pc_thunk.bx:
-.LFB2:
-	movl	(%esp), %ebx
-	ret
-.LFE2:
-#ifdef __ELF__
-	.size	__x86.get_pc_thunk.bx, . - __x86.get_pc_thunk.bx
-#endif
-#endif
-
-#ifdef __ELF__
-#if defined __PIC__
-# if defined __sun__ && defined __svr4__
-/* 32-bit Solaris 2/x86 uses datarel encoding for PIC.  GNU ld before 2.22
-   doesn't correctly sort .eh_frame_hdr with mixed encodings, so match this.  */
-#  define FDE_ENCODING		0x30	/* datarel */
-#  define FDE_ENCODE(X)		X@GOTOFF
-# else
-#  define FDE_ENCODING		0x1b	/* pcrel sdata4 */
-#  if defined HAVE_AS_X86_PCREL
-#   define FDE_ENCODE(X)	X-.
-#  else
-#   define FDE_ENCODE(X)	X@rel
-#  endif
-# endif
-#else
-# define FDE_ENCODING		0	/* absolute */
-# define FDE_ENCODE(X)		X
-#endif
-
-	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
-.Lframe1:
-	.long	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
-.LSCIE1:
-	.long	0x0	/* CIE Identifier Tag */
-	.byte	0x1	/* CIE Version */
-	.ascii "zR\0"	/* CIE Augmentation */
-	.byte	0x1	/* .uleb128 0x1; CIE Code Alignment Factor */
-	.byte	0x7c	/* .sleb128 -4; CIE Data Alignment Factor */
-	.byte	0x8	/* CIE RA Column */
-	.byte	0x1	/* .uleb128 0x1; Augmentation size */
-	.byte	FDE_ENCODING
-	.byte	0xc	/* DW_CFA_def_cfa */
-	.byte	0x4	/* .uleb128 0x4 */
-	.byte	0x4	/* .uleb128 0x4 */
-	.byte	0x88	/* DW_CFA_offset, column 0x8 */
-	.byte	0x1	/* .uleb128 0x1 */
-	.align 4
-.LECIE1:
-.LSFDE1:
-	.long	.LEFDE1-.LASFDE1	/* FDE Length */
-.LASFDE1:
-	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
-	.long	FDE_ENCODE(.LFB1)	/* FDE initial location */
-	.long	.LFE1-.LFB1		/* FDE address range */
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI0-.LFB1
-	.byte	0xe	/* DW_CFA_def_cfa_offset */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 */
-	.byte	0x2	/* .uleb128 0x2 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI1-.LCFI0
-	.byte	0xd	/* DW_CFA_def_cfa_register */
-	.byte	0x5	/* .uleb128 0x5 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI2-.LCFI1
-	.byte	0x83	/* .DW_CFA_offset, column 0x3 */
-	.byte	0x3	/* .uleb128 0x3 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI3-.LCFI2
-	.byte	0xc3	/* DW_CFA_restore, column 0x3 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI4-.LCFI3
-	.byte	0xc5	/* DW_CFA_restore, column 0x5 */
-	.byte	0xc	/* DW_CFA_def_cfa */
-	.byte	0x4	/* .uleb128 0x4 */
-	.byte	0x4	/* .uleb128 0x4 */
-	.align 4
-.LEFDE1:
-#ifdef __PIC__
-.LSFDE2:
-	.long	.LEFDE2-.LASFDE2	/* FDE Length */
-.LASFDE2:
-	.long	.LASFDE2-.Lframe1	/* FDE CIE offset */
-	.long	FDE_ENCODE(.LFB2)	/* FDE initial location */
-	.long	.LFE2-.LFB2		/* FDE address range */
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-	.align 4
-.LEFDE2:
-#endif /* __PIC__ */
-#endif /* __ELF__ */
-
-#if defined(__ELF__) && defined(__linux__)
-	.section	.note.GNU-stack,"",@progbits
-	.section	.note.GNU-split-stack,"",@progbits
-	.section	.note.GNU-no-split-stack,"",@progbits
-#endif
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc_amd64.S b/third_party/gofrontend/libgo/go/reflect/makefunc_amd64.S
deleted file mode 100644
index 88302ee..0000000
--- a/third_party/gofrontend/libgo/go/reflect/makefunc_amd64.S
+++ /dev/null
@@ -1,177 +0,0 @@
-# Copyright 2013 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# MakeFunc amd64 assembly code.
-
-#include "config.h"
-
-	.global	reflect.makeFuncStub
-
-#ifdef __ELF__
-	.type	reflect.makeFuncStub,@function
-#endif
-
-reflect.makeFuncStub:
-.LFB1:
-
-	# Store all the parameter registers in a struct that looks
-	# like:
-	# struct {
-	#   rax uint64		// 0x0
-	#   rdi uint64		// 0x8
-	#   rsi uint64		// 0x10
-	#   rdx uint64		// 0x18
-	#   rcx uint64		// 0x20
-	#   r8 uint64		// 0x28
-	#   r9 uint64		// 0x30
-	#   rsp uint64		// 0x38 Pointer to arguments on stack.
-	#   xmm0 [2]uint64	// 0x40
-	#   xmm1 [2]uint64	// 0x50
-	#   xmm2 [2]uint64	// 0x60
-	#   xmm3 [2]uint64	// 0x70
-	#   xmm4 [2]uint64	// 0x80
-	#   xmm5 [2]uint64	// 0x90
-	#   xmm6 [2]uint64	// 0xa0
-	#   xmm7 [2]uint64	// 0xb0
-	# };
-
-	pushq	%rbp
-.LCFI0:
-	movq	%rsp, %rbp
-.LCFI1:
-
-	subq	$0xc0, %rsp		# Space for struct on stack.
-
-	movq	%rax, 0x0(%rsp)
-	movq	%rdi, 0x8(%rsp)
-	movq	%rsi, 0x10(%rsp)
-	movq	%rdx, 0x18(%rsp)
-	movq	%rcx, 0x20(%rsp)
-	movq	%r8, 0x28(%rsp)
-	movq	%r9, 0x30(%rsp)
-	leaq	16(%rbp), %rax
-	movq	%rax, 0x38(%rsp)
-	movdqa	%xmm0, 0x40(%rsp)
-	movdqa	%xmm1, 0x50(%rsp)
-	movdqa	%xmm2, 0x60(%rsp)
-	movdqa	%xmm3, 0x70(%rsp)
-	movdqa	%xmm4, 0x80(%rsp)
-	movdqa	%xmm5, 0x90(%rsp)
-	movdqa	%xmm6, 0xa0(%rsp)
-	movdqa	%xmm7, 0xb0(%rsp)
-
-	/* For MakeFunc functions that call recover.  */
-	movq	8(%rbp), %rdi
-#ifdef __PIC__
-	call	__go_makefunc_can_recover@PLT
-#else
-	call	__go_makefunc_can_recover
-#endif
-
-	# Get function type.
-#ifdef __PIC__
-	call	__go_get_closure@PLT
-#else
-	call	__go_get_closure
-#endif
-	movq	%rax, %rsi
-
-	movq	%rsp, %rdi
-
-#ifdef __PIC__
-	call	reflect.MakeFuncStubGo@PLT
-#else
-	call	reflect.MakeFuncStubGo
-#endif
-
-	/* MakeFunc functions can no longer call recover.  */
-#ifdef __PIC__
-	call __go_makefunc_returning@PLT
-#else
-	call __go_makefunc_returning
-#endif
-
-	# The structure will be updated with any return values.  Load
-	# all possible return registers before returning to the caller.
-
-	movq	0x0(%rsp), %rax
-	movq	0x18(%rsp), %rdx
-	movq	0x8(%rsp), %rdi
-	movq	0x10(%rsp), %rsi
-	movdqa	0x40(%rsp), %xmm0
-	movdqa	0x50(%rsp), %xmm1
-
-	# long double values are returned on the floating point stack,
-	# but we don't worry about that since Go doesn't have a long
-	# double type.
-
-	leave
-.LCFI2:
-
-	ret
-.LFE1:
-
-#ifdef __ELF__
-	.size	reflect.makeFuncStub, . - reflect.makeFuncStub
-#endif
-
-#ifdef __ELF__
-#ifdef HAVE_AS_X86_64_UNWIND_SECTION_TYPE
-	.section	.eh_frame,"a",@unwind
-#else
-	.section	.eh_frame,"a",@progbits
-#endif
-.Lframe1:
-	.long	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
-.LSCIE1:
-	.long	0x0		/* CIE Identifier Tag */
-	.byte	0x1		/* CIE Version */
-	.ascii "zR\0"		/* CIE Augmentation */
-	.uleb128 1		/* CIE Code Alignment Factor */
-	.sleb128 -8		/* CIE Data Alignment Factor */
-	.byte	0x10		/* CIE RA Column */
-	.uleb128 1		/* Augmentation size */
-	.byte	0x1b		/* FDE Encoding (pcrel sdata4) */
-	.byte	0xc		/* DW_CFA_def_cfa, %rsp offset 8 */
-	.uleb128 7
-	.uleb128 8
-	.byte	0x80+16		/* DW_CFA_offset, %rip offset 1*-8 */
-	.uleb128 1
-	.align 8
-.LECIE1:
-.LSFDE1:
-	.long	.LEFDE1-.LASFDE1	/* FDE Length */
-.LASFDE1:
-	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
-#if HAVE_AS_X86_PCREL
-	.long	.LFB1-.			/* FDE initial location */
-#else
-	.long	.LFB1@rel
-#endif
-	.long	.LFE1-.LFB1		/* FDE address range */
-	.uleb128 0x0			/* Augmentation size */
-	.byte	0x4			/* DW_CFA_advance_loc4 */
-	.long	.LCFI0-.LFB1
-	.byte	0xe			/* DW_CFA_def_cfa_offset */
-	.uleb128 16
-	.byte	0x86			/* DW_CFA_offset, column 0x6 */
-	.uleb128 2
-	.byte	0x4			/* DW_CFA_advance_loc4 */
-	.long	.LCFI1-.LCFI0
-	.byte	0xd			/* DW_CFA_def_cfa_register */
-	.uleb128 6
-	.byte	0x2			/* DW_CFA_advance_loc1 */
-	.byte	.LCFI2-.LCFI1
-	.byte	0xc			/* DW_CFA_def_cfa */
-	.uleb128 7
-	.uleb128 8
-	.align 8
-.LEFDE1:
-#endif /* __ELF__ */
-
-#if defined(__ELF__) && defined(__linux__)
-	.section	.note.GNU-stack,"",@progbits
-	.section	.note.GNU-split-stack,"",@progbits
-	.section	.note.GNU-no-split-stack,"",@progbits
-#endif
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc_dummy.c b/third_party/gofrontend/libgo/go/reflect/makefunc_dummy.c
deleted file mode 100644
index 8eff0c1..0000000
--- a/third_party/gofrontend/libgo/go/reflect/makefunc_dummy.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-
-/* Dummy function for processors that implement MakeFunc using FFI
-   rather than having builtin support.  */
-
-void makeFuncStub (void) __asm__ ("reflect.makeFuncStub");
-
-void makeFuncStub (void)
-{
-  runtime_throw ("impossible call to makeFuncStub");
-}
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc_ffi.go b/third_party/gofrontend/libgo/go/reflect/makefunc_ffi.go
index 40c1ea8..c821131 100644
--- a/third_party/gofrontend/libgo/go/reflect/makefunc_ffi.go
+++ b/third_party/gofrontend/libgo/go/reflect/makefunc_ffi.go
@@ -5,52 +5,27 @@
 package reflect
 
 import (
-	"runtime"
 	"unsafe"
 )
 
-// The ffi function, written in C, allocates an FFI closure.  It
-// returns the code and data pointers.  When the code pointer is
-// called, it will call callback.  CIF is an FFI data structure
-// allocated as part of the closure, and is returned to ensure that
-// the GC retains it.
-func ffi(ftyp *funcType, callback func(unsafe.Pointer, unsafe.Pointer)) (code uintptr, data uintptr, cif unsafe.Pointer)
+// The makeFuncFFI function, written in C, fills in an FFI closure.
+// It arranges for ffiCall to be invoked directly from FFI.
+func makeFuncFFI(ftyp *funcType, impl unsafe.Pointer)
 
-// The ffiFree function, written in C, releases the FFI closure.
-func ffiFree(uintptr)
+// FFICallbackGo implements the Go side of the libffi callback.
+// It is exported so that C code can call it.
+//
+// The call chain arriving here looks like
+//   some_go_caller
+//   ->some_ffi_internals
+//     ->ffi_callback (in C)
+//       ->FFICallbackGo
+//
+// The ffi_callback handles __go_makefunc_can_recover, and
+// then passes off the data as received from ffi here.
 
-// An ffiData holds the information needed to preserve an FFI closure
-// for the garbage collector.
-type ffiData struct {
-	code     uintptr
-	data     uintptr
-	cif      unsafe.Pointer
-	callback func(unsafe.Pointer, unsafe.Pointer)
-}
-
-// The makeFuncFFI function uses libffi closures to implement
-// reflect.MakeFunc.  This is used for processors for which we don't
-// have more efficient support.
-func makeFuncFFI(ftyp *funcType, fn func(args []Value) (results []Value)) (uintptr, *ffiData) {
-	callback := func(params, results unsafe.Pointer) {
-		ffiCall(ftyp, fn, params, results)
-	}
-
-	code, data, cif := ffi(ftyp, callback)
-
-	c := &ffiData{code: code, data: data, cif: cif, callback: callback}
-
-	runtime.SetFinalizer(c,
-		func(p *ffiData) {
-			ffiFree(p.data)
-		})
-
-	return code, c
-}
-
-// ffiCall takes pointers to the parameters, calls the function, and
-// stores the results back into memory.
-func ffiCall(ftyp *funcType, fn func([]Value) []Value, params unsafe.Pointer, results unsafe.Pointer) {
+func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFuncImpl) {
+	ftyp := impl.typ
 	in := make([]Value, 0, len(ftyp.in))
 	ap := params
 	for _, rt := range ftyp.in {
@@ -61,18 +36,18 @@
 		ap = (unsafe.Pointer)(uintptr(ap) + ptrSize)
 	}
 
-	out := fn(in)
+	out := impl.call(in)
 
 	off := uintptr(0)
 	for i, typ := range ftyp.out {
 		v := out[i]
 		if v.typ != typ {
-			panic("reflect: function created by MakeFunc using " + funcName(fn) +
+			panic("reflect: function created by MakeFunc using " + funcName(impl.fn) +
 				" returned wrong type: have " +
 				out[i].typ.String() + " for " + typ.String())
 		}
 		if v.flag&flagRO != 0 {
-			panic("reflect: function created by MakeFunc using " + funcName(fn) +
+			panic("reflect: function created by MakeFunc using " + funcName(impl.fn) +
 				" returned value obtained from unexported field")
 		}
 
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc_ffi_c.c b/third_party/gofrontend/libgo/go/reflect/makefunc_ffi_c.c
index a3dfd4a..06a41ef 100644
--- a/third_party/gofrontend/libgo/go/reflect/makefunc_ffi_c.c
+++ b/third_party/gofrontend/libgo/go/reflect/makefunc_ffi_c.c
@@ -10,7 +10,7 @@
 
 #include "go-ffi.h"
 
-#if FFI_CLOSURES
+#if FFI_GO_CLOSURES
 #define USE_LIBFFI_CLOSURES
 #endif
 
@@ -18,36 +18,28 @@
 
 /* Declare C functions with the names used to call from Go.  */
 
-struct ffi_ret {
-  void *code;
-  void *data;
-  void *cif;
-};
-
-struct ffi_ret ffi(const struct __go_func_type *ftyp, FuncVal *callback)
-  __asm__ (GOSYM_PREFIX "reflect.ffi");
-
-void ffiFree(void *data)
-  __asm__ (GOSYM_PREFIX "reflect.ffiFree");
+void makeFuncFFI(const struct __go_func_type *ftyp, void *impl)
+  __asm__ (GOSYM_PREFIX "reflect.makeFuncFFI");
 
 #ifdef USE_LIBFFI_CLOSURES
 
-/* The function that we pass to ffi_prep_closure_loc.  This calls the
-   Go callback function (passed in user_data) with the pointer to the
-   arguments and the results area.  */
+/* The function that we pass to ffi_prep_closure_loc.  This calls the Go
+   function ffiCall with the pointer to the arguments, the results area,
+   and the closure structure.  */
+
+void FFICallbackGo(void *result, void **args, ffi_go_closure *closure)
+  __asm__ (GOSYM_PREFIX "reflect.FFICallbackGo");
 
 static void ffi_callback (ffi_cif *, void *, void **, void *)
   __asm__ ("reflect.ffi_callback");
 
 static void
 ffi_callback (ffi_cif* cif __attribute__ ((unused)), void *results,
-	      void **args, void *user_data)
+	      void **args, void *closure)
 {
   Location locs[8];
   int n;
   int i;
-  FuncVal *fv;
-  void (*f) (void *, void *);
 
   /* This function is called from some series of FFI closure functions
      called by a Go function.  We want to see whether the caller of
@@ -69,10 +61,7 @@
   if (i < n)
     __go_makefunc_ffi_can_recover (locs + i, n - i);
 
-  fv = (FuncVal *) user_data;
-  __go_set_closure (fv);
-  f = (void *) fv->fn;
-  f (args, results);
+  FFICallbackGo(results, args, closure);
 
   if (i < n)
     __go_makefunc_returning ();
@@ -80,46 +69,22 @@
 
 /* Allocate an FFI closure and arrange to call ffi_callback.  */
 
-struct ffi_ret
-ffi (const struct __go_func_type *ftyp, FuncVal *callback)
+void
+makeFuncFFI(const struct __go_func_type *ftyp, void *impl)
 {
   ffi_cif *cif;
-  void *code;
-  void *data;
-  struct ffi_ret ret;
 
   cif = (ffi_cif *) __go_alloc (sizeof (ffi_cif));
   __go_func_to_cif (ftyp, 0, 0, cif);
-  data = ffi_closure_alloc (sizeof (ffi_closure), &code);
-  if (data == NULL)
-    runtime_panicstring ("ffi_closure_alloc failed");
-  if (ffi_prep_closure_loc (data, cif, ffi_callback, callback, code)
-      != FFI_OK)
-    runtime_panicstring ("ffi_prep_closure_loc failed");
-  ret.code = code;
-  ret.data = data;
-  ret.cif = cif;
-  return ret;
-}
 
-/* Free the FFI closure.  */
-
-void
-ffiFree (void *data)
-{
-  ffi_closure_free (data);
+  ffi_prep_go_closure(impl, cif, ffi_callback);
 }
 
 #else /* !defined(USE_LIBFFI_CLOSURES) */
 
-struct ffi_ret
-ffi(const struct __go_func_type *ftyp, FuncVal *callback)
-{
-  runtime_panicstring ("libgo built without FFI does not support "
-		       "reflect.MakeFunc");
-}
-
-void ffiFree(void *data)
+void
+makeFuncFFI(const struct __go_func_type *ftyp __attribute__ ((unused)),
+	    void *impl __attribute__ ((unused)))
 {
   runtime_panicstring ("libgo built without FFI does not support "
 		       "reflect.MakeFunc");
diff --git a/third_party/gofrontend/libgo/go/reflect/makefunc_s390.c b/third_party/gofrontend/libgo/go/reflect/makefunc_s390.c
deleted file mode 100644
index 78a960c..0000000
--- a/third_party/gofrontend/libgo/go/reflect/makefunc_s390.c
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "go-panic.h"
-
-#ifdef __s390x__
-#  define S390_GO_USE_64_BIT_ABI 1
-#  define S390_GO_S390X_ARGS , double f4, double f6
-#  define S390_GO_S390X_FIELDS double f4; double f6;
-   extern void S390xMakeFuncStubGo(void *, void *)
-	asm ("reflect.S390xMakeFuncStubGo");
-#  define S390_GO_MakeFuncStubGo(r, c) S390xMakeFuncStubGo((r), (c))
-#else
-#  define S390_GO_USE_64_BIT_ABI 0
-#  define S390_GO_S390X_ARGS
-#  define S390_GO_S390X_FIELDS
-   extern void S390MakeFuncStubGo(void *, void *)
-	asm ("reflect.S390MakeFuncStubGo");
-#  define S390_GO_MakeFuncStubGo(r, c) S390MakeFuncStubGo((r), (c))
-   /* Needed to make the unused 64 bit abi conditional code compile.  */
-#  define f4 f0
-#  define f6 f2
-#endif
-
-/* Structure to store all registers used for parameter passing.  */
-typedef struct
-{
-	long r2;
-	long r3;
-	long r4;
-	long r5;
-	long r6;
-	/* Pointer to non-register arguments on the stack.  */
-	long stack_args;
-	double f0;
-	double f2;
-	S390_GO_S390X_FIELDS
-} s390Regs;
-
-void
-makeFuncStub(long r2, long r3, long r4, long r5, long r6,
-	unsigned long stack_args, double f0, double f2
-	S390_GO_S390X_ARGS)
-	asm ("reflect.makeFuncStub");
-
-void
-makeFuncStub(long r2, long r3, long r4, long r5, long r6,
-	unsigned long stack_args, double f0, double f2
-	S390_GO_S390X_ARGS)
-{
-	s390Regs regs;
-	void *closure;
-
-	/* Store the registers in a structure that is passed on to the Go stub
-	   function.  */
-	regs.r2 = r2;
-	regs.r3 = r3;
-	regs.r4 = r4;
-	regs.r5 = r5;
-	regs.r6 = r6;
-	regs.stack_args = (long)&stack_args;
-	regs.f0 = f0;
-	regs.f2 = f2;
-	if (S390_GO_USE_64_BIT_ABI) {
-		regs.f4 = f4;
-		regs.f6 = f6;
-	}
-	/* For MakeFunc functions that call recover.  */
-	__go_makefunc_can_recover(__builtin_return_address(0));
-	/* Call the Go stub function.  */
-	closure = __go_get_closure();
-	S390_GO_MakeFuncStubGo(&regs, closure);
-	/* MakeFunc functions can no longer call recover.  */
-	__go_makefunc_returning();
-	/* Restore all possible return registers.  */
-	if (S390_GO_USE_64_BIT_ABI) {
-		asm volatile ("lg\t%%r2,0(%0)" : : "a" (&regs.r2) : "r2" );
-		asm volatile ("ld\t%%f0,0(%0)" : : "a" (&regs.f0) : "f0" );
-	} else {
-		asm volatile ("l\t%%r2,0(%0)" : : "a" (&regs.r2) : "r2" );
-		asm volatile ("l\t%%r3,0(%0)" : : "a" (&regs.r3) : "r3" );
-		asm volatile ("ld\t%%f0,0(%0)" : : "a" (&regs.f0) : "f0" );
-	}
-}
diff --git a/third_party/gofrontend/libgo/go/reflect/makefuncgo_386.go b/third_party/gofrontend/libgo/go/reflect/makefuncgo_386.go
deleted file mode 100644
index c20f0ac..0000000
--- a/third_party/gofrontend/libgo/go/reflect/makefuncgo_386.go
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// MakeFunc 386 implementation.
-
-package reflect
-
-import "unsafe"
-
-// The assembler stub will pass a pointer to this structure.  We
-// assume that no parameters are passed in registers--that is, we do
-// not support the -mregparm option.  On return we will set the
-// registers that might hold result values.
-type i386Regs struct {
-	esp uint32
-	eax uint32  // Value to return in %eax.
-	st0 float64 // Value to return in %st(0).
-	sr  bool    // Set to true if hidden struct pointer.
-	sf  bool    // Set to true if returning float
-}
-
-// MakeFuncStubGo implements the 386 calling convention for MakeFunc.
-// This should not be called.  It is exported so that assembly code
-// can call it.
-
-func MakeFuncStubGo(regs *i386Regs, c *makeFuncImpl) {
-	ftyp := c.typ
-
-	// See if the result requires a struct.  If it does, the first
-	// parameter is a pointer to the struct.
-	retStruct := false
-	retEmpty := false
-	switch len(ftyp.out) {
-	case 0:
-		retEmpty = true
-	case 1:
-		if ftyp.out[0].size == 0 {
-			retEmpty = true
-		} else {
-			switch ftyp.out[0].Kind() {
-			case Complex64, Complex128, Array, Interface, Slice, String, Struct:
-				retStruct = true
-			}
-		}
-	default:
-		size := uintptr(0)
-		for _, typ := range ftyp.out {
-			size += typ.size
-		}
-		if size == 0 {
-			retEmpty = true
-		} else {
-			retStruct = true
-		}
-	}
-
-	in := make([]Value, 0, len(ftyp.in))
-	ap := uintptr(regs.esp)
-
-	regs.sr = false
-	regs.sf = false
-	var retPtr unsafe.Pointer
-	if retStruct {
-		retPtr = *(*unsafe.Pointer)(unsafe.Pointer(ap))
-		ap += ptrSize
-		regs.sr = true
-	}
-
-	for _, rt := range ftyp.in {
-		ap = align(ap, ptrSize)
-
-		// We have to copy the argument onto the heap in case
-		// the function hangs on the reflect.Value we pass it.
-		p := unsafe_New(rt)
-		memmove(p, unsafe.Pointer(ap), rt.size)
-
-		v := Value{rt, p, flag(rt.Kind()) | flagIndir}
-		in = append(in, v)
-		ap += rt.size
-	}
-
-	// Call the real function.
-
-	out := c.call(in)
-
-	if len(out) != len(ftyp.out) {
-		panic("reflect: wrong return count from function created by MakeFunc")
-	}
-
-	for i, typ := range ftyp.out {
-		v := out[i]
-		if v.typ != typ {
-			panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
-				" returned wrong type: have " +
-				out[i].typ.String() + " for " + typ.String())
-		}
-		if v.flag&flagRO != 0 {
-			panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
-				" returned value obtained from unexported field")
-		}
-	}
-
-	if retEmpty {
-		return
-	}
-
-	if retStruct {
-		off := uintptr(0)
-		for i, typ := range ftyp.out {
-			v := out[i]
-			off = align(off, uintptr(typ.fieldAlign))
-			addr := unsafe.Pointer(uintptr(retPtr) + off)
-			if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
-				*(*unsafe.Pointer)(addr) = v.ptr
-			} else {
-				memmove(addr, v.ptr, typ.size)
-			}
-			off += typ.size
-		}
-		regs.eax = uint32(uintptr(retPtr))
-		return
-	}
-
-	if len(ftyp.out) != 1 {
-		panic("inconsistency")
-	}
-
-	v := out[0]
-	switch v.Kind() {
-	case Ptr, UnsafePointer, Chan, Func, Map:
-		regs.eax = uint32(uintptr(v.pointer()))
-	case Float32, Float64:
-		regs.st0 = v.Float()
-		regs.sf = true
-	default:
-		memmove(unsafe.Pointer(&regs.eax), v.ptr, v.typ.size)
-	}
-}
diff --git a/third_party/gofrontend/libgo/go/reflect/makefuncgo_amd64.go b/third_party/gofrontend/libgo/go/reflect/makefuncgo_amd64.go
deleted file mode 100644
index a236aa2..0000000
--- a/third_party/gofrontend/libgo/go/reflect/makefuncgo_amd64.go
+++ /dev/null
@@ -1,496 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// MakeFunc amd64 implementation.
-
-package reflect
-
-import "unsafe"
-
-// The assembler stub will pass a pointer to this structure.
-// This will come in holding all the registers that might hold
-// function parameters.  On return we will set the registers that
-// might hold result values.
-type amd64Regs struct {
-	rax  uint64
-	rdi  uint64
-	rsi  uint64
-	rdx  uint64
-	rcx  uint64
-	r8   uint64
-	r9   uint64
-	rsp  uint64
-	xmm0 [2]uint64
-	xmm1 [2]uint64
-	xmm2 [2]uint64
-	xmm3 [2]uint64
-	xmm4 [2]uint64
-	xmm5 [2]uint64
-	xmm6 [2]uint64
-	xmm7 [2]uint64
-}
-
-// Argument classifications.  The amd64 ELF ABI uses several more, but
-// these are the only ones that arise for Go types.
-type amd64Class int
-
-const (
-	amd64Integer amd64Class = iota
-	amd64SSE
-	amd64NoClass
-	amd64Memory
-)
-
-// amd64Classify returns the one or two register classes needed to
-// pass the value of type.  Go types never need more than two
-// registers.  amd64Memory means the value is stored in memory.
-// amd64NoClass means the register is not used.
-func amd64Classify(typ *rtype) (amd64Class, amd64Class) {
-	switch typ.Kind() {
-	default:
-		panic("internal error--unknown kind in amd64Classify")
-
-	case Bool, Int, Int8, Int16, Int32, Int64,
-		Uint, Uint8, Uint16, Uint32, Uint64,
-		Uintptr, Chan, Func, Map, Ptr, UnsafePointer:
-
-		return amd64Integer, amd64NoClass
-
-	case Float32, Float64, Complex64:
-		return amd64SSE, amd64NoClass
-
-	case Complex128:
-		return amd64SSE, amd64SSE
-
-	case Array:
-		if typ.size == 0 {
-			return amd64NoClass, amd64NoClass
-		} else if typ.size > 16 {
-			return amd64Memory, amd64NoClass
-		}
-		atyp := (*arrayType)(unsafe.Pointer(typ))
-		eclass1, eclass2 := amd64Classify(atyp.elem)
-		if eclass1 == amd64Memory {
-			return amd64Memory, amd64NoClass
-		}
-		if eclass2 == amd64NoClass && typ.size > 8 {
-			eclass2 = eclass1
-		}
-		return eclass1, eclass2
-
-	case Interface:
-		return amd64Integer, amd64Integer
-
-	case Slice:
-		return amd64Memory, amd64NoClass
-
-	case String:
-		return amd64Integer, amd64Integer
-
-	case Struct:
-		if typ.size == 0 {
-			return amd64NoClass, amd64NoClass
-		} else if typ.size > 16 {
-			return amd64Memory, amd64NoClass
-		}
-		var first, second amd64Class
-		f := amd64NoClass
-		onFirst := true
-		styp := (*structType)(unsafe.Pointer(typ))
-		for _, field := range styp.fields {
-			if onFirst && field.offset >= 8 {
-				first = f
-				f = amd64NoClass
-				onFirst = false
-			}
-			fclass1, fclass2 := amd64Classify(field.typ)
-			f = amd64MergeClasses(f, fclass1)
-			if fclass2 != amd64NoClass {
-				if !onFirst {
-					panic("amd64Classify inconsistent")
-				}
-				first = f
-				f = fclass2
-				onFirst = false
-			}
-		}
-		if onFirst {
-			first = f
-			second = amd64NoClass
-		} else {
-			second = f
-		}
-		if first == amd64Memory || second == amd64Memory {
-			return amd64Memory, amd64NoClass
-		}
-		return first, second
-	}
-}
-
-// amd64MergeClasses merges two register classes as described in the
-// amd64 ELF ABI.
-func amd64MergeClasses(c1, c2 amd64Class) amd64Class {
-	switch {
-	case c1 == c2:
-		return c1
-	case c1 == amd64NoClass:
-		return c2
-	case c2 == amd64NoClass:
-		return c1
-	case c1 == amd64Memory || c2 == amd64Memory:
-		return amd64Memory
-	case c1 == amd64Integer || c2 == amd64Integer:
-		return amd64Integer
-	default:
-		return amd64SSE
-	}
-}
-
-// MakeFuncStubGo implements the amd64 calling convention for
-// MakeFunc.  This should not be called.  It is exported so that
-// assembly code can call it.
-
-func MakeFuncStubGo(regs *amd64Regs, c *makeFuncImpl) {
-	ftyp := c.typ
-
-	// See if the result requires a struct.  If it does, the first
-	// parameter is a pointer to the struct.
-	var ret1, ret2 amd64Class
-	switch len(ftyp.out) {
-	case 0:
-		ret1, ret2 = amd64NoClass, amd64NoClass
-	case 1:
-		ret1, ret2 = amd64Classify(ftyp.out[0])
-	default:
-		off := uintptr(0)
-		f := amd64NoClass
-		onFirst := true
-		for _, rt := range ftyp.out {
-			off = align(off, uintptr(rt.fieldAlign))
-
-			if onFirst && off >= 8 {
-				ret1 = f
-				f = amd64NoClass
-				onFirst = false
-			}
-
-			off += rt.size
-			if off > 16 {
-				break
-			}
-
-			fclass1, fclass2 := amd64Classify(rt)
-			f = amd64MergeClasses(f, fclass1)
-			if fclass2 != amd64NoClass {
-				if !onFirst {
-					panic("amd64Classify inconsistent")
-				}
-				ret1 = f
-				f = fclass2
-				onFirst = false
-			}
-		}
-		if off > 16 {
-			ret1, ret2 = amd64Memory, amd64NoClass
-		} else {
-			if onFirst {
-				ret1, ret2 = f, amd64NoClass
-			} else {
-				ret2 = f
-			}
-		}
-		if ret1 == amd64Memory || ret2 == amd64Memory {
-			ret1, ret2 = amd64Memory, amd64NoClass
-		}
-	}
-
-	in := make([]Value, 0, len(ftyp.in))
-	intreg := 0
-	ssereg := 0
-	ap := uintptr(regs.rsp)
-
-	maxIntregs := 6 // When we support Windows, this would be 4.
-	maxSSEregs := 8
-
-	if ret1 == amd64Memory {
-		// We are returning a value in memory, which means
-		// that the first argument is a hidden parameter
-		// pointing to that return area.
-		intreg++
-	}
-
-argloop:
-	for _, rt := range ftyp.in {
-		c1, c2 := amd64Classify(rt)
-
-		fl := flag(rt.Kind())
-		if c2 == amd64NoClass {
-
-			// Argument is passed in a single register or
-			// in memory.
-
-			switch c1 {
-			case amd64NoClass:
-				v := Value{rt, nil, fl | flagIndir}
-				in = append(in, v)
-				continue argloop
-			case amd64Integer:
-				if intreg < maxIntregs {
-					reg := amd64IntregVal(regs, intreg)
-					iw := unsafe.Pointer(reg)
-					if k := rt.Kind(); k != Ptr && k != UnsafePointer {
-						iw = unsafe.Pointer(&reg)
-						fl |= flagIndir
-					}
-					v := Value{rt, iw, fl}
-					in = append(in, v)
-					intreg++
-					continue argloop
-				}
-			case amd64SSE:
-				if ssereg < maxSSEregs {
-					reg := amd64SSEregVal(regs, ssereg)
-					v := Value{rt, unsafe.Pointer(&reg), fl | flagIndir}
-					in = append(in, v)
-					ssereg++
-					continue argloop
-				}
-			}
-
-			in, ap = amd64Memarg(in, ap, rt)
-			continue argloop
-		}
-
-		// Argument is passed in two registers.
-
-		nintregs := 0
-		nsseregs := 0
-		switch c1 {
-		case amd64Integer:
-			nintregs++
-		case amd64SSE:
-			nsseregs++
-		default:
-			panic("inconsistent")
-		}
-		switch c2 {
-		case amd64Integer:
-			nintregs++
-		case amd64SSE:
-			nsseregs++
-		default:
-			panic("inconsistent")
-		}
-
-		// If the whole argument does not fit in registers, it
-		// is passed in memory.
-
-		if intreg+nintregs > maxIntregs || ssereg+nsseregs > maxSSEregs {
-			in, ap = amd64Memarg(in, ap, rt)
-			continue argloop
-		}
-
-		var word1, word2 uintptr
-		switch c1 {
-		case amd64Integer:
-			word1 = amd64IntregVal(regs, intreg)
-			intreg++
-		case amd64SSE:
-			word1 = amd64SSEregVal(regs, ssereg)
-			ssereg++
-		}
-		switch c2 {
-		case amd64Integer:
-			word2 = amd64IntregVal(regs, intreg)
-			intreg++
-		case amd64SSE:
-			word2 = amd64SSEregVal(regs, ssereg)
-			ssereg++
-		}
-
-		p := unsafe_New(rt)
-		*(*uintptr)(p) = word1
-		*(*uintptr)(unsafe.Pointer(uintptr(p) + ptrSize)) = word2
-		v := Value{rt, p, fl | flagIndir}
-		in = append(in, v)
-	}
-
-	// All the real arguments have been found and turned into
-	// Value's.  Call the real function.
-
-	out := c.call(in)
-
-	if len(out) != len(ftyp.out) {
-		panic("reflect: wrong return count from function created by MakeFunc")
-	}
-
-	for i, typ := range ftyp.out {
-		v := out[i]
-		if v.typ != typ {
-			panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
-				" returned wrong type: have " +
-				out[i].typ.String() + " for " + typ.String())
-		}
-		if v.flag&flagRO != 0 {
-			panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
-				" returned value obtained from unexported field")
-		}
-	}
-
-	if ret1 == amd64NoClass {
-		return
-	}
-
-	if ret1 == amd64Memory {
-		// The address of the memory area was passed as a
-		// hidden parameter in %rdi.
-		ptr := unsafe.Pointer(uintptr(regs.rdi))
-		off := uintptr(0)
-		for i, typ := range ftyp.out {
-			v := out[i]
-			off = align(off, uintptr(typ.fieldAlign))
-			addr := unsafe.Pointer(uintptr(ptr) + off)
-			if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
-				*(*unsafe.Pointer)(addr) = v.ptr
-			} else {
-				memmove(addr, v.ptr, typ.size)
-			}
-			off += typ.size
-		}
-		return
-	}
-
-	if len(out) == 1 && ret2 == amd64NoClass {
-		v := out[0]
-		var w unsafe.Pointer
-		switch v.Kind() {
-		case Ptr, UnsafePointer, Chan, Func, Map:
-			w = v.pointer()
-		default:
-			memmove(unsafe.Pointer(&w), v.ptr, v.typ.size)
-		}
-		switch ret1 {
-		case amd64Integer:
-			regs.rax = uint64(uintptr(w))
-		case amd64SSE:
-			regs.xmm0[0] = uint64(uintptr(w))
-			regs.xmm0[1] = 0
-		default:
-			panic("inconsistency")
-		}
-		return
-	}
-
-	var buf [2]unsafe.Pointer
-	ptr := unsafe.Pointer(&buf[0])
-	off := uintptr(0)
-	for i, typ := range ftyp.out {
-		v := out[i]
-		off = align(off, uintptr(typ.fieldAlign))
-		addr := unsafe.Pointer(uintptr(ptr) + off)
-		if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
-			*(*unsafe.Pointer)(addr) = v.ptr
-		} else {
-			memmove(addr, v.ptr, typ.size)
-		}
-		off += uintptr(typ.size)
-	}
-
-	switch ret1 {
-	case amd64Integer:
-		regs.rax = *(*uint64)(unsafe.Pointer(&buf[0]))
-	case amd64SSE:
-		regs.xmm0[0] = *(*uint64)(unsafe.Pointer(&buf[0]))
-		regs.xmm0[1] = 0
-	default:
-		panic("inconsistency")
-	}
-
-	switch ret2 {
-	case amd64Integer:
-		reg := *(*uint64)(unsafe.Pointer(&buf[1]))
-		if ret1 == amd64Integer {
-			regs.rdx = reg
-		} else {
-			regs.rax = reg
-		}
-	case amd64SSE:
-		reg := *(*uint64)(unsafe.Pointer(&buf[1]))
-		if ret1 == amd64Integer {
-			regs.xmm0[0] = reg
-			regs.xmm0[1] = 0
-		} else {
-			regs.xmm1[0] = reg
-			regs.xmm1[1] = 0
-		}
-	case amd64NoClass:
-	default:
-		panic("inconsistency")
-	}
-}
-
-// The amd64Memarg function adds an argument passed in memory.
-func amd64Memarg(in []Value, ap uintptr, rt *rtype) ([]Value, uintptr) {
-	ap = align(ap, ptrSize)
-	ap = align(ap, uintptr(rt.align))
-
-	// We have to copy the argument onto the heap in case the
-	// function hangs onto the reflect.Value we pass it.
-	p := unsafe_New(rt)
-	memmove(p, unsafe.Pointer(ap), rt.size)
-
-	v := Value{rt, p, flag(rt.Kind()) | flagIndir}
-	in = append(in, v)
-	ap += rt.size
-	return in, ap
-}
-
-// The amd64IntregVal function returns the value of integer register i.
-func amd64IntregVal(regs *amd64Regs, i int) uintptr {
-	var r uint64
-	switch i {
-	case 0:
-		r = regs.rdi
-	case 1:
-		r = regs.rsi
-	case 2:
-		r = regs.rdx
-	case 3:
-		r = regs.rcx
-	case 4:
-		r = regs.r8
-	case 5:
-		r = regs.r9
-	default:
-		panic("amd64IntregVal: bad index")
-	}
-	return uintptr(r)
-}
-
-// The amd64SSEregVal function returns the value of SSE register i.
-// Note that although SSE registers can hold two uinptr's, for the
-// types we use in Go we only ever use the least significant one.  The
-// most significant one would only be used for 128 bit types.
-func amd64SSEregVal(regs *amd64Regs, i int) uintptr {
-	var r uint64
-	switch i {
-	case 0:
-		r = regs.xmm0[0]
-	case 1:
-		r = regs.xmm1[0]
-	case 2:
-		r = regs.xmm2[0]
-	case 3:
-		r = regs.xmm3[0]
-	case 4:
-		r = regs.xmm4[0]
-	case 5:
-		r = regs.xmm5[0]
-	case 6:
-		r = regs.xmm6[0]
-	case 7:
-		r = regs.xmm7[0]
-	}
-	return uintptr(r)
-}
diff --git a/third_party/gofrontend/libgo/go/reflect/makefuncgo_s390.go b/third_party/gofrontend/libgo/go/reflect/makefuncgo_s390.go
deleted file mode 100644
index 47daa77..0000000
--- a/third_party/gofrontend/libgo/go/reflect/makefuncgo_s390.go
+++ /dev/null
@@ -1,454 +0,0 @@
-// Copyright 2014 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// MakeFunc s390 implementation.
-
-package reflect
-
-import "unsafe"
-
-// Convenience types and constants.
-const s390_arch_stack_slot_align uintptr = 4
-const s390_num_gr = 5
-const s390_num_fr = 2
-
-type s390_arch_gr_t uint32
-type s390_arch_fr_t uint64
-
-// The assembler stub will pass a pointer to this structure.
-// This will come in holding all the registers that might hold
-// function parameters.  On return we will set the registers that
-// might hold result values.
-type s390_regs struct {
-	r2         s390_arch_gr_t
-	r3         s390_arch_gr_t
-	r4         s390_arch_gr_t
-	r5         s390_arch_gr_t
-	r6         s390_arch_gr_t
-	stack_args s390_arch_gr_t
-	f0         s390_arch_fr_t
-	f2         s390_arch_fr_t
-}
-
-// Argument classifications that arise for Go types.
-type s390_arg_t int
-
-const (
-	s390_general_reg s390_arg_t = iota
-	s390_general_reg_pair
-	s390_float_reg
-	// Argument passed as a pointer to an in-memory value.
-	s390_mem_ptr
-	s390_empty
-)
-
-// s390ClassifyParameter returns the register class needed to
-// pass the value of type TYP.  s390_empty means the register is
-// not used.  The second and third return values are the offset of
-// an rtype parameter passed in a register (second) or stack slot
-// (third).
-func s390ClassifyParameter(typ *rtype) (s390_arg_t, uintptr, uintptr) {
-	offset := s390_arch_stack_slot_align - typ.Size()
-	if typ.Size() > s390_arch_stack_slot_align {
-		offset = 0
-	}
-	switch typ.Kind() {
-	default:
-		panic("internal error--unknown kind in s390ClassifyParameter")
-	case Bool, Int, Int8, Int16, Int32, Uint, Uint8, Uint16, Uint32:
-		return s390_general_reg, offset, offset
-	case Int64, Uint64:
-		return s390_general_reg_pair, 0, 0
-	case Uintptr, Chan, Func, Map, Ptr, UnsafePointer:
-		return s390_general_reg, 0, 0
-	case Float32, Float64:
-		return s390_float_reg, 0, offset
-	case Complex64, Complex128:
-		// Complex numbers are passed by reference.
-		return s390_mem_ptr, 0, 0
-	case Array, Struct:
-		var ityp *rtype
-		var length int
-
-		if typ.Size() == 0 {
-			return s390_empty, 0, 0
-		}
-		switch typ.Size() {
-		default:
-			// Pointer to memory.
-			return s390_mem_ptr, 0, 0
-		case 1, 2:
-			// Pass in an integer register.
-			return s390_general_reg, offset, offset
-
-		case 4, 8:
-			// See below.
-		}
-		if typ.Kind() == Array {
-			atyp := (*arrayType)(unsafe.Pointer(typ))
-			length = atyp.Len()
-			ityp = atyp.elem
-		} else {
-			styp := (*structType)(unsafe.Pointer(typ))
-			length = len(styp.fields)
-			ityp = styp.fields[0].typ
-		}
-		if length == 1 {
-			class, off_reg, off_slot := s390ClassifyParameter(ityp)
-			if class == s390_float_reg {
-				// The array (stored in a structure) or struct
-				// is "equivalent to a floating point type" as
-				// defined in the S390 Abi.  Note that this
-				// can only be the case in the case 4 of the
-				// switch above.
-				return s390_float_reg, off_reg, off_slot
-			}
-		}
-		switch typ.Size() {
-		case 4:
-			return s390_general_reg, offset, offset
-		case 8:
-			return s390_general_reg_pair, 0, 0
-		default:
-			return s390_general_reg, 0, 0
-		}
-	case Interface, String:
-		// Structure of size 8.
-		return s390_general_reg_pair, 0, 0
-
-	case Slice:
-		return s390_mem_ptr, 0, 0
-	}
-}
-
-// s390ClassifyReturn returns the register classes needed to
-// return the value of type TYP.  s390_empty means the register is
-// not used.  The second value is the offset of an rtype return
-// parameter if stored in a register.
-func s390ClassifyReturn(typ *rtype) (s390_arg_t, uintptr) {
-	offset := s390_arch_stack_slot_align - typ.Size()
-	if typ.Size() > s390_arch_stack_slot_align {
-		offset = 0
-	}
-	switch typ.Kind() {
-	default:
-		panic("internal error--unknown kind in s390ClassifyReturn")
-	case Bool, Int, Int8, Int16, Int32,
-		Uint, Uint8, Uint16, Uint32, Uintptr:
-
-		return s390_general_reg, offset
-	case Int64, Uint64:
-		return s390_general_reg_pair, 0
-	case Chan, Func, Map, Ptr, UnsafePointer:
-		return s390_general_reg, 0
-	case Float32, Float64:
-		return s390_float_reg, 0
-	case Complex64, Complex128:
-		return s390_mem_ptr, 0
-	case Interface, Slice, String:
-		return s390_mem_ptr, 0
-	case Array, Struct:
-		if typ.size == 0 {
-			return s390_empty, 0
-		}
-		// No optimization is done for returned structures and arrays.
-		return s390_mem_ptr, 0
-	}
-}
-
-// Given a value of type *rtype left aligned in an unsafe.Pointer,
-// reload the value so that it can be stored in a general or
-// floating point register.  For general registers the value is
-// sign extend and right aligned.
-func s390ReloadForRegister(typ *rtype, w uintptr, offset uintptr) uintptr {
-	var do_sign_extend bool = false
-	var gr s390_arch_gr_t
-
-	switch typ.Kind() {
-	case Int, Int8, Int16, Int32:
-		do_sign_extend = true
-	default:
-		// Handle all other cases in the next switch.
-	}
-	switch typ.size {
-	case 1:
-		if do_sign_extend == true {
-			se := int32(*(*int8)(unsafe.Pointer(&w)))
-			gr = *(*s390_arch_gr_t)(unsafe.Pointer(&se))
-		} else {
-			e := int32(*(*uint8)(unsafe.Pointer(&w)))
-			gr = *(*s390_arch_gr_t)(unsafe.Pointer(&e))
-		}
-	case 2:
-		if do_sign_extend == true {
-			se := int32(*(*int16)(unsafe.Pointer(&w)))
-			gr = *(*s390_arch_gr_t)(unsafe.Pointer(&se))
-		} else {
-			e := int32(*(*uint16)(unsafe.Pointer(&w)))
-			gr = *(*s390_arch_gr_t)(unsafe.Pointer(&e))
-		}
-	default:
-		panic("reflect: bad size in s390ReloadForRegister")
-	}
-
-	return *(*uintptr)(unsafe.Pointer(&gr))
-}
-
-// MakeFuncStubGo implements the s390 calling convention for
-// MakeFunc.  This should not be called.  It is exported so that
-// assembly code can call it.
-func S390MakeFuncStubGo(regs *s390_regs, c *makeFuncImpl) {
-	ftyp := c.typ
-	gr := 0
-	fr := 0
-	ap := uintptr(regs.stack_args)
-
-	// See if the result requires a struct.  If it does, the first
-	// parameter is a pointer to the struct.
-	var ret_class s390_arg_t
-	var ret_off_reg uintptr
-	var ret_type *rtype
-
-	switch len(ftyp.out) {
-	case 0:
-		ret_type = nil
-		ret_class, ret_off_reg = s390_empty, 0
-	case 1:
-		ret_type = ftyp.out[0]
-		ret_class, ret_off_reg = s390ClassifyReturn(ret_type)
-	default:
-		ret_type = nil
-		ret_class, ret_off_reg = s390_mem_ptr, 0
-	}
-	in := make([]Value, 0, len(ftyp.in))
-	if ret_class == s390_mem_ptr {
-		// We are returning a value in memory, which means
-		// that the first argument is a hidden parameter
-		// pointing to that return area.
-		gr++
-	}
-
-argloop:
-	for _, rt := range ftyp.in {
-		class, off_reg, off_slot := s390ClassifyParameter(rt)
-		fl := flag(rt.Kind())
-		switch class {
-		case s390_empty:
-			v := Value{rt, nil, fl | flagIndir}
-			in = append(in, v)
-			continue argloop
-		case s390_general_reg:
-			// Values stored in a general register are right
-			// aligned.
-			if gr < s390_num_gr {
-				val := s390_general_reg_val(regs, gr)
-				iw := unsafe.Pointer(&val)
-				k := rt.Kind()
-				if k != Ptr && k != UnsafePointer {
-					ix := uintptr(unsafe.Pointer(&val))
-					ix += off_reg
-					iw = unsafe.Pointer(ix)
-					fl |= flagIndir
-				}
-				v := Value{rt, iw, fl}
-				in = append(in, v)
-				gr++
-			} else {
-				in, ap = s390_add_stackreg(
-					in, ap, rt, off_slot)
-			}
-			continue argloop
-		case s390_general_reg_pair:
-			// 64-bit integers and structs are passed in a register
-			// pair.
-			if gr+1 < s390_num_gr {
-				val := uint64(s390_general_reg_val(regs, gr))<<32 + uint64(s390_general_reg_val(regs, gr+1))
-				iw := unsafe.Pointer(&val)
-				v := Value{rt, iw, fl | flagIndir}
-				in = append(in, v)
-				gr += 2
-			} else {
-				in, ap = s390_add_stackreg(in, ap, rt, off_slot)
-				gr = s390_num_gr
-			}
-			continue argloop
-		case s390_float_reg:
-			// In a register, floats are left aligned, but in a
-			// stack slot they are right aligned.
-			if fr < s390_num_fr {
-				val := s390_float_reg_val(regs, fr)
-				ix := uintptr(unsafe.Pointer(&val))
-				v := Value{
-					rt, unsafe.Pointer(unsafe.Pointer(ix)),
-					fl | flagIndir,
-				}
-				in = append(in, v)
-				fr++
-			} else {
-				in, ap = s390_add_stackreg(
-					in, ap, rt, off_slot)
-			}
-			continue argloop
-		case s390_mem_ptr:
-			if gr < s390_num_gr {
-				// Register holding a pointer to memory.
-				val := s390_general_reg_val(regs, gr)
-				v := Value{
-					rt, unsafe.Pointer(uintptr(val)),
-					fl | flagIndir}
-				in = append(in, v)
-				gr++
-			} else {
-				// Stack slot holding a pointer to memory.
-				in, ap = s390_add_memarg(in, ap, rt)
-			}
-			continue argloop
-		}
-		panic("reflect: argtype not handled in MakeFunc:argloop")
-	}
-
-	// All the real arguments have been found and turned into
-	// Values.  Call the real function.
-
-	out := c.call(in)
-
-	if len(out) != len(ftyp.out) {
-		panic("reflect: wrong return count from function created by MakeFunc")
-	}
-
-	for i, typ := range ftyp.out {
-		v := out[i]
-		if v.typ != typ {
-			panic(
-				"reflect: function created by MakeFunc using " +
-					funcName(c.fn) + " returned wrong type: have " +
-					out[i].typ.String() + " for " + typ.String())
-		}
-		if v.flag&flagRO != 0 {
-			panic(
-				"reflect: function created by MakeFunc using " +
-					funcName(c.fn) + " returned value obtained " +
-					"from unexported field")
-		}
-	}
-
-	switch ret_class {
-	case s390_general_reg, s390_float_reg, s390_general_reg_pair:
-		// Single return value in a general or floating point register.
-		v := out[0]
-		var w uintptr
-		switch v.Kind() {
-		case Ptr, UnsafePointer, Chan, Func, Map:
-			w = uintptr(v.pointer())
-		default:
-			memmove(unsafe.Pointer(&w), v.ptr, v.typ.size)
-			if ret_off_reg != 0 {
-				w = s390ReloadForRegister(
-					ret_type, w, ret_off_reg)
-			}
-		}
-		if ret_class == s390_float_reg {
-			regs.f0 = s390_arch_fr_t(uintptr(w))
-		} else if ret_class == s390_general_reg {
-			regs.r2 = s390_arch_gr_t(uintptr(w))
-		} else {
-			regs.r2 = s390_arch_gr_t(uintptr(w) >> 32)
-			regs.r3 = s390_arch_gr_t(uintptr(w) & 0xffffffff)
-		}
-
-	case s390_mem_ptr:
-		// The address of the memory area was passed as a hidden
-		// parameter in %r2.  Multiple return values are always returned
-		// in an in-memory structure.
-		ptr := unsafe.Pointer(uintptr(regs.r2))
-		off := uintptr(0)
-		for i, typ := range ftyp.out {
-			v := out[i]
-			off = align(off, uintptr(typ.fieldAlign))
-			addr := unsafe.Pointer(uintptr(ptr) + off)
-			if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
-				*(*unsafe.Pointer)(addr) = v.ptr
-			} else {
-				memmove(addr, v.ptr, typ.size)
-			}
-			off += typ.size
-		}
-
-	case s390_empty:
-	}
-
-	return
-}
-
-// The s390_add_stackreg function adds an argument passed on the
-// stack that could be passed in a register.
-func s390_add_stackreg(in []Value, ap uintptr, rt *rtype, offset uintptr) ([]Value, uintptr) {
-	// If we're not already at the beginning of a stack slot, round up to
-	// the beginning of the next one.
-	ap = align(ap, s390_arch_stack_slot_align)
-	// If offset is > 0, the data is right aligned on the stack slot.
-	ap += offset
-
-	// We have to copy the argument onto the heap in case the
-	// function hangs onto the reflect.Value we pass it.
-	p := unsafe_New(rt)
-	memmove(p, unsafe.Pointer(ap), rt.size)
-
-	v := Value{rt, p, flag(rt.Kind()) | flagIndir}
-	in = append(in, v)
-	ap += rt.size
-	ap = align(ap, s390_arch_stack_slot_align)
-
-	return in, ap
-}
-
-// The s390_add_memarg function adds an argument passed in memory.
-func s390_add_memarg(in []Value, ap uintptr, rt *rtype) ([]Value, uintptr) {
-	// If we're not already at the beginning of a stack slot,
-	// round up to the beginning of the next one.
-	ap = align(ap, s390_arch_stack_slot_align)
-
-	// We have to copy the argument onto the heap in case the
-	// function hangs onto the reflect.Value we pass it.
-	p := unsafe_New(rt)
-	memmove(p, *(*unsafe.Pointer)(unsafe.Pointer(ap)), rt.size)
-
-	v := Value{rt, p, flag(rt.Kind()) | flagIndir}
-	in = append(in, v)
-	ap += s390_arch_stack_slot_align
-
-	return in, ap
-}
-
-// The s390_general_reg_val function returns the value of integer register GR.
-func s390_general_reg_val(regs *s390_regs, gr int) s390_arch_gr_t {
-	switch gr {
-	case 0:
-		return regs.r2
-	case 1:
-		return regs.r3
-	case 2:
-		return regs.r4
-	case 3:
-		return regs.r5
-	case 4:
-		return regs.r6
-	default:
-		panic("s390_general_reg_val: bad integer register")
-	}
-}
-
-// The s390_float_reg_val function returns the value of float register FR.
-func s390_float_reg_val(regs *s390_regs, fr int) uintptr {
-	var r s390_arch_fr_t
-	switch fr {
-	case 0:
-		r = regs.f0
-	case 1:
-		r = regs.f2
-	default:
-		panic("s390_float_reg_val: bad floating point register")
-	}
-	return uintptr(r)
-}
diff --git a/third_party/gofrontend/libgo/go/reflect/makefuncgo_s390x.go b/third_party/gofrontend/libgo/go/reflect/makefuncgo_s390x.go
deleted file mode 100644
index 6e51015..0000000
--- a/third_party/gofrontend/libgo/go/reflect/makefuncgo_s390x.go
+++ /dev/null
@@ -1,436 +0,0 @@
-// Copyright 2014 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// MakeFunc s390x implementation.
-
-package reflect
-
-import "unsafe"
-
-// Convenience types and constants.
-const s390x_arch_stack_slot_align uintptr = 8
-const s390x_num_gr = 5
-const s390x_num_fr = 4
-
-type s390x_arch_gr_t uint64
-type s390x_arch_fr_t uint64
-
-// The assembler stub will pass a pointer to this structure.
-// This will come in holding all the registers that might hold
-// function parameters.  On return we will set the registers that
-// might hold result values.
-type s390x_regs struct {
-	r2         s390x_arch_gr_t
-	r3         s390x_arch_gr_t
-	r4         s390x_arch_gr_t
-	r5         s390x_arch_gr_t
-	r6         s390x_arch_gr_t
-	stack_args s390x_arch_gr_t
-	f0         s390x_arch_fr_t
-	f2         s390x_arch_fr_t
-	f4         s390x_arch_fr_t
-	f6         s390x_arch_fr_t
-}
-
-// Argument classifications that arise for Go types.
-type s390x_arg_t int
-
-const (
-	s390x_general_reg s390x_arg_t = iota
-	s390x_float_reg
-	// Argument passed as a pointer to an in-memory value.
-	s390x_mem_ptr
-	s390x_empty
-)
-
-// s390xClassifyParameter returns the register class needed to
-// pass the value of type TYP.  s390x_empty means the register is
-// not used.  The second and third return values are the offset of
-// an rtype parameter passed in a register (second) or stack slot
-// (third).
-func s390xClassifyParameter(typ *rtype) (s390x_arg_t, uintptr, uintptr) {
-	offset := s390x_arch_stack_slot_align - typ.Size()
-	switch typ.Kind() {
-	default:
-		panic("internal error--unknown kind in s390xClassifyParameter")
-	case Bool, Int, Int8, Int16, Int32, Uint, Uint8, Uint16, Uint32:
-		return s390x_general_reg, offset, offset
-	case Int64, Uint64, Uintptr, Chan, Func, Map, Ptr, UnsafePointer:
-		return s390x_general_reg, 0, 0
-	case Float32, Float64:
-		return s390x_float_reg, 0, offset
-	case Complex64, Complex128:
-		// Complex numbers are passed by reference.
-		return s390x_mem_ptr, 0, 0
-	case Array, Struct:
-		var ityp *rtype
-		var length int
-
-		if typ.Size() == 0 {
-			return s390x_empty, 0, 0
-		}
-		switch typ.Size() {
-		default:
-			// Pointer to memory.
-			return s390x_mem_ptr, 0, 0
-		case 1, 2:
-			// Pass in an integer register.
-			return s390x_general_reg, offset, offset
-
-		case 4, 8:
-			// See below.
-		}
-		if typ.Kind() == Array {
-			atyp := (*arrayType)(unsafe.Pointer(typ))
-			length = atyp.Len()
-			ityp = atyp.elem
-		} else {
-			styp := (*structType)(unsafe.Pointer(typ))
-			length = len(styp.fields)
-			ityp = styp.fields[0].typ
-		}
-		if length == 1 {
-			class, off_reg, off_slot := s390xClassifyParameter(ityp)
-			if class == s390x_float_reg {
-				// The array (stored in a structure) or struct
-				// is "equivalent to a floating point type" as
-				// defined in the S390x Abi.  Note that this
-				// can only be the case in the cases 4 and 8 of
-				// the switch above.
-				return s390x_float_reg, off_reg, off_slot
-			}
-		}
-		// Otherwise pass in an integer register.
-		switch typ.Size() {
-		case 4, 8:
-			return s390x_general_reg, offset, offset
-		default:
-			return s390x_general_reg, 0, 0
-		}
-	case Interface, Slice, String:
-		return s390x_mem_ptr, 0, 0
-	}
-}
-
-// s390xClassifyReturn returns the register classes needed to
-// return the value of type TYP.  s390_empty means the register is
-// not used.  The second value is the offset of an rtype return
-// parameter if stored in a register.
-func s390xClassifyReturn(typ *rtype) (s390x_arg_t, uintptr) {
-	offset := s390x_arch_stack_slot_align - typ.Size()
-	switch typ.Kind() {
-	default:
-		panic("internal error--unknown kind in s390xClassifyReturn")
-	case Bool, Int, Int8, Int16, Int32, Int64,
-		Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
-
-		return s390x_general_reg, offset
-	case Chan, Func, Map, Ptr, UnsafePointer:
-		return s390x_general_reg, 0
-	case Float32, Float64:
-		return s390x_float_reg, 0
-	case Complex64, Complex128:
-		return s390x_mem_ptr, 0
-	case Interface, Slice, String:
-		return s390x_mem_ptr, 0
-	case Array, Struct:
-		if typ.size == 0 {
-			return s390x_empty, 0
-		}
-		// No optimization is done for returned structures and arrays.
-		return s390x_mem_ptr, 0
-	}
-}
-
-// Given a value of type *rtype left aligned in an unsafe.Pointer,
-// reload the value so that it can be stored in a general or
-// floating point register.  For general registers the value is
-// sign extend and right aligned.
-func s390xReloadForRegister(typ *rtype, w uintptr, offset uintptr) uintptr {
-	var do_sign_extend bool = false
-	var gr s390x_arch_gr_t
-
-	switch typ.Kind() {
-	case Int, Int8, Int16, Int32, Int64:
-		do_sign_extend = true
-	default:
-		// Handle all other cases in the next switch.
-	}
-	switch typ.size {
-	case 1:
-		if do_sign_extend == true {
-			se := int64(*(*int8)(unsafe.Pointer(&w)))
-			gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&se))
-		} else {
-			e := int64(*(*uint8)(unsafe.Pointer(&w)))
-			gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&e))
-		}
-	case 2:
-		if do_sign_extend == true {
-			se := int64(*(*int16)(unsafe.Pointer(&w)))
-			gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&se))
-		} else {
-			e := int64(*(*uint16)(unsafe.Pointer(&w)))
-			gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&e))
-		}
-	case 4:
-		if do_sign_extend == true {
-			se := int64(*(*int32)(unsafe.Pointer(&w)))
-			gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&se))
-		} else {
-			e := int64(*(*uint32)(unsafe.Pointer(&w)))
-			gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&e))
-		}
-	default:
-		panic("reflect: bad size in s390xReloadForRegister")
-	}
-
-	return *(*uintptr)(unsafe.Pointer(&gr))
-}
-
-// MakeFuncStubGo implements the s390x calling convention for
-// MakeFunc.  This should not be called.  It is exported so that
-// assembly code can call it.
-func S390xMakeFuncStubGo(regs *s390x_regs, c *makeFuncImpl) {
-	ftyp := c.typ
-	gr := 0
-	fr := 0
-	ap := uintptr(regs.stack_args)
-
-	// See if the result requires a struct.  If it does, the first
-	// parameter is a pointer to the struct.
-	var ret_class s390x_arg_t
-	var ret_off_reg uintptr
-	var ret_type *rtype
-
-	switch len(ftyp.out) {
-	case 0:
-		ret_type = nil
-		ret_class, ret_off_reg = s390x_empty, 0
-	case 1:
-		ret_type = ftyp.out[0]
-		ret_class, ret_off_reg = s390xClassifyReturn(ret_type)
-	default:
-		ret_type = nil
-		ret_class, ret_off_reg = s390x_mem_ptr, 0
-	}
-	in := make([]Value, 0, len(ftyp.in))
-	if ret_class == s390x_mem_ptr {
-		// We are returning a value in memory, which means
-		// that the first argument is a hidden parameter
-		// pointing to that return area.
-		gr++
-	}
-
-argloop:
-	for _, rt := range ftyp.in {
-		class, off_reg, off_slot := s390xClassifyParameter(rt)
-		fl := flag(rt.Kind())
-		switch class {
-		case s390x_empty:
-			v := Value{rt, nil, fl | flagIndir}
-			in = append(in, v)
-			continue argloop
-		case s390x_general_reg:
-			// Values stored in a general register are right
-			// aligned.
-			if gr < s390x_num_gr {
-				val := s390x_general_reg_val(regs, gr)
-				iw := unsafe.Pointer(val)
-				k := rt.Kind()
-				if k != Ptr && k != UnsafePointer {
-					ix := uintptr(unsafe.Pointer(&val))
-					ix += off_reg
-					iw = unsafe.Pointer(ix)
-					fl |= flagIndir
-				}
-				v := Value{rt, iw, fl}
-				in = append(in, v)
-				gr++
-			} else {
-				in, ap = s390x_add_stackreg(
-					in, ap, rt, off_slot)
-			}
-			continue argloop
-		case s390x_float_reg:
-			// In a register, floats are left aligned, but in a
-			// stack slot they are right aligned.
-			if fr < s390x_num_fr {
-				val := s390x_float_reg_val(regs, fr)
-				ix := uintptr(unsafe.Pointer(&val))
-				v := Value{
-					rt, unsafe.Pointer(unsafe.Pointer(ix)),
-					fl | flagIndir,
-				}
-				in = append(in, v)
-				fr++
-			} else {
-				in, ap = s390x_add_stackreg(
-					in, ap, rt, off_slot)
-			}
-			continue argloop
-		case s390x_mem_ptr:
-			if gr < s390x_num_gr {
-				// Register holding a pointer to memory.
-				val := s390x_general_reg_val(regs, gr)
-				v := Value{
-					rt, unsafe.Pointer(val), fl | flagIndir}
-				in = append(in, v)
-				gr++
-			} else {
-				// Stack slot holding a pointer to memory.
-				in, ap = s390x_add_memarg(in, ap, rt)
-			}
-			continue argloop
-		}
-		panic("reflect: argtype not handled in MakeFunc:argloop")
-	}
-
-	// All the real arguments have been found and turned into
-	// Values.  Call the real function.
-
-	out := c.call(in)
-
-	if len(out) != len(ftyp.out) {
-		panic("reflect: wrong return count from function created by MakeFunc")
-	}
-
-	for i, typ := range ftyp.out {
-		v := out[i]
-		if v.typ != typ {
-			panic(
-				"reflect: function created by MakeFunc using " +
-					funcName(c.fn) + " returned wrong type: have " +
-					out[i].typ.String() + " for " + typ.String())
-		}
-		if v.flag&flagRO != 0 {
-			panic(
-				"reflect: function created by MakeFunc using " +
-					funcName(c.fn) + " returned value obtained " +
-					"from unexported field")
-		}
-	}
-
-	switch ret_class {
-	case s390x_general_reg, s390x_float_reg:
-		// Single return value in a general or floating point register.
-		v := out[0]
-		var w uintptr
-		switch v.Kind() {
-		case Ptr, UnsafePointer, Chan, Func, Map:
-			w = uintptr(v.pointer())
-		default:
-			memmove(unsafe.Pointer(&w), v.ptr, v.typ.size)
-			if ret_off_reg != 0 {
-				w = s390xReloadForRegister(
-					ret_type, w, ret_off_reg)
-			}
-		}
-		if ret_class == s390x_float_reg {
-			regs.f0 = s390x_arch_fr_t(w)
-		} else {
-			regs.r2 = s390x_arch_gr_t(w)
-		}
-
-	case s390x_mem_ptr:
-		// The address of the memory area was passed as a hidden
-		// parameter in %r2.  Multiple return values are always returned
-		// in an in-memory structure.
-		ptr := unsafe.Pointer(uintptr(regs.r2))
-		off := uintptr(0)
-		for i, typ := range ftyp.out {
-			v := out[i]
-			off = align(off, uintptr(typ.fieldAlign))
-			addr := unsafe.Pointer(uintptr(ptr) + off)
-			if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
-				*(*unsafe.Pointer)(addr) = v.ptr
-			} else {
-				memmove(addr, v.ptr, typ.size)
-			}
-			off += typ.size
-		}
-
-	case s390x_empty:
-	}
-
-	return
-}
-
-// The s390x_add_stackreg function adds an argument passed on the
-// stack that could be passed in a register.
-func s390x_add_stackreg(in []Value, ap uintptr, rt *rtype, offset uintptr) ([]Value, uintptr) {
-	// If we're not already at the beginning of a stack slot, round up to
-	// the beginning of the next one.
-	ap = align(ap, s390x_arch_stack_slot_align)
-	// If offset is > 0, the data is right aligned on the stack slot.
-	ap += offset
-
-	// We have to copy the argument onto the heap in case the
-	// function hangs onto the reflect.Value we pass it.
-	p := unsafe_New(rt)
-	memmove(p, unsafe.Pointer(ap), rt.size)
-
-	v := Value{rt, p, flag(rt.Kind()) | flagIndir}
-	in = append(in, v)
-	ap += rt.size
-	ap = align(ap, s390x_arch_stack_slot_align)
-
-	return in, ap
-}
-
-// The s390x_add_memarg function adds an argument passed in memory.
-func s390x_add_memarg(in []Value, ap uintptr, rt *rtype) ([]Value, uintptr) {
-	// If we're not already at the beginning of a stack slot,
-	// round up to the beginning of the next one.
-	ap = align(ap, s390x_arch_stack_slot_align)
-
-	// We have to copy the argument onto the heap in case the
-	// function hangs onto the reflect.Value we pass it.
-	p := unsafe_New(rt)
-	memmove(p, *(*unsafe.Pointer)(unsafe.Pointer(ap)), rt.size)
-
-	v := Value{rt, p, flag(rt.Kind()) | flagIndir}
-	in = append(in, v)
-	ap += s390x_arch_stack_slot_align
-
-	return in, ap
-}
-
-// The s390x_general_reg_val function returns the value of integer register GR.
-func s390x_general_reg_val(regs *s390x_regs, gr int) uintptr {
-	var r s390x_arch_gr_t
-	switch gr {
-	case 0:
-		r = regs.r2
-	case 1:
-		r = regs.r3
-	case 2:
-		r = regs.r4
-	case 3:
-		r = regs.r5
-	case 4:
-		r = regs.r6
-	default:
-		panic("s390x_general_reg_val: bad integer register")
-	}
-	return uintptr(r)
-}
-
-// The s390x_float_reg_val function returns the value of float register FR.
-func s390x_float_reg_val(regs *s390x_regs, fr int) uintptr {
-	var r s390x_arch_fr_t
-	switch fr {
-	case 0:
-		r = regs.f0
-	case 1:
-		r = regs.f2
-	case 2:
-		r = regs.f4
-	case 3:
-		r = regs.f6
-	default:
-		panic("s390x_float_reg_val: bad floating point register")
-	}
-	return uintptr(r)
-}
diff --git a/third_party/gofrontend/libgo/go/reflect/value.go b/third_party/gofrontend/libgo/go/reflect/value.go
index 09210b3..7cc4f7f 100644
--- a/third_party/gofrontend/libgo/go/reflect/value.go
+++ b/third_party/gofrontend/libgo/go/reflect/value.go
@@ -308,9 +308,6 @@
 
 var callGC bool // for testing; see TestCallMethodJump
 
-var makeFuncStubFn = makeFuncStub
-var makeFuncStubCode = **(**uintptr)(unsafe.Pointer(&makeFuncStubFn))
-
 func (v Value) call(op string, in []Value) []Value {
 	// Get function pointer, type.
 	t := v.typ
@@ -388,17 +385,6 @@
 	}
 	nout := t.NumOut()
 
-	// If target is makeFuncStub, short circuit the unpack onto stack /
-	// pack back into []Value for the args and return values.  Just do the
-	// call directly.
-	// We need to do this here because otherwise we have a situation where
-	// reflect.callXX calls makeFuncStub, neither of which knows the
-	// layout of the args.  That's bad for precise gc & stack copying.
-	x := (*makeFuncImpl)(fn)
-	if x.code == makeFuncStubCode {
-		return x.call(in)
-	}
-
 	if v.flag&flagMethod != 0 {
 		nin++
 	}
@@ -1120,16 +1106,6 @@
 	case Chan, Map, Ptr, UnsafePointer:
 		return uintptr(v.pointer())
 	case Func:
-		if v.flag&flagMethod != 0 {
-			// As the doc comment says, the returned pointer is an
-			// underlying code pointer but not necessarily enough to
-			// identify a single function uniquely. All method expressions
-			// created via reflect have the same underlying code pointer,
-			// so their Pointers are equal. The function used here must
-			// match the one used in makeMethodValue.
-			f := makeFuncStub
-			return **(**uintptr)(unsafe.Pointer(&f))
-		}
 		p := v.pointer()
 		// Non-nil func value points at data block.
 		// First word of data block is actual code.
diff --git a/third_party/gofrontend/libgo/go/testing/quick/quick_test.go b/third_party/gofrontend/libgo/go/testing/quick/quick_test.go
index 36745ae..e925ba6 100644
--- a/third_party/gofrontend/libgo/go/testing/quick/quick_test.go
+++ b/third_party/gofrontend/libgo/go/testing/quick/quick_test.go
@@ -7,7 +7,6 @@
 import (
 	"math/rand"
 	"reflect"
-	"runtime"
 	"testing"
 )
 
@@ -158,12 +157,10 @@
 	reportError("fFloat32Alias", CheckEqual(fFloat32Alias, fFloat32Alias, nil), t)
 	reportError("fFloat64", CheckEqual(fFloat64, fFloat64, nil), t)
 	reportError("fFloat64Alias", CheckEqual(fFloat64Alias, fFloat64Alias, nil), t)
-	if runtime.GOARCH != "alpha" {
-		reportError("fComplex64", CheckEqual(fComplex64, fComplex64, nil), t)
-		reportError("fComplex64Alias", CheckEqual(fComplex64Alias, fComplex64Alias, nil), t)
-		reportError("fComplex128", CheckEqual(fComplex128, fComplex128, nil), t)
-		reportError("fComplex128Alias", CheckEqual(fComplex128Alias, fComplex128Alias, nil), t)
-	}
+	reportError("fComplex64", CheckEqual(fComplex64, fComplex64, nil), t)
+	reportError("fComplex64Alias", CheckEqual(fComplex64Alias, fComplex64Alias, nil), t)
+	reportError("fComplex128", CheckEqual(fComplex128, fComplex128, nil), t)
+	reportError("fComplex128Alias", CheckEqual(fComplex128Alias, fComplex128Alias, nil), t)
 	reportError("fInt16", CheckEqual(fInt16, fInt16, nil), t)
 	reportError("fInt16Alias", CheckEqual(fInt16Alias, fInt16Alias, nil), t)
 	reportError("fInt32", CheckEqual(fInt32, fInt32, nil), t)
diff --git a/third_party/gofrontend/libgo/runtime/go-ffi.c b/third_party/gofrontend/libgo/runtime/go-ffi.c
index 175c583..aafc7b2 100644
--- a/third_party/gofrontend/libgo/runtime/go-ffi.c
+++ b/third_party/gofrontend/libgo/runtime/go-ffi.c
@@ -30,8 +30,6 @@
   __attribute__ ((no_split_stack));
 static ffi_type *go_string_to_ffi (void) __attribute__ ((no_split_stack));
 static ffi_type *go_interface_to_ffi (void) __attribute__ ((no_split_stack));
-static ffi_type *go_complex_to_ffi (ffi_type *)
-  __attribute__ ((no_split_stack, unused));
 static ffi_type *go_type_to_ffi (const struct __go_type_descriptor *)
   __attribute__ ((no_split_stack));
 static ffi_type *go_func_return_ffi (const struct __go_func_type *)
@@ -155,7 +153,15 @@
   return ret;
 }
 
-/* Return an ffi_type for a Go complex type.  */
+
+#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
+/* If libffi hasn't been updated for this target to support complex,
+   pretend complex is a structure.  Warning: This does not work for
+   all ABIs.  Eventually libffi should be updated for all targets
+   and this should go away.  */
+
+static ffi_type *go_complex_to_ffi (ffi_type *)
+  __attribute__ ((no_split_stack));
 
 static ffi_type *
 go_complex_to_ffi (ffi_type *float_type)
@@ -170,6 +176,7 @@
   ret->elements[2] = NULL;
   return ret;
 }
+#endif
 
 /* Return an ffi_type for a type described by a
    __go_type_descriptor.  */
@@ -194,23 +201,25 @@
 	return &ffi_type_double;
       abort ();
     case GO_COMPLEX64:
-#ifdef __alpha__
-      runtime_throw("the libffi library does not support Complex64 type with "
-		    "reflect.Call or runtime.SetFinalizer");
-#else
       if (sizeof (float) == 4)
-	return go_complex_to_ffi (&ffi_type_float);
-      abort ();
-#endif
-    case GO_COMPLEX128:
-#ifdef __alpha__
-      runtime_throw("the libffi library does not support Complex128 type with "
-		    "reflect.Call or runtime.SetFinalizer");
+	{
+#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
+	  return &ffi_type_complex_float;
 #else
-      if (sizeof (double) == 8)
-	return go_complex_to_ffi (&ffi_type_double);
-      abort ();
+	  return go_complex_to_ffi (&ffi_type_float);
 #endif
+	}
+      abort ();
+    case GO_COMPLEX128:
+      if (sizeof (double) == 8)
+	{
+#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
+	  return &ffi_type_complex_double;
+#else
+	  return go_complex_to_ffi (&ffi_type_double);
+#endif
+	}
+      abort ();
     case GO_INT16:
       return &ffi_type_sint16;
     case GO_INT32:
@@ -280,21 +289,7 @@
   types = (const struct __go_type_descriptor **) func->__out.__values;
 
   if (count == 1)
-    {
-
-#if defined (__i386__) && !defined (__x86_64__)
-      /* FFI does not support complex types.  On 32-bit x86, a
-	 complex64 will be returned in %eax/%edx.  We normally tell
-	 FFI that a complex64 is a struct of two floats.  On 32-bit
-	 x86 a struct of two floats is returned via a hidden first
-	 pointer parameter.  Fortunately we can make everything work
-	 by pretending that complex64 is int64.  */
-      if ((types[0]->__code & GO_CODE_MASK) == GO_COMPLEX64)
-	return &ffi_type_sint64;
-#endif
-
-      return go_type_to_ffi (types[0]);
-    }
+    return go_type_to_ffi (types[0]);
 
   ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
   ret->type = FFI_TYPE_STRUCT;
diff --git a/third_party/gofrontend/libgo/runtime/go-reflect-call.c b/third_party/gofrontend/libgo/runtime/go-reflect-call.c
index dfc703e..29e814a 100644
--- a/third_party/gofrontend/libgo/runtime/go-reflect-call.c
+++ b/third_party/gofrontend/libgo/runtime/go-reflect-call.c
@@ -12,11 +12,10 @@
 #include "go-alloc.h"
 #include "go-assert.h"
 #include "go-type.h"
-
-#ifdef USE_LIBFFI
-
 #include "go-ffi.h"
 
+#if defined(USE_LIBFFI) && FFI_GO_CLOSURES
+
 /* The functions in this file are only called from reflect_call.  As
    reflect_call calls a libffi function, which will be compiled
    without -fsplit-stack, it will always run with a large stack.  */
@@ -202,11 +201,7 @@
 
    If IS_METHOD is true this is a call to a method expression.  The
    first argument is the receiver.  It is described in FUNC_TYPE, but
-   regardless of FUNC_TYPE, it is passed as a pointer.
-
-   If neither IS_INTERFACE nor IS_METHOD is true then we are calling a
-   function indirectly, and we must pass a closure pointer via
-   __go_set_closure.  The pointer to pass is simply FUNC_VAL.  */
+   regardless of FUNC_TYPE, it is passed as a pointer.  */
 
 void
 reflect_call (const struct __go_func_type *func_type, FuncVal *func_val,
@@ -221,9 +216,7 @@
 
   call_result = (unsigned char *) malloc (go_results_size (func_type));
 
-  if (!is_interface && !is_method)
-    __go_set_closure (func_val);
-  ffi_call (&cif, func_val->fn, call_result, params);
+  ffi_call_go (&cif, func_val->fn, call_result, params, func_val);
 
   /* Some day we may need to free result values if RESULTS is
      NULL.  */
diff --git a/third_party/gofrontend/libgo/runtime/malloc.goc b/third_party/gofrontend/libgo/runtime/malloc.goc
index d86376b..fd5a1cf 100644
--- a/third_party/gofrontend/libgo/runtime/malloc.goc
+++ b/third_party/gofrontend/libgo/runtime/malloc.goc
@@ -84,7 +84,6 @@
 	MLink *v, *next;
 	byte *tiny;
 	bool incallback;
-	void *closure;
 
 	if(size == 0) {
 		// All 0-length allocations use this pointer.
@@ -96,10 +95,6 @@
 	m = runtime_m();
 	g = runtime_g();
 
-	// We should not be called in between __go_set_closure and the
-	// actual function call, but cope with it if we are.
-	closure = g->closure;
-
 	incallback = false;
 	if(m->mcache == nil && g->ncgo > 0) {
 		// For gccgo this case can occur when a cgo or SWIG function
@@ -180,7 +175,6 @@
 					m->locks--;
 					if(incallback)
 						runtime_entersyscall();
-					g->closure = closure;
 					return v;
 				}
 			}
@@ -267,8 +261,6 @@
 	if(incallback)
 		runtime_entersyscall();
 
-	g->closure = closure;
-
 	return v;
 }
 
diff --git a/third_party/gofrontend/libgo/runtime/mgc0.c b/third_party/gofrontend/libgo/runtime/mgc0.c
index d5b9603..e1452a4 100644
--- a/third_party/gofrontend/libgo/runtime/mgc0.c
+++ b/third_party/gofrontend/libgo/runtime/mgc0.c
@@ -133,8 +133,8 @@
 
 	// clear sync.Pool's
 	if(poolcleanup != nil) {
-		__go_set_closure(poolcleanup);
-		poolcleanup->fn();
+		__builtin_call_with_static_chain(poolcleanup->fn(),
+						 poolcleanup);
 	}
 
 	for(pp=runtime_allp; (p=*pp) != nil; pp++) {
diff --git a/third_party/gofrontend/libgo/runtime/proc.c b/third_party/gofrontend/libgo/runtime/proc.c
index 28896ce..6facd40 100644
--- a/third_party/gofrontend/libgo/runtime/proc.c
+++ b/third_party/gofrontend/libgo/runtime/proc.c
@@ -126,6 +126,30 @@
 	c->uc_mcontext._mc_tlsbase = tlsbase;
 }
 
+# elif defined(__sparc__)
+
+static inline void
+initcontext(void)
+{
+}
+
+static inline void
+fixcontext(ucontext_t *c)
+{
+	/* ??? Using 
+	     register unsigned long thread __asm__("%g7");
+	     c->uc_mcontext.gregs[REG_G7] = thread;
+	   results in
+	     error: variable ‘thread’ might be clobbered by \
+		‘longjmp’ or ‘vfork’ [-Werror=clobbered]
+	   which ought to be false, as %g7 is a fixed register.  */
+
+	if (sizeof (c->uc_mcontext.gregs[REG_G7]) == 8)
+		asm ("stx %%g7, %0" : "=m"(c->uc_mcontext.gregs[REG_G7]));
+	else
+		asm ("st %%g7, %0" : "=m"(c->uc_mcontext.gregs[REG_G7]));
+}
+
 # else
 
 #  error unknown case for SETCONTEXT_CLOBBERS_TLS
@@ -3310,26 +3334,6 @@
 	enqueue1(wbufp, (Obj){(byte*)&runtime_sched, sizeof runtime_sched, 0});
 }
 
-// When a function calls a closure, it passes the closure value to
-// __go_set_closure immediately before the function call.  When a
-// function uses a closure, it calls __go_get_closure immediately on
-// function entry.  This is a hack, but it will work on any system.
-// It would be better to use the static chain register when there is
-// one.  It is also worth considering expanding these functions
-// directly in the compiler.
-
-void
-__go_set_closure(void* v)
-{
-	g->closure = v;
-}
-
-void *
-__go_get_closure(void)
-{
-	return g->closure;
-}
-
 // Return whether we are waiting for a GC.  This gc toolchain uses
 // preemption instead.
 bool
diff --git a/third_party/gofrontend/libgo/runtime/runtime.h b/third_party/gofrontend/libgo/runtime/runtime.h
index c1060ae..7e2a375 100644
--- a/third_party/gofrontend/libgo/runtime/runtime.h
+++ b/third_party/gofrontend/libgo/runtime/runtime.h
@@ -195,7 +195,6 @@
 
 struct	G
 {
-	void*	closure;	// Closure value.
 	Defer*	defer;
 	Panic*	panic;
 	void*	exception;	// current exception being thrown
@@ -833,9 +832,6 @@
 
 #define PREFETCH(p) __builtin_prefetch(p)
 
-void	__go_set_closure(void*);
-void*	__go_get_closure(void);
-
 bool	runtime_gcwaiting(void);
 void	runtime_badsignal(int);
 Defer*	runtime_newdefer(void);
diff --git a/third_party/gofrontend/libgo/runtime/time.goc b/third_party/gofrontend/libgo/runtime/time.goc
index 0e4af97..f9227ff 100644
--- a/third_party/gofrontend/libgo/runtime/time.goc
+++ b/third_party/gofrontend/libgo/runtime/time.goc
@@ -237,8 +237,7 @@
 			arg = t->arg;
 			seq = t->seq;
 			runtime_unlock(&timers.lock);
-			__go_set_closure(fv);
-			f(arg, seq);
+			__builtin_call_with_static_chain(f(arg, seq), fv);
 
 			// clear f and arg to avoid leak while sleeping for next timer
 			f = nil;
diff --git a/third_party/gofrontend/missing b/third_party/gofrontend/missing
index 28055d2..f62bbae 100644
--- a/third_party/gofrontend/missing
+++ b/third_party/gofrontend/missing
@@ -1,11 +1,10 @@
 #! /bin/sh
-# Common stub for a few missing GNU programs while installing.
+# Common wrapper for a few potentially missing GNU programs.
 
-scriptversion=2009-04-28.21; # UTC
+scriptversion=2013-10-28.13; # UTC
 
-# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
-# 2008, 2009 Free Software Foundation, Inc.
-# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+# Copyright (C) 1996-2014 Free Software Foundation, Inc.
+# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -26,69 +25,40 @@
 # the same distribution terms that you use for the rest of that program.
 
 if test $# -eq 0; then
-  echo 1>&2 "Try \`$0 --help' for more information"
+  echo 1>&2 "Try '$0 --help' for more information"
   exit 1
 fi
 
-run=:
-sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
-sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
-
-# In the cases where this matters, `missing' is being run in the
-# srcdir already.
-if test -f configure.ac; then
-  configure_ac=configure.ac
-else
-  configure_ac=configure.in
-fi
-
-msg="missing on your system"
-
 case $1 in
---run)
-  # Try to run requested program, and just exit if it succeeds.
-  run=
-  shift
-  "$@" && exit 0
-  # Exit code 63 means version mismatch.  This often happens
-  # when the user try to use an ancient version of a tool on
-  # a file that requires a minimum version.  In this case we
-  # we should proceed has if the program had been absent, or
-  # if --run hadn't been passed.
-  if test $? = 63; then
-    run=:
-    msg="probably too old"
-  fi
-  ;;
+
+  --is-lightweight)
+    # Used by our autoconf macros to check whether the available missing
+    # script is modern enough.
+    exit 0
+    ;;
+
+  --run)
+    # Back-compat with the calling convention used by older automake.
+    shift
+    ;;
 
   -h|--h|--he|--hel|--help)
     echo "\
 $0 [OPTION]... PROGRAM [ARGUMENT]...
 
-Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
-error status if there is no known handling for PROGRAM.
+Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
+to PROGRAM being missing or too old.
 
 Options:
   -h, --help      display this help and exit
   -v, --version   output version information and exit
-  --run           try to run the given command, and emulate it if it fails
 
 Supported PROGRAM values:
-  aclocal      touch file \`aclocal.m4'
-  autoconf     touch file \`configure'
-  autoheader   touch file \`config.h.in'
-  autom4te     touch the output file, or create a stub one
-  automake     touch all \`Makefile.in' files
-  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
-  flex         create \`lex.yy.c', if possible, from existing .c
-  help2man     touch the output file
-  lex          create \`lex.yy.c', if possible, from existing .c
-  makeinfo     touch the output file
-  tar          try tar, gnutar, gtar, then tar without non-portable flags
-  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]
+  aclocal   autoconf  autoheader   autom4te  automake  makeinfo
+  bison     yacc      flex         lex       help2man
 
-Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
-\`g' are ignored when checking the name.
+Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
+'g' are ignored when checking the name.
 
 Send bug reports to <bug-automake@gnu.org>."
     exit $?
@@ -100,272 +70,141 @@
     ;;
 
   -*)
-    echo 1>&2 "$0: Unknown \`$1' option"
-    echo 1>&2 "Try \`$0 --help' for more information"
+    echo 1>&2 "$0: unknown '$1' option"
+    echo 1>&2 "Try '$0 --help' for more information"
     exit 1
     ;;
 
 esac
 
-# normalize program name to check for.
-program=`echo "$1" | sed '
-  s/^gnu-//; t
-  s/^gnu//; t
-  s/^g//; t'`
+# Run the given program, remember its exit status.
+"$@"; st=$?
 
-# Now exit if we have it, but it failed.  Also exit now if we
-# don't have it and --version was passed (most likely to detect
-# the program).  This is about non-GNU programs, so use $1 not
-# $program.
-case $1 in
-  lex*|yacc*)
-    # Not GNU programs, they don't have --version.
+# If it succeeded, we are done.
+test $st -eq 0 && exit 0
+
+# Also exit now if we it failed (or wasn't found), and '--version' was
+# passed; such an option is passed most likely to detect whether the
+# program is present and works.
+case $2 in --version|--help) exit $st;; esac
+
+# Exit code 63 means version mismatch.  This often happens when the user
+# tries to use an ancient version of a tool on a file that requires a
+# minimum version.
+if test $st -eq 63; then
+  msg="probably too old"
+elif test $st -eq 127; then
+  # Program was missing.
+  msg="missing on your system"
+else
+  # Program was found and executed, but failed.  Give up.
+  exit $st
+fi
+
+perl_URL=http://www.perl.org/
+flex_URL=http://flex.sourceforge.net/
+gnu_software_URL=http://www.gnu.org/software
+
+program_details ()
+{
+  case $1 in
+    aclocal|automake)
+      echo "The '$1' program is part of the GNU Automake package:"
+      echo "<$gnu_software_URL/automake>"
+      echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
+      echo "<$gnu_software_URL/autoconf>"
+      echo "<$gnu_software_URL/m4/>"
+      echo "<$perl_URL>"
+      ;;
+    autoconf|autom4te|autoheader)
+      echo "The '$1' program is part of the GNU Autoconf package:"
+      echo "<$gnu_software_URL/autoconf/>"
+      echo "It also requires GNU m4 and Perl in order to run:"
+      echo "<$gnu_software_URL/m4/>"
+      echo "<$perl_URL>"
+      ;;
+  esac
+}
+
+give_advice ()
+{
+  # Normalize program name to check for.
+  normalized_program=`echo "$1" | sed '
+    s/^gnu-//; t
+    s/^gnu//; t
+    s/^g//; t'`
+
+  printf '%s\n' "'$1' is $msg."
+
+  configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
+  case $normalized_program in
+    autoconf*)
+      echo "You should only need it if you modified 'configure.ac',"
+      echo "or m4 files included by it."
+      program_details 'autoconf'
+      ;;
+    autoheader*)
+      echo "You should only need it if you modified 'acconfig.h' or"
+      echo "$configure_deps."
+      program_details 'autoheader'
+      ;;
+    automake*)
+      echo "You should only need it if you modified 'Makefile.am' or"
+      echo "$configure_deps."
+      program_details 'automake'
+      ;;
+    aclocal*)
+      echo "You should only need it if you modified 'acinclude.m4' or"
+      echo "$configure_deps."
+      program_details 'aclocal'
+      ;;
+   autom4te*)
+      echo "You might have modified some maintainer files that require"
+      echo "the 'autom4te' program to be rebuilt."
+      program_details 'autom4te'
+      ;;
+    bison*|yacc*)
+      echo "You should only need it if you modified a '.y' file."
+      echo "You may want to install the GNU Bison package:"
+      echo "<$gnu_software_URL/bison/>"
+      ;;
+    lex*|flex*)
+      echo "You should only need it if you modified a '.l' file."
+      echo "You may want to install the Fast Lexical Analyzer package:"
+      echo "<$flex_URL>"
+      ;;
+    help2man*)
+      echo "You should only need it if you modified a dependency" \
+           "of a man page."
+      echo "You may want to install the GNU Help2man package:"
+      echo "<$gnu_software_URL/help2man/>"
     ;;
+    makeinfo*)
+      echo "You should only need it if you modified a '.texi' file, or"
+      echo "any other file indirectly affecting the aspect of the manual."
+      echo "You might want to install the Texinfo package:"
+      echo "<$gnu_software_URL/texinfo/>"
+      echo "The spurious makeinfo call might also be the consequence of"
+      echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
+      echo "want to install GNU make:"
+      echo "<$gnu_software_URL/make/>"
+      ;;
+    *)
+      echo "You might have modified some files without having the proper"
+      echo "tools for further handling them.  Check the 'README' file, it"
+      echo "often tells you about the needed prerequisites for installing"
+      echo "this package.  You may also peek at any GNU archive site, in"
+      echo "case some other package contains this missing '$1' program."
+      ;;
+  esac
+}
 
-  tar*)
-    if test -n "$run"; then
-       echo 1>&2 "ERROR: \`tar' requires --run"
-       exit 1
-    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
-       exit 1
-    fi
-    ;;
+give_advice "$1" | sed -e '1s/^/WARNING: /' \
+                       -e '2,$s/^/         /' >&2
 
-  *)
-    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
-       # We have it, but it failed.
-       exit 1
-    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
-       # Could not run --version or --help.  This is probably someone
-       # running `$TOOL --version' or `$TOOL --help' to check whether
-       # $TOOL exists and not knowing $TOOL uses missing.
-       exit 1
-    fi
-    ;;
-esac
-
-# If it does not exist, or fails to run (possibly an outdated version),
-# try to emulate it.
-case $program in
-  aclocal*)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
-         to install the \`Automake' and \`Perl' packages.  Grab them from
-         any GNU archive site."
-    touch aclocal.m4
-    ;;
-
-  autoconf*)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-         you modified \`${configure_ac}'.  You might want to install the
-         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
-         archive site."
-    touch configure
-    ;;
-
-  autoheader*)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
-         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
-         from any GNU archive site."
-    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
-    test -z "$files" && files="config.h"
-    touch_files=
-    for f in $files; do
-      case $f in
-      *:*) touch_files="$touch_files "`echo "$f" |
-				       sed -e 's/^[^:]*://' -e 's/:.*//'`;;
-      *) touch_files="$touch_files $f.in";;
-      esac
-    done
-    touch $touch_files
-    ;;
-
-  automake*)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
-         You might want to install the \`Automake' and \`Perl' packages.
-         Grab them from any GNU archive site."
-    find . -type f -name Makefile.am -print |
-	   sed 's/\.am$/.in/' |
-	   while read f; do touch "$f"; done
-    ;;
-
-  autom4te*)
-    echo 1>&2 "\
-WARNING: \`$1' is needed, but is $msg.
-         You might have modified some files without having the
-         proper tools for further handling them.
-         You can get \`$1' as part of \`Autoconf' from any GNU
-         archive site."
-
-    file=`echo "$*" | sed -n "$sed_output"`
-    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
-    if test -f "$file"; then
-	touch $file
-    else
-	test -z "$file" || exec >$file
-	echo "#! /bin/sh"
-	echo "# Created by GNU Automake missing as a replacement of"
-	echo "#  $ $@"
-	echo "exit 0"
-	chmod +x $file
-	exit 1
-    fi
-    ;;
-
-  bison*|yacc*)
-    echo 1>&2 "\
-WARNING: \`$1' $msg.  You should only need it if
-         you modified a \`.y' file.  You may need the \`Bison' package
-         in order for those modifications to take effect.  You can get
-         \`Bison' from any GNU archive site."
-    rm -f y.tab.c y.tab.h
-    if test $# -ne 1; then
-        eval LASTARG="\${$#}"
-	case $LASTARG in
-	*.y)
-	    SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
-	    if test -f "$SRCFILE"; then
-	         cp "$SRCFILE" y.tab.c
-	    fi
-	    SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
-	    if test -f "$SRCFILE"; then
-	         cp "$SRCFILE" y.tab.h
-	    fi
-	  ;;
-	esac
-    fi
-    if test ! -f y.tab.h; then
-	echo >y.tab.h
-    fi
-    if test ! -f y.tab.c; then
-	echo 'main() { return 0; }' >y.tab.c
-    fi
-    ;;
-
-  lex*|flex*)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-         you modified a \`.l' file.  You may need the \`Flex' package
-         in order for those modifications to take effect.  You can get
-         \`Flex' from any GNU archive site."
-    rm -f lex.yy.c
-    if test $# -ne 1; then
-        eval LASTARG="\${$#}"
-	case $LASTARG in
-	*.l)
-	    SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
-	    if test -f "$SRCFILE"; then
-	         cp "$SRCFILE" lex.yy.c
-	    fi
-	  ;;
-	esac
-    fi
-    if test ! -f lex.yy.c; then
-	echo 'main() { return 0; }' >lex.yy.c
-    fi
-    ;;
-
-  help2man*)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-	 you modified a dependency of a manual page.  You may need the
-	 \`Help2man' package in order for those modifications to take
-	 effect.  You can get \`Help2man' from any GNU archive site."
-
-    file=`echo "$*" | sed -n "$sed_output"`
-    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
-    if test -f "$file"; then
-	touch $file
-    else
-	test -z "$file" || exec >$file
-	echo ".ab help2man is required to generate this page"
-	exit $?
-    fi
-    ;;
-
-  makeinfo*)
-    echo 1>&2 "\
-WARNING: \`$1' is $msg.  You should only need it if
-         you modified a \`.texi' or \`.texinfo' file, or any other file
-         indirectly affecting the aspect of the manual.  The spurious
-         call might also be the consequence of using a buggy \`make' (AIX,
-         DU, IRIX).  You might want to install the \`Texinfo' package or
-         the \`GNU make' package.  Grab either from any GNU archive site."
-    # The file to touch is that specified with -o ...
-    file=`echo "$*" | sed -n "$sed_output"`
-    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
-    if test -z "$file"; then
-      # ... or it is the one specified with @setfilename ...
-      infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
-      file=`sed -n '
-	/^@setfilename/{
-	  s/.* \([^ ]*\) *$/\1/
-	  p
-	  q
-	}' $infile`
-      # ... or it is derived from the source name (dir/f.texi becomes f.info)
-      test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
-    fi
-    # If the file does not exist, the user really needs makeinfo;
-    # let's fail without touching anything.
-    test -f $file || exit 1
-    touch $file
-    ;;
-
-  tar*)
-    shift
-
-    # We have already tried tar in the generic part.
-    # Look for gnutar/gtar before invocation to avoid ugly error
-    # messages.
-    if (gnutar --version > /dev/null 2>&1); then
-       gnutar "$@" && exit 0
-    fi
-    if (gtar --version > /dev/null 2>&1); then
-       gtar "$@" && exit 0
-    fi
-    firstarg="$1"
-    if shift; then
-	case $firstarg in
-	*o*)
-	    firstarg=`echo "$firstarg" | sed s/o//`
-	    tar "$firstarg" "$@" && exit 0
-	    ;;
-	esac
-	case $firstarg in
-	*h*)
-	    firstarg=`echo "$firstarg" | sed s/h//`
-	    tar "$firstarg" "$@" && exit 0
-	    ;;
-	esac
-    fi
-
-    echo 1>&2 "\
-WARNING: I can't seem to be able to run \`tar' with the given arguments.
-         You may want to install GNU tar or Free paxutils, or check the
-         command line arguments."
-    exit 1
-    ;;
-
-  *)
-    echo 1>&2 "\
-WARNING: \`$1' is needed, and is $msg.
-         You might have modified some files without having the
-         proper tools for further handling them.  Check the \`README' file,
-         it often tells you about the needed prerequisites for installing
-         this package.  You may also peek at any GNU archive site, in case
-         some other package would contain this missing \`$1' program."
-    exit 1
-    ;;
-esac
-
-exit 0
+# Propagate the correct exit status (expected to be 127 for a program
+# not found, 63 for a program that failed due to version mismatch).
+exit $st
 
 # Local variables:
 # eval: (add-hook 'write-file-hooks 'time-stamp)
diff --git a/update_third_party.sh b/update_third_party.sh
index 49b33e1..735a4eb 100755
--- a/update_third_party.sh
+++ b/update_third_party.sh
@@ -1,10 +1,10 @@
 #!/bin/sh -e
 
 gofrontendrepo=https://code.google.com/p/gofrontend
-gofrontendrev=a6e10414311a
+gofrontendrev=07baa07598ea
 
 gccrepo=svn://gcc.gnu.org/svn/gcc/trunk
-gccrev=216268
+gccrev=219477
 
 gotoolsrepo=https://go.googlesource.com/tools
 gotoolsrev=d4e70101500b43ffe705d4c45e50dd4f1c8e3b2e
@@ -63,10 +63,14 @@
   third_party/gofrontend/libffi/ChangeLog \
   third_party/gofrontend/libffi/doc/libffi.texi \
   third_party/gofrontend/libffi/msvcc.sh \
-  third_party/gofrontend/libffi/testsuite/lib/libffi.exp \
+  third_party/gofrontend/libffi/testsuite/config/default.exp \
   third_party/gofrontend/libffi/testsuite/libffi.call/call.exp \
+  third_party/gofrontend/libffi/testsuite/libffi.complex/complex.exp \
+  third_party/gofrontend/libffi/testsuite/libffi.go/go.exp \
   third_party/gofrontend/libffi/testsuite/libffi.special/special.exp \
-  third_party/gofrontend/libffi/testsuite/config/default.exp
+  third_party/gofrontend/libffi/testsuite/lib/libffi.exp \
+  third_party/gofrontend/libffi/testsuite/lib/target-libpath.exp \
+  third_party/gofrontend/libffi/testsuite/lib/wrapper.exp
 
 # The build requires these files to exist.
 touch \