From 1c626112a06f1f69d3c22771c62d4ced1cfee356 Mon Sep 17 00:00:00 2001
From: Mike Pall <mike>
Date: Wed, 10 Oct 2012 18:16:18 +0200
Subject: FFI: Compile ffi.sizeof(), ffi.alignof() and ffi.offsetof().

---
 src/Makefile.dep |  7 ++++---
 src/lib_ffi.c    |  6 +++---
 src/lj_crecord.c | 23 ++++++++++++++++++++++-
 src/lj_crecord.h |  1 +
 src/lj_jit.h     |  1 +
 src/lj_record.c  | 12 +++++++++++-
 6 files changed, 42 insertions(+), 8 deletions(-)

(limited to 'src')

diff --git a/src/Makefile.dep b/src/Makefile.dep
index cab23b79..9571e16d 100644
--- a/src/Makefile.dep
+++ b/src/Makefile.dep
@@ -82,9 +82,10 @@ lj_cparse.o: lj_cparse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
  lj_bc.h lj_vm.h lj_char.h lj_strscan.h
 lj_crecord.o: lj_crecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
  lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h \
- lj_gc.h lj_cdata.h lj_cparse.h lj_cconv.h lj_clib.h lj_ccall.h lj_ir.h \
- lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \
- lj_record.h lj_ffrecord.h lj_snap.h lj_crecord.h
+ lj_gc.h lj_cdata.h lj_cparse.h lj_cconv.h lj_clib.h lj_ccall.h lj_ff.h \
+ lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \
+ lj_dispatch.h lj_traceerr.h lj_record.h lj_ffrecord.h lj_snap.h \
+ lj_crecord.h
 lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
  lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_ccallback.h
 lj_debug.o: lj_debug.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
diff --git a/src/lib_ffi.c b/src/lib_ffi.c
index 69bebefc..689f7a9d 100644
--- a/src/lib_ffi.c
+++ b/src/lib_ffi.c
@@ -587,7 +587,7 @@ LJLIB_CF(ffi_istype)	LJLIB_REC(.)
   return 1;
 }
 
-LJLIB_CF(ffi_sizeof)
+LJLIB_CF(ffi_sizeof)	LJLIB_REC(ffi_xof FF_ffi_sizeof)
 {
   CTState *cts = ctype_cts(L);
   CTypeID id = ffi_checkctype(L, cts, NULL);
@@ -609,7 +609,7 @@ LJLIB_CF(ffi_sizeof)
   return 1;
 }
 
-LJLIB_CF(ffi_alignof)
+LJLIB_CF(ffi_alignof)	LJLIB_REC(ffi_xof FF_ffi_alignof)
 {
   CTState *cts = ctype_cts(L);
   CTypeID id = ffi_checkctype(L, cts, NULL);
@@ -619,7 +619,7 @@ LJLIB_CF(ffi_alignof)
   return 1;
 }
 
-LJLIB_CF(ffi_offsetof)
+LJLIB_CF(ffi_offsetof)	LJLIB_REC(ffi_xof FF_ffi_offsetof)
 {
   CTState *cts = ctype_cts(L);
   CTypeID id = ffi_checkctype(L, cts, NULL);
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index 6a22544a..f9220322 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -20,6 +20,7 @@
 #include "lj_cconv.h"
 #include "lj_clib.h"
 #include "lj_ccall.h"
+#include "lj_ff.h"
 #include "lj_ir.h"
 #include "lj_jit.h"
 #include "lj_ircall.h"
@@ -1587,7 +1588,27 @@ void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd)
     emitir(IRTG(IR_EQ, IRT_STR), J->base[0], lj_ir_kstr(J, strV(&rd->argv[0])));
     J->postproc = LJ_POST_FIXBOOL;
     J->base[0] = TREF_TRUE;
