Browse Source

FFI: Parse complex and 64 bit integer literals.

Mike Pall 14 years ago
parent
commit
461bf77331
14 changed files with 303 additions and 110 deletions
  1. 10 9
      src/Makefile.dep
  2. 4 4
      src/buildvm.c
  3. 13 0
      src/buildvm_ppc.dasc
  4. 106 82
      src/buildvm_ppcspe.h
  5. 5 0
      src/buildvm_x64.h
  6. 5 0
      src/buildvm_x64win.h
  7. 9 0
      src/buildvm_x86.dasc
  8. 5 0
      src/buildvm_x86.h
  9. 2 1
      src/lib_ffi.c
  10. 2 1
      src/lj_bc.h
  11. 9 0
      src/lj_cdata.h
  12. 90 5
      src/lj_lex.c
  13. 40 8
      src/lj_parse.c
  14. 3 0
      src/lj_parse.h

+ 10 - 9
src/Makefile.dep

@@ -93,7 +93,8 @@ lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
  lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h lj_dispatch.h \
  lj_bc.h lj_traceerr.h lj_lib.h
 lj_lex.o: lj_lex.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_lex.h lj_parse.h lj_char.h
+ lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h lualib.h \
+ lj_lex.h lj_parse.h lj_char.h
 lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \
  lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \
  lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_lib.h
@@ -118,7 +119,7 @@ lj_opt_narrow.o: lj_opt_narrow.c lj_obj.h lua.h luaconf.h lj_def.h \
  lj_dispatch.h lj_traceerr.h
 lj_parse.o: lj_parse.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_func.h lj_state.h \
- lj_bc.h lj_lex.h lj_parse.h lj_vm.h lj_vmevent.h
+ lj_bc.h lj_ctype.h lj_lex.h lj_parse.h lj_vm.h lj_vmevent.h
 lj_record.o: lj_record.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_ff.h \
  lj_ffdef.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h lj_dispatch.h \
@@ -151,13 +152,13 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c lj_obj.h lj_def.h \
  lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_str.c lj_tab.c \
  lj_func.c lj_udata.c lj_meta.c lj_state.c lj_lex.h lj_alloc.h \
  lj_dispatch.c lj_ff.h lj_ffdef.h luajit.h lj_vmevent.c lj_vmevent.h \
- lj_api.c lj_parse.h lj_lex.c lj_parse.c lj_ctype.c lj_cdata.c lj_cconv.h \
- lj_cconv.c lj_cparse.c lj_cparse.h lj_lib.c lj_lib.h lj_ir.c lj_iropt.h \
- lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \
- lj_opt_loop.c lj_snap.h lj_mcode.c lj_mcode.h lj_snap.c lj_target.h \
- lj_target_*.h lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \
- lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_trace.c \
- lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c lualib.h \
+ lj_api.c lj_parse.h lj_lex.c lualib.h lj_parse.c lj_ctype.c lj_cdata.c \
+ lj_cconv.h lj_cconv.c lj_cparse.c lj_cparse.h lj_lib.c lj_lib.h lj_ir.c \
+ lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c \
+ lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_mcode.c lj_mcode.h lj_snap.c \
+ lj_target.h lj_target_*.h lj_record.c lj_record.h lj_ffrecord.h \
+ lj_crecord.c lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h \
+ lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c \
  lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c lib_os.c \
  lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c lib_init.c
 luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h

+ 4 - 4
src/buildvm.c

@@ -207,10 +207,10 @@ static int build_code(BuildCtx *ctx)
     int32_t ofs = dasm_getpclabel(Dst, i);
     if (ofs < 0) return 0x22000000|i;
     ctx->bc_ofs[i] = ofs;
-#if !LJ_HASJIT
-    if (!(i == BC_JFORI || i == BC_JFORL || i == BC_JITERL || i == BC_JLOOP ||
-	  i == BC_IFORL || i == BC_IITERL || i == BC_ILOOP))
-#endif
+    if ((LJ_HASJIT ||
+	 !(i == BC_JFORI || i == BC_JFORL || i == BC_JITERL || i == BC_JLOOP ||
+	   i == BC_IFORL || i == BC_IITERL || i == BC_ILOOP)) &&
+	(LJ_HASFFI || i != BC_KCDATA))
       sym_insert(ctx, ofs, LABEL_PREFIX_BC, bc_names[i]);
   }
 

+ 13 - 0
src/buildvm_ppc.dasc

@@ -2430,6 +2430,19 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  evstddx TMP0, BASE, RA
     |  ins_next2
     break;
+  case BC_KCDATA:
+#if LJ_HASFFI
+    |  // RA = dst*8, RD = cdata_const*8 (~)
+    |  ins_next1
+    |  srwi TMP1, RD, 1
+    |  subfic TMP1, TMP1, -4
+    |  lwzx TMP0, KBASE, TMP1		// KBASE-4-cdata_const*4
+    |  li TMP2, LJ_TCDATA
+    |  evmergelo TMP0, TMP2, TMP0
+    |  evstddx TMP0, BASE, RA
+    |  ins_next2
+#endif
+    break;
   case BC_KSHORT:
     |  // RA = dst*8, RD = int16_literal*8
     |  srwi TMP1, RD, 3

