Search code examples
c++lua32-bitpowerpclua-api

Strange lua push/pop behavior with the C API


I noticed that pushing and popping values onto/off the stack in lua using the C API on my target platform (32-bit PowerPC architecture) behaves very oddly. Consider the following test function:

void test_pushing_and_popping(lua_State *lua) {
    printf("### STARTING PUSHING/POPPING TEST ###\n");
    lua_dump_stack(lua);
    const auto value = static_cast<uint32_t>(0x206D7578);
    lua_pushinteger(lua, value);
    lua_pushnumber(lua, value);
    const auto popped_integer = lua_tointeger(lua, 1);
    const auto popped_float = lua_tonumber(lua, 2);
    printf("Popped integer: %llx\n", popped_integer);
    printf("Popped float: %f\n", popped_float);
    lua_dump_stack(lua);
    printf("Asserting equality... ");
    assert(popped_integer == popped_float);
    printf("OK!\n");
    printf("Wiping the stack...\n");
    lua_settop(lua, 0);
    lua_dump_stack(lua);
    printf("### PUSHING/POPPING TEST ENDED ###\n");
}

I expect this code to run successfully and that the assertion will be passed since the same value is pushed and then popped with lua_pushinteger, lua_pushnumber, lua_tointeger as well as lua_tonumber respectively.

Indeed, if I run the code on Windows as a 32-bit binary, it works:

### STARTING PUSHING/POPPING TEST ###
Dumping the lua stack...
Stack element count: 0
Popped integer: 206d7578
Popped float: 544044408.000000
Dumping the lua stack...
Stack element count: 2
1       number  0x206D7578
2       number  0x206D7578
Asserting equality... OK!
Wiping the stack...
Dumping the lua stack...
Stack element count: 0
### PUSHING/POPPING TEST ENDED ###

Also on Linux as 64-bit binary it works.

However, here's the output on my target platform:

### STARTING PUSHING/POPPING TEST ###
Dumping the lua stack...
Stack element count: 0
Popped integer: 8002b2bc00e3a9ac <-- Wrong!
Popped float: 544044416.000000   <-- Wrong!
Dumping the lua stack...
Stack element count: 2
1   number 0x80000000 <-- Wrong!
2   number 0x206d7580 <-- Wrong!
Asserting equality... <-- Crash (assertion fail)!

What? The first value is completely wrong and even the 2nd value is wrong. 544044416.000000 converted to hexadecimal is 0x206d7580 which is also unequal to the pushed value of 0x206D7578. Where does the inaccuracy come from?).

I'm pretty sure I didn't corrupt anything since I ran the test right after initializing lua:

printf("Initializing lua...\n");
lua = luaL_newstate(); /* Opens Lua */
luaL_openlibs(lua); /* Opens the standard libraries */
test_pushing_and_popping(lua);

Does anyone have an idea what could be the problem?


Solution

  • The initial compliation error I got was worded as follows:

    #error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \
      or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)"
    

    It turns out I used the -DLUA_32BITS compilation flag which causes the data type sizes to be too small:

    #define LUA_INTEGER int
    #define LUA_NUMBER float
    

    Using the largest possible is the way to go which can be accomplished with the flag: -DLUA_C89_NUMBERS.

    This defines the data types as:

    #define LUA_INTEGER long
    #define LUA_NUMBER double