Skip to content
Browse files

Add support for exported global variables.

Fixes #7
  • Loading branch information...
1 parent d0204c3 commit ba38f94673ab4dc874255ae8d8852ead4b3fe4d8 @jmckaskill jmckaskill committed
Showing with 382 additions and 140 deletions.
  1. +2 −2 call_arm.dasc
  2. +3 −3 call_x86.dasc
  3. +205 −67 ffi.c
  4. +1 −0 ffi.h
  5. +34 −49 parser.c
  6. +56 −10 test.c
  7. +81 −9 test.lua
View
4 call_arm.dasc
@@ -393,7 +393,7 @@ void push_function(struct jit* jit, lua_State* L, function_t func, int ct_usr, c
lua_rawgeti(L, ct_usr, i);
mt = (const struct ctype*) lua_touserdata(L, -1);
- if (mt->pointers || mt->type == FUNCTION_TYPE || mt->type == ENUM_TYPE) {
+ if (mt->pointers || mt->type == FUNCTION_PTR_TYPE || mt->type == ENUM_TYPE) {
lua_getuservalue(L, -1);
num_upvals += 2;
@@ -407,7 +407,7 @@ void push_function(struct jit* jit, lua_State* L, function_t func, int ct_usr, c
if (mt->pointers) {
| bl extern to_typed_pointer
- } else if (mt->type == FUNCTION_TYPE) {
+ } else if (mt->type == FUNCTION_PTR_TYPE) {
| bl extern to_typed_function
} else if (mt->type == ENUM_TYPE) {
| bl extern to_enum
View
6 call_x86.dasc
@@ -375,7 +375,7 @@ int x86_return_size(lua_State* L, int usr, const struct ctype* ct)
case UINTPTR_TYPE:
ret += sizeof(void*);
break;
- case FUNCTION_TYPE:
+ case FUNCTION_PTR_TYPE:
ret += sizeof(cfunction);
break;
case BOOL_TYPE:
@@ -1113,7 +1113,7 @@ void compile_function(lua_State* L, cfunction func, int ct_usr, const struct cty
add_pointer(Dst, ct, &reg);
} else {
switch (mbr_ct->type) {
- case FUNCTION_TYPE:
+ case FUNCTION_PTR_TYPE:
lua_getuservalue(L, -1);
num_upvals += 2;
| call_rrrp extern check_typed_cfunction, L_ARG, i, lua_upvalueindex(num_upvals), mbr_ct
@@ -1452,7 +1452,7 @@ void compile_function(lua_State* L, cfunction func, int ct_usr, const struct cty
} else {
switch (mbr_ct->type) {
- case FUNCTION_TYPE:
+ case FUNCTION_PTR_TYPE:
lua_getuservalue(L, -1);
num_upvals += 2;
| mov [rsp+32], rax // save the function pointer
View
272 ffi.c
@@ -412,6 +412,8 @@ static void* check_pointer(lua_State* L, int idx, struct ctype* ct)
return lua_touserdata(L, idx);
} else if (ct->pointers || ct->type == STRUCT_TYPE || ct->type == UNION_TYPE) {
return p;
+ } else if (ct->type == FUNCTION_PTR_TYPE) {
+ return (void*) *(cfunction*) p;
} else if (ct->type == UINTPTR_TYPE) {
return *(void**) p;
}
@@ -546,7 +548,7 @@ static cfunction check_cfunction(lua_State* L, int idx, int to_usr, const struct
lua_pop(L, 1);
return (cfunction) *(void**) p;
- } else if (ft.type != FUNCTION_TYPE) {
+ } else if (ft.type != FUNCTION_PTR_TYPE) {
goto err;
} else if (!check_pointers) {
@@ -888,7 +890,7 @@ static void set_value(lua_State* L, int idx, void* to, int to_usr, const struct
case ENUM_TYPE:
*(int32_t*) to = check_enum(L, idx, to_usr, tt);
break;
- case FUNCTION_TYPE:
+ case FUNCTION_PTR_TYPE:
*(cfunction*) to = check_cfunction(L, idx, to_usr, tt, check_pointers);
break;
default:
@@ -956,7 +958,7 @@ static int do_new(lua_State* L, int is_cast)
/* don't push a callback when we have a c function, as cb:set needs a
* compiled callback from a lua function to work */
- if (!ct.pointers && ct.type == FUNCTION_TYPE && (lua_isnil(L, 2) || lua_isfunction(L, 2))) {
+ if (!ct.pointers && ct.type == FUNCTION_PTR_TYPE && (lua_isnil(L, 2) || lua_isfunction(L, 2))) {
/* Function cdatas are pinned and must be manually cleaned up by
* calling func:free(). */
compile_callback(L, 2, -1, &ct);
@@ -1175,7 +1177,7 @@ static int cdata_call(lua_State* L)
return lua_gettop(L);
}
}
- if (ct.pointers || ct.type != FUNCTION_TYPE) {
+ if (ct.pointers || ct.type != FUNCTION_PTR_TYPE) {
return luaL_error(L, "only function callbacks are callable");
}
@@ -1363,7 +1365,7 @@ static int cdata_index(lua_State* L)
/* Callbacks use the same metatable as standard cdata values, but have set
* and free members. So instead of mt.__index = mt, we do the equiv here. */
- if (!ct.pointers && ct.type == FUNCTION_TYPE) {
+ if (!ct.pointers && ct.type == FUNCTION_PTR_TYPE) {
lua_getmetatable(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
@@ -1417,7 +1419,7 @@ static int cdata_index(lua_State* L)
if (ct.type == UINT64_TYPE || ct.type == INT64_TYPE) {
struct ctype rt;
uint64_t val = *(uint64_t*) data;
- val <<= ct.bit_offset;
+ val >>= ct.bit_offset;
val &= (UINT64_C(1) << ct.bit_size) - 1;
memset(&rt, 0, sizeof(rt));
@@ -1425,7 +1427,7 @@ static int cdata_index(lua_State* L)
rt.type = UINT64_TYPE;
rt.is_defined = 1;
- to = push_cdata(L, -1, &rt);
+ to = push_cdata(L, 0, &rt);
*(uint64_t*) to = val;
return 1;
@@ -1437,7 +1439,7 @@ static int cdata_index(lua_State* L)
} else {
uint64_t val = *(uint64_t*) data;
- val <<= ct.bit_offset;
+ val >>= ct.bit_offset;
val &= (UINT64_C(1) << ct.bit_size) - 1;
lua_pushnumber(L, val);
return 1;
@@ -1466,7 +1468,7 @@ static int cdata_index(lua_State* L)
*(void**) to = data;
return 1;
- } else if (ct.type == FUNCTION_TYPE) {
+ } else if (ct.type == FUNCTION_PTR_TYPE) {
cfunction* pf = (cfunction*) push_cdata(L, -1, &ct);
*pf = *(cfunction*) data;
return 1;
@@ -1547,7 +1549,7 @@ static int64_t check_intptr(lua_State* L, int idx, void* p, struct ctype* ct)
} else if (ct->pointers) {
return (intptr_t) p;
- } else if (ct->type == UINTPTR_TYPE || ct->type == FUNCTION_TYPE) {
+ } else if (ct->type == UINTPTR_TYPE || ct->type == FUNCTION_PTR_TYPE) {
return *(intptr_t*) p;
} else if (ct->type == INT64_TYPE || ct->type == UINT64_TYPE) {
return *(int64_t*) p;
@@ -1992,10 +1994,10 @@ static int cdata_pow(lua_State* L)
goto err; \
} \
\
- } else if (lt.is_null && rt.type == FUNCTION_TYPE) { \
+ } else if (lt.is_null && rt.type == FUNCTION_PTR_TYPE) { \
res = OP((uint64_t) left, (uint64_t) right); \
\
- } else if (rt.is_null && lt.type == FUNCTION_TYPE) { \
+ } else if (rt.is_null && lt.type == FUNCTION_PTR_TYPE) { \
res = OP((uint64_t) left, (uint64_t) right); \
\
} else if (lt.pointers && rt.type == UINTPTR_TYPE) { \
@@ -2088,7 +2090,7 @@ static const char* etype_tostring(int type)
case ENUM_TYPE: return "enum";
case UNION_TYPE: return "union";
case STRUCT_TYPE: return "struct";
- case FUNCTION_TYPE: return "func";
+ case FUNCTION_PTR_TYPE: return "func";
default: return "invalid";
}
}
@@ -2345,46 +2347,84 @@ static int ffi_load(lua_State* L)
return 1;
}
-static int find_function(lua_State* L, int module, const char* asmname, int usr, const struct ctype* ct)
+static void* find_symbol(lua_State* L, int modidx, const char* asmname)
{
size_t i;
- void** libs = (void**) lua_touserdata(L, module);
- size_t num = lua_rawlen(L, module) / sizeof(void*);
+ void** libs;
+ size_t num;
+ void* sym = NULL;
- usr = lua_absindex(L, usr);
+ libs = (void**) lua_touserdata(L, modidx);
+ num = lua_rawlen(L, modidx) / sizeof(void*);
- for (i = 0; i < num; i++) {
+ for (i = 0; i < num && sym == NULL; i++) {
if (libs[i]) {
- cfunction func = (cfunction) GetProcAddressA(libs[i], asmname);
-
- if (func) {
- compile_function(L, func, usr, ct);
- return 1;
- }
+ sym = GetProcAddressA(libs[i], asmname);
}
}
- return 0;
+ return sym;
+}
+
+/* pushes the user table */
+static void* lookup_global(lua_State* L, int modidx, int nameidx, const char** pname, struct ctype* ct)
+{
+ int top = lua_gettop(L);
+ void* sym;
+
+ modidx = lua_absindex(L, modidx);
+ nameidx = lua_absindex(L, nameidx);
+
+ *pname = luaL_checkstring(L, nameidx);
+
+ /* get the ctype */
+ push_upval(L, &functions_key);
+ lua_pushvalue(L, nameidx);
+ lua_rawget(L, -2);
+ if (lua_isnil(L, -1)) {
+ luaL_error(L, "missing declaration for function/global %s", *pname);
+ return NULL;
+ }
+
+ /* leave just the ct_usr on the stack */
+ *ct = *(const struct ctype*) lua_touserdata(L, -1);
+ lua_getuservalue(L, -1);
+ lua_replace(L, top + 1);
+ lua_pop(L, 1);
+
+ assert(lua_gettop(L) == top + 1);
+
+ /* get the assembly name */
+ push_upval(L, &asmname_key);
+ lua_pushvalue(L, nameidx);
+ lua_rawget(L, -2);
+ if (lua_isstring(L, -1)) {
+ *pname = lua_tostring(L, -1);
+ }
+ lua_pop(L, 2);
+
+ sym = find_symbol(L, modidx, *pname);
+
+ assert(lua_gettop(L) == top + 1);
+ return sym;
}
static int cmodule_index(lua_State* L)
{
- const char* funcname;
+ const char* asmname;
struct ctype ct;
- int ct_usr;
- int mod_usr;
+ void *sym;
lua_settop(L, 2);
+
+ /* see if we have already loaded the function */
lua_getuservalue(L, 1);
- mod_usr = lua_gettop(L);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
-
- /* see if we have already loaded the function */
if (!lua_isnil(L, -1)) {
return 1;
}
- lua_pop(L, 1);
+ lua_pop(L, 2);
/* check the constants table */
push_upval(L, &constants_key);
@@ -2395,53 +2435,147 @@ static int cmodule_index(lua_State* L)
}
lua_pop(L, 2);
- funcname = luaL_checkstring(L, 2);
+ /* lookup_global pushes the ct_usr */
+ sym = lookup_global(L, 1, 2, &asmname, &ct);
- /* find the function type */
- push_upval(L, &functions_key);
- lua_pushvalue(L, 2);
- lua_rawget(L, -2);
- lua_remove(L, -2); /* function tbl */
- if (lua_isnil(L, -1)) {
- luaL_error(L, "missing declaration for function %s", funcname);
+#if defined _WIN32 && !defined _WIN64 && (defined __i386__ || defined _M_IX86)
+ if (!sym && ct.type == FUNCTION_TYPE) {
+ ct.calling_convention = STD_CALL;
+ lua_pushfstring(L, "_%s@%d", asmname, x86_return_size(L, -1, &ct));
+ sym = find_symbol(L, 1, lua_tostring(L, -1));
+ lua_pop(L, 1);
}
- ct = *(const struct ctype*) lua_touserdata(L, -1);
- lua_getuservalue(L, -1);
- ct_usr = lua_gettop(L);
- /* replace funcname with the assembly name if its different */
- lua_pushlightuserdata(L, &asmname_key);
- lua_rawget(L, ct_usr);
- if (!lua_isnil(L, -1)) {
- funcname = lua_tostring(L, -1);
+ if (!sym && ct.type == FUNCTION_TYPE) {
+ ct.calling_convention = FAST_CALL;
+ lua_pushfstring(L, "@%s@%d", asmname, x86_return_size(L, -1, &ct));
+ sym = find_symbol(L, 1, lua_tostring(L, -1));
+ lua_pop(L, 1);
}
+#endif
- if (find_function(L, 1, funcname, ct_usr, &ct)) {
- goto end;
+ if (!sym) {
+ return luaL_error(L, "failed to find function/global %s", asmname);
}
-#if defined _WIN32 && !defined _WIN64 && (defined __i386__ || defined _M_IX86)
- ct.calling_convention = STD_CALL;
- lua_pushfstring(L, "_%s@%d", funcname, x86_return_size(L, ct_usr, &ct));
- if (find_function(L, 1, lua_tostring(L, -1), ct_usr, &ct)) {
- goto end;
+ assert(lua_gettop(L) == 3); /* module, name, ct_usr */
+
+ if (ct.type == FUNCTION_TYPE) {
+ compile_function(L, (cfunction) sym, -1, &ct);
+ assert(lua_gettop(L) == 4); /* module, name, ct_usr, function */
+
+ /* set module usr value[luaname] = function to cache for next time */
+ lua_getuservalue(L, 1);
+ lua_pushvalue(L, 2);
+ lua_pushvalue(L, -3);
+ lua_rawset(L, -3);
+ lua_pop(L, 1); /* module uv */
+ return 1;
+ }
+
+ /* extern const char* foo; and extern const char foo[]; */
+ if (ct.pointers == 1 && ct.type == CHAR_TYPE) {
+ char* str = (char*) sym;
+ if (!ct.is_array) {
+ str = *(char**) sym;
+ }
+ lua_pushstring(L, str);
+ return 1;
}
- ct.calling_convention = FAST_CALL;
- lua_pushfstring(L, "@%s@%d", funcname, x86_return_size(L, ct_usr, &ct));
- if (find_function(L, 1, lua_tostring(L, -1), ct_usr, &ct)) {
- goto end;
+ /* extern struct foo foo[], extern void* foo[]; and extern struct foo foo; */
+ if (ct.is_array || (!ct.pointers && (ct.type == UNION_TYPE || ct.type == STRUCT_TYPE))) {
+ void* p;
+ ct.is_reference = 1;
+ p = push_cdata(L, -1, &ct);
+ *(void**) p = sym;
+ return 1;
}
-#endif
- return luaL_error(L, "failed to find function %s", funcname);
+ /* extern void* foo; and extern void (*foo)(); */
+ if (ct.pointers || ct.type == FUNCTION_PTR_TYPE) {
+ void* p = push_cdata(L, -1, &ct);
+ *(void**) p = *(void**) sym;
+ return 1;
+ }
-end:
- /* set module usr value[luaname] = function to cache for next time */
- lua_pushvalue(L, 2);
- lua_pushvalue(L, -2);
- lua_rawset(L, mod_usr);
- return 1;
+ switch (ct.type) {
+ case COMPLEX_DOUBLE_TYPE:
+ case COMPLEX_FLOAT_TYPE:
+ case UINT64_TYPE:
+ case UINTPTR_TYPE:
+ case INT64_TYPE:
+ {
+ /* TODO: complex float/double need to be references if .re and
+ * .imag are setable */
+ void* p = push_cdata(L, -1, &ct);
+ memcpy(p, sym, ct.base_size);
+ return 1;
+ }
+
+ case DOUBLE_TYPE:
+ lua_pushnumber(L, *(double*) sym);
+ return 1;
+
+ case FLOAT_TYPE:
+ lua_pushnumber(L, *(float*) sym);
+ return 1;
+
+ case BOOL_TYPE:
+ lua_pushboolean(L, *(bool*) sym);
+ return 1;
+
+ case INT8_TYPE:
+ lua_pushnumber(L, *(int8_t*) sym);
+ return 1;
+
+ case INT16_TYPE:
+ lua_pushnumber(L, *(int16_t*) sym);
+ return 1;
+
+ case INT32_TYPE:
+ case ENUM_TYPE:
+ lua_pushnumber(L, *(int32_t*) sym);
+ return 1;
+
+ case UINT8_TYPE:
+ lua_pushnumber(L, *(uint8_t*) sym);
+ return 1;
+
+ case UINT16_TYPE:
+ lua_pushnumber(L, *(uint16_t*) sym);
+ return 1;
+
+ case UINT32_TYPE:
+ lua_pushnumber(L, *(uint32_t*) sym);
+ return 1;
+ }
+
+ return luaL_error(L, "NYI - global value type");
+}
+
+static int cmodule_newindex(lua_State* L)
+{
+ const char* name;
+ void* sym;
+ struct ctype ct;
+
+ lua_settop(L, 3);
+
+ /* pushes the ct_usr */
+ sym = lookup_global(L, 1, 2, &name, &ct);
+ assert(lua_gettop(L) == 4); /* module, name, value, ct_usr */
+
+ if (sym == NULL) {
+ return luaL_error(L, "failed to find global %s", name);
+ }
+
+ if (ct.type == FUNCTION_TYPE || ct.is_array || (ct.const_mask & 1)) {
+ return luaL_error(L, "can not set global %s", name);
+ }
+
+ set_value(L, 3, sym, -1, &ct, 1);
+ return 0;
}
static int jit_gc(lua_State* L)
@@ -2557,6 +2691,7 @@ static const luaL_Reg ctype_mt[] = {
static const luaL_Reg cmodule_mt[] = {
{"__index", &cmodule_index},
+ {"__newindex", &cmodule_newindex},
{NULL, NULL}
};
@@ -2928,6 +3063,9 @@ int luaopen_ffi(lua_State* L)
set_upval(L, &functions_key);
lua_newtable(L);
+ set_upval(L, &asmname_key);
+
+ lua_newtable(L);
set_upval(L, &abi_key);
lua_pushinteger(L, 1);
View
1 ffi.h
@@ -286,6 +286,7 @@ enum {
UNION_TYPE,
STRUCT_TYPE,
FUNCTION_TYPE,
+ FUNCTION_PTR_TYPE,
};
#define CHAR_TYPE ((((char) -1) > 0) ? UINT8_TYPE : INT8_TYPE)
View
83 parser.c
@@ -973,11 +973,21 @@ static int parse_type_name(lua_State* L, struct parser* P)
* more following it) or 0 if not. If the token was used, the next token must
* be retrieved using next_token/require_token.
*/
-static int parse_attribute(lua_State* L, struct parser* P, struct token* tok, struct ctype* ct)
+static int parse_attribute(lua_State* L, struct parser* P, struct token* tok, struct ctype* ct, struct token* asmname)
{
if (tok->type != TOK_TOKEN) {
return 0;
+ } else if (asmname && IS_LITERAL(*tok, "__asm")) {
+ check_token(L, P, TOK_OPEN_PAREN, NULL, "unexpected token after __asm on line %d", P->line);
+ require_token(L, P, tok);
+ if (tok->type != TOK_STRING) {
+ luaL_error(L, "unexpected token after __asm on line %d", P->line);
+ }
+ *asmname = *tok;
+ check_token(L, P, TOK_CLOSE_PAREN, NULL, "unexpected token after __asm on line %d", P->line);
+ return 1;
+
} else if (IS_LITERAL(*tok, "__attribute__") || IS_LITERAL(*tok, "__declspec")) {
int parens = 1;
check_token(L, P, TOK_OPEN_PAREN, NULL, "expected parenthesis after __attribute__ or __declspec on line %d", P->line);
@@ -1068,7 +1078,7 @@ int parse_type(lua_State* L, struct parser* P, struct ctype* ct)
require_token(L, P, &tok);
/* get function attributes before the return type */
- while (parse_attribute(L, P, &tok, ct)) {
+ while (parse_attribute(L, P, &tok, ct, NULL)) {
require_token(L, P, &tok);
}
@@ -1152,7 +1162,7 @@ static void append_type_name(luaL_Buffer* B, int usr, const struct ctype* ct)
usr = lua_absindex(L, usr);
- if (ct->type != FUNCTION_TYPE && (ct->const_mask & (1 << ct->pointers))) {
+ if (ct->type != FUNCTION_PTR_TYPE && (ct->const_mask & (1 << ct->pointers))) {
luaL_addstring(B, "const ");
}
@@ -1169,7 +1179,7 @@ static void append_type_name(luaL_Buffer* B, int usr, const struct ctype* ct)
luaL_addstring(B, "union ");
goto get_name;
- case FUNCTION_TYPE:
+ case FUNCTION_PTR_TYPE:
get_name:
lua_pushlightuserdata(L, &g_name_key);
lua_rawget(L, usr);
@@ -1233,7 +1243,7 @@ static void append_type_name(luaL_Buffer* B, int usr, const struct ctype* ct)
luaL_error(L, "internal error - bad type %d", ct->type);
}
- if (ct->type == FUNCTION_TYPE && (ct->const_mask & (1 << ct->pointers))) {
+ if (ct->type == FUNCTION_PTR_TYPE && (ct->const_mask & (1 << ct->pointers))) {
luaL_addstring(B, " const");
}
@@ -1489,7 +1499,7 @@ void parse_argument(lua_State* L, struct parser* P, int ct_usr, struct ctype* ty
} else if (tok.type == TOK_REFERENCE) {
luaL_error(L, "NYI: c++ reference types");
- } else if (parse_attribute(L, P, &tok, type)) {
+ } else if (parse_attribute(L, P, &tok, type, asmname)) {
/* parse attribute has filled out appropriate fields in type */
} else if (tok.type == TOK_OPEN_PAREN) {
@@ -1523,7 +1533,7 @@ void parse_argument(lua_State* L, struct parser* P, int ct_usr, struct ctype* ty
type->pointers++;
type->const_mask <<= 1;
- } else if (parse_attribute(L, P, &tok, type)) {
+ } else if (parse_attribute(L, P, &tok, type, NULL)) {
/* parse_attribute sets the appropriate fields */
} else if (tok.type != TOK_TOKEN) {
@@ -1549,6 +1559,8 @@ void parse_argument(lua_State* L, struct parser* P, int ct_usr, struct ctype* ty
if (type->pointers > 0) {
type->pointers--;
+ type->const_mask >>= 1;
+ type->type = FUNCTION_PTR_TYPE;
}
check_token(L, P, TOK_OPEN_PAREN, "", "unexpected token in function on line %d", P->line);
@@ -1562,18 +1574,7 @@ void parse_argument(lua_State* L, struct parser* P, int ct_usr, struct ctype* ty
break;
}
- if (tok.type == TOK_TOKEN && IS_LITERAL(tok, "__asm")) {
- check_token(L, P, TOK_OPEN_PAREN, NULL, "unexpected token after __asm on line %d", P->line);
- require_token(L, P, &tok);
- if (tok.type != TOK_STRING) {
- luaL_error(L, "unexpected token after __asm on line %d", P->line);
- }
- if (asmname) {
- *asmname = tok;
- }
- check_token(L, P, TOK_CLOSE_PAREN, NULL, "unexpected token after __asm on line %d", P->line);
-
- } else if (!parse_attribute(L, P, &tok, type)) {
+ if (!parse_attribute(L, P, &tok, type, asmname)) {
put_back(P);
break;
}
@@ -1634,19 +1635,6 @@ void parse_argument(lua_State* L, struct parser* P, int ct_usr, struct ctype* ty
put_back(P);
break;
- } else if (IS_LITERAL(tok, "__cdecl")) {
- type->calling_convention = C_CALL;
-
- } else if (IS_LITERAL(tok, "__stdcall")) {
-#if defined __i386__ || defined _M_IX86
- type->calling_convention = STD_CALL;
-#endif
-
- } else if (IS_LITERAL(tok, "__fastcall")) {
-#if defined __i386__ || defined _M_IX86
- type->calling_convention = FAST_CALL;
-#endif
-
} else if (IS_LITERAL(tok, "const")) {
type->const_mask |= 1;
@@ -1662,7 +1650,7 @@ void parse_argument(lua_State* L, struct parser* P, int ct_usr, struct ctype* ty
}
}
- if (type->type != FUNCTION_TYPE && type->calling_convention != C_CALL) {
+ if (type->type != FUNCTION_PTR_TYPE && type->calling_convention != C_CALL) {
/* functions use ftype and have already returned */
luaL_error(L, "calling convention annotation only allowed on functions and function pointers on line %d", P->line);
}
@@ -1819,30 +1807,27 @@ static int parse_root(lua_State* L, struct parser* P)
parse_type(L, P, &type);
parse_argument(L, P, -1, &type, &name, &asmname);
- if (type.pointers || (type.type != ENUM_TYPE && type.type != UNION_TYPE && type.type != STRUCT_TYPE && type.type != FUNCTION_TYPE)) {
- return luaL_error(L, "unexpected type in root on line %d", P->line);
- }
-
- require_token(L, P, &tok);
+ check_token(L, P, TOK_SEMICOLON, NULL, "missing semicolon on line %d", P->line);
- if (tok.type != TOK_SEMICOLON) {
- return luaL_error(L, "missing semicolon on line %d", P->line);
- }
+ if (name.size) {
+ /* global/function declaration */
- /* this was either a function or type declaration/definition - if
- * the latter then the type has already been processed */
- if (type.type == FUNCTION_TYPE && asmname.size) {
- lua_pushlightuserdata(L, &asmname_key);
- lua_pushlstring(L, asmname.str, asmname.size);
- lua_rawset(L, -3);
- }
+ /* set asmname_tbl[name] = asmname */
+ if (asmname.size) {
+ push_upval(L, &asmname_key);
+ lua_pushlstring(L, name.str, name.size);
+ lua_pushlstring(L, asmname.str, asmname.size);
+ lua_rawset(L, -3);
+ lua_pop(L, 1); /* asmname upval */
+ }
- if (type.type == FUNCTION_TYPE && name.size) {
push_upval(L, &functions_key);
lua_pushlstring(L, name.str, name.size);
push_ctype(L, -3, &type);
lua_rawset(L, -3);
lua_pop(L, 1); /* functions upval */
+ } else {
+ /* type declaration/definition - already been processed */
}
lua_pop(L, 2);
View
66 test.c
@@ -37,14 +37,14 @@ enum e8 {
BAR8,
};
enum e16 {
- FOO16,
+ FOO16 = 1 << 8,
BAR16,
- BIG16 = 2 << 14,
+ BIG16 = 1 << 14,
};
enum e32 {
- FOO32,
+ FOO32 = 1 << 16,
BAR32,
- BIG32 = 2 << 30,
+ BIG32 = 1 << 30,
};
EXPORT bool have_complex();
@@ -58,16 +58,14 @@ bool have_complex()
#endif
}
-EXPORT bool is_msvc();
+EXPORT bool is_msvc;
-bool is_msvc()
-{
+bool is_msvc =
#ifdef _MSC_VER
- return 1;
+ 1;
#else
- return 0;
+ 0;
#endif
-}
EXPORT int test_pow(int v);
int test_pow(int v)
@@ -595,6 +593,54 @@ int call_fptr(struct fptr* s, int val) {
return (s->p)(val);
}
+EXPORT bool g_b;
+EXPORT int8_t g_i8;
+EXPORT int16_t g_i16;
+EXPORT int32_t g_i32;
+EXPORT int64_t g_i64;
+EXPORT uint8_t g_u8;
+EXPORT uint16_t g_u16;
+EXPORT uint32_t g_u32;
+EXPORT uint64_t g_u64;
+EXPORT float g_f;
+EXPORT double g_d;
+#ifdef HAVE_COMPLEX
+EXPORT double complex g_dc;
+EXPORT float complex g_fc;
+#endif
+EXPORT bool (*g_fp)();
+EXPORT const char g_s[];
+EXPORT const char* g_sp;
+EXPORT void* g_p;
+EXPORT enum e8 g_e8;
+EXPORT enum e16 g_e16;
+EXPORT enum e32 g_e32;
+EXPORT struct Date g_date;
+
+bool g_b = true;
+int8_t g_i8 = -8;
+int16_t g_i16 = -16;
+int32_t g_i32 = -32;
+int64_t g_i64 = -64;
+uint8_t g_u8 = 8;
+uint16_t g_u16 = 16;
+uint32_t g_u32 = 32;
+uint64_t g_u64 = 64;
+float g_f = 3;
+double g_d = 5;
+#ifdef HAVE_COMPLEX
+double complex g_dc = 7+8i;
+float complex g_fc = 6+9i;
+#endif
+bool (*g_fp)() = &have_complex;
+void* g_p = (void*) &have_complex;
+const char g_s[] = "g_s";
+const char* g_sp = "g_sp";
+enum e8 g_e8 = FOO8;
+enum e16 g_e16 = FOO16;
+enum e32 g_e32 = FOO32;
+struct Date g_date = {1,2,3,4};
+
EXPORT void set_errno(int val);
EXPORT int get_errno(void);
View
90 test.lua
@@ -25,17 +25,18 @@ enum e8 {
BAR8,
};
enum e16 {
- FOO16,
+ FOO16 = 1 << 8,
BAR16,
- BIG16 = 2 << 14,
+ BIG16 = 1 << 14,
};
enum e32 {
- FOO32,
+ FOO32 = 1 << 16,
BAR32,
- BIG32 = 2 << 30,
+ BIG32 = 1 << 30,
};
int max_alignment();
-bool is_msvc();
+bool is_msvc;
+bool is_msvc2 __asm("is_msvc");
bool have_complex();
bool have_complex2() __asm("have_complex");
@@ -185,6 +186,28 @@ struct fptr {
};
int call_fptr(struct fptr* s, int val);
+bool g_b;
+int8_t g_i8;
+int16_t g_i16;
+int32_t g_i32;
+int64_t g_i64;
+uint8_t g_u8;
+uint16_t g_u16;
+uint32_t g_u32;
+uint64_t g_u64;
+float g_f;
+double g_d;
+double complex g_dc;
+float complex g_fc;
+bool (*g_fp)();
+const char g_s[];
+const char* g_sp;
+void* g_p;
+enum e8 g_e8;
+enum e16 g_e16;
+enum e32 g_e32;
+struct Date g_date;
+
void set_errno(int val);
int get_errno(void);
]]
@@ -290,6 +313,9 @@ local function checkalign(type, v, ret)
check(ret, #str)
end
+local u64 = ffi.typeof('uint64_t')
+local i64 = ffi.typeof('int64_t')
+
local first = true
for convention,c in pairs(dlls) do
@@ -320,8 +346,56 @@ for convention,c in pairs(dlls) do
end
check(c.have_complex(), c.have_complex2())
+ check(c.is_msvc, c.is_msvc2)
+
+ check(c.g_b, true)
+ check(c.g_i8, -8)
+ check(c.g_i16, -16)
+ check(c.g_i32, -32)
+ check(c.g_i64, i64(-64))
+ check(c.g_u8, 8)
+ check(c.g_u16, 16)
+ check(c.g_u32, 32)
+ check(c.g_u64, u64(64))
+ check(c.g_f, 3)
+ check(c.g_d, 5)
+ if c.have_complex() then
+ check(c.g_dc, 7 + 8*i)
+ check(c.g_fc, 6 + 9*i)
+ end
+ check(ffi.cast('void*', c.g_fp), c.g_p)
+ check(c.g_s, 'g_s')
+ check(c.g_sp, 'g_sp')
+ check(c.g_e8, c.FOO8)
+ check(c.g_e16, c.FOO16)
+ check(c.g_e32, c.FOO32)
+ check(c.g_date.nWeekDay, 1)
+ check(c.g_date.nMonthDay, 2)
+ check(c.g_date.nMonth, 3)
+ check(c.g_date.nYear, 4)
+
+ c.g_b = false; check(c.g_b, false)
+ c.g_i8 = -108; check(c.g_i8, -108)
+ c.g_i16 = -1016; check(c.g_i16, -1016)
+ c.g_i32 = -1032; check(c.g_i32, -1032)
+ c.g_i64 = -1064; check(c.g_i64, i64(-1064))
+ c.g_u8 = 208; check(c.g_u8, 208)
+ c.g_u16 = 2016; check(c.g_u16, 2016)
+ c.g_u32 = 2032; check(c.g_u32, 2032)
+ c.g_u64 = 2064; check(c.g_u64, u64(2064))
+ c.g_f = 13; check(c.g_f, 13)
+ c.g_d = 15; check(c.g_d, 15)
+ if c.have_complex() then
+ c.g_dc = 17+18*i; check(c.g_dc, 17+18*i)
+ c.g_fc = 16+19*i; check(c.g_fc, 16+19*i)
+ end
+ c.g_sp = 'foo'; check(c.g_sp, 'foo')
+ c.g_e8 = c.BAR8; check(c.g_e8, c.BAR8)
+ c.g_e16 = c.BAR16; check(c.g_e16, c.BAR16)
+ c.g_e32 = c.BAR32; check(c.g_e32, c.BAR32)
+ c.g_date.nWeekDay = 3; check(c.g_date.nWeekDay, 3)
- local align_attr = c.is_msvc() and [[
+ local align_attr = c.is_msvc and [[
struct align_attr_ALIGN_SUFFIX {
char pad;
__declspec(align(ALIGN)) TYPE v;
@@ -363,7 +437,7 @@ for convention,c in pairs(dlls) do
checkalign(type, v, c['print_align_' .. align .. '_' .. suffix](buf, v))
-- MSVC doesn't support aligned attributes on enums
- if not type:match('^enum e[0-9]*$') or not c.is_msvc() then
+ if not type:match('^enum e[0-9]*$') or not c.is_msvc then
local v2 = ffi.new('struct align_attr_' .. align .. '_' .. suffix, {0, test})
checkalign(type, v2, c['print_align_attr_' .. align .. '_' .. suffix](buf, v2))
end
@@ -552,8 +626,6 @@ local suc, err = pcall(function() vls.key = 'val' end)
assert(not suc)
check(err, 'in newindex key 4 val')
-local u64 = ffi.typeof('uint64_t')
-
mt.__add = function(vls, a) return vls.d.a + a end
mt.__sub = function(vls, a) return vls.d.a - a end
mt.__mul = function(vls, a) return vls.d.a * a end

0 comments on commit ba38f94

Please sign in to comment.
Something went wrong with that request. Please try again.