From da682b0e9184d4db7e8e477c682947d106790240 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Mon, 8 Oct 2012 17:14:18 +0200 Subject: [PATCH] FFI: Add support for copy constructors. --- doc/ext_ffi_semantics.html | 5 +++-- src/lj_cconv.c | 6 ++++-- src/lj_cconv.h | 2 +- src/lj_crecord.c | 3 ++- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/doc/ext_ffi_semantics.html b/doc/ext_ffi_semantics.html index 56b3f62e..498bbbb4 100644 --- a/doc/ext_ffi_semantics.html +++ b/doc/ext_ffi_semantics.html @@ -469,8 +469,9 @@ C type. when a single initializer is given. Otherwise they are treated like regular arrays. -
  • Aggregate types (arrays and structs) accept either a single -table initializer or a flat list of +
  • Aggregate types (arrays and structs) accept either a single cdata +initializer of the same type (copy constructor), a single +table initializer, or a flat list of initializers.
  • The elements of an array are initialized, starting at index zero. diff --git a/src/lj_cconv.c b/src/lj_cconv.c index f33ed56d..b81b4e90 100644 --- a/src/lj_cconv.c +++ b/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); diff --git a/src/lj_cconv.h b/src/lj_cconv.h index c53a7cf8..fd5da555 100644 --- a/src/lj_cconv.h +++ b/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); diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 99303310..fbb5d79a 100644 --- a/src/lj_crecord.c +++ b/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. */