+ 106 - 82
src/buildvm_ppcspe.h

@@ -12,7 +12,7 @@
 #define DASM_SECTION_CODE_OP	0
 #define DASM_SECTION_CODE_SUB	1
 #define DASM_MAXSECTION		2
-static const unsigned int build_actionlist[4928] = {
+static const unsigned int build_actionlist[4947] = {
 0x00010001,
 0x00060014,
 0x72000000,
@@ -3372,6 +3372,25 @@ static const unsigned int build_actionlist[4928] = {
 0x7c0903a6,
 0x4e800420,
 0x00000000,
+0x80f00000,
+0x3a100004,
+0x5588007e,
+0x000900ab,
+0x2108fffc,
+0x7c0f402e,
+0x39200000,
+0x00098200,
+0x1009022d,
+0x100ea320,
+0x54e815ba,
+0x54ea5d78,
+0x54ec9b78,
+0x7c11402e,
+0x54f4dd78,
+0x54eb9d78,
+0x7c0903a6,
+0x4e800420,
+0x00000000,
 0x558800fe,
 0x000900ab,
 0x7d080734,
@@ -5619,158 +5638,163 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
   case BC_KSTR:
     dasm_put(Dst, 3342, 32-1);
     break;
+  case BC_KCDATA:
+#if LJ_HASFFI
+    dasm_put(Dst, 3359, 32-1, LJ_TCDATA);
+#endif
+    break;
   case BC_KSHORT:
-    dasm_put(Dst, 3359, 32-3);
+    dasm_put(Dst, 3378, 32-3);
     break;
   case BC_KNUM:
-    dasm_put(Dst, 3375);
+    dasm_put(Dst, 3394);
     break;
   case BC_KPRI:
-    dasm_put(Dst, 3388, 32-3);
+    dasm_put(Dst, 3407, 32-3);
     break;
   case BC_KNIL:
-    dasm_put(Dst, 3403);
+    dasm_put(Dst, 3422);
     break;
 
   /* -- Upvalue and function ops ------------------------------------------ */
 
   case BC_UGET:
-    dasm_put(Dst, 3422, 32-1, offsetof(GCfuncL, uvptr), DtA(->v));
+    dasm_put(Dst, 3441, 32-1, offsetof(GCfuncL, uvptr), DtA(->v));
     break;
   case BC_USETV:
-    dasm_put(Dst, 3443, 32-1, offsetof(GCfuncL, uvptr), DtA(->marked), DtA(->v), LJ_GC_BLACK, DtA(->closed), -LJ_TISNUM, LJ_TISGCV - LJ_TISNUM, Dt4(->gch.marked), LJ_GC_WHITES, GG_DISP2G);
+    dasm_put(Dst, 3462, 32-1, offsetof(GCfuncL, uvptr), DtA(->marked), DtA(->v), LJ_GC_BLACK, DtA(->closed), -LJ_TISNUM, LJ_TISGCV - LJ_TISNUM, Dt4(->gch.marked), LJ_GC_WHITES, GG_DISP2G);
     break;
   case BC_USETS:
-    dasm_put(Dst, 3495, 32-1, 32-1, offsetof(GCfuncL, uvptr), DtA(->marked), DtA(->v), LJ_GC_BLACK, Dt5(->marked), DtA(->closed), LJ_GC_WHITES, GG_DISP2G);
+    dasm_put(Dst, 3514, 32-1, 32-1, offsetof(GCfuncL, uvptr), DtA(->marked), DtA(->v), LJ_GC_BLACK, Dt5(->marked), DtA(->closed), LJ_GC_WHITES, GG_DISP2G);
     break;
   case BC_USETN:
-    dasm_put(Dst, 3544, 32-1, offsetof(GCfuncL, uvptr), DtA(->v));
+    dasm_put(Dst, 3563, 32-1, offsetof(GCfuncL, uvptr), DtA(->v));
     break;
   case BC_USETP:
-    dasm_put(Dst, 3565, 32-1, offsetof(GCfuncL, uvptr), 32-3, DtA(->v));
+    dasm_put(Dst, 3584, 32-1, offsetof(GCfuncL, uvptr), 32-3, DtA(->v));
     break;
 
   case BC_UCLO:
-    dasm_put(Dst, 3588, Dt1(->openupval), 32-1, -(BCBIAS_J*4 >> 16), Dt1(->base), Dt1(->base));
+    dasm_put(Dst, 3607, Dt1(->openupval), 32-1, -(BCBIAS_J*4 >> 16), Dt1(->base), Dt1(->base));
     break;
 
   case BC_FNEW:
-    dasm_put(Dst, 3618, 32-1, Dt1(->base), Dt1(->base));
+    dasm_put(Dst, 3637, 32-1, Dt1(->base), Dt1(->base));
     break;
 
   /* -- Table ops --------------------------------------------------------- */
 
   case BC_TNEW:
   case BC_TDUP:
-    dasm_put(Dst, 3644, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base));
+    dasm_put(Dst, 3663, DISPATCH_GL(gc.total), DISPATCH_GL(gc.threshold), Dt1(->base));
     if (op == BC_TNEW) {
-      dasm_put(Dst, 3657);
+      dasm_put(Dst, 3676);
     } else {
-      dasm_put(Dst, 3665, 32-1);
+      dasm_put(Dst, 3684, 32-1);
     }
-    dasm_put(Dst, 3672, Dt1(->base));
+    dasm_put(Dst, 3691, Dt1(->base));
     break;
 
   case BC_GGET:
   case BC_GSET:
-    dasm_put(Dst, 3695, 32-1, Dt7(->env));
+    dasm_put(Dst, 3714, 32-1, Dt7(->env));
     if (op == BC_GGET) {
-      dasm_put(Dst, 3703);
+      dasm_put(Dst, 3722);
     } else {
-      dasm_put(Dst, 3706);
+      dasm_put(Dst, 3725);
     }
     break;
 
   case BC_TGETV:
-    dasm_put(Dst, 3709, Dt6(->asize), Dt6(->array), 31-3, Dt6(->metatable), Dt6(->nomm), 1<<MM_index);
+    dasm_put(Dst, 3728, Dt6(->asize), Dt6(->array), 31-3, Dt6(->metatable), Dt6(->nomm), 1<<MM_index);
     break;
   case BC_TGETS:
-    dasm_put(Dst, 3767, 32-1, Dt6(->hmask), Dt5(->hash), Dt6(->node), 31-5, 31-3, DtB(->key), DtB(->val), DtB(->next), Dt6(->metatable), Dt6(->nomm), 1<<MM_index);
-    dasm_put(Dst, 3831);
+    dasm_put(Dst, 3786, 32-1, Dt6(->hmask), Dt5(->hash), Dt6(->node), 31-5, 31-3, DtB(->key), DtB(->val), DtB(->next), Dt6(->metatable), Dt6(->nomm), 1<<MM_index);
+    dasm_put(Dst, 3850);
     break;
   case BC_TGETB:
-    dasm_put(Dst, 3836, 32-3, Dt6(->asize), Dt6(->array), Dt6(->metatable), Dt6(->nomm), 1<<MM_index);
+    dasm_put(Dst, 3855, 32-3, Dt6(->asize), Dt6(->array), Dt6(->metatable), Dt6(->nomm), 1<<MM_index);
     break;
 
   case BC_TSETV:
-    dasm_put(Dst, 3880, Dt6(->asize), Dt6(->array), 31-3, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->nomm), 1<<MM_newindex);
-    dasm_put(Dst, 3947, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist));
+    dasm_put(Dst, 3899, Dt6(->asize), Dt6(->array), 31-3, Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->nomm), 1<<MM_newindex);
+    dasm_put(Dst, 3966, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist));
     break;
   case BC_TSETS:
