diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lj_crecord.c | 62 |
1 files changed, 53 insertions, 9 deletions
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 95c32222..d4dc9ef9 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c | |||
| @@ -113,7 +113,32 @@ static IRType crec_ct2irt(CType *ct) | |||
| 113 | return IRT_CDATA; | 113 | return IRT_CDATA; |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | static void crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp) | 116 | /* Determine whether a passed number or cdata number is non-zero. */ |
| 117 | static int crec_isnonzero(CType *s, void *p) | ||
| 118 | { | ||
| 119 | if (p == (void *)0) | ||
| 120 | return 0; | ||
| 121 | if (p == (void *)1) | ||
| 122 | return 1; | ||
| 123 | if ((s->info & CTF_FP)) { | ||
| 124 | if (s->size == sizeof(float)) | ||
| 125 | return (*(float *)p != 0); | ||
| 126 | else | ||
| 127 | return (*(double *)p != 0); | ||
| 128 | } else { | ||
| 129 | if (s->size == 1) | ||
| 130 | return (*(uint8_t *)p != 0); | ||
| 131 | else if (s->size == 2) | ||
| 132 | return (*(uint16_t *)p != 0); | ||
| 133 | else if (s->size == 4) | ||
| 134 | return (*(uint32_t *)p != 0); | ||
| 135 | else | ||
| 136 | return (*(uint64_t *)p != 0); | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | static void crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp, | ||
| 141 | void *svisnz) | ||
| 117 | { | 142 | { |
| 118 | CTSize dsize = d->size, ssize = s->size; | 143 | CTSize dsize = d->size, ssize = s->size; |
| 119 | CTInfo dinfo = d->info, sinfo = s->info; | 144 | CTInfo dinfo = d->info, sinfo = s->info; |
| @@ -134,7 +159,16 @@ static void crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp) | |||
| 134 | goto xstore; /* Source operand is already normalized. */ | 159 | goto xstore; /* Source operand is already normalized. */ |
| 135 | case CCX(B, I): | 160 | case CCX(B, I): |
| 136 | case CCX(B, F): | 161 | case CCX(B, F): |
| 137 | /* NYI: specialize to the result of a comparison against 0. */ | 162 | if (st != IRT_CDATA) { |
| 163 | /* Specialize to the result of a comparison against 0. */ | ||
| 164 | TRef zero = (st == IRT_NUM || st == IRT_FLOAT) ? lj_ir_knum(J, 0) : | ||
| 165 | (st == IRT_I64 || st == IRT_U64) ? lj_ir_kint64(J, 0) : | ||
| 166 | lj_ir_kint(J, 0); | ||
| 167 | int isnz = crec_isnonzero(s, svisnz); | ||
| 168 | emitir(IRTG(isnz ? IR_NE : IR_EQ, st), sp, zero); | ||
| 169 | sp = lj_ir_kint(J, isnz); | ||
| 170 | goto xstore; | ||
| 171 | } | ||
| 138 | goto err_nyi; | 172 | goto err_nyi; |
| 139 | 173 | ||
| 140 | /* Destination is an integer. */ | 174 | /* Destination is an integer. */ |
| @@ -316,11 +350,14 @@ static void crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, TValue *sval) | |||
| 316 | { | 350 | { |
| 317 | CTState *cts = ctype_ctsG(J2G(J)); | 351 | CTState *cts = ctype_ctsG(J2G(J)); |
| 318 | CTypeID sid = CTID_P_VOID; | 352 | CTypeID sid = CTID_P_VOID; |
| 353 | void *svisnz = 0; | ||
| 319 | CType *s; | 354 | CType *s; |
| 320 | if (LJ_LIKELY(tref_isinteger(sp))) { | 355 | if (LJ_LIKELY(tref_isinteger(sp))) { |
| 321 | sid = CTID_INT32; | 356 | sid = CTID_INT32; |
| 357 | svisnz = (void *)(intptr_t)(numV(sval) != 0); | ||
| 322 | } else if (tref_isnum(sp)) { | 358 | } else if (tref_isnum(sp)) { |
| 323 | sid = CTID_DOUBLE; | 359 | sid = CTID_DOUBLE; |
| 360 | svisnz = (void *)(intptr_t)(numV(sval) != 0); | ||
| 324 | } else if (tref_isbool(sp)) { | 361 | } else if (tref_isbool(sp)) { |
| 325 | sp = lj_ir_kint(J, tref_istrue(sp) ? 1 : 0); | 362 | sp = lj_ir_kint(J, tref_istrue(sp) ? 1 : 0); |
| 326 | sid = CTID_BOOL; | 363 | sid = CTID_BOOL; |
| @@ -337,6 +374,7 @@ static void crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, TValue *sval) | |||
| 337 | emitir(IRTG(IR_EQ, IRT_STR), sp, lj_ir_kstr(J, str)); | 374 | emitir(IRTG(IR_EQ, IRT_STR), sp, lj_ir_kstr(J, str)); |
| 338 | if (cct && ctype_isconstval(cct->info)) { | 375 | if (cct && ctype_isconstval(cct->info)) { |
| 339 | lua_assert(ctype_child(cts, cct)->size == 4); | 376 | lua_assert(ctype_child(cts, cct)->size == 4); |
| 377 | svisnz = (void *)(intptr_t)(cct->size != 0); | ||
| 340 | sp = lj_ir_kint(J, (int32_t)cct->size); | 378 | sp = lj_ir_kint(J, (int32_t)cct->size); |
| 341 | sid = ctype_cid(cct->info); | 379 | sid = ctype_cid(cct->info); |
| 342 | } /* else: interpreter will throw. */ | 380 | } /* else: interpreter will throw. */ |
| @@ -346,16 +384,19 @@ static void crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, TValue *sval) | |||
| 346 | sp = emitir(IRT(IR_STRREF, IRT_P32), sp, lj_ir_kint(J, 0)); | 384 | sp = emitir(IRT(IR_STRREF, IRT_P32), sp, lj_ir_kint(J, 0)); |
| 347 | sid = CTID_A_CCHAR; | 385 | sid = CTID_A_CCHAR; |
| 348 | } | 386 | } |
| 349 | } else { /* NYI: tref_isstr(sp), tref_istab(sp), tref_islightud(sp). */ | 387 | } else { /* NYI: tref_istab(sp), tref_islightud(sp). */ |
| 350 | sid = argv2cdata(J, sp, sval)->typeid; | 388 | sid = argv2cdata(J, sp, sval)->typeid; |
| 351 | s = ctype_raw(cts, sid); | 389 | s = ctype_raw(cts, sid); |
| 390 | svisnz = cdataptr(cdataV(sval)); | ||
| 352 | if (ctype_isptr(s->info)) { | 391 | if (ctype_isptr(s->info)) { |
| 353 | IRType t = (LJ_64 && s->size == 8) ? IRT_P64 : IRT_P32; | 392 | IRType t = (LJ_64 && s->size == 8) ? IRT_P64 : IRT_P32; |
| 354 | sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_PTR); | 393 | sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_PTR); |
| 355 | if (ctype_isref(s->info)) | 394 | if (ctype_isref(s->info)) { |
| 395 | svisnz = *(void **)svisnz; | ||
| 356 | s = ctype_rawchild(cts, s); | 396 | s = ctype_rawchild(cts, s); |
| 357 | else | 397 | } else { |
| 358 | goto doconv; /* The pointer value was loaded, don't load number. */ | 398 | goto doconv; /* The pointer value was loaded, don't load number. */ |
| 399 | } | ||
| 359 | } else { | 400 | } else { |
| 360 | sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCcdata))); | 401 | sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCcdata))); |
| 361 | } | 402 | } |
| @@ -369,7 +410,7 @@ static void crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, TValue *sval) | |||
| 369 | s = ctype_get(cts, sid); | 410 | s = ctype_get(cts, sid); |
| 370 | doconv: | 411 | doconv: |
| 371 | if (ctype_isenum(d->info)) d = ctype_child(cts, d); | 412 | if (ctype_isenum(d->info)) d = ctype_child(cts, d); |
| 372 | crec_ct_ct(J, d, s, dp, sp); | 413 | crec_ct_ct(J, d, s, dp, sp, svisnz); |
| 373 | } | 414 | } |
| 374 | 415 | ||
| 375 | /* -- C data metamethods -------------------------------------------------- */ | 416 | /* -- C data metamethods -------------------------------------------------- */ |
| @@ -529,8 +570,10 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
| 529 | CType *dc = ctype_rawchild(cts, d); /* Array element type. */ | 570 | CType *dc = ctype_rawchild(cts, d); /* Array element type. */ |
| 530 | CTSize ofs, esize = dc->size; | 571 | CTSize ofs, esize = dc->size; |
| 531 | TRef sp = 0; | 572 | TRef sp = 0; |
| 532 | TValue *sval = NULL; | 573 | TValue tv; |
| 574 | TValue *sval = &tv; | ||
| 533 | MSize i; | 575 | MSize i; |
| 576 | setnumV(&tv, 0); | ||
| 534 | if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info))) | 577 | if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info))) |
| 535 | lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init array of aggregates. */ | 578 | lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init array of aggregates. */ |
| 536 | for (i = 1, ofs = 0; ofs < sz; ofs += esize) { | 579 | for (i = 1, ofs = 0; ofs < sz; ofs += esize) { |
| @@ -554,7 +597,9 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
| 554 | if (ctype_isfield(df->info)) { | 597 | if (ctype_isfield(df->info)) { |
| 555 | CType *dc; | 598 | CType *dc; |
| 556 | TRef sp, dp; | 599 | TRef sp, dp; |
| 557 | TValue *sval; | 600 | TValue tv; |
| 601 | TValue *sval = &tv; | ||
| 602 | setnumV(&tv, 0); | ||
| 558 | if (!gcref(df->name)) continue; /* Ignore unnamed fields. */ | 603 | if (!gcref(df->name)) continue; /* Ignore unnamed fields. */ |
| 559 | dc = ctype_rawchild(cts, df); /* Field type. */ | 604 | dc = ctype_rawchild(cts, df); /* Field type. */ |
| 560 | if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info))) | 605 | if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info))) |
| @@ -565,7 +610,6 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
| 565 | i++; | 610 | i++; |
| 566 | } else { | 611 | } else { |
| 567 | sp = ctype_isnum(dc->info) ? lj_ir_kint(J, 0) : TREF_NIL; | 612 | sp = ctype_isnum(dc->info) ? lj_ir_kint(J, 0) : TREF_NIL; |
| 568 | sval = NULL; | ||
| 569 | } | 613 | } |
| 570 | dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, | 614 | dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, |
| 571 | lj_ir_kintp(J, df->size + sizeof(GCcdata))); | 615 | lj_ir_kintp(J, df->size + sizeof(GCcdata))); |
