diff options
-rw-r--r-- | doc/ext_ffi_semantics.html | 12 | ||||
-rw-r--r-- | src/lj_opt_mem.c | 36 |
2 files changed, 29 insertions, 19 deletions
diff --git a/doc/ext_ffi_semantics.html b/doc/ext_ffi_semantics.html index afe7e613..56b3f62e 100644 --- a/doc/ext_ffi_semantics.html +++ b/doc/ext_ffi_semantics.html | |||
@@ -192,8 +192,8 @@ a <tt>typedef</tt>, except re-declarations will be ignored): | |||
192 | 192 | ||
193 | </ul> | 193 | </ul> |
194 | <p> | 194 | <p> |
195 | You're encouraged to use these types in preference to the | 195 | You're encouraged to use these types in preference to |
196 | compiler-specific extensions or the target-dependent standard types. | 196 | compiler-specific extensions or target-dependent standard types. |
197 | E.g. <tt>char</tt> differs in signedness and <tt>long</tt> differs in | 197 | E.g. <tt>char</tt> differs in signedness and <tt>long</tt> differs in |
198 | size, depending on the target architecture and platform ABI. | 198 | size, depending on the target architecture and platform ABI. |
199 | </p> | 199 | </p> |
@@ -660,12 +660,18 @@ initialization. The JIT compiler benefits from this fact when applying | |||
660 | certain optimizations. | 660 | certain optimizations. |
661 | </p> | 661 | </p> |
662 | <p> | 662 | <p> |
663 | As a consequence of this, the <em>elements</em> of complex numbers and | 663 | As a consequence, the <em>elements</em> of complex numbers and |
664 | vectors are immutable. But the elements of an aggregate holding these | 664 | vectors are immutable. But the elements of an aggregate holding these |
665 | types <em>may</em> be modified of course. I.e. you cannot assign to | 665 | types <em>may</em> be modified of course. I.e. you cannot assign to |
666 | <tt>foo.c.im</tt>, but you can assign a (newly created) complex number | 666 | <tt>foo.c.im</tt>, but you can assign a (newly created) complex number |
667 | to <tt>foo.c</tt>. | 667 | to <tt>foo.c</tt>. |
668 | </p> | 668 | </p> |
669 | <p> | ||
670 | The JIT compiler implements strict aliasing rules: accesses to different | ||
671 | types do <b>not</b> alias, except for differences in signedness (this | ||
672 | applies even to <tt>char</tt> pointers, unlike C99). Type punning | ||
673 | through unions is explicitly detected and allowed. | ||
674 | </p> | ||
669 | 675 | ||
670 | <h3 id="cdata_call">Calling a cdata object</h3> | 676 | <h3 id="cdata_call">Calling a cdata object</h3> |
671 | <ul> | 677 | <ul> |
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; |