aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/ext_ffi_semantics.html12
-rw-r--r--src/lj_opt_mem.c36
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>
195You're encouraged to use these types in preference to the 195You're encouraged to use these types in preference to
196compiler-specific extensions or the target-dependent standard types. 196compiler-specific extensions or target-dependent standard types.
197E.g. <tt>char</tt> differs in signedness and <tt>long</tt> differs in 197E.g. <tt>char</tt> differs in signedness and <tt>long</tt> differs in
198size, depending on the target architecture and platform ABI. 198size, 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
660certain optimizations. 660certain optimizations.
661</p> 661</p>
662<p> 662<p>
663As a consequence of this, the <em>elements</em> of complex numbers and 663As a consequence, the <em>elements</em> of complex numbers and
664vectors are immutable. But the elements of an aggregate holding these 664vectors are immutable. But the elements of an aggregate holding these
665types <em>may</em> be modified of course. I.e. you cannot assign to 665types <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
667to <tt>foo.c</tt>. 667to <tt>foo.c</tt>.
668</p> 668</p>
669<p>
670The JIT compiler implements strict aliasing rules: accesses to different
671types do <b>not</b> alias, except for differences in signedness (this
672applies even to <tt>char</tt> pointers, unlike C99). Type punning
673through 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;