-    dasm_put(Dst, 3959, 32-1, Dt6(->hmask), Dt5(->hash), Dt6(->node), Dt6(->nomm), 31-5, 31-3, Dt6(->marked), DtB(->key), DtB(->val), LJ_GC_BLACK, DtB(->val), Dt6(->metatable));
-    dasm_put(Dst, 4020, Dt6(->nomm), 1<<MM_newindex, DtB(->next), Dt6(->metatable), DISPATCH_GL(tmptv), Dt1(->base), Dt6(->nomm), 1<<MM_newindex, Dt1(->base), DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain));
-    dasm_put(Dst, 4071, Dt6(->marked), Dt6(->gclist));
+    dasm_put(Dst, 3978, 32-1, Dt6(->hmask), Dt5(->hash), Dt6(->node), Dt6(->nomm), 31-5, 31-3, Dt6(->marked), DtB(->key), DtB(->val), LJ_GC_BLACK, DtB(->val), Dt6(->metatable));
+    dasm_put(Dst, 4039, Dt6(->nomm), 1<<MM_newindex, DtB(->next), Dt6(->metatable), DISPATCH_GL(tmptv), Dt1(->base), Dt6(->nomm), 1<<MM_newindex, Dt1(->base), DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain));
+    dasm_put(Dst, 4090, Dt6(->marked), Dt6(->gclist));
     break;
   case BC_TSETB:
-    dasm_put(Dst, 4078, 32-3, Dt6(->asize), Dt6(->array), Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->nomm), 1<<MM_newindex, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->marked));
-    dasm_put(Dst, 4138, Dt6(->gclist));
+    dasm_put(Dst, 4097, 32-3, Dt6(->asize), Dt6(->array), Dt6(->marked), LJ_GC_BLACK, Dt6(->metatable), Dt6(->nomm), 1<<MM_newindex, DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->marked));
+    dasm_put(Dst, 4157, Dt6(->gclist));
     break;
 
   case BC_TSETM:
-    dasm_put(Dst, 4143, 32-3, Dt6(->asize), 31-3, Dt6(->marked), Dt6(->array), LJ_GC_BLACK, Dt1(->base), DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist));
-    dasm_put(Dst, 4212);
+    dasm_put(Dst, 4162, 32-3, Dt6(->asize), 31-3, Dt6(->marked), Dt6(->array), LJ_GC_BLACK, Dt1(->base), DISPATCH_GL(gc.grayagain), DISPATCH_GL(gc.grayagain), Dt6(->marked), Dt6(->gclist));
+    dasm_put(Dst, 4231);
     break;
 
   /* -- Calls and vararg handling ----------------------------------------- */
 
   case BC_CALLM:
