Kaynağa Gözat

FFI: Record conversions from strings to enums or pointers.

Mike Pall 14 yıl önce
ebeveyn
işleme
0fa32e5d31
1 değiştirilmiş dosya ile 22 ekleme ve 3 silme
  1. 22 3
      src/lj_crecord.c

+ 22 - 3
src/lj_crecord.c

@@ -328,6 +328,24 @@ static void crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, TValue *sval)
     sp = lj_ir_kptr(J, NULL);
   } else if (tref_isudata(sp)) {
     sp = emitir(IRT(IR_ADD, IRT_P32), sp, lj_ir_kint(J, sizeof(GCcdata)));
+  } else if (tref_isstr(sp)) {
+    if (ctype_isenum(d->info)) {  /* Match string against enum constant. */
+      GCstr *str = strV(sval);
+      CTSize ofs;
+      CType *cct = lj_ctype_getfield(cts, d, str, &ofs);
+      /* Specialize to the name of the enum constant. */
+      emitir(IRTG(IR_EQ, IRT_STR), sp, lj_ir_kstr(J, str));
+      if (cct && ctype_isconstval(cct->info)) {
+	lua_assert(ctype_child(cts, cct)->size == 4);
+	sp = lj_ir_kint(J, (int32_t)cct->size);
+	sid = ctype_cid(cct->info);
+      }  /* else: interpreter will throw. */
+    } else if (ctype_isrefarray(d->info)) {  /* Copy string to array. */
+      lj_trace_err(J, LJ_TRERR_BADTYPE);  /* NYI */
+    } else {  /* Otherwise pass the string data as a const char[]. */
+      sp = emitir(IRT(IR_STRREF, IRT_P32), sp, lj_ir_kint(J, 0));
+      sid = CTID_A_CCHAR;
+    }
   } else {  /* NYI: tref_isstr(sp), tref_istab(sp), tref_islightud(sp). */
     sid = argv2cdata(J, sp, sval)->typeid;
     s = ctype_raw(cts, sid);
@@ -350,6 +368,7 @@ static void crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, TValue *sval)
   }
   s = ctype_get(cts, sid);
 doconv:
+  if (ctype_isenum(d->info)) d = ctype_child(cts, d);
   crec_ct_ct(J, d, s, dp, sp);
 }
 
@@ -459,11 +478,11 @@ index_struct:
   if (ctype_isref(ct->info))
     ptr = emitir(IRT(IR_XLOAD, IRT_PTR), ptr, 0);
 
-  /* Skip attributes and enums. */
-  while (ctype_isattrib(ct->info) || ctype_isenum(ct->info))
-    ct = ctype_child(cts, ct);
+  while (ctype_isattrib(ct->info))
+    ct = ctype_child(cts, ct);  /* Skip attributes. */
 
   if (rd->data == 0) {  /* __index metamethod. */
+    if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);  /* Skip enums. */
     J->base[0] = crec_tv_ct(J, ct, sid, ptr);
   } else {  /* __newindex metamethod. */
     rd->nres = 0;