diff options
author | Mike Pall <mike> | 2012-08-27 20:52:15 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2012-08-27 20:53:37 +0200 |
commit | c7826af5a0403b48eeeb6c18532dc076146b1966 (patch) | |
tree | b5f1e86268e3e4ab49d3bb4c8044a9efd61d322f /src/lj_opt_mem.c | |
parent | 76b18b2b465532e528af2162e79365794c8ba290 (diff) | |
download | luajit-c7826af5a0403b48eeeb6c18532dc076146b1966.tar.gz luajit-c7826af5a0403b48eeeb6c18532dc076146b1966.tar.bz2 luajit-c7826af5a0403b48eeeb6c18532dc076146b1966.zip |
FFI: Detect type punning through unions.
Diffstat (limited to 'src/lj_opt_mem.c')
-rw-r--r-- | src/lj_opt_mem.c | 36 |
1 files changed, 20 insertions, 16 deletions
diff --git a/src/lj_opt_mem.c b/src/lj_opt_mem.c index a7e0d35e..560c4ade 100644 --- a/src/lj_opt_mem.c +++ b/src/lj_opt_mem.c | |||
@@ -601,17 +601,8 @@ static AliasRet aa_xref(jit_State *J, IRIns *refa, IRIns *xa, IRIns *xb) | |||
601 | ptrdiff_t ofsa = 0, ofsb = 0; | 601 | ptrdiff_t ofsa = 0, ofsb = 0; |
602 | IRIns *refb = IR(xb->op1); | 602 | IRIns *refb = IR(xb->op1); |
603 | IRIns *basea = refa, *baseb = refb; | 603 | IRIns *basea = refa, *baseb = refb; |
604 | /* This implements (very) strict aliasing rules. | 604 | if (refa == refb && irt_sametype(xa->t, xb->t)) |
605 | ** Different types do NOT alias, except for differences in signedness. | 605 | return ALIAS_MUST; /* Shortcut for same refs with identical type. */ |
606 | ** NYI: this also prevents type punning through unions. | ||
607 | */ | ||
608 | if (irt_sametype(xa->t, xb->t)) { | ||
609 | if (refa == refb) | ||
610 | return ALIAS_MUST; /* Shortcut for same refs with identical type. */ | ||
611 | } else if (!(irt_typerange(xa->t, IRT_I8, IRT_U64) && | ||
612 | ((xa->t.irt - IRT_I8) ^ (xb->t.irt - IRT_I8)) == 1)) { | ||
613 | return ALIAS_NO; | ||
614 | } | ||
615 | /* Offset-based disambiguation. */ | 606 | /* Offset-based disambiguation. */ |
616 | if (refa->o == IR_ADD && irref_isk(refa->op2)) { | 607 | if (refa->o == IR_ADD && irref_isk(refa->op2)) { |
617 | IRIns *irk = IR(refa->op2); | 608 | IRIns *irk = IR(refa->op2); |
@@ -629,12 +620,25 @@ static AliasRet aa_xref(jit_State *J, IRIns *refa, IRIns *xa, IRIns *xb) | |||
629 | if (refa == baseb && ofsb != 0) | 620 | if (refa == baseb && ofsb != 0) |
630 | return ALIAS_NO; /* base vs. base+-ofs. */ | 621 | return ALIAS_NO; /* base vs. base+-ofs. */ |
631 | } | 622 | } |
623 | /* This implements (very) strict aliasing rules. | ||
624 | ** Different types do NOT alias, except for differences in signedness. | ||
625 | ** Type punning through unions is allowed (but forces a reload). | ||
626 | */ | ||
632 | if (basea == baseb) { | 627 | if (basea == baseb) { |
633 | /* This assumes strictly-typed, non-overlapping accesses. */ | 628 | ptrdiff_t sza = irt_size(xa->t), szb = irt_size(xb->t); |
634 | if (ofsa != ofsb) | 629 | if (ofsa == ofsb) { |
635 | return ALIAS_NO; /* base+-o1 vs. base+-o2 and o1 != o2. */ | 630 | if (sza == szb && irt_isfp(xa->t) == irt_isfp(xb->t)) |
636 | return ALIAS_MUST; /* Unsigned vs. signed access to the same address. */ | 631 | return ALIAS_MUST; /* Same-sized, same-kind. May need to convert. */ |
632 | } else if (ofsa + sza <= ofsb || ofsb + szb <= ofsa) { | ||
633 | return ALIAS_NO; /* Non-overlapping base+-o1 vs. base+-o2. */ | ||
634 | } | ||
635 | /* NYI: extract, extend or reinterpret bits (int <-> fp). */ | ||
636 | return ALIAS_MAY; /* Overlapping or type punning: force reload. */ | ||
637 | } | 637 | } |
638 | if (!irt_sametype(xa->t, xb->t) && | ||
639 | !(irt_typerange(xa->t, IRT_I8, IRT_U64) && | ||
640 | ((xa->t.irt - IRT_I8) ^ (xb->t.irt - IRT_I8)) == 1)) | ||
641 | return ALIAS_NO; | ||
638 | /* NYI: structural disambiguation. */ | 642 | /* NYI: structural disambiguation. */ |
639 | return aa_cnew(J, basea, baseb); /* Try to disambiguate allocations. */ | 643 | return aa_cnew(J, basea, baseb); /* Try to disambiguate allocations. */ |
640 | } | 644 | } |
@@ -730,7 +734,7 @@ retry: | |||
730 | if (st == IRT_I8 || st == IRT_I16) { /* Trunc + sign-extend. */ | 734 | if (st == IRT_I8 || st == IRT_I16) { /* Trunc + sign-extend. */ |
731 | st |= IRCONV_SEXT; | 735 | st |= IRCONV_SEXT; |
732 | } else if (st == IRT_U8 || st == IRT_U16) { /* Trunc + zero-extend. */ | 736 | } else if (st == IRT_U8 || st == IRT_U16) { /* Trunc + zero-extend. */ |
733 | } else if (st == IRT_INT && !irt_isint(IR(store->op2)->t)) { | 737 | } else if (st == IRT_INT) { |
734 | st = irt_type(IR(store->op2)->t); /* Needs dummy CONV.int.*. */ | 738 | st = irt_type(IR(store->op2)->t); /* Needs dummy CONV.int.*. */ |
735 | } else { /* I64/U64 are boxed, U32 is hidden behind a CONV.num.u32. */ | 739 | } else { /* I64/U64 are boxed, U32 is hidden behind a CONV.num.u32. */ |
736 | goto store_fwd; | 740 | goto store_fwd; |