lj_cconv.c (24454B)
1 /* 2 ** C type conversions. 3 ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h 4 */ 5 6 #include "lj_obj.h" 7 8 #if LJ_HASFFI 9 10 #include "lj_err.h" 11 #include "lj_tab.h" 12 #include "lj_ctype.h" 13 #include "lj_cdata.h" 14 #include "lj_cconv.h" 15 #include "lj_ccallback.h" 16 17 /* -- Conversion errors --------------------------------------------------- */ 18 19 /* Bad conversion. */ 20 LJ_NORET static void cconv_err_conv(CTState *cts, CType *d, CType *s, 21 CTInfo flags) 22 { 23 const char *dst = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, d), NULL)); 24 const char *src; 25 if ((flags & CCF_FROMTV)) 26 src = lj_obj_typename[1+(ctype_isnum(s->info) ? LUA_TNUMBER : 27 ctype_isarray(s->info) ? LUA_TSTRING : LUA_TNIL)]; 28 else 29 src = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, s), NULL)); 30 if (CCF_GETARG(flags)) 31 lj_err_argv(cts->L, CCF_GETARG(flags), LJ_ERR_FFI_BADCONV, src, dst); 32 else 33 lj_err_callerv(cts->L, LJ_ERR_FFI_BADCONV, src, dst); 34 } 35 36 /* Bad conversion from TValue. */ 37 LJ_NORET static void cconv_err_convtv(CTState *cts, CType *d, TValue *o, 38 CTInfo flags) 39 { 40 const char *dst = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, d), NULL)); 41 const char *src = lj_typename(o); 42 if (CCF_GETARG(flags)) 43 lj_err_argv(cts->L, CCF_GETARG(flags), LJ_ERR_FFI_BADCONV, src, dst); 44 else 45 lj_err_callerv(cts->L, LJ_ERR_FFI_BADCONV, src, dst); 46 } 47 48 /* Initializer overflow. */ 49 LJ_NORET static void cconv_err_initov(CTState *cts, CType *d) 50 { 51 const char *dst = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, d), NULL)); 52 lj_err_callerv(cts->L, LJ_ERR_FFI_INITOV, dst); 53 } 54 55 /* -- C type compatibility checks ----------------------------------------- */ 56 57 /* Get raw type and qualifiers for a child type. Resolves enums, too. */ 58 static CType *cconv_childqual(CTState *cts, CType *ct, CTInfo *qual) 59 { 60 ct = ctype_child(cts, ct); 61 for (;;) { 62 if (ctype_isattrib(ct->info)) { 63 if (ctype_attrib(ct->info) == CTA_QUAL) *qual |= ct->size; 64 } else if (!ctype_isenum(ct->info)) { 65 break; 66 } 67 ct = ctype_child(cts, ct); 68 } 69 *qual |= (ct->info & CTF_QUAL); 70 return ct; 71 } 72 73 /* Check for compatible types when converting to a pointer. 74 ** Note: these checks are more relaxed than what C99 mandates. 75 */ 76 int lj_cconv_compatptr(CTState *cts, CType *d, CType *s, CTInfo flags) 77 { 78 if (!((flags & CCF_CAST) || d == s)) { 79 CTInfo dqual = 0, squal = 0; 80 d = cconv_childqual(cts, d, &dqual); 81 if (!ctype_isstruct(s->info)) 82 s = cconv_childqual(cts, s, &squal); 83 if ((flags & CCF_SAME)) { 84 if (dqual != squal) 85 return 0; /* Different qualifiers. */ 86 } else if (!(flags & CCF_IGNQUAL)) { 87 if ((dqual & squal) != squal) 88 return 0; /* Discarded qualifiers. */ 89 if (ctype_isvoid(d->info) || ctype_isvoid(s->info)) 90 return 1; /* Converting to/from void * is always ok. */ 91 } 92 if (ctype_type(d->info) != ctype_type(s->info) || 93 d->size != s->size) 94 return 0; /* Different type or different size. */ 95 if (ctype_isnum(d->info)) { 96 if (((d->info ^ s->info) & (CTF_BOOL|CTF_FP))) 97 return 0; /* Different numeric types. */ 98 } else if (ctype_ispointer(d->info)) { 99 /* Check child types for compatibility. */ 100 return lj_cconv_compatptr(cts, d, s, flags|CCF_SAME); 101 } else if (ctype_isstruct(d->info)) { 102 if (d != s) 103 return 0; /* Must be exact same type for struct/union. */ 104 } else if (ctype_isfunc(d->info)) { 105 /* NYI: structural equality of functions. */ 106 } 107 } 108 return 1; /* Types are compatible. */ 109 } 110 111 /* -- C type to C type conversion ----------------------------------------- */ 112 113 /* Convert C type to C type. Caveat: expects to get the raw CType! 114 ** 115 ** Note: This is only used by the interpreter and not optimized at all. 116 ** The JIT compiler will do a much better job specializing for each case. 117 */ 118 int lj_cconv_ct_ct(CTState *cts, CType *d, CType *s, 119 uint8_t *dp, uint8_t *sp, CTInfo flags) 120 { 121 CTSize dsize = d->size, ssize = s->size; 122 CTInfo dinfo = d->info, sinfo = s->info; 123 void *tmpptr; 124 125 lua_assert(!ctype_isenum(dinfo) && !ctype_isenum(sinfo)); 126 lua_assert(!ctype_isattrib(dinfo) && !ctype_isattrib(sinfo)); 127 128 if (ctype_type(dinfo) > CT_MAYCONVERT || ctype_type(sinfo) > CT_MAYCONVERT) 129 goto err_conv; 130 131 /* Some basic sanity checks. */ 132 lua_assert(!ctype_isnum(dinfo) || dsize > 0); 133 lua_assert(!ctype_isnum(sinfo) || ssize > 0); 134 lua_assert(!ctype_isbool(dinfo) || dsize == 1 || dsize == 4); 135 lua_assert(!ctype_isbool(sinfo) || ssize == 1 || ssize == 4); 136 lua_assert(!ctype_isinteger(dinfo) || (1u<<lj_fls(dsize)) == dsize); 137 lua_assert(!ctype_isinteger(sinfo) || (1u<<lj_fls(ssize)) == ssize); 138 139 switch (cconv_idx2(dinfo, sinfo)) { 140 /* Destination is a bool. */ 141 case CCX(B, B): 142 /* Source operand is already normalized. */ 143 if (dsize == 1) *dp = *sp; else *(int *)dp = *sp; 144 break; 145 case CCX(B, I): { 146 MSize i; 147 uint8_t b = 0; 148 for (i = 0; i < ssize; i++) b |= sp[i]; 149 b = (b != 0); 150 if (dsize == 1) *dp = b; else *(int *)dp = b; 151 break; 152 } 153 case CCX(B, F): { 154 uint8_t b; 155 if (ssize == sizeof(double)) b = (*(double *)sp != 0); 156 else if (ssize == sizeof(float)) b = (*(float *)sp != 0); 157 else goto err_conv; /* NYI: long double. */ 158 if (dsize == 1) *dp = b; else *(int *)dp = b; 159 break; 160 } 161 162 /* Destination is an integer. */ 163 case CCX(I, B): 164 case CCX(I, I): 165 conv_I_I: 166 if (dsize > ssize) { /* Zero-extend or sign-extend LSB. */ 167 #if LJ_LE 168 uint8_t fill = (!(sinfo & CTF_UNSIGNED) && (sp[ssize-1]&0x80)) ? 0xff : 0; 169 memcpy(dp, sp, ssize); 170 memset(dp + ssize, fill, dsize-ssize); 171 #else 172 uint8_t fill = (!(sinfo & CTF_UNSIGNED) && (sp[0]&0x80)) ? 0xff : 0; 173 memset(dp, fill, dsize-ssize); 174 memcpy(dp + (dsize-ssize), sp, ssize); 175 #endif 176 } else { /* Copy LSB. */ 177 #if LJ_LE 178 memcpy(dp, sp, dsize); 179 #else 180 memcpy(dp, sp + (ssize-dsize), dsize); 181 #endif 182 } 183 break; 184 case CCX(I, F): { 185 double n; /* Always convert via double. */ 186 conv_I_F: 187 /* Convert source to double. */ 188 if (ssize == sizeof(double)) n = *(double *)sp; 189 else if (ssize == sizeof(float)) n = (double)*(float *)sp; 190 else goto err_conv; /* NYI: long double. */ 191 /* Then convert double to integer. */ 192 /* The conversion must exactly match the semantics of JIT-compiled code! */ 193 if (dsize < 4 || (dsize == 4 && !(dinfo & CTF_UNSIGNED))) { 194 int32_t i = (int32_t)n; 195 if (dsize == 4) *(int32_t *)dp = i; 196 else if (dsize == 2) *(int16_t *)dp = (int16_t)i; 197 else *(int8_t *)dp = (int8_t)i; 198 } else if (dsize == 4) { 199 *(uint32_t *)dp = (uint32_t)n; 200 } else if (dsize == 8) { 201 if (!(dinfo & CTF_UNSIGNED)) 202 *(int64_t *)dp = (int64_t)n; 203 else 204 *(uint64_t *)dp = lj_num2u64(n); 205 } else { 206 goto err_conv; /* NYI: conversion to >64 bit integers. */ 207 } 208 break; 209 } 210 case CCX(I, C): 211 s = ctype_child(cts, s); 212 sinfo = s->info; 213 ssize = s->size; 214 goto conv_I_F; /* Just convert re. */ 215 case CCX(I, P): 216 if (!(flags & CCF_CAST)) goto err_conv; 217 sinfo = CTINFO(CT_NUM, CTF_UNSIGNED); 218 goto conv_I_I; 219 case CCX(I, A): 220 if (!(flags & CCF_CAST)) goto err_conv; 221 sinfo = CTINFO(CT_NUM, CTF_UNSIGNED); 222 ssize = CTSIZE_PTR; 223 tmpptr = sp; 224 sp = (uint8_t *)&tmpptr; 225 goto conv_I_I; 226 227 /* Destination is a floating-point number. */ 228 case CCX(F, B): 229 case CCX(F, I): { 230 double n; /* Always convert via double. */ 231 conv_F_I: 232 /* First convert source to double. */ 233 /* The conversion must exactly match the semantics of JIT-compiled code! */ 234 if (ssize < 4 || (ssize == 4 && !(sinfo & CTF_UNSIGNED))) { 235 int32_t i; 236 if (ssize == 4) { 237 i = *(int32_t *)sp; 238 } else if (!(sinfo & CTF_UNSIGNED)) { 239 if (ssize == 2) i = *(int16_t *)sp; 240 else i = *(int8_t *)sp; 241 } else { 242 if (ssize == 2) i = *(uint16_t *)sp; 243 else i = *(uint8_t *)sp; 244 } 245 n = (double)i; 246 } else if (ssize == 4) { 247 n = (double)*(uint32_t *)sp; 248 } else if (ssize == 8) { 249 if (!(sinfo & CTF_UNSIGNED)) n = (double)*(int64_t *)sp; 250 else n = (double)*(uint64_t *)sp; 251 } else { 252 goto err_conv; /* NYI: conversion from >64 bit integers. */ 253 } 254 /* Convert double to destination. */ 255 if (dsize == sizeof(double)) *(double *)dp = n; 256 else if (dsize == sizeof(float)) *(float *)dp = (float)n; 257 else goto err_conv; /* NYI: long double. */ 258 break; 259 } 260 case CCX(F, F): { 261 double n; /* Always convert via double. */ 262 conv_F_F: 263 if (ssize == dsize) goto copyval; 264 /* Convert source to double. */ 265 if (ssize == sizeof(double)) n = *(double *)sp; 266 else if (ssize == sizeof(float)) n = (double)*(float *)sp; 267 else goto err_conv; /* NYI: long double. */ 268 /* Convert double to destination. */ 269 if (dsize == sizeof(double)) *(double *)dp = n; 270 else if (dsize == sizeof(float)) *(float *)dp = (float)n; 271 else goto err_conv; /* NYI: long double. */ 272 break; 273 } 274 case CCX(F, C): 275 s = ctype_child(cts, s); 276 sinfo = s->info; 277 ssize = s->size; 278 goto conv_F_F; /* Ignore im, and convert from re. */ 279 280 /* Destination is a complex number. */ 281 case CCX(C, I): 282 d = ctype_child(cts, d); 283 dinfo = d->info; 284 dsize = d->size; 285 memset(dp + dsize, 0, dsize); /* Clear im. */ 286 goto conv_F_I; /* Convert to re. */ 287 case CCX(C, F): 288 d = ctype_child(cts, d); 289 dinfo = d->info; 290 dsize = d->size; 291 memset(dp + dsize, 0, dsize); /* Clear im. */ 292 goto conv_F_F; /* Convert to re. */ 293 294 case CCX(C, C): 295 if (dsize != ssize) { /* Different types: convert re/im separately. */ 296 CType *dc = ctype_child(cts, d); 297 CType *sc = ctype_child(cts, s); 298 lj_cconv_ct_ct(cts, dc, sc, dp, sp, flags); 299 lj_cconv_ct_ct(cts, dc, sc, dp + dc->size, sp + sc->size, flags); 300 return 0; 301 } 302 goto copyval; /* Otherwise this is easy. */ 303 304 /* Destination is a vector. */ 305 case CCX(V, I): 306 case CCX(V, F): 307 case CCX(V, C): { 308 CType *dc = ctype_child(cts, d); 309 CTSize esize; 310 /* First convert the scalar to the first element. */ 311 lj_cconv_ct_ct(cts, dc, s, dp, sp, flags); 312 /* Then replicate it to the other elements (splat). */ 313 for (sp = dp, esize = dc->size; dsize > esize; dsize -= esize) { 314 dp += esize; 315 memcpy(dp, sp, esize); 316 } 317 break; 318 } 319 320 case CCX(V, V): 321 /* Copy same-sized vectors, even for different lengths/element-types. */ 322 if (dsize != ssize) goto err_conv; 323 goto copyval; 324 325 /* Destination is a pointer. */ 326 case CCX(P, I): 327 if (!(flags & CCF_CAST)) goto err_conv; 328 dinfo = CTINFO(CT_NUM, CTF_UNSIGNED); 329 goto conv_I_I; 330 331 case CCX(P, F): 332 if (!(flags & CCF_CAST) || !(flags & CCF_FROMTV)) goto err_conv; 333 /* The signed conversion is cheaper. x64 really has 47 bit pointers. */ 334 dinfo = CTINFO(CT_NUM, (LJ_64 && dsize == 8) ? 0 : CTF_UNSIGNED); 335 goto conv_I_F; 336 337 case CCX(P, P): 338 if (!lj_cconv_compatptr(cts, d, s, flags)) goto err_conv; 339 cdata_setptr(dp, dsize, cdata_getptr(sp, ssize)); 340 break; 341 342 case CCX(P, A): 343 case CCX(P, S): 344 if (!lj_cconv_compatptr(cts, d, s, flags)) goto err_conv; 345 cdata_setptr(dp, dsize, sp); 346 break; 347 348 /* Destination is an array. */ 349 case CCX(A, A): 350 if ((flags & CCF_CAST) || (d->info & CTF_VLA) || dsize != ssize || 351 d->size == CTSIZE_INVALID || !lj_cconv_compatptr(cts, d, s, flags)) 352 goto err_conv; 353 goto copyval; 354 355 /* Destination is a struct/union. */ 356 case CCX(S, S): 357 if ((flags & CCF_CAST) || (d->info & CTF_VLA) || d != s) 358 goto err_conv; /* Must be exact same type. */ 359 copyval: /* Copy value. */ 360 lua_assert(dsize == ssize); 361 memcpy(dp, sp, dsize); 362 break; 363 364 default: 365 err_conv: 366 if (!(flags & CCF_NOERROR)) 367 cconv_err_conv(cts, d, s, flags); 368 return -1; 369 } 370 return 0; 371 } 372 373 /* -- C type to TValue conversion ----------------------------------------- */ 374 375 /* Convert C type to TValue. Caveat: expects to get the raw CType! */ 376 int lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid, 377 TValue *o, uint8_t *sp) 378 { 379 CTInfo sinfo = s->info; 380 if (ctype_isnum(sinfo)) { 381 if (!ctype_isbool(sinfo)) { 382 if (ctype_isinteger(sinfo) && s->size > 4) goto copyval; 383 if (LJ_DUALNUM && ctype_isinteger(sinfo)) { 384 int32_t i; 385 lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT32), s, 386 (uint8_t *)&i, sp, 0); 387 if ((sinfo & CTF_UNSIGNED) && i < 0) 388 setnumV(o, (lua_Number)(uint32_t)i); 389 else 390 setintV(o, i); 391 } else { 392 lj_cconv_ct_ct(cts, ctype_get(cts, CTID_DOUBLE), s, 393 (uint8_t *)&o->n, sp, 0); 394 /* Numbers are NOT canonicalized here! Beware of uninitialized data. */ 395 lua_assert(tvisnum(o)); 396 } 397 } else { 398 uint32_t b = s->size == 1 ? (*sp != 0) : (*(int *)sp != 0); 399 setboolV(o, b); 400 setboolV(&cts->g->tmptv2, b); /* Remember for trace recorder. */ 401 } 402 return 0; 403 } else if (ctype_isrefarray(sinfo) || ctype_isstruct(sinfo)) { 404 /* Create reference. */ 405 setcdataV(cts->L, o, lj_cdata_newref(cts, sp, sid)); 406 return 1; /* Need GC step. */ 407 } else { 408 GCcdata *cd; 409 CTSize sz; 410 copyval: /* Copy value. */ 411 sz = s->size; 412 lua_assert(sz != CTSIZE_INVALID); 413 /* Attributes are stripped, qualifiers are kept (but mostly ignored). */ 414 cd = lj_cdata_new(cts, ctype_typeid(cts, s), sz); 415 setcdataV(cts->L, o, cd); 416 memcpy(cdataptr(cd), sp, sz); 417 return 1; /* Need GC step. */ 418 } 419 } 420 421 /* Convert bitfield to TValue. */ 422 int lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp) 423 { 424 CTInfo info = s->info; 425 CTSize pos, bsz; 426 uint32_t val; 427 lua_assert(ctype_isbitfield(info)); 428 /* NYI: packed bitfields may cause misaligned reads. */ 429 switch (ctype_bitcsz(info)) { 430 case 4: val = *(uint32_t *)sp; break; 431 case 2: val = *(uint16_t *)sp; break; 432 case 1: val = *(uint8_t *)sp; break; 433 default: lua_assert(0); val = 0; break; 434 } 435 /* Check if a packed bitfield crosses a container boundary. */ 436 pos = ctype_bitpos(info); 437 bsz = ctype_bitbsz(info); 438 lua_assert(pos < 8*ctype_bitcsz(info)); 439 lua_assert(bsz > 0 && bsz <= 8*ctype_bitcsz(info)); 440 if (pos + bsz > 8*ctype_bitcsz(info)) 441 lj_err_caller(cts->L, LJ_ERR_FFI_NYIPACKBIT); 442 if (!(info & CTF_BOOL)) { 443 CTSize shift = 32 - bsz; 444 if (!(info & CTF_UNSIGNED)) { 445 setintV(o, (int32_t)(val << (shift-pos)) >> shift); 446 } else { 447 val = (val << (shift-pos)) >> shift; 448 if (!LJ_DUALNUM || (int32_t)val < 0) 449 setnumV(o, (lua_Number)(uint32_t)val); 450 else 451 setintV(o, (int32_t)val); 452 } 453 } else { 454 lua_assert(bsz == 1); 455 setboolV(o, (val >> pos) & 1); 456 } 457 return 0; /* No GC step needed. */ 458 } 459 460 /* -- TValue to C type conversion ----------------------------------------- */ 461 462 /* Convert table to array. */ 463 static void cconv_array_tab(CTState *cts, CType *d, 464 uint8_t *dp, GCtab *t, CTInfo flags) 465 { 466 int32_t i; 467 CType *dc = ctype_rawchild(cts, d); /* Array element type. */ 468 CTSize size = d->size, esize = dc->size, ofs = 0; 469 for (i = 0; ; i++) { 470 TValue *tv = (TValue *)lj_tab_getint(t, i); 471 if (!tv || tvisnil(tv)) { 472 if (i == 0) continue; /* Try again for 1-based tables. */ 473 break; /* Stop at first nil. */ 474 } 475 if (ofs >= size) 476 cconv_err_initov(cts, d); 477 lj_cconv_ct_tv(cts, dc, dp + ofs, tv, flags); 478 ofs += esize; 479 } 480 if (size != CTSIZE_INVALID) { /* Only fill up arrays with known size. */ 481 if (ofs == esize) { /* Replicate a single element. */ 482 for (; ofs < size; ofs += esize) memcpy(dp + ofs, dp, esize); 483 } else { /* Otherwise fill the remainder with zero. */ 484 memset(dp + ofs, 0, size - ofs); 485 } 486 } 487 } 488 489 /* Convert table to sub-struct/union. */ 490 static void cconv_substruct_tab(CTState *cts, CType *d, uint8_t *dp, 491 GCtab *t, int32_t *ip, CTInfo flags) 492 { 493 CTypeID id = d->sib; 494 while (id) { 495 CType *df = ctype_get(cts, id); 496 id = df->sib; 497 if (ctype_isfield(df->info) || ctype_isbitfield(df->info)) { 498 TValue *tv; 499 int32_t i = *ip, iz = i; 500 if (!gcref(df->name)) continue; /* Ignore unnamed fields. */ 501 if (i >= 0) { 502 retry: 503 tv = (TValue *)lj_tab_getint(t, i); 504 if (!tv || tvisnil(tv)) { 505 if (i == 0) { i = 1; goto retry; } /* 1-based tables. */ 506 if (iz == 0) { *ip = i = -1; goto tryname; } /* Init named fields. */ 507 break; /* Stop at first nil. */ 508 } 509 *ip = i + 1; 510 } else { 511 tryname: 512 tv = (TValue *)lj_tab_getstr(t, gco2str(gcref(df->name))); 513 if (!tv || tvisnil(tv)) continue; 514 } 515 if (ctype_isfield(df->info)) 516 lj_cconv_ct_tv(cts, ctype_rawchild(cts, df), dp+df->size, tv, flags); 517 else 518 lj_cconv_bf_tv(cts, df, dp+df->size, tv); 519 if ((d->info & CTF_UNION)) break; 520 } else if (ctype_isxattrib(df->info, CTA_SUBTYPE)) { 521 cconv_substruct_tab(cts, ctype_rawchild(cts, df), 522 dp+df->size, t, ip, flags); 523 } /* Ignore all other entries in the chain. */ 524 } 525 } 526 527 /* Convert table to struct/union. */ 528 static void cconv_struct_tab(CTState *cts, CType *d, 529 uint8_t *dp, GCtab *t, CTInfo flags) 530 { 531 int32_t i = 0; 532 memset(dp, 0, d->size); /* Much simpler to clear the struct first. */ 533 cconv_substruct_tab(cts, d, dp, t, &i, flags); 534 } 535 536 /* Convert TValue to C type. Caveat: expects to get the raw CType! */ 537 void lj_cconv_ct_tv(CTState *cts, CType *d, 538 uint8_t *dp, TValue *o, CTInfo flags) 539 { 540 CTypeID sid = CTID_P_VOID; 541 CType *s; 542 void *tmpptr; 543 uint8_t tmpbool, *sp = (uint8_t *)&tmpptr; 544 if (LJ_LIKELY(tvisint(o))) { 545 sp = (uint8_t *)&o->i; 546 sid = CTID_INT32; 547 flags |= CCF_FROMTV; 548 } else if (LJ_LIKELY(tvisnum(o))) { 549 sp = (uint8_t *)&o->n; 550 sid = CTID_DOUBLE; 551 flags |= CCF_FROMTV; 552 } else if (tviscdata(o)) { 553 sp = cdataptr(cdataV(o)); 554 sid = cdataV(o)->ctypeid; 555 s = ctype_get(cts, sid); 556 if (ctype_isref(s->info)) { /* Resolve reference for value. */ 557 lua_assert(s->size == CTSIZE_PTR); 558 sp = *(void **)sp; 559 sid = ctype_cid(s->info); 560 } 561 s = ctype_raw(cts, sid); 562 if (ctype_isfunc(s->info)) { 563 sid = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|sid), CTSIZE_PTR); 564 } else { 565 if (ctype_isenum(s->info)) s = ctype_child(cts, s); 566 goto doconv; 567 } 568 } else if (tvisstr(o)) { 569 GCstr *str = strV(o); 570 if (ctype_isenum(d->info)) { /* Match string against enum constant. */ 571 CTSize ofs; 572 CType *cct = lj_ctype_getfield(cts, d, str, &ofs); 573 if (!cct || !ctype_isconstval(cct->info)) 574 goto err_conv; 575 lua_assert(d->size == 4); 576 sp = (uint8_t *)&cct->size; 577 sid = ctype_cid(cct->info); 578 } else if (ctype_isrefarray(d->info)) { /* Copy string to array. */ 579 CType *dc = ctype_rawchild(cts, d); 580 CTSize sz = str->len+1; 581 if (!ctype_isinteger(dc->info) || dc->size != 1) 582 goto err_conv; 583 if (d->size != 0 && d->size < sz) 584 sz = d->size; 585 memcpy(dp, strdata(str), sz); 586 return; 587 } else { /* Otherwise pass it as a const char[]. */ 588 sp = (uint8_t *)strdata(str); 589 sid = CTID_A_CCHAR; 590 flags |= CCF_FROMTV; 591 } 592 } else if (tvistab(o)) { 593 if (ctype_isarray(d->info)) { 594 cconv_array_tab(cts, d, dp, tabV(o), flags); 595 return; 596 } else if (ctype_isstruct(d->info)) { 597 cconv_struct_tab(cts, d, dp, tabV(o), flags); 598 return; 599 } else { 600 goto err_conv; 601 } 602 } else if (tvisbool(o)) { 603 tmpbool = boolV(o); 604 sp = &tmpbool; 605 sid = CTID_BOOL; 606 } else if (tvisnil(o)) { 607 tmpptr = (void *)0; 608 flags |= CCF_FROMTV; 609 } else if (tvisudata(o)) { 610 GCudata *ud = udataV(o); 611 tmpptr = uddata(ud); 612 if (ud->udtype == UDTYPE_IO_FILE) 613 tmpptr = *(void **)tmpptr; 614 } else if (tvislightud(o)) { 615 tmpptr = lightudV(o); 616 } else if (tvisfunc(o)) { 617 void *p = lj_ccallback_new(cts, d, funcV(o)); 618 if (p) { 619 *(void **)dp = p; 620 return; 621 } 622 goto err_conv; 623 } else { 624 err_conv: 625 cconv_err_convtv(cts, d, o, flags); 626 } 627 s = ctype_get(cts, sid); 628 doconv: 629 if (ctype_isenum(d->info)) d = ctype_child(cts, d); 630 lj_cconv_ct_ct(cts, d, s, dp, sp, flags); 631 } 632 633 /* Convert TValue to bitfield. */ 634 void lj_cconv_bf_tv(CTState *cts, CType *d, uint8_t *dp, TValue *o) 635 { 636 CTInfo info = d->info; 637 CTSize pos, bsz; 638 uint32_t val, mask; 639 lua_assert(ctype_isbitfield(info)); 640 if ((info & CTF_BOOL)) { 641 uint8_t tmpbool; 642 lua_assert(ctype_bitbsz(info) == 1); 643 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_BOOL), &tmpbool, o, 0); 644 val = tmpbool; 645 } else { 646 CTypeID did = (info & CTF_UNSIGNED) ? CTID_UINT32 : CTID_INT32; 647 lj_cconv_ct_tv(cts, ctype_get(cts, did), (uint8_t *)&val, o, 0); 648 } 649 pos = ctype_bitpos(info); 650 bsz = ctype_bitbsz(info); 651 lua_assert(pos < 8*ctype_bitcsz(info)); 652 lua_assert(bsz > 0 && bsz <= 8*ctype_bitcsz(info)); 653 /* Check if a packed bitfield crosses a container boundary. */ 654 if (pos + bsz > 8*ctype_bitcsz(info)) 655 lj_err_caller(cts->L, LJ_ERR_FFI_NYIPACKBIT); 656 mask = ((1u << bsz) - 1u) << pos; 657 val = (val << pos) & mask; 658 /* NYI: packed bitfields may cause misaligned reads/writes. */ 659 switch (ctype_bitcsz(info)) { 660 case 4: *(uint32_t *)dp = (*(uint32_t *)dp & ~mask) | (uint32_t)val; break; 661 case 2: *(uint16_t *)dp = (*(uint16_t *)dp & ~mask) | (uint16_t)val; break; 662 case 1: *(uint8_t *)dp = (*(uint8_t *)dp & ~mask) | (uint8_t)val; break; 663 default: lua_assert(0); break; 664 } 665 } 666 667 /* -- Initialize C type with TValues -------------------------------------- */ 668 669 /* Initialize an array with TValues. */ 670 static void cconv_array_init(CTState *cts, CType *d, CTSize sz, uint8_t *dp, 671 TValue *o, MSize len) 672 { 673 CType *dc = ctype_rawchild(cts, d); /* Array element type. */ 674 CTSize ofs, esize = dc->size; 675 MSize i; 676 if (len*esize > sz) 677 cconv_err_initov(cts, d); 678 for (i = 0, ofs = 0; i < len; i++, ofs += esize) 679 lj_cconv_ct_tv(cts, dc, dp + ofs, o + i, 0); 680 if (ofs == esize) { /* Replicate a single element. */ 681 for (; ofs < sz; ofs += esize) memcpy(dp + ofs, dp, esize); 682 } else { /* Otherwise fill the remainder with zero. */ 683 memset(dp + ofs, 0, sz - ofs); 684 } 685 } 686 687 /* Initialize a sub-struct/union with TValues. */ 688 static void cconv_substruct_init(CTState *cts, CType *d, uint8_t *dp, 689 TValue *o, MSize len, MSize *ip) 690 { 691 CTypeID id = d->sib; 692 while (id) { 693 CType *df = ctype_get(cts, id); 694 id = df->sib; 695 if (ctype_isfield(df->info) || ctype_isbitfield(df->info)) { 696 MSize i = *ip; 697 if (!gcref(df->name)) continue; /* Ignore unnamed fields. */ 698 if (i >= len) break; 699 *ip = i + 1; 700 if (ctype_isfield(df->info)) 701 lj_cconv_ct_tv(cts, ctype_rawchild(cts, df), dp+df->size, o + i, 0); 702 else 703 lj_cconv_bf_tv(cts, df, dp+df->size, o + i); 704 if ((d->info & CTF_UNION)) break; 705 } else if (ctype_isxattrib(df->info, CTA_SUBTYPE)) { 706 cconv_substruct_init(cts, ctype_rawchild(cts, df), 707 dp+df->size, o, len, ip); 708 if ((d->info & CTF_UNION)) break; 709 } /* Ignore all other entries in the chain. */ 710 } 711 } 712 713 /* Initialize a struct/union with TValues. */ 714 static void cconv_struct_init(CTState *cts, CType *d, CTSize sz, uint8_t *dp, 715 TValue *o, MSize len) 716 { 717 MSize i = 0; 718 memset(dp, 0, sz); /* Much simpler to clear the struct first. */ 719 cconv_substruct_init(cts, d, dp, o, len, &i); 720 if (i < len) 721 cconv_err_initov(cts, d); 722 } 723 724 /* Check whether to use a multi-value initializer. 725 ** This is true if an aggregate is to be initialized with a value. 726 ** Valarrays are treated as values here so ct_tv handles (V|C, I|F). 727 */ 728 int lj_cconv_multi_init(CTState *cts, CType *d, TValue *o) 729 { 730 if (!(ctype_isrefarray(d->info) || ctype_isstruct(d->info))) 731 return 0; /* Destination is not an aggregate. */ 732 if (tvistab(o) || (tvisstr(o) && !ctype_isstruct(d->info))) 733 return 0; /* Initializer is not a value. */ 734 if (tviscdata(o) && lj_ctype_rawref(cts, cdataV(o)->ctypeid) == d) 735 return 0; /* Source and destination are identical aggregates. */ 736 return 1; /* Otherwise the initializer is a value. */ 737 } 738 739 /* Initialize C type with TValues. Caveat: expects to get the raw CType! */ 740 void lj_cconv_ct_init(CTState *cts, CType *d, CTSize sz, 741 uint8_t *dp, TValue *o, MSize len) 742 { 743 if (len == 0) 744 memset(dp, 0, sz); 745 else if (len == 1 && !lj_cconv_multi_init(cts, d, o)) 746 lj_cconv_ct_tv(cts, d, dp, o, 0); 747 else if (ctype_isarray(d->info)) /* Also handles valarray init with len>1. */ 748 cconv_array_init(cts, d, sz, dp, o, len); 749 else if (ctype_isstruct(d->info)) 750 cconv_struct_init(cts, d, sz, dp, o, len); 751 else 752 cconv_err_initov(cts, d); 753 } 754 755 #endif