Преглед на файлове

FFI: Add support for copy constructors.

Mike Pall преди 13 години
родител
ревизия
da682b0e91
променени са 4 файла, в които са добавени 10 реда и са изтрити 6 реда
  1. 3 2
      doc/ext_ffi_semantics.html
  2. 4 2
      src/lj_cconv.c
  3. 1 1
      src/lj_cconv.h
  4. 2 1
      src/lj_crecord.c

+ 3 - 2
doc/ext_ffi_semantics.html

@@ -469,8 +469,9 @@ C&nbsp;type</a>.</li>
 when a single initializer is given. Otherwise they are treated like
 regular arrays.</li>
 
-<li>Aggregate types (arrays and structs) accept either a single
-<a href="#init_table">table initializer</a> or a flat list of
+<li>Aggregate types (arrays and structs) accept either a single cdata
+initializer of the same type (copy constructor), a single
+<a href="#init_table">table initializer</a>, or a flat list of
 initializers.</li>
 
 <li>The elements of an array are initialized, starting at index zero.

+ 4 - 2
src/lj_cconv.c

@@ -718,12 +718,14 @@ static void cconv_struct_init(CTState *cts, CType *d, CTSize sz, uint8_t *dp,
 ** This is true if an aggregate is to be initialized with a value.
 ** Valarrays are treated as values here so ct_tv handles (V|C, I|F).
 */
-int lj_cconv_multi_init(CType *d, TValue *o)
+int lj_cconv_multi_init(CTState *cts, CType *d, TValue *o)
 {
   if (!(ctype_isrefarray(d->info) || ctype_isstruct(d->info)))
     return 0;  /* Destination is not an aggregate. */
   if (tvistab(o) || (tvisstr(o) && !ctype_isstruct(d->info)))
     return 0;  /* Initializer is not a value. */
+  if (tviscdata(o) && lj_ctype_rawref(cts, cdataV(o)->ctypeid) == d)
+    return 0;  /* Source and destination are identical aggregates. */
   return 1;  /* Otherwise the initializer is a value. */
 }
 
@@ -733,7 +735,7 @@ void lj_cconv_ct_init(CTState *cts, CType *d, CTSize sz,
 {
   if (len == 0)
     memset(dp, 0, sz);
-  else if (len == 1 && !lj_cconv_multi_init(d, o))
+  else if (len == 1 && !lj_cconv_multi_init(cts, d, o))
     lj_cconv_ct_tv(cts, d, dp, o, 0);
   else if (ctype_isarray(d->info))  /* Also handles valarray init with len>1. */
     cconv_array_init(cts, d, sz, dp, o, len);

+ 1 - 1
src/lj_cconv.h

@@ -61,7 +61,7 @@ LJ_FUNC int lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp);
 LJ_FUNC void lj_cconv_ct_tv(CTState *cts, CType *d,
 			    uint8_t *dp, TValue *o, CTInfo flags);
 LJ_FUNC void lj_cconv_bf_tv(CTState *cts, CType *d, uint8_t *dp, TValue *o);
-LJ_FUNC int lj_cconv_multi_init(CType *d, TValue *o);
+LJ_FUNC int lj_cconv_multi_init(CTState *cts, CType *d, TValue *o);
 LJ_FUNC void lj_cconv_ct_init(CTState *cts, CType *d, CTSize sz,
 			      uint8_t *dp, TValue *o, MSize len);
 

+ 2 - 1
src/lj_crecord.c

@@ -654,7 +654,8 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
     TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL);
     cTValue *fin;
     J->base[0] = trcd;
-    if (J->base[1] && !J->base[2] && !lj_cconv_multi_init(d, &rd->argv[1])) {
+    if (J->base[1] && !J->base[2] &&
+	!lj_cconv_multi_init(cts, d, &rd->argv[1])) {
       goto single_init;
     } else if (ctype_isarray(d->info)) {
       CType *dc = ctype_rawchild(cts, d);  /* Array element type. */