[Tarantool-patches] [PATCH luajit] FFI: Fix recording of union initialization.

Maxim Kokryashkin m.kokryashkin at tarantool.org
Fri Jul 14 17:57:05 MSK 2023


Hi!
Thanks for the review!
Added a comment with the test description, the branch is force-pushed.
Here is the diff for the test description:
==============================================
diff --git a/test/tarantool-tests/lj-128-fix-union-init.test.lua b/test/tarantool-tests/lj-128-fix-union-init.test.lua
index 6a49cec8..65ba0f28 100644
--- a/test/tarantool-tests/lj-128-fix-union-init.test.lua
+++ b/test/tarantool-tests/lj-128-fix-union-init.test.lua
@@ -10,6 +10,46 @@ test:plan(NITERATIONS)
 local ffi = require('ffi')
 local union_type = ffi.typeof('union { uint32_t u; float f; }')
 
+-- Before the patch, the `union_type` call resulted in the
+-- initialization of both the integer and the float members
+-- of the union, leading to undefined behavior since the
+-- integer member was overwritten.
+-- The IR was the following:
+--
+-- 0031 ------ LOOP ------------
+-- 0032    u8  XLOAD  [0x100684521]  V
+-- 0033    int BAND   0032  +12
+-- 0034 >  int EQ     0033  +0
+-- 0035 >  cdt CNEW   +96
+-- 0036    p64 ADD    0035  +16
+-- 0037    u32 XSTORE 0036  0029 <--- `u` member init
+-- 0038    flt XSTORE 0036  0022 <--- `f` member init
+-- 0039    u32 XLOAD  0036
+-- 0040    num CONV   0039  num.u32
+-- 0041    num CONV   0029  num.int
+-- 0042 >  num EQ     0041  0040
+-- 0043  + int ADD    0029  +1
+-- 0044 >  int LE     0043  0001
+-- 0045    int PHI    0029  0043
+--
+-- After the patch, the initialization is performed only
+-- for the first member of the union, so now IR looks
+-- like this:
+-- 0029 ------ LOOP ------------
+-- 0030    u8  XLOAD  [0x1047c4521]  V
+-- 0031    int BAND   0030  +12
+-- 0032 >  int EQ     0031  +0
+-- 0033 }  cdt CNEW   +96
+-- 0034    p64 ADD    0033  +16
+-- 0035 }  u32 XSTORE 0034  0027 <--- `u` member init
+-- 0036    u32 CONV   0027  u32.int
+-- 0037    num CONV   0036  num.u32
+-- 0038    num CONV   0027  num.int
+-- 0039 >  num EQ     0038  0037
+-- 0040  + int ADD    0027  +1
+-- 0041 >  int LE     0040  0001
+-- 0042    int PHI    0027  0040
+
 jit.opt.start('hotloop=1')
 for i = 1, NITERATIONS do
   test:ok(union_type(i).u == i)
==============================================
--
Best regards,
Maxim Kokryashkin
 
 
> 
>>Hi, Max!
>>
>>
>>thanks for the patch!
>>
>>See my comments inline.
>>
>>
>>Sergey
>>
>>On 7/10/23 18:56, Maksim Kokryashkin wrote:
>>> From: Mike Pall <mike>
>>>
>>> Thanks to Alex Shpilkin.
>>>
>>> (cherry-picked from commit 56c04accf975bff2519c34721dccbbdb7b8e6963)
>>>
>>> As stated here[1], only the first field of a union can be
>>> initialized with a flat initializer. However, before this
>>> patch, on-trace initialization instructions were emitted
>>> for other union members too, overwriting the previous
>>> initialization values.
>>>
>>> This patch fixes the mentioned behavior by preventing
>>> initialization of members other than the first one.
>>>
>>> [1]:  https://luajit.org/ext_ffi_semantics.html#init
>>>
>>> Maxim Kokryashkin:
>>> * added the description and the test for the problem
>>>
>>> Part of tarantool/tarantool#8825
>>> ---
>>> Branch:  https://github.com/tarantool/luajit/tree/fckxorg/lj-128-fix-union-init
>>> PR:  https://github.com/tarantool/tarantool/pull/8867
>>> Original LuaJIT PR:  https://github.com/LuaJIT/LuaJIT/pull/650
>>>
>>> src/lj_crecord.c | 5 +++++
>>> .../lj-128-fix-union-init.test.lua | 18 ++++++++++++++++++
>>> 2 files changed, 23 insertions(+)
>>> create mode 100644 test/tarantool-tests/lj-128-fix-union-init.test.lua
>>>
>>> diff --git a/src/lj_crecord.c b/src/lj_crecord.c
>>> index 0008a865..ffe995f4 100644
>>> --- a/src/lj_crecord.c
>>> +++ b/src/lj_crecord.c
>>> @@ -1065,6 +1065,11 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
>>> dp = emitir(IRT(IR_ADD, IRT_PTR), trcd,
>>> lj_ir_kintp(J, df->size + sizeof(GCcdata)));
>>> crec_ct_tv(J, dc, dp, sp, sval);
>>> + if ((d->info & CTF_UNION)) {
>>> + if (d->size != dc->size) /* NYI: partial init of union. */
>>> + lj_trace_err(J, LJ_TRERR_NYICONV);
>>> + break;
>>> + }
>>> } else if (!ctype_isconstval(df->info)) {
>>> /* NYI: init bitfields and sub-structures. */
>>> lj_trace_err(J, LJ_TRERR_NYICONV);
>>> diff --git a/test/tarantool-tests/lj-128-fix-union-init.test.lua b/test/tarantool-tests/lj-128-fix-union-init.test.lua
>>> new file mode 100644
>>> index 00000000..6a49cec8
>>> --- /dev/null
>>> +++ b/test/tarantool-tests/lj-128-fix-union-init.test.lua
>>> @@ -0,0 +1,18 @@
>>> +local tap = require('tap')
>>> +local test = tap.test('lj-128-fix-union-init'):skipcond({
>>> + ['Test requires JIT enabled'] = not jit.status(),
>>> +})
>>> +
>>> +local NITERATIONS = 4
>>> +
>>> +test:plan(NITERATIONS)
>>> +
>>> +local ffi = require('ffi')
>>> +local union_type = ffi.typeof('union { uint32_t u; float f; }')
>>> +
>>> +jit.opt.start('hotloop=1')
>>> +for i = 1, NITERATIONS do
>>> + test:ok(union_type(i).u == i)
>>testcases description is missed, please add one.
>>> +end
>>> +
>>> +os.exit(test:check() and 0 or 1)
> 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.tarantool.org/pipermail/tarantool-patches/attachments/20230714/792b8ebf/attachment.htm>


More information about the Tarantool-patches mailing list