-    dasm_put(Dst, 4215);
+    dasm_put(Dst, 4234);
     break;
   case BC_CALL:
-    dasm_put(Dst, 4217, Dt7(->pc));
+    dasm_put(Dst, 4236, Dt7(->pc));
     break;
 
   case BC_CALLMT:
-    dasm_put(Dst, 4237);
+    dasm_put(Dst, 4256);
     break;
   case BC_CALLT:
-    dasm_put(Dst, 4239, FRAME_TYPE, Dt7(->ffid), FRAME_VARG, Dt7(->pc), -4-8, Dt7(->pc), PC2PROTO(k), FRAME_TYPEP);
-    dasm_put(Dst, 4304, FRAME_TYPE);
+    dasm_put(Dst, 4258, FRAME_TYPE, Dt7(->ffid), FRAME_VARG, Dt7(->pc), -4-8, Dt7(->pc), PC2PROTO(k), FRAME_TYPEP);
+    dasm_put(Dst, 4323, FRAME_TYPE);
     break;
 
   case BC_ITERC:
-    dasm_put(Dst, 4311, Dt7(->pc));
+    dasm_put(Dst, 4330, Dt7(->pc));
     break;
 
   case BC_ITERN:
 #if LJ_HASJIT
 #endif
-    dasm_put(Dst, 4337, Dt6(->asize), Dt6(->array), 31-3, -(BCBIAS_J*4 >> 16), Dt6(->hmask), Dt6(->node), 31-5, 31-3, DtB(->key), -(BCBIAS_J*4 >> 16));
-    dasm_put(Dst, 4416);
+    dasm_put(Dst, 4356, Dt6(->asize), Dt6(->array), 31-3, -(BCBIAS_J*4 >> 16), Dt6(->hmask), Dt6(->node), 31-5, 31-3, DtB(->key), -(BCBIAS_J*4 >> 16));
+    dasm_put(Dst, 4435);
     break;
 
   case BC_ISNEXT:
-    dasm_put(Dst, 4420, LJ_TTAB, LJ_TFUNC, LJ_TNIL, Dt8(->ffid), FF_next_N, 32-1, -(BCBIAS_J*4 >> 16), BC_JMP, BC_ITERC, -(BCBIAS_J*4 >> 16));
+    dasm_put(Dst, 4439, LJ_TTAB, LJ_TFUNC, LJ_TNIL, Dt8(->ffid), FF_next_N, 32-1, -(BCBIAS_J*4 >> 16), BC_JMP, BC_ITERC, -(BCBIAS_J*4 >> 16));
     break;
 
   case BC_VARG:
-    dasm_put(Dst, 4471, FRAME_VARG, Dt1(->maxstack), Dt1(->top), Dt1(->base), 32-3, Dt1(->base));
-    dasm_put(Dst, 4551);
+    dasm_put(Dst, 4490, FRAME_VARG, Dt1(->maxstack), Dt1(->top), Dt1(->base), 32-3, Dt1(->base));
+    dasm_put(Dst, 4570);
     break;
 
   /* -- Returns ----------------------------------------------------------- */
 
   case BC_RETM:
-    dasm_put(Dst, 4557);
+    dasm_put(Dst, 4576);
     break;
 
   case BC_RET:
-    dasm_put(Dst, 4559, FRAME_TYPE, FRAME_VARG, Dt7(->pc), PC2PROTO(k), FRAME_TYPEP);
+    dasm_put(Dst, 4578, FRAME_TYPE, FRAME_VARG, Dt7(->pc), PC2PROTO(k), FRAME_TYPEP);
     break;
 
   case BC_RET0: case BC_RET1:
-    dasm_put(Dst, 4629, FRAME_TYPE, FRAME_VARG);
+    dasm_put(Dst, 4648, FRAME_TYPE, FRAME_VARG);
     if (op == BC_RET1) {
-      dasm_put(Dst, 4642);
+      dasm_put(Dst, 4661);
     }
-    dasm_put(Dst, 4645, Dt7(->pc), PC2PROTO(k));
+    dasm_put(Dst, 4664, Dt7(->pc), PC2PROTO(k));
     break;
 
   /* -- Loops and branches ------------------------------------------------ */
 
   case BC_FORL:
 #if LJ_HASJIT
-    dasm_put(Dst, 4673);
+    dasm_put(Dst, 4692);
 #endif
     break;
 
@@ -5782,35 +5806,35 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
   case BC_FORI:
   case BC_IFORL:
     vk = (op == BC_IFORL || op == BC_JFORL);
-    dasm_put(Dst, 4675, FORL_IDX*8, FORL_STEP*8, FORL_STOP*8);
+    dasm_put(Dst, 4694, FORL_IDX*8, FORL_STEP*8, FORL_STOP*8);
     if (!vk) {
-      dasm_put(Dst, 4683);
+      dasm_put(Dst, 4702);
     }
     if (vk) {
-      dasm_put(Dst, 4691, FORL_IDX*8);
+      dasm_put(Dst, 4710, FORL_IDX*8);
     }
