Mercurial
comparison third_party/luajit/src/host/genminilua.lua @ 178:94705b5986b3
[ThirdParty] Added WRK and luajit for load testing.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Thu, 22 Jan 2026 20:10:30 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 177:24fe8ff94056 | 178:94705b5986b3 |
|---|---|
| 1 ---------------------------------------------------------------------------- | |
| 2 -- Lua script to generate a customized, minified version of Lua. | |
| 3 -- The resulting 'minilua' is used for the build process of LuaJIT. | |
| 4 ---------------------------------------------------------------------------- | |
| 5 -- Copyright (C) 2005-2023 Mike Pall. All rights reserved. | |
| 6 -- Released under the MIT license. See Copyright Notice in luajit.h | |
| 7 ---------------------------------------------------------------------------- | |
| 8 | |
| 9 local sub, match, gsub = string.sub, string.match, string.gsub | |
| 10 | |
| 11 local LUA_VERSION = "5.1.5" | |
| 12 local LUA_SOURCE | |
| 13 | |
| 14 local function usage() | |
| 15 io.stderr:write("Usage: ", arg and arg[0] or "genminilua", | |
| 16 " lua-", LUA_VERSION, "-source-dir\n") | |
| 17 os.exit(1) | |
| 18 end | |
| 19 | |
| 20 local function find_sources() | |
| 21 LUA_SOURCE = arg and arg[1] | |
| 22 if not LUA_SOURCE then usage() end | |
| 23 if sub(LUA_SOURCE, -1) ~= "/" then LUA_SOURCE = LUA_SOURCE.."/" end | |
| 24 local fp = io.open(LUA_SOURCE .. "lua.h") | |
| 25 if not fp then | |
| 26 LUA_SOURCE = LUA_SOURCE.."src/" | |
| 27 fp = io.open(LUA_SOURCE .. "lua.h") | |
| 28 if not fp then usage() end | |
| 29 end | |
| 30 local all = fp:read("*a") | |
| 31 fp:close() | |
| 32 if not match(all, 'LUA_RELEASE%s*"Lua '..LUA_VERSION..'"') then | |
| 33 io.stderr:write("Error: version mismatch\n") | |
| 34 usage() | |
| 35 end | |
| 36 end | |
| 37 | |
| 38 local LUA_FILES = { | |
| 39 "lmem.c", "lobject.c", "ltm.c", "lfunc.c", "ldo.c", "lstring.c", "ltable.c", | |
| 40 "lgc.c", "lstate.c", "ldebug.c", "lzio.c", "lopcodes.c", | |
| 41 "llex.c", "lcode.c", "lparser.c", "lvm.c", "lapi.c", "lauxlib.c", | |
| 42 "lbaselib.c", "ltablib.c", "liolib.c", "loslib.c", "lstrlib.c", "linit.c", | |
| 43 } | |
| 44 | |
| 45 local REMOVE_LIB = {} | |
| 46 gsub([[ | |
| 47 collectgarbage dofile gcinfo getfenv getmetatable load print rawequal rawset | |
| 48 select tostring xpcall | |
| 49 foreach foreachi getn maxn setn | |
| 50 popen tmpfile seek setvbuf __tostring | |
| 51 clock date difftime execute getenv rename setlocale time tmpname | |
| 52 dump gfind len reverse | |
| 53 LUA_LOADLIBNAME LUA_MATHLIBNAME LUA_DBLIBNAME | |
| 54 ]], "%S+", function(name) | |
| 55 REMOVE_LIB[name] = true | |
| 56 end) | |
| 57 | |
| 58 local REMOVE_EXTINC = { ["<assert.h>"] = true, ["<locale.h>"] = true, } | |
| 59 | |
| 60 local CUSTOM_MAIN = [[ | |
| 61 typedef unsigned int UB; | |
| 62 static UB barg(lua_State *L,int idx){ | |
| 63 union{lua_Number n;U64 b;}bn; | |
| 64 bn.n=lua_tonumber(L,idx)+6755399441055744.0; | |
| 65 if (bn.n==0.0&&!lua_isnumber(L,idx))luaL_typerror(L,idx,"number"); | |
| 66 return(UB)bn.b; | |
| 67 } | |
| 68 #define BRET(b) lua_pushnumber(L,(lua_Number)(int)(b));return 1; | |
| 69 static int tobit(lua_State *L){ | |
| 70 BRET(barg(L,1))} | |
| 71 static int bnot(lua_State *L){ | |
| 72 BRET(~barg(L,1))} | |
| 73 static int band(lua_State *L){ | |
| 74 int i;UB b=barg(L,1);for(i=lua_gettop(L);i>1;i--)b&=barg(L,i);BRET(b)} | |
| 75 static int bor(lua_State *L){ | |
| 76 int i;UB b=barg(L,1);for(i=lua_gettop(L);i>1;i--)b|=barg(L,i);BRET(b)} | |
| 77 static int bxor(lua_State *L){ | |
| 78 int i;UB b=barg(L,1);for(i=lua_gettop(L);i>1;i--)b^=barg(L,i);BRET(b)} | |
| 79 static int lshift(lua_State *L){ | |
| 80 UB b=barg(L,1),n=barg(L,2)&31;BRET(b<<n)} | |
| 81 static int rshift(lua_State *L){ | |
| 82 UB b=barg(L,1),n=barg(L,2)&31;BRET(b>>n)} | |
| 83 static int arshift(lua_State *L){ | |
| 84 UB b=barg(L,1),n=barg(L,2)&31;BRET((int)b>>n)} | |
| 85 static int rol(lua_State *L){ | |
| 86 UB b=barg(L,1),n=barg(L,2)&31;BRET((b<<n)|(b>>(32-n)))} | |
| 87 static int ror(lua_State *L){ | |
| 88 UB b=barg(L,1),n=barg(L,2)&31;BRET((b>>n)|(b<<(32-n)))} | |
| 89 static int bswap(lua_State *L){ | |
| 90 UB b=barg(L,1);b=(b>>24)|((b>>8)&0xff00)|((b&0xff00)<<8)|(b<<24);BRET(b)} | |
| 91 static int tohex(lua_State *L){ | |
| 92 UB b=barg(L,1); | |
| 93 int n=lua_isnone(L,2)?8:(int)barg(L,2); | |
| 94 const char *hexdigits="0123456789abcdef"; | |
| 95 char buf[8]; | |
| 96 int i; | |
| 97 if(n<0){n=-n;hexdigits="0123456789ABCDEF";} | |
| 98 if(n>8)n=8; | |
| 99 for(i=(int)n;--i>=0;){buf[i]=hexdigits[b&15];b>>=4;} | |
| 100 lua_pushlstring(L,buf,(size_t)n); | |
| 101 return 1; | |
| 102 } | |
| 103 static const struct luaL_Reg bitlib[] = { | |
| 104 {"tobit",tobit}, | |
| 105 {"bnot",bnot}, | |
| 106 {"band",band}, | |
| 107 {"bor",bor}, | |
| 108 {"bxor",bxor}, | |
| 109 {"lshift",lshift}, | |
| 110 {"rshift",rshift}, | |
| 111 {"arshift",arshift}, | |
| 112 {"rol",rol}, | |
| 113 {"ror",ror}, | |
| 114 {"bswap",bswap}, | |
| 115 {"tohex",tohex}, | |
| 116 {NULL,NULL} | |
| 117 }; | |
| 118 int main(int argc, char **argv){ | |
| 119 lua_State *L = luaL_newstate(); | |
| 120 int i; | |
| 121 luaL_openlibs(L); | |
| 122 luaL_register(L, "bit", bitlib); | |
| 123 if (argc < 2) return sizeof(void *); | |
| 124 lua_createtable(L, 0, 1); | |
| 125 lua_pushstring(L, argv[1]); | |
| 126 lua_rawseti(L, -2, 0); | |
| 127 lua_setglobal(L, "arg"); | |
| 128 if (luaL_loadfile(L, argv[1])) | |
| 129 goto err; | |
| 130 for (i = 2; i < argc; i++) | |
| 131 lua_pushstring(L, argv[i]); | |
| 132 if (lua_pcall(L, argc - 2, 0, 0)) { | |
| 133 err: | |
| 134 fprintf(stderr, "Error: %s\n", lua_tostring(L, -1)); | |
| 135 return 1; | |
| 136 } | |
| 137 lua_close(L); | |
| 138 return 0; | |
| 139 } | |
| 140 ]] | |
| 141 | |
| 142 local function read_sources() | |
| 143 local t = {} | |
| 144 for i, name in ipairs(LUA_FILES) do | |
| 145 local fp = assert(io.open(LUA_SOURCE..name, "r")) | |
| 146 t[i] = fp:read("*a") | |
| 147 assert(fp:close()) | |
| 148 end | |
| 149 t[#t+1] = CUSTOM_MAIN | |
| 150 return table.concat(t) | |
| 151 end | |
| 152 | |
| 153 local includes = {} | |
| 154 | |
| 155 local function merge_includes(src) | |
| 156 return gsub(src, '#include%s*"([^"]*)"%s*\n', function(name) | |
| 157 if includes[name] then return "" end | |
| 158 includes[name] = true | |
| 159 local fp = assert(io.open(LUA_SOURCE..name, "r")) | |
| 160 local inc = fp:read("*a") | |
| 161 assert(fp:close()) | |
| 162 inc = gsub(inc, "#ifndef%s+%w+_h\n#define%s+%w+_h\n", "") | |
| 163 inc = gsub(inc, "#endif%s*$", "") | |
| 164 return merge_includes(inc) | |
| 165 end) | |
| 166 end | |
| 167 | |
| 168 local function get_license(src) | |
| 169 return match(src, "/%*+\n%* Copyright %(.-%*/\n") | |
| 170 end | |
| 171 | |
| 172 local function fold_lines(src) | |
| 173 return gsub(src, "\\\n", " ") | |
| 174 end | |
| 175 | |
| 176 local strings = {} | |
| 177 | |
| 178 local function save_str(str) | |
| 179 local n = #strings+1 | |
| 180 strings[n] = str | |
| 181 return "\1"..n.."\2" | |
| 182 end | |
| 183 | |
| 184 local function save_strings(src) | |
| 185 src = gsub(src, '"[^"\n]*"', save_str) | |
| 186 return gsub(src, "'[^'\n]*'", save_str) | |
| 187 end | |
| 188 | |
| 189 local function restore_strings(src) | |
| 190 return gsub(src, "\1(%d+)\2", function(numstr) | |
| 191 return strings[tonumber(numstr)] | |
| 192 end) | |
| 193 end | |
| 194 | |
| 195 local function def_istrue(def) | |
| 196 return def == "INT_MAX > 2147483640L" or | |
| 197 def == "LUAI_BITSINT >= 32" or | |
| 198 def == "SIZE_Bx < LUAI_BITSINT-1" or | |
| 199 def == "cast" or | |
| 200 def == "defined(LUA_CORE)" or | |
| 201 def == "MINSTRTABSIZE" or | |
| 202 def == "LUA_MINBUFFER" or | |
| 203 def == "HARDSTACKTESTS" or | |
| 204 def == "UNUSED" | |
| 205 end | |
| 206 | |
| 207 local head, defs = {[[ | |
| 208 #ifdef _MSC_VER | |
| 209 typedef unsigned __int64 U64; | |
| 210 #else | |
| 211 typedef unsigned long long U64; | |
| 212 #endif | |
| 213 int _CRT_glob = 0; | |
| 214 ]]}, {} | |
| 215 | |
| 216 local function preprocess(src) | |
| 217 local t = { match(src, "^(.-)#") } | |
| 218 local lvl, on, oldon = 0, true, {} | |
| 219 for pp, def, txt in string.gmatch(src, "#(%w+) *([^\n]*)\n([^#]*)") do | |
| 220 if pp == "if" or pp == "ifdef" or pp == "ifndef" then | |
| 221 lvl = lvl + 1 | |
| 222 oldon[lvl] = on | |
| 223 on = def_istrue(def) | |
| 224 elseif pp == "else" then | |
| 225 if oldon[lvl] then | |
| 226 if on == false then on = true else on = false end | |
| 227 end | |
| 228 elseif pp == "elif" then | |
| 229 if oldon[lvl] then | |
| 230 on = def_istrue(def) | |
| 231 end | |
| 232 elseif pp == "endif" then | |
| 233 on = oldon[lvl] | |
| 234 lvl = lvl - 1 | |
| 235 elseif on then | |
| 236 if pp == "include" then | |
| 237 if not head[def] and not REMOVE_EXTINC[def] then | |
| 238 head[def] = true | |
| 239 head[#head+1] = "#include "..def.."\n" | |
| 240 end | |
| 241 elseif pp == "define" then | |
| 242 local k, sp, v = match(def, "([%w_]+)(%s*)(.*)") | |
| 243 if k and not (sp == "" and sub(v, 1, 1) == "(") then | |
| 244 defs[k] = gsub(v, "%a[%w_]*", function(tok) | |
| 245 return defs[tok] or tok | |
| 246 end) | |
| 247 else | |
| 248 t[#t+1] = "#define "..def.."\n" | |
| 249 end | |
| 250 elseif pp ~= "undef" then | |
| 251 error("unexpected directive: "..pp.." "..def) | |
| 252 end | |
| 253 end | |
| 254 if on then t[#t+1] = txt end | |
| 255 end | |
| 256 return gsub(table.concat(t), "%a[%w_]*", function(tok) | |
| 257 return defs[tok] or tok | |
| 258 end) | |
| 259 end | |
| 260 | |
| 261 local function merge_header(src, license) | |
| 262 local hdr = string.format([[ | |
| 263 /* This is a heavily customized and minimized copy of Lua %s. */ | |
| 264 /* It's only used to build LuaJIT. It does NOT have all standard functions! */ | |
| 265 ]], LUA_VERSION) | |
| 266 return hdr..license..table.concat(head)..src | |
| 267 end | |
| 268 | |
| 269 local function strip_unused1(src) | |
| 270 return gsub(src, '( {"?([%w_]+)"?,%s+%a[%w_]*},\n)', function(line, func) | |
| 271 return REMOVE_LIB[func] and "" or line | |
| 272 end) | |
| 273 end | |
| 274 | |
| 275 local function strip_unused2(src) | |
| 276 return gsub(src, "Symbolic Execution.-}=", "") | |
| 277 end | |
| 278 | |
| 279 local function strip_unused3(src) | |
| 280 src = gsub(src, "extern", "static") | |
| 281 src = gsub(src, "\nstatic([^\n]-)%(([^)]*)%)%(", "\nstatic%1 %2(") | |
| 282 src = gsub(src, "#define lua_assert[^\n]*\n", "") | |
| 283 src = gsub(src, "lua_assert%b();?", "") | |
| 284 src = gsub(src, "default:\n}", "default:;\n}") | |
| 285 src = gsub(src, "lua_lock%b();", "") | |
| 286 src = gsub(src, "lua_unlock%b();", "") | |
| 287 src = gsub(src, "luai_threadyield%b();", "") | |
| 288 src = gsub(src, "luai_userstateopen%b();", "{}") | |
| 289 src = gsub(src, "luai_userstate%w+%b();", "") | |
| 290 src = gsub(src, "%(%(c==.*luaY_parser%)", "luaY_parser") | |
| 291 src = gsub(src, "trydecpoint%(ls,seminfo%)", | |
| 292 "luaX_lexerror(ls,\"malformed number\",TK_NUMBER)") | |
| 293 src = gsub(src, "int c=luaZ_lookahead%b();", "") | |
| 294 src = gsub(src, "luaL_register%(L,[^,]*,co_funcs%);\nreturn 2;", | |
| 295 "return 1;") | |
| 296 src = gsub(src, "getfuncname%b():", "NULL:") | |
| 297 src = gsub(src, "getobjname%b():", "NULL:") | |
| 298 src = gsub(src, "if%([^\n]*hookmask[^\n]*%)\n[^\n]*\n", "") | |
| 299 src = gsub(src, "if%([^\n]*hookmask[^\n]*%)%b{}\n", "") | |
| 300 src = gsub(src, "if%([^\n]*hookmask[^\n]*&&\n[^\n]*%b{}\n", "") | |
| 301 src = gsub(src, "(twoto%b()%()", "%1(size_t)") | |
| 302 src = gsub(src, "i<sizenode", "i<(int)sizenode") | |
| 303 src = gsub(src, "cast%(unsigned int,key%-1%)", "cast(unsigned int,key)-1") | |
| 304 return gsub(src, "\n\n+", "\n") | |
| 305 end | |
| 306 | |
| 307 local function strip_comments(src) | |
| 308 return gsub(src, "/%*.-%*/", " ") | |
| 309 end | |
| 310 | |
| 311 local function strip_whitespace(src) | |
| 312 src = gsub(src, "^%s+", "") | |
| 313 src = gsub(src, "%s*\n%s*", "\n") | |
| 314 src = gsub(src, "[ \t]+", " ") | |
| 315 src = gsub(src, "(%W) ", "%1") | |
| 316 return gsub(src, " (%W)", "%1") | |
| 317 end | |
| 318 | |
| 319 local function rename_tokens1(src) | |
| 320 src = gsub(src, "getline", "getline_") | |
| 321 src = gsub(src, "struct ([%w_]+)", "ZX%1") | |
| 322 return gsub(src, "union ([%w_]+)", "ZY%1") | |
| 323 end | |
| 324 | |
| 325 local function rename_tokens2(src) | |
| 326 src = gsub(src, "ZX([%w_]+)", "struct %1") | |
| 327 return gsub(src, "ZY([%w_]+)", "union %1") | |
| 328 end | |
| 329 | |
| 330 local function fix_bugs_and_warnings(src) | |
| 331 src = gsub(src, "(luaD_checkstack%(L,p%->maxstacksize)%)", "%1+p->numparams)") | |
| 332 src = gsub(src, "if%(sep==%-1%)(return'%[';)\nelse (luaX_lexerror%b();)", "if (sep!=-1)%2\n%1") | |
| 333 return gsub(src, "(default:{\nNode%*n=mainposition)", "/*fallthrough*/\n%1") | |
| 334 end | |
| 335 | |
| 336 local function func_gather(src) | |
| 337 local nodes, list = {}, {} | |
| 338 local pos, len = 1, #src | |
| 339 while pos < len do | |
| 340 local d, w = match(src, "^(#define ([%w_]+)[^\n]*\n)", pos) | |
| 341 if d then | |
| 342 local n = #list+1 | |
| 343 list[n] = d | |
| 344 nodes[w] = n | |
| 345 else | |
| 346 local s | |
| 347 d, w, s = match(src, "^(([%w_]+)[^\n]*([{;])\n)", pos) | |
| 348 if not d then | |
| 349 d, w, s = match(src, "^(([%w_]+)[^(]*%b()([{;])\n)", pos) | |
| 350 if not d then d = match(src, "^[^\n]*\n", pos) end | |
| 351 end | |
| 352 if s == "{" then | |
| 353 d = d..sub(match(src, "^%b{}[^;\n]*;?\n", pos+#d-2), 3) | |
| 354 if sub(d, -2) == "{\n" then | |
| 355 d = d..sub(match(src, "^%b{}[^;\n]*;?\n", pos+#d-2), 3) | |
| 356 end | |
| 357 end | |
| 358 local k, v = nil, d | |
| 359 if w == "typedef" then | |
| 360 if match(d, "^typedef enum") then | |
| 361 head[#head+1] = d | |
| 362 else | |
| 363 k = match(d, "([%w_]+);\n$") | |
| 364 if not k then k = match(d, "^.-%(.-([%w_]+)%)%(") end | |
| 365 end | |
| 366 elseif w == "enum" then | |
| 367 head[#head+1] = v | |
| 368 elseif w ~= nil then | |
| 369 k = match(d, "^[^\n]-([%w_]+)[(%[=]") | |
| 370 if k then | |
| 371 if w ~= "static" and k ~= "main" then v = "static "..d end | |
| 372 else | |
| 373 k = w | |
| 374 end | |
| 375 end | |
| 376 if w and k then | |
| 377 local o = nodes[k] | |
| 378 if o then nodes["*"..k] = o end | |
| 379 local n = #list+1 | |
| 380 list[n] = v | |
| 381 nodes[k] = n | |
| 382 end | |
| 383 end | |
| 384 pos = pos + #d | |
| 385 end | |
| 386 return nodes, list | |
| 387 end | |
| 388 | |
| 389 local function func_visit(nodes, list, used, n) | |
| 390 local i = nodes[n] | |
| 391 for m in string.gmatch(list[i], "[%w_]+") do | |
| 392 if nodes[m] then | |
| 393 local j = used[m] | |
| 394 if not j then | |
| 395 used[m] = i | |
| 396 func_visit(nodes, list, used, m) | |
| 397 elseif i < j then | |
| 398 used[m] = i | |
| 399 end | |
| 400 end | |
| 401 end | |
| 402 end | |
| 403 | |
| 404 local function func_collect(src) | |
| 405 local nodes, list = func_gather(src) | |
| 406 local used = {} | |
| 407 func_visit(nodes, list, used, "main") | |
| 408 for n,i in pairs(nodes) do | |
| 409 local j = used[n] | |
| 410 if j and j < i then used["*"..n] = j end | |
| 411 end | |
| 412 for n,i in pairs(nodes) do | |
| 413 if not used[n] then list[i] = "" end | |
| 414 end | |
| 415 return table.concat(list) | |
| 416 end | |
| 417 | |
| 418 find_sources() | |
| 419 local src = read_sources() | |
| 420 src = merge_includes(src) | |
| 421 local license = get_license(src) | |
| 422 src = fold_lines(src) | |
| 423 src = strip_unused1(src) | |
| 424 src = save_strings(src) | |
| 425 src = strip_unused2(src) | |
| 426 src = strip_comments(src) | |
| 427 src = preprocess(src) | |
| 428 src = strip_whitespace(src) | |
| 429 src = strip_unused3(src) | |
| 430 src = rename_tokens1(src) | |
| 431 src = func_collect(src) | |
| 432 src = rename_tokens2(src) | |
| 433 src = restore_strings(src) | |
| 434 src = fix_bugs_and_warnings(src) | |
| 435 src = merge_header(src, license) | |
| 436 io.write(src) |