Lua’s authors do not document the precompiled format; it is defined by the source of
each release. This page follows Lua 5.1’s ldump.c,
lundump.c, lobject.h and lopcodes.h as published on
lua.org (see sources). A chunk
is written in the byte order and with the number sizes of the machine that wrote it,
which the header records; a standard Lua refuses a chunk whose header differs from
its own.
Header (12 bytes)
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 4 | signature | 1B 4C 75 61: escape and Lua. |
4 | 1 | version | 0x51: major × 16 + minor. |
5 | 1 | format | 0 for the official format. |
6 | 1 | endianness | 1 little-endian, 0 big-endian: the first byte of an int holding 1. |
7 | 1 | sizeof(int) | Bytes in an int on the writing machine. |
8 | 1 | sizeof(size_t) | Bytes in a size_t. |
9 | 1 | sizeof(Instruction) | Bytes in an instruction. |
10 | 1 | sizeof(lua_Number) | Bytes in a number. |
11 | 1 | integral flag | 0 if lua_Number is floating point, 1 if it is an integer type. |
The main function follows directly.
Basic types
| Type | Encoding |
|---|---|
| byte | One byte. |
| int | sizeof(int) bytes, in the header’s byte order. |
| size_t | sizeof(size_t) bytes. |
| number | sizeof(lua_Number) bytes, the machine representation (an IEEE 754 double by default). |
| string | A size_t length that counts the terminating zero, then that many bytes including the zero. A length of 0 means no string. |
| list of T | An int count, then that many T. |
Function prototype
| Field | Type | Meaning |
|---|---|---|
| source | string | Source name. When it is empty (no string), the loader uses the enclosing function’s source. |
| linedefined | int | Line where the function starts. |
| lastlinedefined | int | Line where it ends. |
| nups | byte | Number of upvalues. |
| numparams | byte | Number of fixed parameters. |
| is_vararg | byte | Flags (“masks for new-style vararg” in lobject.h): 1 VARARG_HASARG, 2 VARARG_ISVARARG, 4 VARARG_NEEDSARG. |
| maxstacksize | byte | Number of registers the function needs. |
| code | list of Instruction | The instructions, each 4 bytes. |
| constants | list of constant | See constants. |
| protos | list of function | Nested function prototypes, each in this same layout. |
| lineinfo | list of int | Source line of each instruction. |
| locvars | list of (string, int, int) | Local variables: name, first and last instruction where it is active. |
| upvalues | list of string | Upvalue names. |
Constants
| Tag byte | Type | Then |
|---|---|---|
0 | nil | nothing |
1 | boolean | one byte, 0 false, otherwise true |
3 | number | a number |
4 | string | a string |
The tags are the LUA_T type constants; their values (0, 1, 3, 4) were
read from the 5.2 and 5.4 lua.h, not re-read for 5.1. Any other tag is an
error (“bad constant”).
Instructions
Each instruction is a 32-bit unsigned number in the chunk’s byte order. The opcode is in the low six bits.
| Mode | Bits 31–23 | Bits 22–14 | Bits 13–6 | Bits 5–0 |
|---|---|---|---|---|
iABC | B (9) | C (9) | A (8) | opcode (6) |
iABx | Bx (18), unsigned | A (8) | opcode (6) | |
iAsBx | sBx (18): stored as value + 131,071 | A (8) | opcode (6) | |
R(x) is register x; Kst(x) is constant
x; RK(x) is a constant when bit 8 of the 9-bit field is set
(BITRK = 256, so constant x − 256) and a register otherwise.
SETLIST stores 50 items per batch (LFIELDS_PER_FLUSH). Every
“skip” assumes the next instruction is a jump.
| Op | Name | Mode | Action |
|---|---|---|---|
| 0 | MOVE | A B | R(A) := R(B) |
| 1 | LOADK | A Bx | R(A) := Kst(Bx) |
| 2 | LOADBOOL | A B C | R(A) := (Bool)B; if C, skip the next instruction |
| 3 | LOADNIL | A B | R(A) to R(B) := nil |
| 4 | GETUPVAL | A B | R(A) := UpValue[B] |
| 5 | GETGLOBAL | A Bx | R(A) := Gbl[Kst(Bx)] |
| 6 | GETTABLE | A B C | R(A) := R(B)[RK(C)] |
| 7 | SETGLOBAL | A Bx | Gbl[Kst(Bx)] := R(A) |
| 8 | SETUPVAL | A B | UpValue[B] := R(A) |
| 9 | SETTABLE | A B C | R(A)[RK(B)] := RK(C) |
| 10 | NEWTABLE | A B C | R(A) := {} with sizes given by B and C |
| 11 | SELF | A B C | R(A+1) := R(B); R(A) := R(B)[RK(C)] |
| 12 | ADD | A B C | R(A) := RK(B) + RK(C) |
| 13 | SUB | A B C | R(A) := RK(B) − RK(C) |
| 14 | MUL | A B C | R(A) := RK(B) × RK(C) |
| 15 | DIV | A B C | R(A) := RK(B) / RK(C) |
| 16 | MOD | A B C | R(A) := RK(B) % RK(C) |
| 17 | POW | A B C | R(A) := RK(B) ^ RK(C) |
| 18 | UNM | A B | R(A) := −R(B) |
| 19 | NOT | A B | R(A) := not R(B) |
| 20 | LEN | A B | R(A) := length of R(B) |
| 21 | CONCAT | A B C | R(A) := R(B) .. … .. R(C) |
| 22 | JMP | sBx | pc += sBx |
| 23 | EQ | A B C | if (RK(B) == RK(C)) ~= A then skip the next instruction |
| 24 | LT | A B C | if (RK(B) < RK(C)) ~= A then skip |
| 25 | LE | A B C | if (RK(B) <= RK(C)) ~= A then skip |
| 26 | TEST | A C | if not (R(A) <=> C) then skip |
| 27 | TESTSET | A B C | if R(B) <=> C then R(A) := R(B) else skip |
| 28 | CALL | A B C | R(A), …, R(A+C−2) := R(A)(R(A+1), …, R(A+B−1)); B = 0 means arguments up to the top; C is the number of results plus 1, and 0 sets the top after the last result |
| 29 | TAILCALL | A B C | return R(A)(R(A+1), …, R(A+B−1)) |
| 30 | RETURN | A B | return R(A), …, R(A+B−2); B = 0 means up to the top |
| 31 | FORLOOP | A sBx | R(A) += R(A+2); if R(A) is within R(A+1), pc += sBx and R(A+3) := R(A) |
| 32 | FORPREP | A sBx | R(A) −= R(A+2); pc += sBx |
| 33 | TFORLOOP | A C | R(A+3), …, R(A+2+C) := R(A)(R(A+1), R(A+2)); if R(A+3) ~= nil then R(A+2) := R(A+3) else skip |
| 34 | SETLIST | A B C | R(A)[(C−1) × 50 + i] := R(A+i) for 1 ≤ i ≤ B; B = 0 means up to the top; C = 0 means the real C is the next instruction word |
| 35 | CLOSE | A | close all variables in the stack at or above R(A) |
| 36 | CLOSURE | A Bx | R(A) := closure(KPROTO[Bx], upvalues) |
| 37 | VARARG | A B | R(A), R(A+1), … := the vararg values; B = 0 means use the actual number of varargs |
Example
The header written by Lua 5.1 on a 64-bit little-endian machine:
1B 4C 75 61 signature
51 version 5.1
00 official format
01 little-endian
04 int: 4 bytes
08 size_t: 8 bytes
04 Instruction: 4 bytes
08 lua_Number: 8 bytes
00 floating-point numbers
The instruction 01 00 00 00 read little-endian is 0x00000001:
opcode 1 (LOADK), A = 0, Bx = 0, so R(0) := Kst(0).
Sources
Lua 5.1 source on lua.org:
lundump.c (luaU_header, LoadFunction,
LoadConstants, LoadDebug), lobject.h (vararg
masks) and lopcodes.h (field sizes and positions, BITRK,
MAXARG_sBx, LFIELDS_PER_FLUSH, every opcode and its comment,
and the notes on B or C = 0). The header values in the example are those of a
64-bit little-endian build and are illustrative.