-    dasm_put(Dst, 4695, FORL_EXT*8);
+    dasm_put(Dst, 4714, FORL_EXT*8);
     if (op != BC_JFORL) {
-      dasm_put(Dst, 4703, 32-1);
+      dasm_put(Dst, 4722, 32-1);
       if (op == BC_JFORI) {
-	dasm_put(Dst, 4707, -(BCBIAS_J*4 >> 16));
+	dasm_put(Dst, 4726, -(BCBIAS_J*4 >> 16));
       } else {
-	dasm_put(Dst, 4710, -(BCBIAS_J*4 >> 16));
+	dasm_put(Dst, 4729, -(BCBIAS_J*4 >> 16));
       }
     }
     if (op == BC_FORI) {
-      dasm_put(Dst, 4713);
+      dasm_put(Dst, 4732);
     } else if (op == BC_IFORL) {
-      dasm_put(Dst, 4715);
+      dasm_put(Dst, 4734);
     } else {
-      dasm_put(Dst, 4717, BC_JLOOP);
+      dasm_put(Dst, 4736, BC_JLOOP);
     }
-    dasm_put(Dst, 4720);
+    dasm_put(Dst, 4739);
     break;
 
   case BC_ITERL:
 #if LJ_HASJIT
-    dasm_put(Dst, 4735);
+    dasm_put(Dst, 4754);
 #endif
     break;
 
@@ -5819,40 +5843,40 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     break;
 #endif
   case BC_IITERL:
-    dasm_put(Dst, 4737);
+    dasm_put(Dst, 4756);
     if (op == BC_JITERL) {
-      dasm_put(Dst, 4743);
+      dasm_put(Dst, 4762);
     } else {
-      dasm_put(Dst, 4745, 32-1, -(BCBIAS_J*4 >> 16));
+      dasm_put(Dst, 4764, 32-1, -(BCBIAS_J*4 >> 16));
     }
-    dasm_put(Dst, 4752);
+    dasm_put(Dst, 4771);
     break;
 
   case BC_LOOP:
 #if LJ_HASJIT
-    dasm_put(Dst, 4764);
+    dasm_put(Dst, 4783);
 #endif
     break;
 
   case BC_ILOOP:
-    dasm_put(Dst, 4766);
+    dasm_put(Dst, 4785);
     break;
 
   case BC_JLOOP:
 #if LJ_HASJIT
-    dasm_put(Dst, 4777);
+    dasm_put(Dst, 4796);
 #endif
     break;
 
   case BC_JMP:
-    dasm_put(Dst, 4779, 32-1, -(BCBIAS_J*4 >> 16));
+    dasm_put(Dst, 4798, 32-1, -(BCBIAS_J*4 >> 16));
     break;
 
   /* -- Function headers -------------------------------------------------- */
 
   case BC_FUNCF:
 #if LJ_HASJIT
-    dasm_put(Dst, 4795);
+    dasm_put(Dst, 4814);
 #endif
   case BC_FUNCV:  /* NYI: compiled vararg functions. */
     break;
@@ -5862,38 +5886,38 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     break;
 #endif
   case BC_IFUNCF:
-    dasm_put(Dst, 4797, Dt1(->maxstack), -4+PC2PROTO(numparams), -4+PC2PROTO(k), 31-3);
+    dasm_put(Dst, 4816, Dt1(->maxstack), -4+PC2PROTO(numparams), -4+PC2PROTO(k), 31-3);
     if (op == BC_JFUNCF) {
-      dasm_put(Dst, 4815);
+      dasm_put(Dst, 4834);
     } else {
-      dasm_put(Dst, 4817);
+      dasm_put(Dst, 4836);
     }
-    dasm_put(Dst, 4826);
+    dasm_put(Dst, 4845);
     break;
 
   case BC_JFUNCV:
 #if !LJ_HASJIT
     break;
 #endif
-    dasm_put(Dst, 4832);
+    dasm_put(Dst, 4851);
     break;  /* NYI: compiled vararg functions. */
 
   case BC_IFUNCV:
-    dasm_put(Dst, 4834, Dt1(->maxstack), 8+FRAME_VARG, -4+PC2PROTO(k), -4+PC2PROTO(numparams));
+    dasm_put(Dst, 4853, Dt1(->maxstack), 8+FRAME_VARG, -4+PC2PROTO(k), -4+PC2PROTO(numparams));
     break;
 
   case BC_FUNCC:
   case BC_FUNCCW:
     if (op == BC_FUNCC) {
-      dasm_put(Dst, 4884, Dt8(->f));
+      dasm_put(Dst, 4903, Dt8(->f));
     } else {
-      dasm_put(Dst, 4887, DISPATCH_GL(wrapf));
+      dasm_put(Dst, 4906, DISPATCH_GL(wrapf));
     }
-    dasm_put(Dst, 4890, Dt1(->maxstack), Dt1(->base), Dt1(->top), ~LJ_VMST_C);
+    dasm_put(Dst, 4909, Dt1(->maxstack), Dt1(->base), Dt1(->top), ~LJ_VMST_C);
     if (op == BC_FUNCCW) {
-      dasm_put(Dst, 4903, Dt8(->f));
+      dasm_put(Dst, 4922, Dt8(->f));
     }
-    dasm_put(Dst, 4906, DISPATCH_GL(vmstate), Dt1(->top), 31-3, Dt1(->base), ~LJ_VMST_INTERP, DISPATCH_GL(vmstate));
+    dasm_put(Dst, 4925, DISPATCH_GL(vmstate), Dt1(->top), 31-3, Dt1(->base), ~LJ_VMST_INTERP, DISPATCH_GL(vmstate));
     break;
 
   /* ---------------------------------------------------------------------- */
