Project

General

Profile

Feature #1798 ยป 0051-lua-5.5-Update-to-lua-5.5.0-rc2.patch

Marko Lindqvist, 12/04/2025 07:56 AM

View differences:

dependencies/lua-5.5/README
This is Lua 5.5.0, released on 14 Nov 2025.
This is Lua 5.5.0, released on 01 Dec 2025.
For installation instructions, license details, and
further information about Lua, see doc/readme.html.
dependencies/lua-5.5/Version.txt
Sources here are from lua-5.5.0-rc1
(http://www.lua.org/ftp/lua-5.5.0-rc1.tar.gz)
Sources here are from lua-5.5.0-rc2
(http://www.lua.org/ftp/lua-5.5.0-rc2.tar.gz)
Upstream bug fixes from https://www.lua.org/bugs.html applied:
dependencies/lua-5.5/src/lcode.c
** Change a vararg parameter into a regular local variable
*/
void luaK_vapar2local (FuncState *fs, expdesc *var) {
fs->f->flag |= PF_VATAB; /* function will need a vararg table */
needvatab(fs->f); /* function will need a vararg table */
/* now a vararg parameter is equivalent to a regular local variable */
var->k = VLOCAL;
}
......
break;
}
case VVARGIND: {
fs->f->flag |= PF_VATAB; /* function will need a vararg table */
needvatab(fs->f); /* function will need a vararg table */
/* now, assignment is to a regular table */
} /* FALLTHROUGH */
case VINDEXED: {
......
void luaK_finish (FuncState *fs) {
int i;
Proto *p = fs->f;
if (p->flag & PF_VATAB) /* will it use a vararg table? */
p->flag &= cast_byte(~PF_VAHID); /* then it will not use hidden args. */
for (i = 0; i < fs->pc; i++) {
Instruction *pc = &p->code[i];
/* avoid "not used" warnings when assert is off (for 'onelua.c') */
......
lua_assert(i == 0 || luaP_isOT(*(pc - 1)) == luaP_isIT(*pc));
switch (GET_OPCODE(*pc)) {
case OP_RETURN0: case OP_RETURN1: {
if (!(fs->needclose || (p->flag & PF_ISVARARG)))
if (!(fs->needclose || (p->flag & PF_VAHID)))
break; /* no extra work */
/* else use OP_RETURN to do the extra work */
SET_OPCODE(*pc, OP_RETURN);
......
case OP_RETURN: case OP_TAILCALL: {
if (fs->needclose)
SETARG_k(*pc, 1); /* signal that it needs to close */
if (p->flag & PF_ISVARARG)
SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */
if (p->flag & PF_VAHID) /* does it use hidden arguments? */
SETARG_C(*pc, p->numparams + 1); /* signal that */
break;
}
case OP_GETVARG: {
......
SET_OPCODE(*pc, OP_GETTABLE); /* must get vararg there */
break;
}
case OP_VARARG: {
if (p->flag & PF_VATAB) /* function has a vararg table? */
SETARG_k(*pc, 1); /* must get vararg there */
break;
}
case OP_JMP: { /* to optimize jumps to jumps */
int target = finaltarget(p->code, i);
fixjump(fs, i, target); /* jump directly to final target */
dependencies/lua-5.5/src/lcorolib.c
return 2;
}
}
case COS_RUN: /* running coroutine? */
case COS_NORM:
return luaL_error(L, "cannot close a %s coroutine", statname[status]);
case COS_RUN:
lua_geti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); /* get main */
if (lua_tothread(L, -1) == co)
return luaL_error(L, "cannot close main thread");
lua_closethread(co, L); /* close itself */
lua_assert(0); /* previous call does not return */
/* previous call does not return *//* FALLTHROUGH */
default:
lua_assert(0);
return 0;
default: /* normal or running coroutine */
return luaL_error(L, "cannot close a %s coroutine", statname[status]);
}
}
dependencies/lua-5.5/src/ldebug.c
static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
if (clLvalue(s2v(ci->func.p))->p->flag & PF_ISVARARG) {
if (clLvalue(s2v(ci->func.p))->p->flag & PF_VAHID) {
int nextra = ci->u.l.nextraargs;
if (n >= -nextra) { /* 'n' is negative */
*pos = ci->func.p - nextra - (n + 1);
......
int i;
TValue v;
setbtvalue(&v); /* boolean 'true' to be the value of all indices */
if (!(p->flag & PF_ISVARARG)) /* regular function? */
if (!(isvararg(p))) /* regular function? */
i = 0; /* consider all instructions */
else { /* vararg function */
lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP);
......
ar->nparams = 0;
}
else {
ar->isvararg = (f->l.p->flag & PF_ISVARARG) ? 1 : 0;
ar->isvararg = (isvararg(f->l.p)) ? 1 : 0;
ar->nparams = f->l.p->numparams;
}
break;
......
Proto *p = ci_func(ci)->p;
ci->u.l.trap = 1; /* ensure hooks will be checked */
if (ci->u.l.savedpc == p->code) { /* first instruction (not resuming)? */
if (p->flag & PF_ISVARARG)
if (isvararg(p))
return 0; /* hooks will start at VARARGPREP instruction */
else if (!(ci->callstatus & CIST_HOOKYIELD)) /* not yielded? */
luaD_hookcall(L, ci); /* check 'call' hook */
dependencies/lua-5.5/src/ldo.c
int ftransfer;
if (isLua(ci)) {
Proto *p = ci_func(ci)->p;
if (p->flag & PF_ISVARARG)
if (p->flag & PF_VAHID)
delta = ci->u.l.nextraargs + p->numparams + 1;
}
ci->func.p += delta; /* if vararg, back to virtual 'func' */
dependencies/lua-5.5/src/lobject.h
/*
** Flags in Prototypes
*/
#define PF_ISVARARG 1 /* function is vararg */
#define PF_VAVAR 2 /* function has vararg parameter */
#define PF_VATAB 4 /* function has vararg table */
#define PF_FIXED 8 /* prototype has parts in fixed memory */
#define PF_VAHID 1 /* function has hidden vararg arguments */
#define PF_VATAB 2 /* function has vararg table */
#define PF_FIXED 4 /* prototype has parts in fixed memory */
/* a vararg function either has hidden args. or a vararg table */
#define isvararg(p) ((p)->flag & (PF_VAHID | PF_VATAB))
/*
** mark that a function needs a vararg table. (The flag PF_VAHID will
** be cleared later.)
*/
#define needvatab(p) ((p)->flag |= PF_VATAB)
/*
** Function Prototypes
dependencies/lua-5.5/src/lopcodes.h
/*
** Grep "ORDER OP" if you change these enums. Opcodes marked with a (*)
** has extra descriptions in the notes after the enumeration.
** Grep "ORDER OP" if you change this enum.
** See "Notes" below for more information about some instructions.
*/
typedef enum {
......
OP_LOADK,/* A Bx R[A] := K[Bx] */
OP_LOADKX,/* A R[A] := K[extra arg] */
OP_LOADFALSE,/* A R[A] := false */
OP_LFALSESKIP,/*A R[A] := false; pc++ (*) */
OP_LFALSESKIP,/*A R[A] := false; pc++ */
OP_LOADTRUE,/* A R[A] := true */
OP_LOADNIL,/* A B R[A], R[A+1], ..., R[A+B] := nil */
OP_GETUPVAL,/* A B R[A] := UpValue[B] */
......
OP_SHL,/* A B C R[A] := R[B] << R[C] */
OP_SHR,/* A B C R[A] := R[B] >> R[C] */
OP_MMBIN,/* A B C call C metamethod over R[A] and R[B] (*) */
OP_MMBIN,/* A B C call C metamethod over R[A] and R[B] */
OP_MMBINI,/* A sB C k call C metamethod over R[A] and sB */
OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */
......
OP_GEI,/* A sB k if ((R[A] >= sB) ~= k) then pc++ */
OP_TEST,/* A k if (not R[A] == k) then pc++ */
OP_TESTSET,/* A B k if (not R[B] == k) then pc++ else R[A] := R[B] (*) */
OP_TESTSET,/* A B k if (not R[B] == k) then pc++ else R[A] := R[B] */
OP_CALL,/* A B C R[A], ... ,R[A+C-2] := R[A](R[A+1], ... ,R[A+B-1]) */
OP_TAILCALL,/* A B C k return R[A](R[A+1], ... ,R[A+B-1]) */
OP_RETURN,/* A B C k return R[A], ... ,R[A+B-2] (see note) */
OP_RETURN,/* A B C k return R[A], ... ,R[A+B-2] */
OP_RETURN0,/* return */
OP_RETURN1,/* A return R[A] */
......
OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */
OP_VARARG,/* A C R[A], R[A+1], ..., R[A+C-2] = vararg */
OP_VARARG,/* A B C k R[A], ..., R[A+C-2] = varargs */
OP_GETVARG, /* A B C R[A] := R[B][R[C]], R[B] is vararg parameter */
OP_ERRNNIL,/* A Bx raise error if R[A] ~= nil (K[Bx] is global name)*/
OP_ERRNNIL,/* A Bx raise error if R[A] ~= nil (K[Bx - 1] is global name)*/
OP_VARARGPREP,/* (adjust vararg parameters) */
OP_VARARGPREP,/* (adjust varargs) */
OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
} OpCode;
......
OP_RETURN*, OP_SETLIST) may use 'top'.
(*) In OP_VARARG, if (C == 0) then use actual number of varargs and
set top (like in OP_CALL with C == 0).
set top (like in OP_CALL with C == 0). 'k' means function has a
vararg table, which is in R[B].
(*) In OP_RETURN, if (B == 0) then return up to 'top'.
......
power of 2) plus 1, or zero for size zero. If not k, the array size
is vC. Otherwise, the array size is EXTRAARG _ vC.
(*) In OP_ERRNNIL, (Bx == 0) means index of global name doesn't
fit in Bx. (So, that name is not available for the error message.)
(*) For comparisons, k specifies what condition the test should accept
(true or false).
(*) In OP_MMBINI/OP_MMBINK, k means the arguments were flipped
(the constant is the first operand).
(the constant is the first operand).
(*) All 'skips' (pc++) assume that next instruction is a jump.
(*) All comparison and test instructions assume that the instruction
being skipped (pc++) is a jump.
(*) In instructions OP_RETURN/OP_TAILCALL, 'k' specifies that the
function builds upvalues, which may need to be closed. C > 0 means
the function is vararg, so that its 'func' must be corrected before
returning; in this case, (C - 1) is its number of fixed parameters.
the function has hidden vararg arguments, so that its 'func' must be
corrected before returning; in this case, (C - 1) is its number of
fixed parameters.
(*) In comparisons with an immediate operand, C signals whether the
original operand was a float. (It must be corrected in case of
dependencies/lua-5.5/src/lparser.c
break;
}
case VVARGIND: {
fs->f->flag |= PF_VATAB; /* function will need a vararg table */
needvatab(fs->f); /* function will need a vararg table */
e->k = VINDEXED;
} /* FALLTHROUGH */
case VINDEXUP: case VINDEXSTR: case VINDEXED: { /* global variable */
......
/* }====================================================================== */
static void setvararg (FuncState *fs, int kind) {
lua_assert(kind & PF_ISVARARG);
fs->f->flag |= cast_byte(kind);
static void setvararg (FuncState *fs) {
fs->f->flag |= PF_VAHID; /* by default, use hidden vararg arguments */
luaK_codeABC(fs, OP_VARARGPREP, 0, 0, 0);
}
......
break;
}
case TK_DOTS: {
varargk |= PF_ISVARARG;
varargk = 1;
luaX_next(ls); /* skip '...' */
if (ls->t.token == TK_NAME) {
if (ls->t.token == TK_NAME)
new_varkind(ls, str_checkname(ls), RDKVAVAR);
varargk |= PF_VAVAR;
}
else
new_localvarliteral(ls, "(vararg table)");
break;
}
default: luaX_syntaxerror(ls, "<name> or '...' expected");
......
}
adjustlocalvars(ls, nparams);
f->numparams = cast_byte(fs->nactvar);
if (varargk != 0) {
setvararg(fs, varargk); /* declared vararg */
if (varargk & PF_VAVAR)
adjustlocalvars(ls, 1); /* vararg parameter */
if (varargk) {
setvararg(fs); /* declared vararg */
adjustlocalvars(ls, 1); /* vararg parameter */
}
/* reserve registers for parameters (plus vararg parameter, if present) */
luaK_reserveregs(fs, fs->nactvar);
......
}
case TK_DOTS: { /* vararg */
FuncState *fs = ls->fs;
check_condition(ls, fs->f->flag & PF_ISVARARG,
check_condition(ls, isvararg(fs->f),
"cannot use '...' outside a vararg function");
init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 0, 1));
init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, fs->f->numparams, 1));
break;
}
case '{' /*}*/: { /* constructor */
......
BlockCnt bl;
Upvaldesc *env;
open_func(ls, fs, &bl);
setvararg(fs, PF_ISVARARG); /* main function is always vararg */
setvararg(fs); /* main function is always vararg */
env = allocupvalue(fs); /* ...set environment upvalue */
env->instack = 1;
env->idx = 0;
dependencies/lua-5.5/src/ltm.c
luaH_set(L, t, &key, &value); /* t.n = n */
for (i = 0; i < n; i++)
luaH_setint(L, t, i + 1, s2v(f + i));
luaC_checkGC(L);
}
......
** initial stack: func arg1 ... argn extra1 ...
** ^ ci->func ^ L->top
** final stack: func nil ... nil extra1 ... func arg1 ... argn
** ^ ci->func ^ L->top
** ^ ci->func
*/
void luaT_adjustvarargs (lua_State *L, CallInfo *ci, const Proto *p) {
static void buildhiddenargs (lua_State *L, CallInfo *ci, const Proto *p,
int totalargs, int nfixparams, int nextra) {
int i;
int totalargs = cast_int(L->top.p - ci->func.p) - 1;
int nfixparams = p->numparams;
int nextra = totalargs - nfixparams; /* number of extra arguments */
ci->u.l.nextraargs = nextra;
luaD_checkstack(L, p->maxstacksize + 1);
/* copy function to the top of the stack */
/* copy function to the top of the stack, after extra arguments */
setobjs2s(L, L->top.p++, ci->func.p);
/* move fixed parameters to the top of the stack */
/* move fixed parameters to after the copied function */
for (i = 1; i <= nfixparams; i++) {
setobjs2s(L, L->top.p++, ci->func.p + i);
setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */
}
if (p->flag & PF_VAVAR) { /* is there a vararg parameter? */
if (p->flag & PF_VATAB) /* does it need a vararg table? */
createvarargtab(L, ci->func.p + nfixparams + 1, nextra);
else /* no table; set parameter to nil */
setnilvalue(s2v(L->top.p));
}
ci->func.p += totalargs + 1;
ci->func.p += totalargs + 1; /* 'func' now lives after hidden arguments */
ci->top.p += totalargs + 1;
lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p);
}
void luaT_adjustvarargs (lua_State *L, CallInfo *ci, const Proto *p) {
int totalargs = cast_int(L->top.p - ci->func.p) - 1;
int nfixparams = p->numparams;
int nextra = totalargs - nfixparams; /* number of extra arguments */
if (p->flag & PF_VATAB) { /* does it need a vararg table? */
lua_assert(!(p->flag & PF_VAHID));
createvarargtab(L, ci->func.p + nfixparams + 1, nextra);
/* move table to proper place (last parameter) */
setobjs2s(L, ci->func.p + nfixparams + 1, L->top.p - 1);
}
else { /* no table */
lua_assert(p->flag & PF_VAHID);
buildhiddenargs(L, ci, p, totalargs, nfixparams, nextra);
/* set vararg parameter to nil */
setnilvalue(s2v(ci->func.p + nfixparams + 1));
lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p);
}
}
......
}
void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) {
int i;
int nextra = ci->u.l.nextraargs;
/*
** Get the number of extra arguments in a vararg function. If vararg
** table has been optimized away, that number is in the call info.
** Otherwise, get the field 'n' from the vararg table and check that it
** has a proper value (non-negative integer not larger than the stack
** limit).
*/
static int getnumargs (lua_State *L, CallInfo *ci, Table *h) {
if (h == NULL) /* no vararg table? */
return ci->u.l.nextraargs;
else {
TValue res;
if (luaH_getshortstr(h, luaS_new(L, "n"), &res) != LUA_VNUMINT ||
l_castS2U(ivalue(&res)) > cast_uint(INT_MAX/2))
luaG_runerror(L, "vararg table has no proper 'n'");
return cast_int(ivalue(&res));
}
}
/*
** Get 'wanted' vararg arguments and put them in 'where'. 'vatab' is
** the register of the vararg table or -1 if there is no vararg table.
*/
void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted,
int vatab) {
Table *h = (vatab < 0) ? NULL : hvalue(s2v(ci->func.p + vatab + 1));
int nargs = getnumargs(L, ci, h); /* number of available vararg args. */
int i, touse; /* 'touse' is minimum between 'wanted' and 'nargs' */
if (wanted < 0) {
wanted = nextra; /* get all extra arguments available */
checkstackp(L, nextra, where); /* ensure stack space */
L->top.p = where + nextra; /* next instruction will need top */
touse = wanted = nargs; /* get all extra arguments available */
checkstackp(L, nargs, where); /* ensure stack space */
L->top.p = where + nargs; /* next instruction will need top */
}
else
touse = (nargs > wanted) ? wanted : nargs;
if (h == NULL) { /* no vararg table? */
for (i = 0; i < touse; i++) /* get vararg values from the stack */
setobjs2s(L, where + i, ci->func.p - nargs + i);
}
else { /* get vararg values from vararg table */
for (i = 0; i < touse; i++) {
lu_byte tag = luaH_getint(h, i + 1, s2v(where + i));
if (tagisempty(tag))
setnilvalue(s2v(where + i));
}
}
for (i = 0; i < wanted && i < nextra; i++)
setobjs2s(L, where + i, ci->func.p - nextra + i);
for (; i < wanted; i++) /* complete required results with nil */
setnilvalue(s2v(where + i));
}
dependencies/lua-5.5/src/ltm.h
LUAI_FUNC void luaT_adjustvarargs (lua_State *L, struct CallInfo *ci,
const Proto *p);
LUAI_FUNC void luaT_getvararg (CallInfo *ci, StkId ra, TValue *rc);
LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci,
StkId where, int wanted);
LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, StkId where,
int wanted, int vatab);
#endif
dependencies/lua-5.5/src/lvm.c
}
vmcase(OP_VARARG) {
StkId ra = RA(i);
int n = GETARG_C(i) - 1; /* required results */
Protect(luaT_getvarargs(L, ci, ra, n));
int n = GETARG_C(i) - 1; /* required results (-1 means all) */
int vatab = GETARG_k(i) ? GETARG_B(i) : -1;
Protect(luaT_getvarargs(L, ci, ra, n, vatab));
vmbreak;
}
vmcase(OP_GETVARG) {
    (1-1/1)