Git Product home page Git Product logo

luavela's Introduction

README for LuaVela (codename uJIT)

testing-badge lint-badge docs-badge

LuaVela is an interpreter and a Just-In-Time (JIT) compiler for the Lua programming language.

Project Homepage: https://github.com/luavela/luavela

LuaVela is Copyright (C) 2020-2024 LuaVela Authors. See Copyright Notice in COPYRIGHT

LuaVela was previously called "uJIT" internally. The developers of LuaVela use "uJIT", "ujit" and "uj"/"UJ" prefixes in a code base.

The team has given a number of talks (in English or Russian) about the project:

LuaVela is a fork of LuaJIT, the README for LuaJIT is below.

README for LuaJIT 2.0.5

LuaJIT is a Just-In-Time (JIT) compiler for the Lua programming language.

Project Homepage: http://luajit.org/

LuaJIT is Copyright (C) 2005-2017 Mike Pall. LuaJIT is free software, released under the MIT license. See full Copyright Notice in the COPYRIGHT file or in luajit.h.

Documentation for LuaJIT is available in HTML format. Please point your favorite browser to:

doc/luajit.html

luavela's People

Contributors

einsamhauer avatar eliasdaler avatar igelhaus avatar igormunkin avatar keeprocking avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

luavela's Issues

Fully Static Build (Migrating from LuaJIT to uJIT)

Hi there.

I'm currently using Openresty's LuaJIT2.1 fork as the basis for my program. My build involves a slight modification to LuaJIT to enable fully static builds (disabling dlopen and dlsym).

Here's the build command used on the original repo:

make -j \
    STATIC_CC="cc" \
    CCOPT="-static -fPIC -DLJ_TARGET_DLOPEN=0 -fomit-frame-pointer -Os" \
    BUILDMODE="static" \
    PREFIX="$(pwd)/dbin"

And a small patch to make LJ_TARGET_DLOPEN=0 stick on POSIX/Linux:

// in lj_arch.h, commenting out the following line:
// #define LJ_TARGET_DLOPEN    LJ_TARGET_POSIX

This will produce a static CLI, as well as the required ./dbin/lib/libluajit-5.1.a. Linking that static library will now no longer require ldl, which was the intention. The FFI is still used, but by passing a calltable struct between the C main program and Lua-land (https://www.freelists.org/post/luajit/How-to-call-functions-from-a-static-library-in-Luajit,8). FFI.C.* and FFI.load() (which depend on dlsym) are disabled.

Now I wanted to investigate uJIT as an alternative because I want to make use of the better profiling and mutability features. However, I'm having a hard time even getting a static build from the default config. Building with:

cmake .. -DCMAKE_BUILD_TYPE=Release
make ...

Gives me a dynamic CLI and only a shared library libujit.so. How do I configure the build to be static (reproducing the other CFLAGS from my original LuaJIT make command would be nice, too)?

Missing dependency on `libdl`

When linking against LuaVela using its pkg-config, I get this:

/usr/bin/ld: /home/seny/local/lib/libujit.so: undefined reference to `dlopen'
/usr/bin/ld: /home/seny/local/lib/libujit.so: undefined reference to `dlclose'
/usr/bin/ld: /home/seny/local/lib/libujit.so: undefined reference to `dlerror'
/usr/bin/ld: /home/seny/local/lib/libujit.so: undefined reference to `dlsym'

Checking dependencies via ldd reveals a missing dependency on libdl:

$ ldd libujit.so
	linux-vdso.so.1 (0x00007fff8f1fd000)
	libm.so.6 => /usr/lib/libm.so.6 (0x00007fea4b4e2000)
	libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fea4b4c1000)
	librt.so.1 => /usr/lib/librt.so.1 (0x00007fea4b4b6000)
	libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007fea4b49c000)
	libc.so.6 => /usr/lib/libc.so.6 (0x00007fea4b2d9000)
	/usr/lib64/ld-linux-x86-64.so.2 (0x00007fea4b7b6000)

For example, Lua 5.1 has it:

$ ldd /usr/lib/liblua5.1.so
	linux-vdso.so.1 (0x00007ffe36ffa000)
	libdl.so.2 => /usr/lib/libdl.so.2 (0x00007ff63e868000)
	libm.so.6 => /usr/lib/libm.so.6 (0x00007ff63e722000)
	libc.so.6 => /usr/lib/libc.so.6 (0x00007ff63e55f000)
	/usr/lib64/ld-linux-x86-64.so.2 (0x00007ff63e8bf000)

Fix `clang-analyzer-core.UndefinedBinaryOperatorResult` warnings

As a result of updating clang-tidy up to version 11, new check clang-analyzer-core.UndefinedBinaryOperatorResult produced several warnings.