@@ -5913,7 +5937,7 @@ static int build_backend(BuildCtx *ctx)
 
   build_subroutines(ctx);
 
-  dasm_put(Dst, 4927);
+  dasm_put(Dst, 4946);
   for (op = 0; op < BC__MAX; op++)
     build_ins(ctx, (BCOp)op, op);
 

+ 5 - 0
src/buildvm_x64.h

@@ -1862,6 +1862,11 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
   case BC_KSTR:
     dasm_put(Dst, 10553, LJ_TSTR);
     break;
+  case BC_KCDATA:
+#if LJ_HASFFI
+    dasm_put(Dst, 10553, LJ_TCDATA);
+#endif
+    break;
   case BC_KSHORT:
     if (sse) {
       dasm_put(Dst, 10590);

+ 5 - 0
src/buildvm_x64win.h

@@ -1863,6 +1863,11 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
   case BC_KSTR:
     dasm_put(Dst, 10534, LJ_TSTR);
     break;
+  case BC_KCDATA:
+#if LJ_HASFFI
+    dasm_put(Dst, 10534, LJ_TCDATA);
+#endif
+    break;
   case BC_KSHORT:
     if (sse) {
       dasm_put(Dst, 10569);

+ 9 - 0
src/buildvm_x86.dasc

@@ -3795,6 +3795,15 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
     |  mov [BASE+RA*8], RD
     |  ins_next
     break;
+  case BC_KCDATA:
+#if LJ_HASFFI
+    |  ins_AND	// RA = dst, RD = cdata const (~)
+    |  mov RD, [KBASE+RD*4]
+    |  mov dword [BASE+RA*8+4], LJ_TCDATA
+    |  mov [BASE+RA*8], RD
+    |  ins_next
+#endif
+    break;
   case BC_KSHORT:
     |  ins_AD	// RA = dst, RD = signed int16 literal
     if (sse) {

+ 5 - 0
src/buildvm_x86.h

@@ -1982,6 +1982,11 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
   case BC_KSTR:
     dasm_put(Dst, 11907, LJ_TSTR);
     break;
+  case BC_KCDATA:
+#if LJ_HASFFI
+    dasm_put(Dst, 11907, LJ_TCDATA);
+#endif
+    break;
   case BC_KSHORT:
     if (sse) {
       dasm_put(Dst, 11940);

+ 2 - 1
src/lib_ffi.c

@@ -474,7 +474,8 @@ LUALIB_API int luaopen_ffi(lua_State *L)
   lj_ctype_init(L);
   LJ_LIB_REG_(L, NULL, ffi_meta);
   /* NOBARRIER: basemt is a GC root. */
-  setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1)));
+  L->top--;
+  setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top)));
   lua_pushliteral(L, LJ_OS_NAME);
   lua_pushliteral(L, LJ_ARCH_NAME);
   LJ_LIB_REG_(L, NULL, ffi);  /* Note: no global "ffi" created! */

+ 2 - 1
src/lj_bc.h

@@ -121,6 +121,7 @@
   \
   /* Constant ops. */ \
   _(KSTR,	dst,	___,	str,	___) \
+  _(KCDATA,	dst,	___,	cdata,	___) \
   _(KSHORT,	dst,	___,	lits,	___) \
   _(KNUM,	dst,	___,	num,	___) \
   _(KPRI,	dst,	___,	pri,	___) \
@@ -234,7 +235,7 @@ enum {
 /* Bytecode operand modes. ORDER BCMode */
 typedef enum {
   BCMnone, BCMdst, BCMbase, BCMvar, BCMrbase, BCMuv,  /* Mode A must be <= 7 */
-  BCMlit, BCMlits, BCMpri, BCMnum, BCMstr, BCMtab, BCMfunc, BCMjump,
+  BCMlit, BCMlits, BCMpri, BCMnum, BCMstr, BCMtab, BCMfunc, BCMjump, BCMcdata,
   BCM_max
 } BCMode;
 #define BCM___		BCMnone

+ 9 - 0
src/lj_cdata.h

@@ -45,6 +45,15 @@ static LJ_AINLINE GCcdata *lj_cdata_new(CTState *cts, CTypeID id, CTSize sz)
   return cd;
 }
 
+/* Variant which works without a valid CTState. */
+static LJ_AINLINE GCcdata *lj_cdata_new_(lua_State *L, CTypeID id, CTSize sz)
+{
+  GCcdata *cd = (GCcdata *)lj_mem_newgco(L, sizeof(GCcdata) + sz);
+  cd->gct = ~LJ_TCDATA;
+  cd->typeid = id;
+  return cd;
+}
+
 LJ_FUNC GCcdata *lj_cdata_newref(CTState *cts, const void *pp, CTypeID id);
 LJ_FUNC GCcdata *lj_cdata_newv(CTState *cts, CTypeID id, CTSize sz,
 			       CTSize align);

+ 90 - 5
src/lj_lex.c

@@ -13,6 +13,12 @@
 #include "lj_gc.h"
 #include "lj_err.h"
 #include "lj_str.h"
