Skip to content

Commit

Permalink
FFI: Fix recording of union initialization.
Browse files Browse the repository at this point in the history
Thanks to Alex Shpilkin.

(cherry-picked from commit 56c04ac)

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
  • Loading branch information
Mike Pall authored and mkokryashkin committed Jul 10, 2023
1 parent 8e46d60 commit 0656e3e
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/lj_crecord.c
Expand Up @@ -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);
Expand Down
18 changes: 18 additions & 0 deletions 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)
end

os.exit(test:check() and 0 or 1)

0 comments on commit 0656e3e

Please sign in to comment.