/luavela/src/jit/lj_record.c:921:7: error: The left operand of '&' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult,-warnings-as-errors]
  if (tref_istab(ix->tab)) {
      ^
/luavela/src/jit/lj_ir.h:485:34: note: expanded from macro 'tref_istab'
#define tref_istab(tr)          (tref_istype((tr), IRT_TAB))   
                                 ^
/luavela/src/jit/lj_ir.h:478:40: note: expanded from macro 'tref_istype'
#define tref_istype(tr, t)      (((tr) & (IRT_TYPE<<24)) == ((t)<<24))
                                       ^
/luavela/src/jit/lj_record.c:1763:19: note: Assuming field 'postproc' is equal to LJ_POST_NONE
  if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) {
                  ^
/luavela/src/lj_def.h:87:45: note: expanded from macro 'LJ_UNLIKELY'
#define LJ_UNLIKELY(x)  __builtin_expect(!!(x), 0)
                                            ^
/luavela/src/jit/lj_record.c:1763:3: note: Taking false branch
  if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) {
  ^
/luavela/src/jit/lj_record.c:1835:7: note: Assuming field 'needsnap' is 0
  if (J->needsnap) {
      ^
/luavela/src/jit/lj_record.c:1835:3: note: Taking false branch
  if (J->needsnap) {
  ^
/luavela/src/jit/lj_record.c:1843:19: note: Assuming field 'bcskip' is <= 0
  if (LJ_UNLIKELY(J->bcskip > 0)) {
                  ^
/luavela/src/lj_def.h:87:45: note: expanded from macro 'LJ_UNLIKELY'
#define LJ_UNLIKELY(x)  __builtin_expect(!!(x), 0)
                                            ^
/luavela/src/jit/lj_record.c:1843:3: note: Taking false branch
  if (LJ_UNLIKELY(J->bcskip > 0)) {
  ^
/luavela/src/jit/lj_record.c:1850:7: note: Assuming field 'framedepth' is not equal to 0
  if (J->framedepth == 0 &&
      ^
/luavela/src/jit/lj_record.c:1850:26: note: Left side of '&&' is false
  if (J->framedepth == 0 &&
                         ^
/luavela/src/jit/lj_record.c:1869:3: note: Control jumps to the 'default' case at line 1872
  switch (bcmode_a(op)) {
  ^
/luavela/src/jit/lj_record.c:1872:12: note:  Execution continues on line 1874
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1876:3: note: Control jumps to the 'default' case at line 1880
  switch (bcmode_b(op)) {
  ^
/luavela/src/jit/lj_record.c:1880:12: note:  Execution continues on line 1882
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1882:3: note: Control jumps to the 'default' case at line 1890
  switch (bcmode_c(op)) {
  ^
/luavela/src/jit/lj_record.c:1890:12: note:  Execution continues on line 1893
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1893:3: note: Control jumps to 'case BC_POW:'  at line 2028
  switch (op) {
  ^
/luavela/src/jit/lj_record.c:2029:9: note: Assuming the condition is false
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
        ^
/luavela/src/jit/lj_ir.h:495:34: note: expanded from macro 'tref_isnumber_str'
#define tref_isnumber_str(tr)   (tref_isnumber((tr)) || tref_isstr((tr)))
                                 ^
/luavela/src/jit/lj_ir.h:494:34: note: expanded from macro 'tref_isnumber'
#define tref_isnumber(tr)       (tref_typerange((tr), IRT_NUM, IRT_U64))
                                 ^
/luavela/src/jit/lj_ir.h:476:4: note: expanded from macro 'tref_typerange'
  ((((tr)>>24) & IRT_TYPE) - (TRef)(first) <= (TRef)((last) - (first)))
   ^
/luavela/src/jit/lj_record.c:2029:9: note: Left side of '||' is false
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
        ^
/luavela/src/jit/lj_ir.h:495:34: note: expanded from macro 'tref_isnumber_str'
#define tref_isnumber_str(tr)   (tref_isnumber((tr)) || tref_isstr((tr)))
                                 ^
/luavela/src/jit/lj_ir.h:494:33: note: expanded from macro 'tref_isnumber'
#define tref_isnumber(tr)       (tref_typerange((tr), IRT_NUM, IRT_U64))
                                ^
/luavela/src/jit/lj_record.c:2029:9: note: Assuming the condition is false
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
        ^
/luavela/src/jit/lj_ir.h:495:57: note: expanded from macro 'tref_isnumber_str'
#define tref_isnumber_str(tr)   (tref_isnumber((tr)) || tref_isstr((tr)))
                                                        ^
/luavela/src/jit/lj_ir.h:482:34: note: expanded from macro 'tref_isstr'
#define tref_isstr(tr)          (tref_istype((tr), IRT_STR))
                                 ^
/luavela/src/jit/lj_ir.h:478:34: note: expanded from macro 'tref_istype'
#define tref_istype(tr, t)      (((tr) & (IRT_TYPE<<24)) == ((t)<<24))
                                 ^
/luavela/src/jit/lj_record.c:2029:31: note: Left side of '&&' is false
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
                              ^
/luavela/src/jit/lj_record.c:2032:12: note: Calling 'rec_mm_arith'
      rc = rec_mm_arith(J, &ix, MM_pow);
           ^
/luavela/src/jit/lj_record.c:996:8: note: Calling 'lj_record_mm_lookup'
  if (!lj_record_mm_lookup(J, ix, mm)) {  /* Lookup mm on 1st operand. */
       ^
/luavela/src/jit/lj_record.c:921:7: note: The left operand of '&' is a garbage value
  if (tref_istab(ix->tab)) {
      ^
/luavela/src/jit/lj_ir.h:485:34: note: expanded from macro 'tref_istab'
#define tref_istab(tr)          (tref_istype((tr), IRT_TAB))
                                 ^
/luavela/src/jit/lj_ir.h:478:40: note: expanded from macro 'tref_istype'
#define tref_istype(tr, t)      (((tr) & (IRT_TYPE<<24)) == ((t)<<24))
                                       ^
/luavela/src/jit/lj_record.c:1927:27: error: The left operand of '==' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult,-warnings-as-errors]
        if (!lj_ir_numcmp(numV(rav), numV(rcv), (IROp)irop))
                          ^
/luavela/src/lj_obj.h:798:35: note: expanded from macro 'numV'
#define numV(o)         lua_check(tvisnum(o), (o)->n)
                                  ^
/luavela/src/lj_obj.h:773:36: note: expanded from macro 'tvisnum'
#define tvisnum(o)      (gettag(o) == LJ_TNUMX)
                                   ^
/luavela/src/lj_def.h:144:37: note: expanded from macro 'lua_check'
#define lua_check(c, e) (lua_assert(c), (e))
                                    ^
/luavela/src/luaconf.h:25:36: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                                   ^
/usr/include/assert.h:98:7: note: expanded from macro 'assert'
    ((expr)                                                             \
      ^
/luavela/src/jit/lj_record.c:1763:19: note: Assuming field 'postproc' is equal to LJ_POST_NONE
  if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) {
                  ^
/luavela/src/lj_def.h:87:45: note: expanded from macro 'LJ_UNLIKELY'
#define LJ_UNLIKELY(x)  __builtin_expect(!!(x), 0)
                                            ^
/luavela/src/jit/lj_record.c:1763:3: note: Taking false branch
  if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) {
  ^
/luavela/src/jit/lj_record.c:1835:7: note: Assuming field 'needsnap' is 0
  if (J->needsnap) {
      ^
/luavela/src/jit/lj_record.c:1835:3: note: Taking false branch
  if (J->needsnap) {
  ^
/luavela/src/jit/lj_record.c:1843:19: note: Assuming field 'bcskip' is <= 0
  if (LJ_UNLIKELY(J->bcskip > 0)) {
                  ^
/luavela/src/lj_def.h:87:45: note: expanded from macro 'LJ_UNLIKELY'
#define LJ_UNLIKELY(x)  __builtin_expect(!!(x), 0)
                                            ^
/luavela/src/jit/lj_record.c:1843:3: note: Taking false branch
  if (LJ_UNLIKELY(J->bcskip > 0)) {
  ^
/luavela/src/jit/lj_record.c:1850:7: note: Assuming field 'framedepth' is not equal to 0
  if (J->framedepth == 0 &&
      ^
/luavela/src/jit/lj_record.c:1850:26: note: Left side of '&&' is false
  if (J->framedepth == 0 &&
                         ^
/luavela/src/jit/lj_record.c:1869:3: note: Control jumps to the 'default' case at line 1872
  switch (bcmode_a(op)) {
  ^
/luavela/src/jit/lj_record.c:1872:12: note:  Execution continues on line 1874
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1876:3: note: Control jumps to the 'default' case at line 1880
  switch (bcmode_b(op)) {
  ^
/luavela/src/jit/lj_record.c:1880:12: note:  Execution continues on line 1882
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1882:3: note: Control jumps to the 'default' case at line 1890
  switch (bcmode_c(op)) {
  ^
/luavela/src/jit/lj_record.c:1890:12: note:  Execution continues on line 1893
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1893:3: note: Control jumps to 'case BC_ISLT:'  at line 1897
  switch (op) {
  ^
/luavela/src/jit/lj_record.c:1899:9: note: Left side of '||' is false
    if (tref_iscdata(ra) || tref_iscdata(rc)) {
        ^
/luavela/src/jit/lj_ir.h:484:33: note: expanded from macro 'tref_iscdata'
#define tref_iscdata(tr)        (tref_istype((tr), IRT_CDATA))
                                ^
/luavela/src/jit/lj_record.c:1899:5: note: Taking false branch
    if (tref_iscdata(ra) || tref_iscdata(rc)) {
    ^
/luavela/src/jit/lj_record.c:1905:11: note: Assuming the condition is false
    if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) {
          ^
/luavela/src/jit/lj_ir.h:499:34: note: expanded from macro 'tref_isk2'
#define tref_isk2(tr1, tr2)     (irref_isk(tref_ref((tr1) | (tr2))))
                                 ^
/luavela/src/jit/lj_ir.h:452:34: note: expanded from macro 'irref_isk'
#define irref_isk(ref)          ((ref) < REF_BIAS)
                                 ^
/luavela/src/jit/lj_record.c:1905:28: note: Left side of '&&' is false
    if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) {
                           ^
/luavela/src/jit/lj_record.c:1905:5: note: Taking true branch
    if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) {
    ^
/luavela/src/jit/lj_record.c:1906:19: note: Assuming the condition is false
      IRType ta = tref_isinteger(ra) ? IRT_INT : tref_type(ra);
                  ^
/luavela/src/jit/lj_ir.h:493:34: note: expanded from macro 'tref_isinteger'
#define tref_isinteger(tr)      (tref_typerange((tr), IRT_I8, IRT_INT))
                                 ^
/luavela/src/jit/lj_ir.h:476:4: note: expanded from macro 'tref_typerange'
  ((((tr)>>24) & IRT_TYPE) - (TRef)(first) <= (TRef)((last) - (first)))
   ^
/luavela/src/jit/lj_record.c:1906:19: note: '?' condition is false
      IRType ta = tref_isinteger(ra) ? IRT_INT : tref_type(ra);
                  ^
/luavela/src/jit/lj_ir.h:493:33: note: expanded from macro 'tref_isinteger'
#define tref_isinteger(tr)      (tref_typerange((tr), IRT_I8, IRT_INT))
                                ^
/luavela/src/jit/lj_record.c:1907:19: note: Assuming the condition is false
      IRType tc = tref_isinteger(rc) ? IRT_INT : tref_type(rc);
                  ^
/luavela/src/jit/lj_ir.h:493:34: note: expanded from macro 'tref_isinteger'
#define tref_isinteger(tr)      (tref_typerange((tr), IRT_I8, IRT_INT))
                                 ^
/luavela/src/jit/lj_ir.h:476:4: note: expanded from macro 'tref_typerange'
  ((((tr)>>24) & IRT_TYPE) - (TRef)(first) <= (TRef)((last) - (first)))
   ^
/luavela/src/jit/lj_record.c:1907:19: note: '?' condition is false
      IRType tc = tref_isinteger(rc) ? IRT_INT : tref_type(rc);
                  ^
/luavela/src/jit/lj_ir.h:493:33: note: expanded from macro 'tref_isinteger'
#define tref_isinteger(tr)      (tref_typerange((tr), IRT_I8, IRT_INT))
                                ^
/luavela/src/jit/lj_record.c:1909:11: note: Assuming 'ta' is equal to 'tc'
      if (ta != tc) {
          ^
/luavela/src/jit/lj_record.c:1909:7: note: Taking false branch
      if (ta != tc) {
      ^
/luavela/src/jit/lj_record.c:1925:11: note: Assuming 'ta' is equal to IRT_NUM
      if (ta == IRT_NUM) {
          ^
/luavela/src/jit/lj_record.c:1925:7: note: Taking true branch
      if (ta == IRT_NUM) {
      ^
/luavela/src/jit/lj_record.c:1926:9: note: Taking false branch
        if ((irop & 1)) irop ^= 4;  /* ISGE/ISGT are unordered. */
        ^
/luavela/src/jit/lj_record.c:1927:27: note: The left operand of '==' is a garbage value
        if (!lj_ir_numcmp(numV(rav), numV(rcv), (IROp)irop))
                          ^
/luavela/src/lj_obj.h:798:35: note: expanded from macro 'numV'
#define numV(o)         lua_check(tvisnum(o), (o)->n)
                                  ^
/luavela/src/lj_obj.h:773:36: note: expanded from macro 'tvisnum'
#define tvisnum(o)      (gettag(o) == LJ_TNUMX)
                                   ^
/luavela/src/lj_def.h:144:37: note: expanded from macro 'lua_check'
#define lua_check(c, e) (lua_assert(c), (e))
                                    ^
/luavela/src/luaconf.h:25:36: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                                   ^
/usr/include/assert.h:98:7: note: expanded from macro 'assert'
    ((expr)                                                             \
      ^
/luavela/src/jit/lj_record.c:1933:27: error: The left operand of '==' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult,-warnings-as-errors]
        if (!lj_ir_strcmp(strV(rav), strV(rcv), (IROp)irop)) irop ^= 1;
                          ^
/luavela/src/lj_obj.h:791:35: note: expanded from macro 'strV'
#define strV(o)         lua_check(tvisstr(o), &gcval(o)->str)
                                  ^
/luavela/src/lj_obj.h:766:36: note: expanded from macro 'tvisstr'
#define tvisstr(o)      (gettag(o) == LJ_TSTR)
                                   ^
/luavela/src/lj_def.h:144:37: note: expanded from macro 'lua_check'
#define lua_check(c, e) (lua_assert(c), (e))
                                    ^
/luavela/src/luaconf.h:25:36: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                                   ^
/usr/include/assert.h:98:7: note: expanded from macro 'assert'
    ((expr)                                                             \
      ^
/luavela/src/jit/lj_record.c:1763:19: note: Assuming field 'postproc' is equal to LJ_POST_NONE
  if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) {
                  ^
/luavela/src/lj_def.h:87:45: note: expanded from macro 'LJ_UNLIKELY'
#define LJ_UNLIKELY(x)  __builtin_expect(!!(x), 0)
                                            ^
/luavela/src/jit/lj_record.c:1763:3: note: Taking false branch
  if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) {
  ^
/luavela/src/jit/lj_record.c:1835:7: note: Assuming field 'needsnap' is 0
  if (J->needsnap) {
      ^
/luavela/src/jit/lj_record.c:1835:3: note: Taking false branch
  if (J->needsnap) {
  ^
/luavela/src/jit/lj_record.c:1843:19: note: Assuming field 'bcskip' is <= 0
  if (LJ_UNLIKELY(J->bcskip > 0)) {
                  ^
/luavela/src/lj_def.h:87:45: note: expanded from macro 'LJ_UNLIKELY'
#define LJ_UNLIKELY(x)  __builtin_expect(!!(x), 0)
                                            ^
/luavela/src/jit/lj_record.c:1843:3: note: Taking false branch
  if (LJ_UNLIKELY(J->bcskip > 0)) {
  ^
/luavela/src/jit/lj_record.c:1850:7: note: Assuming field 'framedepth' is not equal to 0
  if (J->framedepth == 0 &&
      ^
/luavela/src/jit/lj_record.c:1850:26: note: Left side of '&&' is false
  if (J->framedepth == 0 &&
                         ^
/luavela/src/jit/lj_record.c:1869:3: note: Control jumps to the 'default' case at line 1872
  switch (bcmode_a(op)) {
  ^
/luavela/src/jit/lj_record.c:1872:12: note:  Execution continues on line 1874
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1876:3: note: Control jumps to the 'default' case at line 1880
  switch (bcmode_b(op)) {
  ^
/luavela/src/jit/lj_record.c:1880:12: note:  Execution continues on line 1882
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1882:3: note: Control jumps to the 'default' case at line 1890
  switch (bcmode_c(op)) {
  ^
/luavela/src/jit/lj_record.c:1890:12: note:  Execution continues on line 1893
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1893:3: note: Control jumps to 'case BC_ISLT:'  at line 1897
  switch (op) {
  ^
/luavela/src/jit/lj_record.c:1899:9: note: Left side of '||' is false
    if (tref_iscdata(ra) || tref_iscdata(rc)) {
        ^
/luavela/src/jit/lj_ir.h:484:33: note: expanded from macro 'tref_iscdata'
#define tref_iscdata(tr)        (tref_istype((tr), IRT_CDATA))
                                ^
/luavela/src/jit/lj_record.c:1899:5: note: Taking false branch
    if (tref_iscdata(ra) || tref_iscdata(rc)) {
    ^
/luavela/src/jit/lj_record.c:1905:11: note: Assuming the condition is false
    if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) {
          ^
/luavela/src/jit/lj_ir.h:499:34: note: expanded from macro 'tref_isk2'
#define tref_isk2(tr1, tr2)     (irref_isk(tref_ref((tr1) | (tr2))))
                                 ^
/luavela/src/jit/lj_ir.h:452:34: note: expanded from macro 'irref_isk'
#define irref_isk(ref)          ((ref) < REF_BIAS)
                                 ^
/luavela/src/jit/lj_record.c:1905:28: note: Left side of '&&' is false
    if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) {
                           ^
/luavela/src/jit/lj_record.c:1905:5: note: Taking true branch
    if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) {
    ^
/luavela/src/jit/lj_record.c:1906:19: note: Assuming the condition is false
      IRType ta = tref_isinteger(ra) ? IRT_INT : tref_type(ra);
                  ^
/luavela/src/jit/lj_ir.h:493:34: note: expanded from macro 'tref_isinteger'
#define tref_isinteger(tr)      (tref_typerange((tr), IRT_I8, IRT_INT))
                                 ^
/luavela/src/jit/lj_ir.h:476:4: note: expanded from macro 'tref_typerange'
  ((((tr)>>24) & IRT_TYPE) - (TRef)(first) <= (TRef)((last) - (first)))
   ^
/luavela/src/jit/lj_record.c:1906:19: note: '?' condition is false
      IRType ta = tref_isinteger(ra) ? IRT_INT : tref_type(ra);
                  ^
/luavela/src/jit/lj_ir.h:493:33: note: expanded from macro 'tref_isinteger'
#define tref_isinteger(tr)      (tref_typerange((tr), IRT_I8, IRT_INT))
                                ^
/luavela/src/jit/lj_record.c:1907:19: note: Assuming the condition is false
      IRType tc = tref_isinteger(rc) ? IRT_INT : tref_type(rc);
                  ^
/luavela/src/jit/lj_ir.h:493:34: note: expanded from macro 'tref_isinteger'
#define tref_isinteger(tr)      (tref_typerange((tr), IRT_I8, IRT_INT))
                                 ^
/luavela/src/jit/lj_ir.h:476:4: note: expanded from macro 'tref_typerange'
  ((((tr)>>24) & IRT_TYPE) - (TRef)(first) <= (TRef)((last) - (first)))
   ^
/luavela/src/jit/lj_record.c:1907:19: note: '?' condition is false
      IRType tc = tref_isinteger(rc) ? IRT_INT : tref_type(rc);
                  ^
/luavela/src/jit/lj_ir.h:493:33: note: expanded from macro 'tref_isinteger'
#define tref_isinteger(tr)      (tref_typerange((tr), IRT_I8, IRT_INT))
                                ^
/luavela/src/jit/lj_record.c:1909:11: note: Assuming 'ta' is equal to 'tc'
      if (ta != tc) {
          ^
/luavela/src/jit/lj_record.c:1909:7: note: Taking false branch
      if (ta != tc) {
      ^
/luavela/src/jit/lj_record.c:1925:11: note: Assuming 'ta' is not equal to IRT_NUM
      if (ta == IRT_NUM) {
          ^
/luavela/src/jit/lj_record.c:1925:7: note: Taking false branch
      if (ta == IRT_NUM) {
      ^
/luavela/src/jit/lj_record.c:1929:18: note: 'ta' is not equal to IRT_INT
      } else if (ta == IRT_INT) {
                 ^
/luavela/src/jit/lj_record.c:1929:14: note: Taking false branch
      } else if (ta == IRT_INT) {
             ^
/luavela/src/jit/lj_record.c:1932:18: note: Assuming 'ta' is equal to IRT_STR
      } else if (ta == IRT_STR) {
                 ^
/luavela/src/jit/lj_record.c:1932:14: note: Taking true branch
      } else if (ta == IRT_STR) {
             ^
/luavela/src/jit/lj_record.c:1933:27: note: The left operand of '==' is a garbage value
        if (!lj_ir_strcmp(strV(rav), strV(rcv), (IROp)irop)) irop ^= 1;
                          ^
/luavela/src/lj_obj.h:791:35: note: expanded from macro 'strV'
#define strV(o)         lua_check(tvisstr(o), &gcval(o)->str)
                                  ^
/luavela/src/lj_obj.h:766:36: note: expanded from macro 'tvisstr'
#define tvisstr(o)      (gettag(o) == LJ_TSTR)
                                   ^
/luavela/src/lj_def.h:144:37: note: expanded from macro 'lua_check'
#define lua_check(c, e) (lua_assert(c), (e))
                                    ^
/luavela/src/luaconf.h:25:36: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                                   ^
/usr/include/assert.h:98:7: note: expanded from macro 'assert'
    ((expr)                                                             \
      ^

All the warnings should be verified whether any of them found the real bug or it's just a false positive.

Fix `bugprone-not-null-terminated-result` warnings

As a result of updating clang-tidy up to version 11, new check bugprone-not-null-terminated-result produced several warnings.

/luavela/tools/parse_profile/ujpp_demangle_lua.c:39:2: error: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result,-warnings-as-errors]
        memcpy(buf, anon, strlen(anon));
        ^~~~~~          ~~~~~~~~~~~~~~
        strcpy
/luavela/src/dump/uj_dump_bc.c:57:2: error: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result,-warnings-as-errors]
        memcpy(fmt_buf, uvname, uvname_len);
        ^~~~~~
        strncpy
/luavela/src/dump/uj_dump_bc.c:176:4: error: the result from calling 'memmove' is not null-terminated [bugprone-not-null-terminated-result,-warnings-as-errors]
                        memmove(hint + uvnamea_len + 3, hint, strlen(hint));
                        ^
                                                                           + 1

All the warnings should be verified whether any of them found the real bug or it's just a false positive.

Wrong prefix when configuring via pkg-config

It appears the prefix in ujit.pc is always /usr even when a non-standard prefix is set via CMake:

$ cmake -DCMAKE_INSTALL_PREFIX=~/local .
...
$ make install
...
$ PKG_CONFIG_PATH=~/local/lib/pkgconfig pkg-config ujit --cflags
-I/usr/include/ujit

Fix `bugprone-signed-char-misuse` warnings

As a result of updating clang-tidy up to version 11, new check bugprone-signed-char-misuse produced several warnings.

/luavela/src/jit/emit/lj_emit.c:15:11: error: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse,-warnings-as-errors]
  int n = (int8_t)xo;
          ^
/luavela/src/jit/opt/fold.c:730:51: error: 'signed char' to 'int32_t' (aka 'int') conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse,-warnings-as-errors]
  if ((fins->op2 & IRCONV_SRCMASK) == IRT_I8) k = (int8_t)k;
                                                  ^
/luavela/src/lj_gc.c:181:17: error: 'signed char' to 'int' conversion; consider casting to 'unsigned char' first. [bugprone-signed-char-misuse,-warnings-as-errors]
    while ((c = *modestr++)) {
                ^

All the warnings should be verified whether any of them found the real bug or it's just a false positive.

Unexpected ujit profiler results

As by submitted profile module1 spends 24.2109% of total lua time
This file consists of "obj.func(...)" calls in a cycle
Of all used objects only 1 (module2) is mentioned in profile with significant time % (6.4665)
The question is how is 24.2109% calculated?
Is it module1 time without "obj.func(...)" calls? If yes then how can cycle over max 4 elements take so much time and where are other 17%?
If no then still were are 17% left?

Relevant profile part:
module1 24.2109
module2 6.4665

module1.txt

Segfault after lua_yield()

LuaVela as a drop-in replacement crashes in our environment where Lua threads are used extensively. Please see the following code snippet that illustrates the problem:

#include <lauxlib.h>
#include <lualib.h>

static int yield(lua_State *L) {
    return lua_yield(L, lua_gettop(L));
}

int main(void) {
    lua_State *L = luaL_newstate();
    lua_State *T = lua_newthread(L);
    lua_pushcfunction(L, yield);
    lua_setglobal(L, "yield");
    luaL_openlibs(L);
    luaL_loadstring(T, "print('ENTER #1');yield();print('LEAVE #1')");
    lua_resume(T, 0); /* ENTER #1 */
    lua_resume(T, 0); /* LEAVE #1 */
    /* Normally finished thread can be reused - https://www.lua.org/manual/5.3/manual.html#lua_status */
    luaL_loadstring(T, "print('ENTER #2');yield();print('LEAVE #2')");
    lua_resume(T, 0); /* ENTER #2 */
    lua_resume(T, 0); /* LEAVE #2 */
    lua_close(L);
    return 0;
}

Expected output:

ENTER #1
LEAVE #1
ENTER #2
LEAVE #2

Observed output:

ENTER #1
Segmentation fault (core dumped)

Output under gdb:

...
(gdb) r
Starting program: /mnt/seny/devel/tmp/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
ENTER #1

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7e71a79 in lj_BC_RET () from /home/seny/local/lib/libujit.so.0
(gdb) bt
#0  0x00007ffff7e71a79 in lj_BC_RET () from /home/seny/local/lib/libujit.so.0
#1  0x00007ffff7e9f91b in lua_resume (L=0x7ffff7acb338, nargs=0) at /home/seny/devel/luavela/src/uj_capi.c:1037
#2  0x0000555555555274 in main () at ujit1.c:15

Fix `bugprone-narrowing-conversions` warnings

As a result of updating clang-tidy up to version 11, new check bugprone-narrowing-conversions produced several warnings.

/luavela/tools/parse_profile/ujpp_main.c:56:42: error: narrowing conversion from 'unsigned long' to 'double' [bugprone-narrowing-conversions,-warnings-as-errors]
        overruns_share = (double)num_overruns / (num_samples + num_overruns);
                                                ^
/luavela/src/dump/uj_dump_utils.c:98:19: error: narrowing conversion from 'unsigned char' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
                        *(fmt_buf++) = c;
                                       ^
/luavela/src/frontend/lj_bcwrite.c:50:27: error: narrowing conversion from 'unsigned int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
    uj_sbuf_push_char(sb, BCDUMP_KTAB_NIL+~gettag(o));
                          ^
/luavela/src/frontend/lj_bcwrite.c:228:25: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
  uj_sbuf_push_char(sb, (pt->flags & (PROTO_CHILD|PROTO_VARARG|PROTO_FFI)));
                        ^
/luavela/src/frontend/lj_bcwrite.c:281:25: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
  uj_sbuf_push_char(sb, (ctx->strip ? BCDUMP_F_STRIP : 0) +
                        ^
/luavela/src/frontend/lj_lex.c:91:25: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
    if (lj_char_casecmp(ls->current, 'x')) xp = 'p';
                        ^
/luavela/src/frontend/lj_lex.c:94:73: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
         ((ls->current == '-' || ls->current == '+') && lj_char_casecmp(c, xp))) {
                                                                        ^
/luavela/src/frontend/lj_lex.c:94:76: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
         ((ls->current == '-' || ls->current == '+') && lj_char_casecmp(c, xp))) {
                                                                           ^
/luavela/src/frontend/lj_lex.c:209:13: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
        c = (next(ls) & 15u) << 4;
            ^
/luavela/src/frontend/lj_lex.c:214:14: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
        c += (next(ls) & 15u);
             ^
/luavela/src/frontend/lj_parse.c:1026:12: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
  for (i = fs->nactvar-1; i >= 0; i--) {
           ^
/luavela/src/jit/lj_snap.c:827:56: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
      snap_restoreval(J, T, ex, snapno, rfilt, ref, o, sn & SNAP_LOW);
                                                       ^
/luavela/src/jit/uj_record_indexed.c:298:23: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
        int hrefk_disabled = J->flags & JIT_F_OPT_NOHREFK;
                             ^
/luavela/src/lib/ffi.c:304:48: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
                                               (ct->info & CTF_UNSIGNED)));
                                               ^
/luavela/src/lib/io.c:119:22: error: narrowing conversion from 'unsigned long' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
    if (fgets(buf+n, m-n, fp) == NULL) break;
                     ^
/luavela/src/uj_cstr.c:54:9: error: narrowing conversion from 'unsigned int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
        *s++ = '0' + u / 1000;
               ^
/luavela/src/uj_cstr.c:57:9: error: narrowing conversion from 'unsigned int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
        *s++ = '0' + u / 100;
               ^
/luavela/src/uj_cstr.c:60:9: error: narrowing conversion from 'unsigned int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
        *s++ = '0' + u / 10;
               ^
/luavela/src/uj_cstr.c:63:9: error: narrowing conversion from 'unsigned int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
        *s++ = '0' + u;
               ^
/luavela/src/uj_cstr.c:71:10: error: narrowing conversion from 'unsigned int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
                *s++ = '0' + u / 10;
                       ^
/luavela/src/uj_cstr.c:74:9: error: narrowing conversion from 'unsigned int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
        *s++ = '0' + u;
               ^
/luavela/src/uj_lib.c:225:18: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
                uj_err_argt(L, narg, LUA_TSTRING);
                               ^
/luavela/src/uj_lib.c:246:31: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
        uj_err_arg(L, UJ_ERR_NOTABN, narg);
                                     ^
/luavela/src/uj_lib.c:270:33: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
        uj_err_argv(L, UJ_ERR_INVOPTM, narg, opt);
                                       ^
/luavela/src/uj_lib.h:99:31: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
                uj_err_arg(L, UJ_ERR_NOVAL, narg);
                                            ^
/luavela/src/uj_lib.h:117:18: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
                uj_err_argt(L, narg, LUA_TNUMBER);
                               ^
/luavela/src/uj_lib.h:151:18: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
                uj_err_argt(L, narg, LUA_TFUNCTION);
                               ^
/luavela/src/uj_lib.h:160:18: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
                uj_err_argt(L, narg, LUA_TTABLE);
                               ^
/luavela/src/uj_lib.h:176:18: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
                uj_err_argt(L, narg, LUA_TUSERDATA);
                               ^
/luavela/src/uj_timerint.c:40:9: error: narrowing conversion from 'unsigned long' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
        return timerint.flags & TIMERINT_IS_TICKING;
               ^
/luavela/src/utils/cpuinfo.c:28:12: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
    return ((edx >> 15) & 1);
           ^
/luavela/src/utils/cpuinfo.c:36:12: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
    return ((edx >> 26) & 1);
           ^
/luavela/src/utils/cpuinfo.c:44:12: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
    return ((ecx >> 9) & 1);
           ^
/luavela/src/utils/cpuinfo.c:52:12: error: narrowing conversion from 'unsigned int' to signed type 'int' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
    return ((ecx >> 19) & 1);
           ^
/luavela/src/utils/lj_char.h:38:35: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
  return (c >= 'A' && c <= 'Z') ? (c + CASE_BIT) : c;
                                  ^
/luavela/src/utils/lj_char.h:38:52: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
  return (c >= 'A' && c <= 'Z') ? (c + CASE_BIT) : c;
                                                   ^
/luavela/src/utils/lj_char.h:42:35: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
  return (c >= 'a' && c <= 'z') ? (c - CASE_BIT) : c;
                                  ^
/luavela/src/utils/lj_char.h:42:52: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
  return (c >= 'a' && c <= 'z') ? (c - CASE_BIT) : c;
                                                   ^
/luavela/src/utils/lj_char.h:55:10: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
  return c ^ CASE_BIT;
         ^
/luavela/src/utils/lj_char.h:38:35: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
  return (c >= 'A' && c <= 'Z') ? (c + CASE_BIT) : c;
                                  ^
/luavela/src/utils/lj_char.h:38:52: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
  return (c >= 'A' && c <= 'Z') ? (c + CASE_BIT) : c;
                                                   ^
/luavela/src/utils/lj_char.h:42:35: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
  return (c >= 'a' && c <= 'z') ? (c - CASE_BIT) : c;
                                  ^
/luavela/src/utils/lj_char.h:42:52: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
  return (c >= 'a' && c <= 'z') ? (c - CASE_BIT) : c;
                                                   ^
/luavela/src/utils/lj_char.h:55:10: error: narrowing conversion from 'int' to signed type 'char' is implementation-defined [bugprone-narrowing-conversions,-warnings-as-errors]
  return c ^ CASE_BIT;
         ^

All the warnings should be verified whether any of them found the real bug or it's just making the noise.

aux.* is a reserved filename on windows

On windows(10) I get the following error during checkout:

error: unable to stat just-written file tests/impl/uJIT-tests-Lua/suite/chunks/profile-leaf/aux.lua: No such file or directory

I tried to manually write the file on disk and figured out, win10 does not allow any "aux.*" filenames.

Can you rename the aux.lua file? Thank you.

Clean up temporary directory before running uJIT testing

Ah shit, here we go again.

Ironically, CI failed when the fix for flaky test was merged to the master branch.

After the glance on the failure log, I've found the reason.

FAILED--Further testing stopped: Unable to mkdir '/home/runner/work/_temp/build-3975141220/tests/impl/uJIT-tests-Lua/suite_run/tests-run': File exists
Bailout called.  Further testing stopped:  Unable to mkdir '/home/runner/work/_temp/build-3975141220/tests/impl/uJIT-tests-Lua/suite_run/tests-run': File exists
make[3]: *** [tests/impl/uJIT-tests-Lua/CMakeFiles/uJIT-tests-Lua.dir/build.make:359: tests/impl/uJIT-tests-Lua/suite_run/run_tests.ok] Error 1
make[2]: *** [CMakeFiles/Makefile2:2801: tests/impl/uJIT-tests-Lua/CMakeFiles/uJIT-tests-Lua.dir/all] Error 2
make[2]: *** Waiting for unfinished jobs....

To avoid clashing with the artefacts of the previous builds, the temporary directory need to properly cleaned prior to the build and test steps.

Fix `clang-analyzer-core.uninitialized.Branch` warnings

As a result of updating clang-tidy up to version 11, new check clang-analyzer-core.uninitialized.Branch produced several warnings.

/luavela/src/jit/lj_asm_x86.h:291:9: error: Branch condition evaluates to a garbage value [clang-analyzer-core.uninitialized.Branch,-warnings-as-errors]
    if (args[i] && irt_isfp(IR(args[i])->t)) {
        ^
/luavela/src/jit/lj_asm.c:1328:47: note: Assuming 'ir' is >= 'lastir'
  for (ir = IR(T->nk), lastir = IR(REF_BASE); ir < lastir; ir++)
                                              ^
/luavela/src/jit/lj_asm.c:1328:3: note: Loop condition is false. Execution continues on line 1332
  for (ir = IR(T->nk), lastir = IR(REF_BASE); ir < lastir; ir++)
  ^
/luavela/src/jit/lj_asm.c:1335:7: note: Assuming field 'o' is not equal to IR_RENAME
  if (ir->o == IR_RENAME) {
      ^
/luavela/src/jit/lj_asm.c:1335:3: note: Taking false branch
  if (ir->o == IR_RENAME) {
  ^
/luavela/src/jit/lj_asm.c:1349:7: note: Assuming field 'parent' is null
  if (as->parent) {
      ^
/luavela/src/jit/lj_asm.c:1349:3: note: Taking false branch
  if (as->parent) {
  ^
/luavela/src/jit/lj_asm.c:1367:27: note: Assuming 'ir' is < 'lastir'
  for (lastir = IR(nins); ir < lastir; ir++) {
                          ^
/luavela/src/jit/lj_asm.c:1367:3: note: Loop condition is true.  Entering loop body
  for (lastir = IR(nins); ir < lastir; ir++) {
  ^
/luavela/src/jit/lj_asm.c:1368:9: note: Assuming 'sink' is 0
    if (sink) {
        ^
/luavela/src/jit/lj_asm.c:1368:5: note: Taking false branch
    if (sink) {
    ^
/luavela/src/jit/lj_asm.c:1376:5: note: Control jumps to 'case IR_CALLXS:'  at line 1380
    switch (ir->o) {
    ^
/luavela/src/jit/lj_asm.c:1383:18: note: Calling 'asm_setup_call_slots'
      ir->prev = asm_setup_call_slots(as, ir, &ci);
                 ^
/luavela/src/jit/lj_asm_x86.h:2587:3: note: Calling 'asm_collectargs'
  asm_collectargs(as, ir, ci, args);
  ^
/luavela/src/jit/lj_asm.c:710:14: note: Assuming the condition is true
  lua_assert(n <= CCI_NARGS_MAX*2);  /* Account for split args. */
             ^
/luavela/src/luaconf.h:25:36: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                                   ^
/usr/include/assert.h:98:7: note: expanded from macro 'assert'  
    ((expr)                                                             \
      ^
/luavela/src/jit/lj_asm.c:710:3: note: '?' condition is true
  lua_assert(n <= CCI_NARGS_MAX*2);  /* Account for split args. */
  ^
/luavela/src/luaconf.h:25:29: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                            ^
/usr/include/assert.h:98:6: note: expanded from macro 'assert'  
    ((expr)                                                             \
     ^
/luavela/src/jit/lj_asm.c:711:8: note: Assuming the condition is true
  if ((ci->flags & CCI_L)) { *args++ = ASMREF_L; n--; }
       ^
/luavela/src/jit/lj_asm.c:711:3: note: Taking true branch
  if ((ci->flags & CCI_L)) { *args++ = ASMREF_L; n--; }
  ^
/luavela/src/jit/lj_asm.c:712:10: note: Assuming the condition is true
  while (n-- > 1) {
         ^
/luavela/src/jit/lj_asm.c:712:3: note: Loop condition is true.  Entering loop body
  while (n-- > 1) {
  ^
/luavela/src/jit/lj_asm.c:714:16: note: Assuming field 'o' is equal to IR_CARG
    lua_assert(ir->o == IR_CARG);
               ^
/luavela/src/luaconf.h:25:36: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                                   ^
/usr/include/assert.h:98:7: note: expanded from macro 'assert'  
    ((expr)                                                             \
      ^
/luavela/src/jit/lj_asm.c:714:5: note: '?' condition is true
    lua_assert(ir->o == IR_CARG);
    ^
/luavela/src/luaconf.h:25:29: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                            ^
/usr/include/assert.h:98:6: note: expanded from macro 'assert'  
    ((expr)                                                             \
     ^
/luavela/src/jit/lj_asm.c:715:15: note: Assuming field 'op2' is equal to REF_NIL
    args[n] = ir->op2 == REF_NIL ? 0 : ir->op2;
              ^
/luavela/src/jit/lj_asm.c:715:15: note: '?' condition is true
/luavela/src/jit/lj_asm.c:712:10: note: Assuming the condition is false
  while (n-- > 1) {
         ^
/luavela/src/jit/lj_asm.c:712:3: note: Loop condition is false. Execution continues on line 717
  while (n-- > 1) {
  ^
/luavela/src/jit/lj_asm.c:717:13: note: Assuming field 'op1' is not equal to REF_NIL
  args[0] = ir->op1 == REF_NIL ? 0 : ir->op1;
            ^
/luavela/src/jit/lj_asm.c:717:13: note: '?' condition is false
/luavela/src/jit/lj_asm.c:718:14: note: Assuming field 'o' is not equal to IR_CARG
  lua_assert(IR(ir->op1)->o != IR_CARG);
             ^
/luavela/src/jit/lj_asm.c:37:33: note: expanded from macro 'IR'
#define IR(ref)                 (&as->ir[(ref)])
                                ^
/luavela/src/luaconf.h:25:36: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                                   ^
/usr/include/assert.h:98:7: note: expanded from macro 'assert'  
    ((expr)                                                             \
      ^
/luavela/src/jit/lj_asm.c:718:3: note: '?' condition is true
  lua_assert(IR(ir->op1)->o != IR_CARG);
  ^
/luavela/src/luaconf.h:25:29: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                            ^
/usr/include/assert.h:98:6: note: expanded from macro 'assert'  
    ((expr)                                                             \
     ^
/luavela/src/jit/lj_asm_x86.h:2587:3: note: Returning from 'asm_collectargs'
  asm_collectargs(as, ir, ci, args);
  ^
/luavela/src/jit/lj_asm_x86.h:2588:12: note: Calling 'asm_count_call_slots'
  nslots = asm_count_call_slots(as, ci, args);
           ^
/luavela/src/jit/lj_asm_x86.h:290:3: note: Loop condition is true.  Entering loop body
  for (i = 0; i < nargs; i++) {
  ^
/luavela/src/jit/lj_asm_x86.h:291:9: note: Left side of '&&' is true
    if (args[i] && irt_isfp(IR(args[i])->t)) {
        ^
/luavela/src/jit/lj_asm_x86.h:291:20: note: Assuming the condition is true
    if (args[i] && irt_isfp(IR(args[i])->t)) {
                   ^
/luavela/src/jit/lj_ir.h:384:34: note: expanded from macro 'irt_isfp'
#define irt_isfp(t)             (irt_isnum(t) || irt_isfloat(t))
                                 ^
/luavela/src/jit/lj_ir.h:373:34: note: expanded from macro 'irt_isnum'
#define irt_isnum(t)            (irt_type(t) == IRT_NUM)
                                 ^
/luavela/src/jit/lj_ir.h:360:33: note: expanded from macro 'irt_type'
#define irt_type(t)             ((IRType)((t).irt & IRT_TYPE))  
                                ^
/luavela/src/jit/lj_asm_x86.h:291:20: note: Left side of '||' is true
    if (args[i] && irt_isfp(IR(args[i])->t)) {
                   ^
/luavela/src/jit/lj_ir.h:384:47: note: expanded from macro 'irt_isfp'
#define irt_isfp(t)             (irt_isnum(t) || irt_isfloat(t))
                                              ^
/luavela/src/jit/lj_asm_x86.h:292:11: note: 'nfpr' is > 0
      if (nfpr > 0) nfpr--; else nslots += 2;
          ^
/luavela/src/jit/lj_asm_x86.h:292:7: note: Taking true branch
      if (nfpr > 0) nfpr--; else nslots += 2;
      ^
/luavela/src/jit/lj_asm_x86.h:290:3: note: Loop condition is true.  Entering loop body
  for (i = 0; i < nargs; i++) {
  ^
/luavela/src/jit/lj_asm_x86.h:291:9: note: Assuming the condition is false
    if (args[i] && irt_isfp(IR(args[i])->t)) {
        ^
/luavela/src/jit/lj_asm_x86.h:291:17: note: Left side of '&&' is false
    if (args[i] && irt_isfp(IR(args[i])->t)) {
                ^
/luavela/src/jit/lj_asm_x86.h:294:11: note: 'ngpr' is > 0
      if (ngpr > 0) ngpr--; else nslots += 2;
          ^
/luavela/src/jit/lj_asm_x86.h:294:7: note: Taking true branch
      if (ngpr > 0) ngpr--; else nslots += 2;
      ^
/luavela/src/jit/lj_asm_x86.h:290:26: note: The value 2 is assigned to 'i'
  for (i = 0; i < nargs; i++) {
                         ^
/luavela/src/jit/lj_asm_x86.h:290:3: note: Loop condition is true.  Entering loop body
  for (i = 0; i < nargs; i++) {
  ^
/luavela/src/jit/lj_asm_x86.h:291:9: note: Branch condition evaluates to a garbage value
    if (args[i] && irt_isfp(IR(args[i])->t)) {
        ^

All the warnings should be verified whether any of them found the real bug or it's just a false positive.

Fix `clang-analyzer-core.uninitialized.Assign` warnings

As a result of updating clang-tidy up to version 11, new check clang-analyzer-core.uninitialized.Assign produced several warnings.

/luavela/src/jit/lj_record.c:993:11: error: Assigned value is garbage or undefined [clang-analyzer-core.uninitialized.Assign,-warnings-as-errors]
  base[1] = ix->tab; base[2] = ix->key;
          ^
/luavela/src/jit/lj_record.c:1763:19: note: Assuming field 'postproc' is equal to LJ_POST_NONE
  if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) {
                  ^
/luavela/src/lj_def.h:87:45: note: expanded from macro 'LJ_UNLIKELY'
#define LJ_UNLIKELY(x)  __builtin_expect(!!(x), 0)
                                            ^
/luavela/src/jit/lj_record.c:1763:3: note: Taking false branch
  if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) {
  ^
/luavela/src/jit/lj_record.c:1835:7: note: Assuming field 'needsnap' is 0
  if (J->needsnap) {
      ^
/luavela/src/jit/lj_record.c:1835:3: note: Taking false branch
  if (J->needsnap) {
  ^
/luavela/src/jit/lj_record.c:1843:19: note: Assuming field 'bcskip' is <= 0
  if (LJ_UNLIKELY(J->bcskip > 0)) {
                  ^
/luavela/src/lj_def.h:87:45: note: expanded from macro 'LJ_UNLIKELY'
#define LJ_UNLIKELY(x)  __builtin_expect(!!(x), 0)
                                            ^
/luavela/src/jit/lj_record.c:1843:3: note: Taking false branch
  if (LJ_UNLIKELY(J->bcskip > 0)) {
  ^
/luavela/src/jit/lj_record.c:1850:7: note: Assuming field 'framedepth' is not equal to 0
  if (J->framedepth == 0 &&
      ^
/luavela/src/jit/lj_record.c:1850:26: note: Left side of '&&' is false
  if (J->framedepth == 0 &&
                         ^
/luavela/src/jit/lj_record.c:1869:3: note: Control jumps to the 'default' case at line 1872
  switch (bcmode_a(op)) {
  ^
/luavela/src/jit/lj_record.c:1872:12: note:  Execution continues on line 1874
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1876:3: note: Control jumps to the 'default' case at line 1880
  switch (bcmode_b(op)) {
  ^
/luavela/src/jit/lj_record.c:1880:12: note:  Execution continues on line 1882
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1882:3: note: Control jumps to the 'default' case at line 1890
  switch (bcmode_c(op)) {
  ^
/luavela/src/jit/lj_record.c:1890:12: note:  Execution continues on line 1893
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1893:3: note: Control jumps to 'case BC_MOD:'  at line 2021
  switch (op) {
  ^
/luavela/src/jit/lj_record.c:2022:9: note: Assuming the condition is true
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
        ^
/luavela/src/jit/lj_ir.h:495:34: note: expanded from macro 'tref_isnumber_str'
#define tref_isnumber_str(tr)   (tref_isnumber((tr)) || tref_isstr((tr)))
                                 ^
/luavela/src/jit/lj_ir.h:494:34: note: expanded from macro 'tref_isnumber'
#define tref_isnumber(tr)       (tref_typerange((tr), IRT_NUM, IRT_U64))
                                 ^
/luavela/src/jit/lj_ir.h:476:4: note: expanded from macro 'tref_typerange'
  ((((tr)>>24) & IRT_TYPE) - (TRef)(first) <= (TRef)((last) - (first)))
   ^
/luavela/src/jit/lj_record.c:2022:9: note: Left side of '||' is true
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
        ^
/luavela/src/jit/lj_ir.h:495:54: note: expanded from macro 'tref_isnumber_str'
#define tref_isnumber_str(tr)   (tref_isnumber((tr)) || tref_isstr((tr)))
                                                     ^
/luavela/src/jit/lj_record.c:2022:34: note: Assuming the condition is false
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
                                 ^
/luavela/src/jit/lj_ir.h:495:34: note: expanded from macro 'tref_isnumber_str'
#define tref_isnumber_str(tr)   (tref_isnumber((tr)) || tref_isstr((tr)))
                                 ^
/luavela/src/jit/lj_ir.h:494:34: note: expanded from macro 'tref_isnumber'
#define tref_isnumber(tr)       (tref_typerange((tr), IRT_NUM, IRT_U64))
                                 ^
/luavela/src/jit/lj_ir.h:476:4: note: expanded from macro 'tref_typerange'
  ((((tr)>>24) & IRT_TYPE) - (TRef)(first) <= (TRef)((last) - (first)))
   ^
/luavela/src/jit/lj_record.c:2022:34: note: Left side of '||' is false
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
                                 ^
/luavela/src/jit/lj_ir.h:495:34: note: expanded from macro 'tref_isnumber_str'
#define tref_isnumber_str(tr)   (tref_isnumber((tr)) || tref_isstr((tr)))
                                 ^
/luavela/src/jit/lj_ir.h:494:33: note: expanded from macro 'tref_isnumber'
#define tref_isnumber(tr)       (tref_typerange((tr), IRT_NUM, IRT_U64))
                                ^
/luavela/src/jit/lj_record.c:2022:5: note: Taking false branch
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
    ^
/luavela/src/jit/lj_record.c:2025:12: note: Calling 'rec_mm_arith'
      rc = rec_mm_arith(J, &ix, MM_mod);
           ^
/luavela/src/jit/lj_record.c:993:11: note: Assigned value is garbage or undefined
  base[1] = ix->tab; base[2] = ix->key;
          ^
/luavela/src/jit/lj_record.c:993:30: error: Assigned value is garbage or undefined [clang-analyzer-core.uninitialized.Assign,-warnings-as-errors]
  base[1] = ix->tab; base[2] = ix->key;
                             ^
/luavela/src/jit/lj_record.c:1763:19: note: Assuming field 'postproc' is equal to LJ_POST_NONE
  if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) {
                  ^
/luavela/src/lj_def.h:87:45: note: expanded from macro 'LJ_UNLIKELY'
#define LJ_UNLIKELY(x)  __builtin_expect(!!(x), 0)
                                            ^
/luavela/src/jit/lj_record.c:1763:3: note: Taking false branch
  if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) {
  ^
/luavela/src/jit/lj_record.c:1835:7: note: Assuming field 'needsnap' is 0
  if (J->needsnap) {
      ^
/luavela/src/jit/lj_record.c:1835:3: note: Taking false branch
  if (J->needsnap) {
  ^
/luavela/src/jit/lj_record.c:1843:19: note: Assuming field 'bcskip' is <= 0
  if (LJ_UNLIKELY(J->bcskip > 0)) {
                  ^
/luavela/src/lj_def.h:87:45: note: expanded from macro 'LJ_UNLIKELY'
#define LJ_UNLIKELY(x)  __builtin_expect(!!(x), 0)
                                            ^
/luavela/src/jit/lj_record.c:1843:3: note: Taking false branch
  if (LJ_UNLIKELY(J->bcskip > 0)) {
  ^
/luavela/src/jit/lj_record.c:1850:7: note: Assuming field 'framedepth' is not equal to 0
  if (J->framedepth == 0 &&
      ^
/luavela/src/jit/lj_record.c:1850:26: note: Left side of '&&' is false
  if (J->framedepth == 0 &&
                         ^
/luavela/src/jit/lj_record.c:1869:3: note: Control jumps to the 'default' case at line 1872
  switch (bcmode_a(op)) {
  ^
/luavela/src/jit/lj_record.c:1872:12: note:  Execution continues on line 1874
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1876:3: note: Control jumps to the 'default' case at line 1880
  switch (bcmode_b(op)) {
  ^
/luavela/src/jit/lj_record.c:1880:12: note:  Execution continues on line 1882
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1882:3: note: Control jumps to the 'default' case at line 1890
  switch (bcmode_c(op)) {
  ^
/luavela/src/jit/lj_record.c:1890:12: note:  Execution continues on line 1893
  default: break;  /* Handled later. */
           ^
/luavela/src/jit/lj_record.c:1893:3: note: Control jumps to 'case BC_MOD:'  at line 2021
  switch (op) {
  ^
/luavela/src/jit/lj_record.c:2022:9: note: Assuming the condition is true
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
        ^
/luavela/src/jit/lj_ir.h:495:34: note: expanded from macro 'tref_isnumber_str'
#define tref_isnumber_str(tr)   (tref_isnumber((tr)) || tref_isstr((tr)))
                                 ^
/luavela/src/jit/lj_ir.h:494:34: note: expanded from macro 'tref_isnumber'
#define tref_isnumber(tr)       (tref_typerange((tr), IRT_NUM, IRT_U64))
                                 ^
/luavela/src/jit/lj_ir.h:476:4: note: expanded from macro 'tref_typerange'
  ((((tr)>>24) & IRT_TYPE) - (TRef)(first) <= (TRef)((last) - (first)))
   ^
/luavela/src/jit/lj_record.c:2022:9: note: Left side of '||' is true
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
        ^
/luavela/src/jit/lj_ir.h:495:54: note: expanded from macro 'tref_isnumber_str'
#define tref_isnumber_str(tr)   (tref_isnumber((tr)) || tref_isstr((tr)))
                                                     ^
/luavela/src/jit/lj_record.c:2022:34: note: Assuming the condition is false
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
                                 ^
/luavela/src/jit/lj_ir.h:495:34: note: expanded from macro 'tref_isnumber_str'
#define tref_isnumber_str(tr)   (tref_isnumber((tr)) || tref_isstr((tr)))
                                 ^
/luavela/src/jit/lj_ir.h:494:34: note: expanded from macro 'tref_isnumber'
#define tref_isnumber(tr)       (tref_typerange((tr), IRT_NUM, IRT_U64))
                                 ^
/luavela/src/jit/lj_ir.h:476:4: note: expanded from macro 'tref_typerange'
  ((((tr)>>24) & IRT_TYPE) - (TRef)(first) <= (TRef)((last) - (first)))
   ^
/luavela/src/jit/lj_record.c:2022:34: note: Left side of '||' is false
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
                                 ^
/luavela/src/jit/lj_ir.h:495:34: note: expanded from macro 'tref_isnumber_str'
#define tref_isnumber_str(tr)   (tref_isnumber((tr)) || tref_isstr((tr)))
                                 ^
/luavela/src/jit/lj_ir.h:494:33: note: expanded from macro 'tref_isnumber'
#define tref_isnumber(tr)       (tref_typerange((tr), IRT_NUM, IRT_U64))
                                ^
/luavela/src/jit/lj_record.c:2022:5: note: Taking false branch
    if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
    ^
/luavela/src/jit/lj_record.c:2025:12: note: Calling 'rec_mm_arith'
      rc = rec_mm_arith(J, &ix, MM_mod);
           ^
/luavela/src/jit/lj_record.c:993:30: note: Assigned value is garbage or undefined
  base[1] = ix->tab; base[2] = ix->key;
                             ^

All the warnings should be verified whether any of them found the real bug or it's just a false positive.

Unused result of `fgets()` in `src/dump/uj_dump_bc.c`

My compiler warnings are only paranoid, but not crazy, so I get this when I compile:

/home/sofar/git/luavela/src/dump/uj_dump_bc.c: In function ‘dump_bc_get_file_line’:
/home/sofar/git/luavela/src/dump/uj_dump_bc.c:296:2: error: ignoring return value of ‘fgets’, declared with attribute warn_unused_result [-Werror=unused-result]
  296 |  fgets(sds->buf, MAX_SRC_LINE_LEN + 2, sds->file);
      |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Would be good to have this fixed, since fgets may return NULL on error, and you really want to at least do something with that. (Don't be like me and if (!fgets()) return though, that probably won't be the right solution here). :)

Fix `bugprone-branch-clone` warnings

As a result of updating clang-tidy up to version 11, new check bugprone-branch-clone produced several warnings.

/luavela/src/jit/lj_asm_x86.h:2565:3: error: switch has 2 consecutive identical branches [bugprone-branch-clone,-warnings-as-errors]
  case IR_CARG:
  ^
/luavela/src/jit/lj_asm_x86.h:2570:10: note: last of these clones ends here
    break; /* no op; IR -> mcode will happen in the finalizer (TVARGF) */
         ^
/luavela/src/jit/lj_ffrecord.c:828:22: error: conditional operator with identical true and false expressions [bugprone-branch-clone,-warnings-as-errors]
  if (!(op < IR_BROL ? UJ_TARGET_MASKSHIFT : UJ_TARGET_MASKROT) &&
                     ^
/luavela/src/jit/opt/fold.c:1538:26: error: conditional operator with identical true and false expressions [bugprone-branch-clone,-warnings-as-errors]
  if ((fins->o < IR_BROL ? UJ_TARGET_MASKSHIFT : UJ_TARGET_MASKROT) &&
                         ^
/luavela/src/lauxlib.h:127:14: error: conditional operator with identical true and false expressions [bugprone-branch-clone,-warnings-as-errors]
        char buffer[LUAL_BUFFERSIZE];
                    ^
/luavela/src/luaconf.h:150:41: note: expanded from macro 'LUAL_BUFFERSIZE'
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
                                        ^
/luavela/src/lib/base.c:556:37: error: repeated branch in conditional chain [bugprone-branch-clone,-warnings-as-errors]
  else if (co->status == LUA_YIELD) s = "suspended";
                                    ^
/luavela/src/lib/base.c:556:52: note: end of the original
  else if (co->status == LUA_YIELD) s = "suspended";
                                                   ^
/luavela/src/lib/base.c:560:8: note: clone 1 starts here
  else s = "suspended";
       ^
/luavela/src/lib/base.c:557:29: error: repeated branch in conditional chain [bugprone-branch-clone,-warnings-as-errors]
  else if (co->status != 0) s = "dead";
                            ^
/luavela/src/lib/base.c:557:39: note: end of the original
  else if (co->status != 0) s = "dead";
                                      ^
/luavela/src/lib/base.c:559:33: note: clone 1 starts here
  else if (co->top == co->base) s = "dead";
                                ^
/luavela/src/lib/ffi.c:576:21: error: repeated branch in conditional chain [bugprone-branch-clone,-warnings-as-errors]
    if (ct1 == ct2) {
                    ^
/luavela/src/lib/ffi.c:578:6: note: end of the original
    } else if (ctype_type(ct1->info) == ctype_type(ct2->info) &&
     ^
/luavela/src/lib/ffi.c:585:49: note: clone 1 starts here
               ct1 == ctype_rawchild(cts, ct2)) {
                                                ^
/luavela/src/lib/io.c:115:14: error: conditional operator with identical true and false expressions [bugprone-branch-clone,-warnings-as-errors]
  size_t m = LUAL_BUFFERSIZE, n = 0, ok = 0;
             ^
/luavela/src/luaconf.h:150:41: note: expanded from macro 'LUAL_BUFFERSIZE'
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
                                        ^
/luavela/src/lib/io.c:133:12: error: conditional operator with identical true and false expressions [bugprone-branch-clone,-warnings-as-errors]
  for (m = LUAL_BUFFERSIZE, n = 0; ; m += m) {
           ^
/luavela/src/luaconf.h:150:41: note: expanded from macro 'LUAL_BUFFERSIZE'
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
                                        ^
/luavela/src/lib/io.c:304:43: error: conditional operator with identical true and false expressions [bugprone-branch-clone,-warnings-as-errors]
  size_t sz = (size_t)uj_lib_optint(L, 3, LUAL_BUFFERSIZE);
                                          ^
/luavela/src/luaconf.h:150:41: note: expanded from macro 'LUAL_BUFFERSIZE'
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
                                        ^
/luavela/src/lib/os.c:164:9: error: conditional operator with identical true and false expressions [bugprone-branch-clone,-warnings-as-errors]
        luaL_addchar(&b, *s);
        ^
/luavela/src/lauxlib.h:131:32: note: expanded from macro 'luaL_addchar'
        ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
                                      ^
/luavela/src/luaconf.h:150:41: note: expanded from macro 'LUAL_BUFFERSIZE'
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
                                        ^
/luavela/src/lib/string.c:597:9: error: conditional operator with identical true and false expressions [bugprone-branch-clone,-warnings-as-errors]
        luaL_addchar(b, news[i]);
        ^
/luavela/src/lauxlib.h:131:32: note: expanded from macro 'luaL_addchar'
        ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
                                      ^
/luavela/src/luaconf.h:150:41: note: expanded from macro 'LUAL_BUFFERSIZE'
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
                                        ^
/luavela/src/lib/string.c:669:7: error: conditional operator with identical true and false expressions [bugprone-branch-clone,-warnings-as-errors]
      luaL_addchar(&b, *src++);
      ^
/luavela/src/lauxlib.h:131:32: note: expanded from macro 'luaL_addchar'
        ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
                                      ^
/luavela/src/luaconf.h:150:41: note: expanded from macro 'LUAL_BUFFERSIZE'
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
                                        ^
/luavela/src/luajit.c:79:5: error: repeated branch in conditional chain [bugprone-branch-clone,-warnings-as-errors]
                                return 0;
                                ^
/luavela/src/luajit.c:79:13: note: end of the original
                                return 0;
                                        ^
/luavela/src/luajit.c:84:5: note: clone 1 starts here
                                return 0;
                                ^
/luavela/src/profile/uj_profile.c:137:2: error: switch has 2 consecutive identical branches [bugprone-branch-clone,-warnings-as-errors]
        case PS_ERROR:
        ^
/luavela/src/profile/uj_profile.c:140:9: note: last of these clones ends here
                return;
                      ^
/luavela/src/profile/uj_symtab.c:47:3: error: switch has 2 consecutive identical branches [bugprone-branch-clone,-warnings-as-errors]
                case (~LJ_TTRACE): {
                ^
/luavela/src/profile/uj_symtab.c:53:4: note: last of these clones ends here
                }
                 ^
/luavela/src/uj_capi.c:272:39: error: repeated branch in conditional chain [bugprone-branch-clone,-warnings-as-errors]
        } else if (gettag(o1) != gettag(o2)) {
                                             ^
/luavela/src/uj_capi.c:274:3: note: end of the original
        } else if (tvispri(o1)) {
         ^
/luavela/src/uj_capi.c:280:29: note: clone 1 starts here
        } else if (!tvistabud(o1)) {
                                   ^
/luavela/src/uj_capi_aux.c:151:18: error: conditional operator with identical true and false expressions [bugprone-branch-clone,-warnings-as-errors]
        return (size_t)(LUAL_BUFFERSIZE - bufflen(B));
                        ^
/luavela/src/luaconf.h:150:41: note: expanded from macro 'LUAL_BUFFERSIZE'
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
                                        ^
/luavela/src/uj_capi_aux.c:194:3: error: conditional operator with identical true and false expressions [bugprone-branch-clone,-warnings-as-errors]
                luaL_addchar(B, *s++);
                ^
/luavela/src/lauxlib.h:131:32: note: expanded from macro 'luaL_addchar'
        ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
                                      ^
/luavela/src/luaconf.h:150:41: note: expanded from macro 'LUAL_BUFFERSIZE'
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
                                        ^
/luavela/src/uj_capi_aux.c:487:11: error: conditional operator with identical true and false expressions [bugprone-branch-clone,-warnings-as-errors]
        char buf[LUAL_BUFFERSIZE];
                 ^
/luavela/src/luaconf.h:150:41: note: expanded from macro 'LUAL_BUFFERSIZE'
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
                                        ^

All the warnings should be verified whether any of them found the real bug or it's just making the noise.

toset method

local a = {"a","b","a","b"}
local b = ujit.table.toset(a)
local c = 0
for _ in pairs(b) do c = c + 1 end
assert(c == 4)

LuaJIT 2.0 differences documentation?

Hello!

I just found this project. I was wondering if you have any documentation which detais the differences beween this and luajit. The post sent to the mailing list is the most I've found so far (http://lua-users.org/lists/lua-l/2019-08/msg00041.html).

I'm particularly curiuous about the behaviour of what that post describes as "Coroutine timeouts". Is that essentially pre-emption from coroutines? How does it interact with jit-compiled code?

Thanks for sharing this project!

Fix `clang-analyzer-core.NullDereference` warnings

As a result of updating clang-tidy up to version 11, new check clang-analyzer-core.NullDereference produced several warnings.

/luavela/src/jit/opt/mem.c:48:9: error: Dereference of null pointer [clang-analyzer-core.NullDereference,-warnings-as-errors]
    if (ir->op2 == ref &&
        ^
/luavela/src/jit/opt/mem.c:800:7: note: Assuming the condition is false
  if (J->chain[IR_CALLXS] > lim) lim = J->chain[IR_CALLXS];
      ^
/luavela/src/jit/opt/mem.c:800:3: note: Taking false branch
  if (J->chain[IR_CALLXS] > lim) lim = J->chain[IR_CALLXS];
  ^
/luavela/src/jit/opt/mem.c:801:7: note: Assuming the condition is false
  if (J->chain[IR_XBAR] > lim) lim = J->chain[IR_XBAR];
      ^
/luavela/src/jit/opt/mem.c:801:3: note: Taking false branch
  if (J->chain[IR_XBAR] > lim) lim = J->chain[IR_XBAR];
  ^
/luavela/src/jit/opt/mem.c:802:7: note: Assuming the condition is false
  if (J->chain[IR_XSNEW] > lim) lim = J->chain[IR_XSNEW];
      ^
/luavela/src/jit/opt/mem.c:802:3: note: Taking false branch
  if (J->chain[IR_XSNEW] > lim) lim = J->chain[IR_XSNEW];
  ^
/luavela/src/jit/opt/mem.c:803:10: note: Assuming 'ref' is > 'lim'
  while (ref > lim) {  /* Search for redundant or conflicting stores. */
         ^
/luavela/src/jit/opt/mem.c:803:3: note: Loop condition is true.  Entering loop body
  while (ref > lim) {  /* Search for redundant or conflicting stores. */
  ^
/luavela/src/jit/opt/mem.c:805:5: note: Control jumps to 'case ALIAS_NO:'  at line 806
    switch (aa_xref(J, xr, fins, store)) {
    ^
/luavela/src/jit/opt/mem.c:807:7: note:  Execution continues on line 829
      break;  /* Continue searching. */
      ^
/luavela/src/jit/opt/mem.c:803:10: note: Assuming 'ref' is > 'lim'
  while (ref > lim) {  /* Search for redundant or conflicting stores. */
         ^
/luavela/src/jit/opt/mem.c:803:3: note: Loop condition is true.  Entering loop body
  while (ref > lim) {  /* Search for redundant or conflicting stores. */
  ^
/luavela/src/jit/opt/mem.c:805:5: note: Control jumps to 'case ALIAS_MAY:'  at line 808
    switch (aa_xref(J, xr, fins, store)) {
    ^
/luavela/src/jit/opt/mem.c:809:11: note: Assuming 'val' is equal to field 'op2'
      if (store->op2 != val)  /* Conflict if the value is different. */
          ^
/luavela/src/jit/opt/mem.c:809:7: note: Taking false branch
      if (store->op2 != val)  /* Conflict if the value is different. */
      ^
/luavela/src/jit/opt/mem.c:811:7: note:  Execution continues on line 829
      break;  /* Otherwise continue searching. */
      ^
/luavela/src/jit/opt/mem.c:803:10: note: Assuming 'ref' is > 'lim'
  while (ref > lim) {  /* Search for redundant or conflicting stores. */
         ^
/luavela/src/jit/opt/mem.c:803:3: note: Loop condition is true.  Entering loop body
  while (ref > lim) {  /* Search for redundant or conflicting stores. */
  ^
/luavela/src/jit/opt/mem.c:805:13: note: Calling 'aa_xref'
    switch (aa_xref(J, xr, fins, store)) {
            ^
/luavela/src/jit/opt/mem.c:619:7: note: Assuming 'refa' is not equal to 'refb'
  if (refa == refb && irt_sametype(xa->t, xb->t))
      ^
/luavela/src/jit/opt/mem.c:619:20: note: Left side of '&&' is false
  if (refa == refb && irt_sametype(xa->t, xb->t))
                   ^
/luavela/src/jit/opt/mem.c:622:13: note: Field 'o' is not equal to IR_ADD
  if (refa->o == IR_ADD && irref_isk(refa->op2)) {
            ^
/luavela/src/jit/opt/mem.c:622:25: note: Left side of '&&' is false
  if (refa->o == IR_ADD && irref_isk(refa->op2)) {
                        ^
/luavela/src/jit/opt/mem.c:628:7: note: Assuming field 'o' is not equal to IR_ADD
  if (refb->o == IR_ADD && irref_isk(refb->op2)) {
      ^
/luavela/src/jit/opt/mem.c:628:25: note: Left side of '&&' is false
  if (refb->o == IR_ADD && irref_isk(refb->op2)) {
                        ^
/luavela/src/jit/opt/mem.c:635:14: note: Field 'o' is not equal to IR_KPTR
  if (basea->o == IR_KPTR && baseb->o == IR_KPTR) {
             ^
/luavela/src/jit/opt/mem.c:635:27: note: Left side of '&&' is false
  if (basea->o == IR_KPTR && baseb->o == IR_KPTR) {
                          ^
/luavela/src/jit/opt/mem.c:643:7: note: 'basea' is not equal to 'baseb'
  if (basea == baseb) {
      ^
/luavela/src/jit/opt/mem.c:643:3: note: Taking false branch
  if (basea == baseb) {
  ^
/luavela/src/jit/opt/mem.c:654:8: note: Assuming the condition is true
  if (!irt_sametype(xa->t, xb->t) &&
       ^
/luavela/src/jit/lj_ir.h:361:34: note: expanded from macro 'irt_sametype'
#define irt_sametype(t1, t2)    ((((t1).irt ^ (t2).irt) & IRT_TYPE) == 0)
                                 ^
/luavela/src/jit/opt/mem.c:654:35: note: Left side of '&&' is false
  if (!irt_sametype(xa->t, xb->t) &&
                                  ^
/luavela/src/jit/opt/mem.c:659:10: note: Calling 'aa_cnew'
  return aa_cnew(J, basea, baseb);  /* Try to disambiguate allocations. */
         ^
/luavela/src/jit/opt/mem.c:605:7: note: Assuming 'cnewa' is not equal to 'cnewb'
  if (cnewa == cnewb)
      ^
/luavela/src/jit/opt/mem.c:605:3: note: Taking false branch
  if (cnewa == cnewb)
  ^
/luavela/src/jit/opt/mem.c:607:7: note: Assuming 'cnewa' is null
  if (cnewa && cnewb)
      ^
/luavela/src/jit/opt/mem.c:607:13: note: Left side of '&&' is false
  if (cnewa && cnewb)
            ^
/luavela/src/jit/opt/mem.c:609:7: note: Assuming 'cnewb' is null
  if (cnewb) { cnewa = cnewb; refb = refa; }
      ^
/luavela/src/jit/opt/mem.c:609:3: note: Taking false branch
  if (cnewb) { cnewa = cnewb; refb = refa; }
  ^
/luavela/src/jit/opt/mem.c:610:10: note: Calling 'aa_escape'
  return aa_escape(J, cnewa, refb);
         ^
/luavela/src/jit/opt/mem.c:47:8: note: Null pointer value stored to 'ir'
  for (ir++; ir < stop; ir++)
       ^
/luavela/src/jit/opt/mem.c:47:3: note: Loop condition is true.  Entering loop body
  for (ir++; ir < stop; ir++)
  ^
/luavela/src/jit/opt/mem.c:48:9: note: Dereference of null pointer
    if (ir->op2 == ref &&
        ^
/luavela/src/lib/string.c:317:43: error: Dereference of null pointer (loaded from variable 's') [clang-analyzer-core.NullDereference,-warnings-as-errors]
    else if (s<ms->src_end && singlematch(uchar(*s), p, ep))
                                          ^
/luavela/src/lib/string.c:162:41: note: expanded from macro 'uchar'
#define uchar(c)        ((unsigned char)(c))
                                        ^
/luavela/src/lib/string.c:643:3: note: 'src' initialized here
  const char *src = luaL_checklstring(L, 1, &srcl);
  ^
/luavela/src/lib/string.c:647:17: note: Assuming the condition is false
  int anchor = (*p == '^') ? (p++, 1) : 0;
                ^
/luavela/src/lib/string.c:647:16: note: '?' condition is false
  int anchor = (*p == '^') ? (p++, 1) : 0;
               ^
/luavela/src/lib/string.c:651:9: note: Assuming 'tr' is equal to LUA_TNUMBER
  if (!(tr == LUA_TNUMBER || tr == LUA_TSTRING ||
        ^
/luavela/src/lib/string.c:651:27: note: Left side of '||' is true
  if (!(tr == LUA_TNUMBER || tr == LUA_TSTRING ||
                          ^
/luavela/src/lib/string.c:651:3: note: Taking false branch
  if (!(tr == LUA_TNUMBER || tr == LUA_TSTRING ||
  ^
/luavela/src/lib/string.c:658:10: note: Assuming 'n' is < 'max_s'
  while (n < max_s) {
         ^
/luavela/src/lib/string.c:658:3: note: Loop condition is true.  Entering loop body
  while (n < max_s) {
  ^
/luavela/src/lib/string.c:661:20: note: Passing value via 2nd parameter 's'
    e = match(&ms, src, p);
                   ^
/luavela/src/lib/string.c:661:9: note: Calling 'match'
    e = match(&ms, src, p);
        ^
/luavela/src/lib/string.c:363:3: note: Taking false branch
  if (++ms->depth > LJ_MAX_XLEVEL)
  ^
/luavela/src/lib/string.c:366:3: note: Control jumps to the 'default' case at line 412
  switch (*p) {
  ^
/luavela/src/lib/string.c:414:13: note: Assuming 's' is >= field 'src_end'
    int m = s<ms->src_end && singlematch(uchar(*s), p, ep);
            ^
/luavela/src/lib/string.c:414:27: note: Left side of '&&' is false
    int m = s<ms->src_end && singlematch(uchar(*s), p, ep);
                          ^
/luavela/src/lib/string.c:415:5: note: Control jumps to 'case 45:'  at line 431
    switch (*ep) {
    ^
/luavela/src/lib/string.c:432:26: note: Passing value via 2nd parameter 's'
      s = min_expand(ms, s, p, ep);
                         ^
/luavela/src/lib/string.c:432:11: note: Calling 'min_expand'
      s = min_expand(ms, s, p, ep);
          ^
/luavela/src/lib/string.c:313:3: note: Loop condition is true.  Entering loop body
  for (;;) {
  ^
/luavela/src/lib/string.c:315:9: note: Assuming 'res' is equal to NULL
    if (res != NULL)
        ^
/luavela/src/lib/string.c:315:5: note: Taking false branch
    if (res != NULL)
    ^
/luavela/src/lib/string.c:317:14: note: 's' is < field 'src_end'
    else if (s<ms->src_end && singlematch(uchar(*s), p, ep))
             ^
/luavela/src/lib/string.c:317:14: note: Left side of '&&' is true
/luavela/src/lib/string.c:317:43: note: Dereference of null pointer (loaded from variable 's')
    else if (s<ms->src_end && singlematch(uchar(*s), p, ep))
                                          ^
/luavela/src/lib/string.c:162:41: note: expanded from macro 'uchar'
#define uchar(c)        ((unsigned char)(c))
                                        ^
/luavela/src/lib/string.c:669:7: error: Dereference of null pointer [clang-analyzer-core.NullDereference,-warnings-as-errors]
      luaL_addchar(&b, *src++);
      ^
/luavela/src/lauxlib.h:132:21: note: expanded from macro 'luaL_addchar'
        (*(B)->p++ = (char)(c)))
                           ^
/luavela/src/lib/string.c:643:3: note: 'src' initialized here
  const char *src = luaL_checklstring(L, 1, &srcl);
  ^
/luavela/src/lib/string.c:647:17: note: Assuming the condition is false
  int anchor = (*p == '^') ? (p++, 1) : 0;
                ^
/luavela/src/lib/string.c:647:16: note: '?' condition is false
  int anchor = (*p == '^') ? (p++, 1) : 0;
               ^
/luavela/src/lib/string.c:651:9: note: Assuming 'tr' is equal to LUA_TNUMBER
  if (!(tr == LUA_TNUMBER || tr == LUA_TSTRING ||
        ^
/luavela/src/lib/string.c:651:27: note: Left side of '||' is true
  if (!(tr == LUA_TNUMBER || tr == LUA_TSTRING ||
                          ^
/luavela/src/lib/string.c:651:3: note: Taking false branch
  if (!(tr == LUA_TNUMBER || tr == LUA_TSTRING ||
  ^
/luavela/src/lib/string.c:658:10: note: Assuming 'n' is < 'max_s'
  while (n < max_s) {
         ^
/luavela/src/lib/string.c:658:3: note: Loop condition is true.  Entering loop body
  while (n < max_s) {
  ^
/luavela/src/lib/string.c:661:9: note: Calling 'match'
    e = match(&ms, src, p);
        ^
/luavela/src/lib/string.c:363:3: note: Taking false branch
  if (++ms->depth > LJ_MAX_XLEVEL)
  ^
/luavela/src/lib/string.c:366:3: note: Control jumps to 'case 36:'  at line 407
  switch (*p) {
  ^
/luavela/src/lib/string.c:409:9: note: Assuming the condition is false
    if (*(p+1) != '\0') goto dflt;
        ^
/luavela/src/lib/string.c:409:5: note: Taking false branch
    if (*(p+1) != '\0') goto dflt;
    ^
/luavela/src/lib/string.c:410:9: note: Assuming 's' is equal to field 'src_end'
    if (s != ms->src_end) s = NULL;  /* check end of string */
        ^
/luavela/src/lib/string.c:410:5: note: Taking false branch
    if (s != ms->src_end) s = NULL;  /* check end of string */
    ^
/luavela/src/lib/string.c:411:5: note:  Execution continues on line 442
    break;
    ^
/luavela/src/lib/string.c:443:3: note: Returning pointer (loaded from 's'), which participates in a condition later
  return s;
  ^
/luavela/src/lib/string.c:661:9: note: Returning from 'match'
    e = match(&ms, src, p);
        ^
/luavela/src/lib/string.c:662:9: note: Assuming 'e' is null
    if (e) {
        ^
/luavela/src/lib/string.c:662:5: note: Taking false branch
    if (e) {
    ^
/luavela/src/lib/string.c:666:9: note: 'e' is null
    if (e && e>src) /* non empty match? */
        ^
/luavela/src/lib/string.c:666:11: note: Left side of '&&' is false
    if (e && e>src) /* non empty match? */
          ^
/luavela/src/lib/string.c:668:14: note: 'src' is < field 'src_end'
    else if (src < ms.src_end)
             ^
/luavela/src/lib/string.c:668:10: note: Taking true branch
    else if (src < ms.src_end)
         ^
/luavela/src/lib/string.c:669:7: note: 8192 is <= 16384
      luaL_addchar(&b, *src++);
      ^
/luavela/src/lauxlib.h:131:32: note: expanded from macro 'luaL_addchar'
        ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
                                      ^
/luavela/src/luaconf.h:150:26: note: expanded from macro 'LUAL_BUFFERSIZE'
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
                         ^
/usr/include/stdio.h:99:16: note: expanded from macro 'BUFSIZ'
#define BUFSIZ 8192
               ^
/luavela/src/lib/string.c:669:7: note: '?' condition is false
      luaL_addchar(&b, *src++);
      ^
/luavela/src/lauxlib.h:131:32: note: expanded from macro 'luaL_addchar'
        ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
                                      ^
/luavela/src/luaconf.h:150:26: note: expanded from macro 'LUAL_BUFFERSIZE'
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
                         ^
/usr/include/stdio.h:99:16: note: expanded from macro 'BUFSIZ'
#define BUFSIZ 8192
               ^
/luavela/src/lib/string.c:669:7: note: Assuming the condition is true
      luaL_addchar(&b, *src++);
      ^
/luavela/src/lauxlib.h:131:10: note: expanded from macro 'luaL_addchar'
        ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
                ^
/luavela/src/lib/string.c:669:7: note: Left side of '||' is true
      luaL_addchar(&b, *src++);
      ^
/luavela/src/lauxlib.h:131:49: note: expanded from macro 'luaL_addchar'
        ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
                                                       ^
/luavela/src/lib/string.c:669:7: note: Dereference of null pointer
      luaL_addchar(&b, *src++);
      ^
/luavela/src/lauxlib.h:132:21: note: expanded from macro 'luaL_addchar'
        (*(B)->p++ = (char)(c)))
                           ^
/luavela/src/lj_obj.h:840:10: error: Dereference of null pointer [clang-analyzer-core.NullDereference,-warnings-as-errors]
  o->gcr = v;
         ^
/luavela/src/lj_tab.c:1121:31: note: Assuming field 'hmask' is <= 0
  dst = newtab(L, src->asize, src->hmask > 0 ? lj_bsr(src->hmask) + 1 : 0);
                              ^
/luavela/src/lj_tab.c:1121:31: note: '?' condition is false
/luavela/src/lj_tab.c:1121:9: note: Calling 'newtab'
  dst = newtab(L, src->asize, src->hmask > 0 ? lj_bsr(src->hmask) + 1 : 0);
        ^
/luavela/src/lj_tab.c:145:7: note: LJ_MAX_COLOSIZE is not equal to 0
  if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) {
      ^
/luavela/src/lj_def.h:33:25: note: expanded from macro 'LJ_MAX_COLOSIZE'
#define LJ_MAX_COLOSIZE 16              /* Max. elems for colocated array. */
                        ^
/luavela/src/lj_tab.c:145:7: note: Left side of '&&' is true
  if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) {
      ^
/luavela/src/lj_def.h:33:25: note: expanded from macro 'LJ_MAX_COLOSIZE'
#define LJ_MAX_COLOSIZE 16              /* Max. elems for colocated array. */
                        ^
/luavela/src/lj_tab.c:145:31: note: Assuming 'asize' is <= 0
  if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) {
                              ^
/luavela/src/lj_tab.c:145:41: note: Left side of '&&' is false
  if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) {
                                        ^
/luavela/src/lj_tab.c:154:5: note: Null pointer value stored to field 'array'
    t->array = NULL;
    ^
/luavela/src/lj_tab.c:156:9: note: 'asize' is <= 0
    if (asize > 0) {
        ^
/luavela/src/lj_tab.c:156:5: note: Taking false branch
    if (asize > 0) {
    ^
/luavela/src/lj_tab.c:164:3: note: Calling 'clearapart'
  clearapart(t);
  ^
/luavela/src/lj_tab.c:125:3: note: Loop condition is false. Execution continues on line 125
  for (i = 0; i < asize; i++) {
  ^
/luavela/src/lj_tab.c:128:1: note: Returning without writing to 't->array'
}
^
/luavela/src/lj_tab.c:164:3: note: Returning from 'clearapart'
  clearapart(t);
  ^
/luavela/src/lj_tab.c:176:3: note: Calling 'newhpart'
  newhpart(L, t, hbits);
  ^
/luavela/src/lj_tab.c:100:7: note: 'hbits' is 0
  if (hbits) { /* Allocate and clear new hash part. */
      ^
/luavela/src/lj_tab.c:100:3: note: Taking false branch
  if (hbits) { /* Allocate and clear new hash part. */
  ^
/luavela/src/lj_tab.c:118:1: note: Returning without writing to 't->array'
}
^
/luavela/src/lj_tab.c:176:3: note: Returning from 'newhpart'
  newhpart(L, t, hbits);
  ^
/luavela/src/lj_tab.c:1121:9: note: Returning from 'newtab'
  dst = newtab(L, src->asize, src->hmask > 0 ? lj_bsr(src->hmask) + 1 : 0);
        ^
/luavela/src/lj_tab.c:1122:19: note: 'src->asize' is equal to 'dst->asize'
  lua_assert(src->asize == dst->asize);
                  ^
/luavela/src/lj_tab.c:1122:3: note: '?' condition is true
  lua_assert(src->asize == dst->asize);
  ^
/luavela/src/luaconf.h:25:29: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                            ^
/usr/include/assert.h:98:6: note: expanded from macro 'assert'
    ((expr)                                                             \
     ^
/luavela/src/lj_tab.c:1123:19: note: 'src->hmask' is equal to 'dst->hmask'
  lua_assert(src->hmask == dst->hmask);
                  ^
/luavela/src/lj_tab.c:1123:3: note: '?' condition is true
  lua_assert(src->hmask == dst->hmask);
  ^
/luavela/src/luaconf.h:25:29: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                            ^
/usr/include/assert.h:98:6: note: expanded from macro 'assert'
    ((expr)                                                             \
     ^
/luavela/src/lj_tab.c:1126:3: note: Calling 'tab_deepcopy_map_add'
  tab_deepcopy_map_add(L, ctx->map, src, dst);
  ^
/luavela/src/lj_tab.c:1064:3: note: Calling 'settabV'
  settabV(L, valuetv, val);
  ^
/luavela/src/lj_obj.h:862:3: note: Calling 'setgcV'
  setgcV(L, tv, obj2gco(v), LJ_TTAB);
  ^
/luavela/src/lj_obj.h:842:3: note: Left side of '||' is false
  tvchecklive(L, o);
  ^
/luavela/src/lj_obj.h:835:25: note: expanded from macro 'tvchecklive'
  UNUSED(L), lua_assert(!tvisgcv(o) || uj_obj_is_sealed(gcval(o)) || \
                        ^
/luavela/src/lj_obj.h:842:3: note: Assuming the condition is true
  tvchecklive(L, o);
  ^
/luavela/src/lj_obj.h:835:40: note: expanded from macro 'tvchecklive'
  UNUSED(L), lua_assert(!tvisgcv(o) || uj_obj_is_sealed(gcval(o)) || \
                                       ^
/luavela/src/luaconf.h:25:36: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                                   ^
/usr/include/assert.h:98:7: note: expanded from macro 'assert'
    ((expr)                                                             \
      ^
/luavela/src/lj_obj.h:842:3: note: Left side of '||' is true
  tvchecklive(L, o);
  ^
/luavela/src/lj_obj.h:835:67: note: expanded from macro 'tvchecklive'
  UNUSED(L), lua_assert(!tvisgcv(o) || uj_obj_is_sealed(gcval(o)) || \
                                                                  ^
/luavela/src/lj_obj.h:862:3: note: Returning from 'setgcV'
  setgcV(L, tv, obj2gco(v), LJ_TTAB);
  ^
/luavela/src/lj_obj.h:863:1: note: Returning without writing to 'v->array'
}
^
/luavela/src/lj_tab.c:1064:3: note: Returning from 'settabV'
  settabV(L, valuetv, val);
  ^
/luavela/src/lj_tab.c:1065:1: note: Returning without writing to 'val->array'
}
^
/luavela/src/lj_tab.c:1126:3: note: Returning from 'tab_deepcopy_map_add'
  tab_deepcopy_map_add(L, ctx->map, src, dst);
  ^
/luavela/src/lj_tab.c:1130:3: note: Calling 'tab_deepcopy_apart'
  tab_deepcopy_apart(L, dst, src, ctx);
  ^
/luavela/src/lj_tab.c:1086:15: note: Assuming 'i' is < field 'asize'
  for (i = 0; i < src->asize; i++)
              ^
/luavela/src/lj_tab.c:1086:3: note: Loop condition is true.  Entering loop body
  for (i = 0; i < src->asize; i++)
  ^
/luavela/src/lj_tab.c:1087:24: note: Passing null pointer value via 2nd parameter 'dst'
    tab_deepcopy_tv(L, arrayslot(dst, i), arrayslot(src, i), ctx);
                       ^
/luavela/src/lj_tab.h:58:33: note: expanded from macro 'arrayslot'
#define arrayslot(t, i)         (&((t)->array)[(i)])
                                ^
/luavela/src/lj_tab.c:1087:5: note: Calling 'tab_deepcopy_tv'
    tab_deepcopy_tv(L, arrayslot(dst, i), arrayslot(src, i), ctx);
    ^
/luavela/src/lj_tab.c:1072:8: note: Assuming the condition is true
  if (!tvisgcv(src)) {
       ^
/luavela/src/lj_obj.h:778:26: note: expanded from macro 'tvisgcv'
#define tvisgcv(o)      ((gettag(o) - LJ_TISGCV) > (LJ_TNUMX - LJ_TISGCV))
                         ^
/luavela/src/lj_tab.c:1072:3: note: Taking false branch
  if (!tvisgcv(src)) {
  ^
/luavela/src/lj_tab.c:1077:9: note: '?' condition is true
  obj = gcV(src);
        ^
/luavela/src/lj_obj.h:790:25: note: expanded from macro 'gcV'
#define gcV(o)          lua_check(tvisgcv(o), gcval(o))
                        ^
/luavela/src/lj_def.h:144:26: note: expanded from macro 'lua_check'
#define lua_check(c, e) (lua_assert(c), (e))
                         ^
/luavela/src/luaconf.h:25:29: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                            ^
/usr/include/assert.h:98:6: note: expanded from macro 'assert'
    ((expr)                                                             \
     ^
/luavela/src/lj_tab.c:1078:13: note: Passing null pointer value via 2nd parameter 'o'
  setgcV(L, dst, uj_obj_deepcopy(L, obj, ctx), ~obj->gch.gct);
            ^
/luavela/src/lj_tab.c:1078:3: note: Calling 'setgcV'
  setgcV(L, dst, uj_obj_deepcopy(L, obj, ctx), ~obj->gch.gct);
  ^
/luavela/src/lj_obj.h:840:10: note: Dereference of null pointer
  o->gcr = v;
         ^
/luavela/src/lj_obj.h:897:7: error: Dereference of null pointer (loaded from variable 'o1') [clang-analyzer-core.NullDereference,-warnings-as-errors]
  *o1 = *o2; tvchecklive(L, o1);
      ^
/luavela/src/lj_tab.c:1121:31: note: Assuming field 'hmask' is <= 0
  dst = newtab(L, src->asize, src->hmask > 0 ? lj_bsr(src->hmask) + 1 : 0);
                              ^
/luavela/src/lj_tab.c:1121:31: note: '?' condition is false
/luavela/src/lj_tab.c:1121:9: note: Calling 'newtab'
  dst = newtab(L, src->asize, src->hmask > 0 ? lj_bsr(src->hmask) + 1 : 0);
        ^
/luavela/src/lj_tab.c:145:7: note: LJ_MAX_COLOSIZE is not equal to 0
  if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) {
      ^
/luavela/src/lj_def.h:33:25: note: expanded from macro 'LJ_MAX_COLOSIZE'
#define LJ_MAX_COLOSIZE 16              /* Max. elems for colocated array. */
                        ^
/luavela/src/lj_tab.c:145:7: note: Left side of '&&' is true
  if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) {
      ^
/luavela/src/lj_def.h:33:25: note: expanded from macro 'LJ_MAX_COLOSIZE'
#define LJ_MAX_COLOSIZE 16              /* Max. elems for colocated array. */
                        ^
/luavela/src/lj_tab.c:145:31: note: Assuming 'asize' is <= 0
  if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) {
                              ^
/luavela/src/lj_tab.c:145:41: note: Left side of '&&' is false
  if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) {
                                        ^
/luavela/src/lj_tab.c:154:5: note: Null pointer value stored to field 'array'
    t->array = NULL;
    ^
/luavela/src/lj_tab.c:156:9: note: 'asize' is <= 0
    if (asize > 0) {
        ^
/luavela/src/lj_tab.c:156:5: note: Taking false branch
    if (asize > 0) {
    ^
/luavela/src/lj_tab.c:164:3: note: Calling 'clearapart'
  clearapart(t);
  ^
/luavela/src/lj_tab.c:125:3: note: Loop condition is false. Execution continues on line 125
  for (i = 0; i < asize; i++) {
  ^
/luavela/src/lj_tab.c:128:1: note: Returning without writing to 't->array'
}
^
/luavela/src/lj_tab.c:164:3: note: Returning from 'clearapart'
  clearapart(t);
  ^
/luavela/src/lj_tab.c:176:3: note: Calling 'newhpart'
  newhpart(L, t, hbits);
  ^
/luavela/src/lj_tab.c:100:7: note: 'hbits' is 0
  if (hbits) { /* Allocate and clear new hash part. */
      ^
/luavela/src/lj_tab.c:100:3: note: Taking false branch
  if (hbits) { /* Allocate and clear new hash part. */
  ^
/luavela/src/lj_tab.c:118:1: note: Returning without writing to 't->array'
}
^
/luavela/src/lj_tab.c:176:3: note: Returning from 'newhpart'
  newhpart(L, t, hbits);
  ^
/luavela/src/lj_tab.c:1121:9: note: Returning from 'newtab'
  dst = newtab(L, src->asize, src->hmask > 0 ? lj_bsr(src->hmask) + 1 : 0);
        ^
/luavela/src/lj_tab.c:1122:19: note: 'src->asize' is equal to 'dst->asize'
  lua_assert(src->asize == dst->asize);
                  ^
/luavela/src/lj_tab.c:1122:3: note: '?' condition is true
  lua_assert(src->asize == dst->asize);
  ^
/luavela/src/luaconf.h:25:29: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                            ^
/usr/include/assert.h:98:6: note: expanded from macro 'assert'
    ((expr)                                                             \
     ^
/luavela/src/lj_tab.c:1123:19: note: 'src->hmask' is equal to 'dst->hmask'
  lua_assert(src->hmask == dst->hmask);
                  ^
/luavela/src/lj_tab.c:1123:3: note: '?' condition is true
  lua_assert(src->hmask == dst->hmask);
  ^
/luavela/src/luaconf.h:25:29: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                            ^
/usr/include/assert.h:98:6: note: expanded from macro 'assert'
    ((expr)                                                             \
     ^
/luavela/src/lj_tab.c:1126:3: note: Calling 'tab_deepcopy_map_add'
  tab_deepcopy_map_add(L, ctx->map, src, dst);
  ^
/luavela/src/lj_tab.c:1064:3: note: Calling 'settabV'
  settabV(L, valuetv, val);
  ^
/luavela/src/lj_obj.h:862:3: note: Calling 'setgcV'
  setgcV(L, tv, obj2gco(v), LJ_TTAB);
  ^
/luavela/src/lj_obj.h:842:3: note: Left side of '||' is false
  tvchecklive(L, o);
  ^
/luavela/src/lj_obj.h:835:25: note: expanded from macro 'tvchecklive'
  UNUSED(L), lua_assert(!tvisgcv(o) || uj_obj_is_sealed(gcval(o)) || \
                        ^
/luavela/src/lj_obj.h:842:3: note: Assuming the condition is true
  tvchecklive(L, o);
  ^
/luavela/src/lj_obj.h:835:40: note: expanded from macro 'tvchecklive'
  UNUSED(L), lua_assert(!tvisgcv(o) || uj_obj_is_sealed(gcval(o)) || \
                                       ^
/luavela/src/luaconf.h:25:36: note: expanded from macro 'lua_assert'
#define lua_assert(c)       assert(c)
                                   ^
/usr/include/assert.h:98:7: note: expanded from macro 'assert'
    ((expr)                                                             \
      ^
/luavela/src/lj_obj.h:842:3: note: Left side of '||' is true
  tvchecklive(L, o);
  ^
/luavela/src/lj_obj.h:835:67: note: expanded from macro 'tvchecklive'
  UNUSED(L), lua_assert(!tvisgcv(o) || uj_obj_is_sealed(gcval(o)) || \
                                                                  ^
/luavela/src/lj_obj.h:862:3: note: Returning from 'setgcV'
  setgcV(L, tv, obj2gco(v), LJ_TTAB);
  ^
/luavela/src/lj_obj.h:863:1: note: Returning without writing to 'v->array'
}
^
/luavela/src/lj_tab.c:1064:3: note: Returning from 'settabV'
  settabV(L, valuetv, val);
  ^
/luavela/src/lj_tab.c:1065:1: note: Returning without writing to 'val->array'
}
^
/luavela/src/lj_tab.c:1126:3: note: Returning from 'tab_deepcopy_map_add'
  tab_deepcopy_map_add(L, ctx->map, src, dst);
  ^
/luavela/src/lj_tab.c:1130:3: note: Calling 'tab_deepcopy_apart'
  tab_deepcopy_apart(L, dst, src, ctx);
  ^
/luavela/src/lj_tab.c:1086:15: note: Assuming 'i' is < field 'asize'
  for (i = 0; i < src->asize; i++)
              ^
/luavela/src/lj_tab.c:1086:3: note: Loop condition is true.  Entering loop body
  for (i = 0; i < src->asize; i++)
  ^
/luavela/src/lj_tab.c:1087:24: note: Passing null pointer value via 2nd parameter 'dst'
    tab_deepcopy_tv(L, arrayslot(dst, i), arrayslot(src, i), ctx);
                       ^
/luavela/src/lj_tab.h:58:33: note: expanded from macro 'arrayslot'
#define arrayslot(t, i)         (&((t)->array)[(i)])
                                ^
/luavela/src/lj_tab.c:1087:5: note: Calling 'tab_deepcopy_tv'
    tab_deepcopy_tv(L, arrayslot(dst, i), arrayslot(src, i), ctx);
    ^
/luavela/src/lj_tab.c:1072:8: note: Assuming the condition is false
  if (!tvisgcv(src)) {
       ^
/luavela/src/lj_obj.h:778:26: note: expanded from macro 'tvisgcv'
#define tvisgcv(o)      ((gettag(o) - LJ_TISGCV) > (LJ_TNUMX - LJ_TISGCV))
                         ^
/luavela/src/lj_tab.c:1072:3: note: Taking true branch
  if (!tvisgcv(src)) {
  ^
/luavela/src/lj_tab.c:1073:15: note: Passing null pointer value via 2nd parameter 'o1'
    copyTV(L, dst, src);
              ^
/luavela/src/lj_tab.c:1073:5: note: Calling 'copyTV'
    copyTV(L, dst, src);
    ^
/luavela/src/lj_obj.h:897:7: note: Dereference of null pointer (loaded from variable 'o1')
  *o1 = *o2; tvchecklive(L, o1);
      ^

All the warnings should be verified whether any of them found the real bug or it's just a false positive.

README states that the LuaVela is a fork of LuaJIT

LuaVela is a fork of LuaJIT, the README for LuaJIT is below.

This might be misleading, as LuaVela is a rewrite of LuaJIT. "Fork", IMHO, leads to assume some level of future feature / semantics compatibility.

Fix `misc-no-recursion` warnings

As a result of updating clang-tidy up to version 11, new check misc-no-recursion produced several warnings.

/luavela/src/dump/uj_dump_ir.c:294:13: error: function 'dump_ir_func_args' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void dump_ir_func_args(FILE *out, const GCtrace *trace, IRRef ref)
            ^
/luavela/src/dump/uj_dump_ir.c:294:13: note: example recursive call chain, starting from function 'dump_ir_func_args'
/luavela/src/dump/uj_dump_ir.c:309:2: note: Frame #1: function 'dump_ir_func_args' calls function 'dump_ir_func_args' here:
        dump_ir_func_args(out, trace, ins->op1);
        ^
/luavela/src/dump/uj_dump_ir.c:309:2: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/frontend/lj_bcwrite.c:206:13: error: function 'bcwrite_proto' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
            ^
/luavela/src/frontend/lj_bcwrite.c:206:13: note: example recursive call chain, starting from function 'bcwrite_proto'
/luavela/src/frontend/lj_bcwrite.c:220:9: note: Frame #1: function 'bcwrite_proto' calls function 'bcwrite_proto' here:
        bcwrite_proto(ctx, gco2pt(o));
        ^
/luavela/src/frontend/lj_bcwrite.c:220:9: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/frontend/lj_lex.c:62:24: error: function 'save' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static LJ_AINLINE void save(LexState *ls, int c) {
                       ^
/luavela/src/frontend/lj_lex.c:458:20: note: example recursive call chain, starting from function 'lex_error_tok_str'
static const char *lex_error_tok_str(LexState *ls, LexToken token)
                   ^
/luavela/src/frontend/lj_lex.c:465:5: note: Frame #1: function 'lex_error_tok_str' calls function 'save' here:
    save(ls, '\0');
    ^
/luavela/src/frontend/lj_lex.c:66:5: note: Frame #2: function 'save' calls function 'lj_lex_error_' here:
    lj_lex_error(ls, 0, UJ_ERR_XELEM, NULL);
    ^
/luavela/src/frontend/lj_lex.h:107:3: note: expanded from macro 'lj_lex_error'
  lj_lex_error_((ls), (token), uj_errmsg(em), __VA_ARGS__)
  ^
/luavela/src/frontend/lj_lex.c:488:13: note: Frame #3: function 'lj_lex_error_' calls function 'lex_error_tok_str' here:
  tok_str = lex_error_tok_str(ls, token);
            ^
/luavela/src/frontend/lj_lex.c:488:13: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/frontend/lj_lex.c:458:20: error: function 'lex_error_tok_str' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static const char *lex_error_tok_str(LexState *ls, LexToken token)
                   ^
/luavela/src/frontend/lj_lex.c:480:6: error: function 'lj_lex_error_' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
void lj_lex_error_(LexState *ls, LexToken token, const char *em, ...)
     ^
/luavela/src/frontend/lj_parse.c:1053:15: error: function 'var_lookup_' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static size_t var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first)
              ^
/luavela/src/frontend/lj_parse.c:1053:15: note: example recursive call chain, starting from function 'var_lookup_'
/luavela/src/frontend/lj_parse.c:1063:21: note: Frame #1: function 'var_lookup_' calls function 'var_lookup_' here:
      size_t vidx = var_lookup_(fs->prev, name, e, 0);  /* Var in outer func? */
                    ^
/luavela/src/frontend/lj_parse.c:1063:21: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/frontend/lj_parse.c:1609:13: error: function 'expr_bracket' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void expr_bracket(LexState *ls, ExpDesc *v)
            ^
/luavela/src/frontend/lj_parse.c:2044:13: note: example recursive call chain, starting from function 'expr'
static void expr(LexState *ls, ExpDesc *v)
            ^
/luavela/src/frontend/lj_parse.c:2046:3: note: Frame #1: function 'expr' calls function 'expr_binop' here:
  expr_binop(ls, v, 0);  /* Priority 0: parse whole expression. */
  ^
/luavela/src/frontend/lj_parse.c:2027:3: note: Frame #2: function 'expr_binop' calls function 'expr_unop' here:
  expr_unop(ls, v);
  ^
/luavela/src/frontend/lj_parse.c:2014:5: note: Frame #3: function 'expr_unop' calls function 'expr_simple' here:
    expr_simple(ls, v);
    ^
/luavela/src/frontend/lj_parse.c:1941:5: note: Frame #4: function 'expr_simple' calls function 'expr_table' here:
    expr_table(ls, v);
    ^
/luavela/src/frontend/lj_parse.c:1649:7: note: Frame #5: function 'expr_table' calls function 'expr_bracket' here:
      expr_bracket(ls, &key);  /* Already calls expr_toval. */ 
      ^
/luavela/src/frontend/lj_parse.c:1612:3: note: Frame #6: function 'expr_bracket' calls function 'expr' here:
  expr(ls, v);
  ^
/luavela/src/frontend/lj_parse.c:1612:3: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/frontend/lj_parse.c:1631:13: error: function 'expr_table' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void expr_table(LexState *ls, ExpDesc *e)
            ^
/luavela/src/frontend/lj_parse.c:1778:13: error: function 'parse_body' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line)
            ^
/luavela/src/frontend/lj_parse.c:1812:14: error: function 'expr_list' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static BCReg expr_list(LexState *ls, ExpDesc *v)
             ^
/luavela/src/frontend/lj_parse.c:1825:13: error: function 'parse_args' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_args(LexState *ls, ExpDesc *e)
            ^
/luavela/src/frontend/lj_parse.c:1871:13: error: function 'expr_primary' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void expr_primary(LexState *ls, ExpDesc *v)
            ^
/luavela/src/frontend/lj_parse.c:1910:13: error: function 'expr_simple' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void expr_simple(LexState *ls, ExpDesc *v)
            ^
/luavela/src/frontend/lj_parse.c:2004:13: error: function 'expr_unop' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void expr_unop(LexState *ls, ExpDesc *v)
            ^
/luavela/src/frontend/lj_parse.c:2023:15: error: function 'expr_binop' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static BinOpr expr_binop(LexState *ls, ExpDesc *v, uint32_t limit)
              ^
/luavela/src/frontend/lj_parse.c:2044:13: error: function 'expr' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void expr(LexState *ls, ExpDesc *v)
            ^
/luavela/src/frontend/lj_parse.c:2050:13: error: function 'expr_next' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void expr_next(LexState *ls)
            ^
/luavela/src/frontend/lj_parse.c:2058:14: error: function 'expr_cond' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static BCPos expr_cond(LexState *ls)
             ^
/luavela/src/frontend/lj_parse.c:2124:13: error: function 'parse_assignment' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_assignment(LexState *ls, LHSVarList *lh, BCReg nvars)
            ^
/luavela/src/frontend/lj_parse.c:2161:13: error: function 'parse_call_assign' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_call_assign(LexState *ls)
            ^
/luavela/src/frontend/lj_parse.c:2175:13: error: function 'parse_local' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_local(LexState *ls)
            ^
/luavela/src/frontend/lj_parse.c:2209:13: error: function 'parse_func' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_func(LexState *ls, BCLine line)
            ^
/luavela/src/frontend/lj_parse.c:2243:13: error: function 'parse_return' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_return(LexState *ls)
            ^
/luavela/src/frontend/lj_parse.c:2302:13: error: function 'parse_label' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_label(LexState *ls)
            ^
/luavela/src/frontend/lj_parse.c:2302:13: note: example recursive call chain, starting from function 'parse_label'
/luavela/src/frontend/lj_parse.c:2319:7: note: Frame #1: function 'parse_label' calls function 'parse_label' here:
      parse_label(ls);
      ^
/luavela/src/frontend/lj_parse.c:2319:7: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/frontend/lj_parse.c:2336:13: error: function 'parse_block' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_block(LexState *ls)
            ^
/luavela/src/frontend/lj_parse.c:2346:13: error: function 'parse_while' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_while(LexState *ls, BCLine line)
            ^
/luavela/src/frontend/lj_parse.c:2367:13: error: function 'parse_repeat' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_repeat(LexState *ls, BCLine line)
            ^
/luavela/src/frontend/lj_parse.c:2399:13: error: function 'parse_for_num' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_for_num(LexState *ls, GCstr *varname, BCLine line)
            ^
/luavela/src/frontend/lj_parse.c:2471:13: error: function 'parse_for_iter' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_for_iter(LexState *ls, GCstr *indexname)
            ^
/luavela/src/frontend/lj_parse.c:2514:13: error: function 'parse_for' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_for(LexState *ls, BCLine line)
            ^
/luavela/src/frontend/lj_parse.c:2533:14: error: function 'parse_then' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static BCPos parse_then(LexState *ls)
             ^
/luavela/src/frontend/lj_parse.c:2544:13: error: function 'parse_if' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_if(LexState *ls, BCLine line)
            ^
/luavela/src/frontend/lj_parse.c:2570:12: error: function 'parse_stmt' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static int parse_stmt(LexState *ls)
           ^
/luavela/src/frontend/lj_parse.c:2627:13: error: function 'parse_chunk' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void parse_chunk(LexState *ls)
            ^
/luavela/src/jit/lj_snap.c:605:13: error: function 'snap_restoreval' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void snap_restoreval(jit_State *J, GCtrace *T, ExitState *ex,
            ^
/luavela/src/jit/lj_snap.c:605:13: note: example recursive call chain, starting from function 'snap_restoreval'
/luavela/src/jit/lj_snap.c:643:7: note: Frame #1: function 'snap_restoreval' calls function 'snap_restoreval' here:
      snap_restoreval(J, T, ex, snapno, rfilt, ir->op1, o, low);
      ^
/luavela/src/jit/lj_snap.c:643:7: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/jit/lj_snap.c:666:13: error: function 'snap_restoredata' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void snap_restoredata(GCtrace *T, ExitState *ex,
            ^
/luavela/src/jit/lj_snap.c:666:13: note: example recursive call chain, starting from function 'snap_restoredata'
/luavela/src/jit/lj_snap.c:693:9: note: Frame #1: function 'snap_restoredata' calls function 'snap_restoredata' here:
        snap_restoredata(T, ex, snapno, rfilt, ir->op1, dst, 4);
        ^
/luavela/src/jit/lj_snap.c:693:9: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/jit/opt/narrow.c:241:13: error: function 'narrow_stripov_backprop' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void narrow_stripov_backprop(NarrowConv *nc, IRRef ref, int depth)
            ^
/luavela/src/jit/opt/narrow.c:241:13: note: example recursive call chain, starting from function 'narrow_stripov_backprop'
/luavela/src/jit/opt/narrow.c:252:7: note: Frame #1: function 'narrow_stripov_backprop' calls function 'narrow_stripov_backprop' here:
      narrow_stripov_backprop(nc, ir->op1, depth);
      ^
/luavela/src/jit/opt/narrow.c:252:7: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/jit/opt/narrow.c:267:12: error: function 'narrow_conv_backprop' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static int narrow_conv_backprop(NarrowConv *nc, IRRef ref, int depth)
           ^
/luavela/src/jit/opt/narrow.c:267:12: note: example recursive call chain, starting from function 'narrow_conv_backprop'
/luavela/src/jit/opt/narrow.c:344:19: note: Frame #1: function 'narrow_conv_backprop' calls function 'narrow_conv_backprop' here:
      int count = narrow_conv_backprop(nc, ir->op1, depth);
                  ^
/luavela/src/jit/opt/narrow.c:344:19: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/jit/opt/narrow.c:433:13: error: function 'narrow_stripov' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static TRef narrow_stripov(jit_State *J, TRef tr, int lastop, IRRef mode)
            ^
/luavela/src/jit/opt/narrow.c:433:13: note: example recursive call chain, starting from function 'narrow_stripov'
/luavela/src/jit/opt/narrow.c:444:13: note: Frame #1: function 'narrow_stripov' calls function 'narrow_stripov' here:
      op1 = narrow_stripov(J, op1, lastop, mode);
            ^
/luavela/src/jit/opt/narrow.c:444:13: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/jit/opt/sink.c:40:12: error: function 'sink_phidep' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static int sink_phidep(jit_State *J, IRRef ref)
           ^
/luavela/src/jit/opt/sink.c:40:12: note: example recursive call chain, starting from function 'sink_phidep'
/luavela/src/jit/opt/sink.c:44:31: note: Frame #1: function 'sink_phidep' calls function 'sink_phidep' here:
  if (ir->op1 >= REF_FIRST && sink_phidep(J, ir->op1)) return 1;
                              ^
/luavela/src/jit/opt/sink.c:44:31: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/lib/table.c:189:13: error: function 'auxsort' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void auxsort(lua_State *L, int l, int u)
            ^
/luavela/src/lib/table.c:189:13: note: example recursive call chain, starting from function 'auxsort'
/luavela/src/lib/table.c:248:5: note: Frame #1: function 'auxsort' calls function 'auxsort' here:
    auxsort(L, j, i);  /* call recursively the smaller one */
    ^
/luavela/src/lib/table.c:248:5: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/lj_debug.c:171:13: error: function 'lj_debug_slotname' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
const char *lj_debug_slotname(GCproto *pt, const BCIns *ip, BCReg slot,
            ^
/luavela/src/lj_debug.c:171:13: note: example recursive call chain, starting from function 'lj_debug_slotname'
/luavela/src/lj_debug.c:191:14: note: Frame #1: function 'lj_debug_slotname' calls function 'lj_debug_slotname' here:
      return lj_debug_slotname(pt, ip, slot, name);
             ^
/luavela/src/lj_debug.c:191:14: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/lj_gc.c:65:13: error: function 'gc_mark' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void gc_mark(global_State *g, GCobj *o) {
            ^
/luavela/src/lj_gc.c:65:13: note: example recursive call chain, starting from function 'gc_mark'
/luavela/src/lj_gc.c:73:15: note: Frame #1: function 'gc_mark' calls function 'gc_mark' here:
    if (mt) { gc_markobj(g, mt); }
              ^
/luavela/src/lj_gc.c:59:30: note: expanded from macro 'gc_markobj'
  { if (iswhite(obj2gco(o))) gc_mark(g, obj2gco(o)); }
                             ^
/luavela/src/lj_gc.c:73:15: note: ... which was the starting point of the recursive call chain; there may be other cycles
    if (mt) { gc_markobj(g, mt); }
              ^
/luavela/src/lj_gc.c:59:30: note: expanded from macro 'gc_markobj'
  { if (iswhite(obj2gco(o))) gc_mark(g, obj2gco(o)); }
                             ^
/luavela/src/lj_gc.c:463:16: error: function 'gc_sweep' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static GCobj** gc_sweep(global_State *g, GCobj **p, uint32_t lim) {
               ^
/luavela/src/lj_gc.c:463:16: note: example recursive call chain, starting from function 'gc_sweep'
/luavela/src/lj_gc.c:474:7: note: Frame #1: function 'gc_sweep' calls function 'gc_sweep' here:
      gc_fullsweep(g, &gco2th(o)->openupval);
      ^
/luavela/src/lj_gc.c:455:33: note: expanded from macro 'gc_fullsweep'
#define gc_fullsweep(g, p)      gc_sweep(g, (p), LJ_MAX_MEM)
                                ^
/luavela/src/lj_gc.c:474:7: note: ... which was the starting point of the recursive call chain; there may be other cycles
      gc_fullsweep(g, &gco2th(o)->openupval);
      ^
/luavela/src/lj_gc.c:455:33: note: expanded from macro 'gc_fullsweep'
#define gc_fullsweep(g, p)      gc_sweep(g, (p), LJ_MAX_MEM)
                                ^
/luavela/src/luajit.c:37:13: error: function 'luajit_setptmode_all' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void luajit_setptmode_all(struct global_State *g, struct GCproto *pt,
            ^
/luavela/src/luajit.c:37:13: note: example recursive call chain, starting from function 'luajit_setptmode_all'
/luavela/src/luajit.c:47:4: note: Frame #1: function 'luajit_setptmode_all' calls function 'luajit_setptmode_all' here:
                        luajit_setptmode_all(g, gco2pt(o), mode);
                        ^
/luavela/src/luajit.c:47:4: note: ... which was the starting point of the recursive call chain; there may be other cycles
/luavela/src/profile/uj_iprof.c:151:13: error: function 'iprof_entity_finalize' is within a recursive call chain [misc-no-recursion,-warnings-as-errors]
static void iprof_entity_finalize(lua_State *L, GCtab *entity)
            ^
/luavela/src/profile/uj_iprof.c:151:13: note: example recursive call chain, starting from function 'iprof_entity_finalize'
/luavela/src/profile/uj_iprof.c:177:3: note: Frame #1: function 'iprof_entity_finalize' calls function 'iprof_entity_finalize' here:
                iprof_entity_finalize(L, sub);
                ^
/luavela/src/profile/uj_iprof.c:177:3: note: ... which was the starting point of the recursive call chain; there may be other cycles

All the warnings should be verified whether any of them found the real bug or it's just making the noise.

Use luajit's git history

Since this project is a fork of luajit, why not include their history? I gave it a shot in a fork.

Caveats:

  • It doesn't have a zero-line diff. I'm going to try to address this by doing it from a real unix machine.
  • It rewrites your history (it must to add the history).
  • I can't send it as a PR because I rewrote the beginning of history.
  • Accepting this change won't show luavela as a "forked from LuaJIT/LuaJIT" on github.

My process

echo Add remotes.
git remote add luajit http://luajit.org/git/luajit-2.0.git
git remote add vela https://github.com/iponweb/luavela.git

read -p "Grab first commit to luavela. " pause
git checkout -b luajit-history vela/master~

read -p "Move head to luajit, but keep luavela changes. " pause
git reset luajit/master
git add -A
git commit -C vela/master~

read -p "Grab remaining luavela changes. " pause
git cherry-pick vela/master 


read -p "Diff results. " pause
git diff --summary vela/master

I did a diff against a clean checkout of luavela and found no changes, but git diff finds lots of mode changes (I'm on ntfs so I can't help it) and a couple deletions that I don't understand. I can try again on a real filesystem.

build broken with gcc 10.2.0

Everything works fine with gcc 9.3.0 (Ubuntu 20.04).
But fails with gcc 10.2.0 (Ubuntu 20.10)

[ 98%] Linking C executable ujit-parse-profile
/usr/bin/ld: CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_table.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: multiple definition of `v'; CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_main.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: first defined here
/usr/bin/ld: CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_utils.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: multiple definition of `v'; CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_main.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: first defined here
/usr/bin/ld: CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_parser.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: multiple definition of `v'; CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_main.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: first defined here
/usr/bin/ld: CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_callgraph.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: multiple definition of `v'; CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_main.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: first defined here
/usr/bin/ld: CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_demangle.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: multiple definition of `v'; CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_main.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: first defined here
/usr/bin/ld: CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_output.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: multiple definition of `v'; CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_main.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: first defined here
/usr/bin/ld: CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_read.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: multiple definition of `v'; CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_main.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: first defined here
/usr/bin/ld: CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_state.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: multiple definition of `v'; CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_main.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: first defined here
/usr/bin/ld: CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_demangle_lua.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: multiple definition of `v'; CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_main.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: first defined here
/usr/bin/ld: CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_elf.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: multiple definition of `v'; CMakeFiles/ujit-parse-profile.dir/parse_profile/ujpp_main.c.o:/home/user/checkout/luavela/tools/parse_profile/ujpp_demangle.h:15: first defined here
collect2: error: ld returned 1 exit status

Hosted documentation

Would it be possible to generate and host the documentation through GitHub pages or similar? That could serve a website in the meanwhile and would be helpful to new users exploring LuaVela.

lua_tointeger() incapable to convert into 64-bit integers.

Hi guys, I found where the issue with segfault was. It was not lua_tolstring().

After some debugging I found that lua_tointeger() behaves differently in Lua/LuaJIT and LuaVela.

Here is the testcase (testluapi.cpp):

#ifdef VELA
extern "C" {
#include <ujit/lua.h>
#include <ujit/lualib.h>
#include <ujit/lauxlib.h>
}
#else
extern "C" {
#include <ujit/lua.h>
#include <ujit/lualib.h>
#include <ujit/lauxlib.h>
}
#endif

int main()
{
lua_State* L=luaL_newstate();
luaL_openlibs(L);

// putting large integer into lua: 7f210b001810
lua_pushinteger(L,0x7f210b001810LL);
lua_setfield(L, LUA_GLOBALSINDEX, "bigint");

// printing out large integer from lua: b001810 for VELA
// and correct 7f210b001810 for Lua/LuaJIT

luaL_dostring(L,"print(string.format('%X',bigint))");
}

---- and here is how does it work with different Lua variants---

6415:pk@friskr > gcc -fPIC ./testluapi.cpp -lluajit-5.1 -ldl

[~/test]
16416:pk@friskr > ./a.out
7F210B001810

[~/test]
16417:pk@friskr > gcc -DVELA -fPIC ./testluapi.cpp -lujit -ldl

[~/test]
16418:pk@friskr > ./a.out
B001810

[~/test]
16419:pk@friskr > gcc -fPIC ./testluapi.cpp -llua -ldl

[~/test]
16420:pk@friskr > ./a.out
7F210B001810


Here is the difference in lua_tointeger (LuaJIT-2.0.5, lj_api.c):

``LUA_API` lua_Integer lua_tointeger(lua_State *L, int idx)
{
cTValue *o = index2adr(L, idx);
TValue tmp;
lua_Number n;
if (LJ_LIKELY(tvisint(o))) {
return intV(o);
} else if (LJ_LIKELY(tvisnum(o))) {
n = numV(o);
} else {
if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp)))
return 0;
if (tvisint(&tmp))
return (lua_Integer)intV(&tmp);
n = numV(&tmp);
}
#if LJ_64
return (lua_Integer)n;
#else
return lj_num2int(n);
#endif
}

-------- LuaVela uj_capi.c --------------
``LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
{
return (lua_Integer)lua_tonumber(L, idx);
}


Yes it is way faster, but incapable to convert into 64-bit integers.

One more thing, conversion strings within Lua with tonumber() works fine. If we add to above testcase following lines:


// pushing string representing same integer
lua_pushstring(L,"139779895203856");
lua_setfield(L, LUA_GLOBALSINDEX, "bigint");
luaL_dostring(L,"print(string.format('%X',tonumber(bigint)))");


It will print out correct hex number.

Regards,
Pavel.

uJIT hits assertion at lj_record.c:1453

uJIT (current master) crashes with assertion on Centos 7 if built with CMAKE_BUILD_TYPE=DEBUG.

ujit: /home/master/rpm/luavela-master/src/jit/lj_record.c:1453: rec_varg_setup: Assertion `nvararg >= 0' failed.

I guess this assertion goes largely unnoticed in release builds introducing opportunity for more subtle bugs and/or state corruption somewhere down the line.

The code that causes this is rather complex, and we couldn't strip it down to a simple test case. Nevertheless, it works well on vanilla Lua 5.1 and LuaJIT 2.x, and a move to uJIT has been just an experiment for us for some time. The code employs heavy use of coroutines, varargs/results and various tricks using setfenv().

Using LuaVela as a drop-in-replacement, - segmentation fault in lua_tolstring

Hi guys, I was excited to find out about your project. And of course tried to immediatelly test it.

And I have stumbled on segmentation fault in the code that works normally with LuaJIT and the Lua.

The problematic part of the code looks like this:
if(lua_isstring(L,udidx))
{
size_t len;
const char* msg=lua_tolstring(L,udidx,&len); /// SEGFAULT here
....

Regards,
Pavel
P.S.: if you need more context on this matter, I can provide all the sources or the part of them. The full project is too large for this matter anyways it is here: https://github.com/ITpC/LAppS
Or we can make a debugging session together over anydesk for example.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.