+#if LJ_HASFFI
+#include "lj_tab.h"
+#include "lj_ctype.h"
+#include "lj_cdata.h"
+#include "lualib.h"
+#endif
 #include "lj_lex.h"
 #include "lj_parse.h"
 #include "lj_char.h"
@@ -77,7 +83,64 @@ static void inclinenumber(LexState *ls)
 
 /* -- Scanner for terminals ----------------------------------------------- */
 
-static void read_numeral(LexState *ls, TValue *tv)
+#if LJ_HASFFI
+/* Load FFI library on-demand. Needed if we create cdata objects. */
+static void lex_loadffi(lua_State *L)
+{
+  cTValue *tmp;
+  luaopen_ffi(L);
+  tmp = lj_tab_getstr(tabV(registry(L)), lj_str_newlit(L, "_LOADED"));
+  if (tmp && tvistab(tmp)) {
+    GCtab *t = tabV(tmp);
+    copyTV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "ffi")), L->top-1);
+    lj_gc_anybarriert(L, t);
+  }
+  L->top--;
+}
+
+/* Parse 64 bit integer. */
+static int lex_number64(LexState *ls, TValue *tv)
+{
+  uint64_t n = 0;
+  uint8_t *p = (uint8_t *)ls->sb.buf;
+  CTypeID id = CTID_INT64;
+  GCcdata *cd;
+  int numl = 0;
+  if (p[0] == '0' && (p[1] & ~0x20) == 'X') {  /* Hexadecimal. */
+    p += 2;
+    if (!lj_char_isxdigit(*p)) return 0;
+    do {
+      n = n*16 + (*p & 15);
+      if (!lj_char_isdigit(*p)) n += 9;
+      p++;
+    } while (lj_char_isxdigit(*p));
+  } else {  /* Decimal. */
+    if (!lj_char_isdigit(*p)) return 0;
+    do {
+      n = n*10 + (*p - '0');
+      p++;
+    } while (lj_char_isdigit(*p));
+  }
+  for (;;) {  /* Parse suffixes. */
+    if ((*p & ~0x20) == 'U')
+      id = CTID_UINT64;
+    else if ((*p & ~0x20) == 'L')
+      numl++;
+    else
+      break;
+    p++;
+  }
+  if (numl != 2 || *p != '\0') return 0;
+  /* Return cdata holding a 64 bit integer. */
+  cd = lj_cdata_new_(ls->L, id, 8);
+  *(uint64_t *)cdataptr(cd) = n;
+  lj_parse_keepcdata(ls, tv, cd);
+  return 1;  /* Ok. */
+}
+#endif
+
+/* Parse a number literal. */
+static void lex_number(LexState *ls, TValue *tv)
 {
   int c;
   lua_assert(lj_char_isdigit(ls->current));
@@ -87,9 +150,31 @@ static void read_numeral(LexState *ls, TValue *tv)
   } while (lj_char_isident(ls->current) || ls->current == '.' ||
 	   ((ls->current == '-' || ls->current == '+') &&
 	    ((c & ~0x20) == 'E' || (c & ~0x20) == 'P')));
+#if LJ_HASFFI
+  c &= ~0x20;
+  if ((c == 'I' || c == 'L' || c == 'U') && !ctype_ctsG(G(ls->L)))
+    lex_loadffi(ls->L);
+  if (c == 'I')  /* Parse imaginary part of complex number. */
+    ls->sb.n--;
+#endif
   save(ls, '\0');
-  if (!lj_str_numconv(ls->sb.buf, tv))
-    lj_lex_error(ls, TK_number, LJ_ERR_XNUMBER);
+#if LJ_HASFFI
+  if ((c == 'L' || c == 'U') && lex_number64(ls, tv)) {  /* Parse 64 bit int. */
+    return;
+  } else
+#endif
+  if (lj_str_numconv(ls->sb.buf, tv)) {
+#if LJ_HASFFI
+    if (c == 'I') {  /* Return cdata holding a complex number. */
+      GCcdata *cd = lj_cdata_new_(ls->L, CTID_COMPLEX_DOUBLE, 2*sizeof(double));
+      ((double *)cdataptr(cd))[0] = 0;
+      ((double *)cdataptr(cd))[1] = tv->n;
+      lj_parse_keepcdata(ls, tv, cd);
+    }
+#endif
+    return;
+  }
+  lj_lex_error(ls, TK_number, LJ_ERR_XNUMBER);
 }
 
 static int skip_sep(LexState *ls)
@@ -224,7 +309,7 @@ static int llex(LexState *ls, TValue *tv)
     if (lj_char_isident(ls->current)) {
       GCstr *s;
       if (lj_char_isdigit(ls->current)) {  /* Numeric literal. */
-	read_numeral(ls, tv);
+	lex_number(ls, tv);
 	return TK_number;
       }
       /* Identifier or reserved word. */
@@ -306,7 +391,7 @@ static int llex(LexState *ls, TValue *tv)
       } else if (!lj_char_isdigit(ls->current)) {
 	return '.';
       } else {
-	read_numeral(ls, tv);
+	lex_number(ls, tv);
 	return TK_number;
       }
     case END_OF_STREAM:

+ 40 - 8
src/lj_parse.c