-  }  /* else: interpreter will throw. */
+  } else {
+    lj_trace_err(J, LJ_TRERR_BADTYPE);
+  }
+}
+
+/* Record ffi.sizeof(), ffi.alignof(), ffi.offsetof(). */
+void LJ_FASTCALL recff_ffi_xof(jit_State *J, RecordFFData *rd)
+{
+  CTypeID id = argv2ctype(J, J->base[0], &rd->argv[0]);
+  if (rd->data == FF_ffi_sizeof) {
+    CType *ct = lj_ctype_rawref(ctype_ctsG(J2G(J)), id);
+    if (ctype_isvltype(ct->info))
+      lj_trace_err(J, LJ_TRERR_BADTYPE);
+  } else if (rd->data == FF_ffi_offsetof) {  /* Specialize to the field name. */
+    if (!tref_isstr(J->base[1]))
+      lj_trace_err(J, LJ_TRERR_BADTYPE);
+    emitir(IRTG(IR_EQ, IRT_STR), J->base[1], lj_ir_kstr(J, strV(&rd->argv[1])));
+    rd->nres = 3;  /* Just in case. */
+  }
+  J->postproc = LJ_POST_FIXCONST;
+  J->base[0] = J->base[1] = J->base[2] = TREF_NIL;
 }
 
 /* -- Miscellaneous library functions ------------------------------------- */
diff --git a/src/lj_crecord.h b/src/lj_crecord.h
index ab0e27e7..bd217651 100644
--- a/src/lj_crecord.h
+++ b/src/lj_crecord.h
@@ -23,6 +23,7 @@ LJ_FUNC void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd);
 LJ_FUNC void LJ_FASTCALL recff_ffi_typeof(jit_State *J, RecordFFData *rd);
 LJ_FUNC void LJ_FASTCALL recff_ffi_istype(jit_State *J, RecordFFData *rd);
 LJ_FUNC void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd);
+LJ_FUNC void LJ_FASTCALL recff_ffi_xof(jit_State *J, RecordFFData *rd);
 LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd);
 #endif
 
diff --git a/src/lj_jit.h b/src/lj_jit.h
index 43a99392..4549ac6c 100644
--- a/src/lj_jit.h
+++ b/src/lj_jit.h
@@ -144,6 +144,7 @@ typedef enum {
   LJ_POST_FIXGUARD,	/* Fixup and emit pending guard. */
   LJ_POST_FIXGUARDSNAP,	/* Fixup and emit pending guard and snapshot. */
   LJ_POST_FIXBOOL,	/* Fixup boolean result. */
+  LJ_POST_FIXCONST,	/* Fixup constant results. */
   LJ_POST_FFRETRY	/* Suppress recording of retried fast functions. */
 } PostProc;
 
diff --git a/src/lj_record.c b/src/lj_record.c
index 956f3bed..ea391bf1 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -1654,13 +1654,23 @@ void lj_record_ins(jit_State *J)
     case LJ_POST_FIXBOOL:
       if (!tvistruecond(&J2G(J)->tmptv2)) {
 	BCReg s;
+	TValue *tv = J->L->base;
 	for (s = 0; s < J->maxslot; s++)  /* Fixup stack slot (if any). */
-	  if (J->base[s] == TREF_TRUE && tvisfalse(&J->L->base[s])) {
+	  if (J->base[s] == TREF_TRUE && tvisfalse(&tv[s])) {
 	    J->base[s] = TREF_FALSE;
 	    break;
 	  }
       }
       break;
+    case LJ_POST_FIXCONST:
+      {
+	BCReg s;
+	TValue *tv = J->L->base;
+	for (s = 0; s < J->maxslot; s++)  /* Constify stack slots (if any). */
+	  if (J->base[s] == TREF_NIL && !tvisnil(&tv[s]))
+	    J->base[s] = lj_record_constify(J, &tv[s]);
+      }
+      break;
     case LJ_POST_FFRETRY:  /* Suppress recording of retried fast function. */
       if (bc_op(*J->pc) >= BC__MAX)
 	return;
-- 
cgit v1.2.3-55-g6feb