@@ -17,6 +17,9 @@
 #include "lj_func.h"
 #include "lj_state.h"
 #include "lj_bc.h"
+#if LJ_HASFFI
+#include "lj_ctype.h"
+#endif
 #include "lj_lex.h"
 #include "lj_parse.h"
 #include "lj_vm.h"
@@ -33,6 +36,7 @@ typedef enum {
   VKSTR,	/* sval = string value */
   VKNUM,	/* nval = number value */
   VKLAST = VKNUM,
+  VKCDATA,	/* nval = cdata value, not treated as a constant expression */
   /* Non-constant expressions follow: */
   VLOCAL,	/* info = local register */
   VUPVAL,	/* info = upvalue index */
@@ -61,7 +65,7 @@ typedef struct ExpDesc {
 } ExpDesc;
 
 /* Macros for expressions. */
-#define expr_hasjump(e)	((e)->t != (e)->f)
+#define expr_hasjump(e)		((e)->t != (e)->f)
 
 #define expr_isk(e)		((e)->k <= VKLAST)
 #define expr_isk_nojump(e)	(expr_isk(e) && !expr_hasjump(e))
@@ -216,6 +220,17 @@ GCstr *lj_parse_keepstr(LexState *ls, const char *str, size_t len)
   return s;
 }
 
+#if LJ_HASFFI
+/* Anchor cdata to avoid GC. */
+void lj_parse_keepcdata(LexState *ls, TValue *tv, GCcdata *cd)
+{
+  /* NOBARRIER: the key is new or kept alive. */
+  lua_State *L = ls->L;
+  setcdataV(L, tv, cd);
+  setboolV(lj_tab_set(L, ls->fs->kt, tv), 1);
+}
+#endif
+
 /* -- Jump list handling -------------------------------------------------- */
 
 /* Get next element in jump list. */
@@ -469,6 +484,11 @@ static void expr_toreg_nobranch(FuncState *fs, ExpDesc *e, BCReg reg)
       ins = BCINS_AD(BC_KSHORT, reg, (BCReg)(uint16_t)k);
     else
       ins = BCINS_AD(BC_KNUM, reg, const_num(fs, e));
+#if LJ_HASFFI
+  } else if (e->k == VKCDATA) {
+    ins = BCINS_AD(BC_KCDATA, reg,
+		   const_gc(fs, obj2gco(cdataV(&e->u.nval)), LJ_TCDATA));
+#endif
   } else if (e->k == VRELOCABLE) {
     setbc_a(bcptr(fs, e), reg);
     goto noins;
@@ -856,7 +876,7 @@ static void bcemit_unop(FuncState *fs, BCOp op, ExpDesc *e)
     if (e->k == VKNIL || e->k == VKFALSE) {
       e->k = VKTRUE;
       return;
-    } else if (expr_isk(e)) {
+    } else if (expr_isk(e) || (LJ_HASFFI && e->k == VKCDATA)) {
       e->k = VKFALSE;
       return;
     } else if (e->k == VJMP) {
@@ -872,10 +892,22 @@ static void bcemit_unop(FuncState *fs, BCOp op, ExpDesc *e)
     }
   } else {
     lua_assert(op == BC_UNM || op == BC_LEN);
-    /* Constant-fold negations. But avoid folding to -0. */
-    if (op == BC_UNM && expr_isnumk_nojump(e) && expr_numV(e) != 0) {
-      setnumV(&e->u.nval, -expr_numV(e));
-      return;
+    if (op == BC_UNM && !expr_hasjump(e)) {  /* Constant-fold negations. */
+#if LJ_HASFFI
+      if (e->k == VKCDATA) {  /* Fold in-place since cdata is not interned. */
+	GCcdata *cd = cdataV(&e->u.nval);
+	int64_t *p = (int64_t *)cdataptr(cd);
+	if (cd->typeid == CTID_COMPLEX_DOUBLE)
+	  p[1] ^= (int64_t)U64x(80000000,00000000);
+	else
+	  *p = -*p;
+	return;
+      } else
+#endif
+      if (expr_isnumk(e) && expr_numV(e) != 0) {  /* Avoid folding to -0. */
+	e->u.nval.u64 ^= U64x(80000000,00000000);
+	return;
+      }
     }
     expr_toanyreg(fs, e);
   }
@@ -1554,8 +1586,8 @@ static void expr_simple(LexState *ls, ExpDesc *v)
 {
   switch (ls->token) {
   case TK_number:
-    expr_init(v, VKNUM, 0);
-    setnumV(&v->u.nval, numV(&ls->tokenval));
+    expr_init(v, (LJ_HASFFI && tviscdata(&ls->tokenval)) ? VKCDATA : VKNUM, 0);
+    copyTV(ls->L, &v->u.nval, &ls->tokenval);
     break;
   case TK_string:
     expr_init(v, VKSTR, 0);

+ 3 - 0
src/lj_parse.h

@@ -11,5 +11,8 @@
 
 LJ_FUNC GCproto *lj_parse(LexState *ls);
 LJ_FUNC GCstr *lj_parse_keepstr(LexState *ls, const char *str, size_t l);
+#if LJ_HASFFI
+LJ_FUNC void lj_parse_keepcdata(LexState *ls, TValue *tv, GCcdata *cd);
+#endif
 
 #endif