diff --git a/src/lj_ccall.c b/src/lj_ccall.c index 6234a05a..3881ad50 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c @@ -275,8 +275,16 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, #endif } + /* Skip initial attributes. */ + fid = ct->sib; + while (fid) { + CType *ctf = ctype_get(cts, fid); + if (!ctype_isattrib(ctf->info)) break; + fid = ctf->sib; + } + /* Walk through all passed arguments. */ - for (fid = ct->sib, o = L->base+1; o < top; o++) { + for (o = L->base+1; o < top; o++) { CTypeID did; CType *d; CTSize sz; diff --git a/src/lj_clib.c b/src/lj_clib.c index 4a81bb7d..e2d349fd 100644 --- a/src/lj_clib.c +++ b/src/lj_clib.c @@ -242,6 +242,17 @@ static CTSize clib_func_argsize(CTState *cts, CType *ct) } #endif +/* Get redirected or mangled external symbol. */ +static const char *clib_extsym(CTState *cts, CType *ct, GCstr *name) +{ + if (ct->sib) { + CType *ctf = ctype_get(cts, ct->sib); + if (ctype_isxattrib(ctf->info, CTA_REDIR)) + return strdata(gco2str(gcref(ctf->name))); + } + return strdata(name); +} + /* Index a C library by name. */ TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name) { @@ -260,7 +271,8 @@ TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name) else setnumV(tv, (lua_Number)(int32_t)ct->size); } else { - void *p = clib_getsym(cl, strdata(name)); + const char *sym = clib_extsym(cts, ct, name); + void *p = clib_getsym(cl, sym); GCcdata *cd; lua_assert(ctype_isfunc(ct->info) || ctype_isextern(ct->info)); #if LJ_TARGET_X86 && LJ_ABI_WIN @@ -269,8 +281,8 @@ TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name) CTInfo cconv = ctype_cconv(ct->info); if (cconv == CTCC_FASTCALL || cconv == CTCC_STDCALL) { CTSize sz = clib_func_argsize(cts, ct); - const char *sym = lj_str_pushf(L, - cconv == CTCC_FASTCALL ? "@%s@%d" : "_%s@%d", strdata(name), sz); + sym = lj_str_pushf(L, cconv == CTCC_FASTCALL ? "@%s@%d" : "_%s@%d", + sym, sz); L->top--; p = clib_getsym(cl, sym); } diff --git a/src/lj_cparse.c b/src/lj_cparse.c index 333e7a07..925894a3 100644 --- a/src/lj_cparse.c +++ b/src/lj_cparse.c @@ -342,6 +342,7 @@ typedef struct CPDecl { uint32_t mode; /* Declarator mode. */ CPState *cp; /* C parser state. */ GCstr *name; /* Name of declared identifier (if direct). */ + GCstr *redir; /* Redirected symbol name. */ CTypeID nameid; /* Existing typedef for declared identifier. */ CTInfo attr; /* Attributes. */ CTInfo fattr; /* Function attributes. */ @@ -923,6 +924,7 @@ static void cp_decl_reset(CPDecl *decl) decl->attr = decl->specattr; decl->fattr = decl->specfattr; decl->name = NULL; + decl->redir = NULL; } /* Parse constant initializer. */ @@ -982,7 +984,15 @@ static void cp_decl_asm(CPState *cp, CPDecl *decl) UNUSED(decl); cp_next(cp); cp_check(cp, '('); - while (cp->tok == CTOK_STRING) cp_next(cp); /* NYI: currently ignored. */ + if (cp->tok == CTOK_STRING) { + GCstr *str = cp->str; + while (cp_next(cp) == CTOK_STRING) { + lj_str_pushf(cp->L, "%s%s", strdata(str), strdata(cp->str)); + cp->L->top--; + str = strV(cp->L->top); + } + decl->redir = str; + } cp_check(cp, ')'); } @@ -1428,6 +1438,7 @@ static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl) decl->cp = cp; decl->mode = cp->mode; decl->name = NULL; + decl->redir = NULL; decl->attr = 0; decl->fattr = 0; decl->pos = decl->top = 0; @@ -1729,31 +1740,36 @@ static void cp_decl_multi(CPState *cp) cp_declarator(cp, &decl); typeid = cp_decl_intern(cp, &decl); if (decl.name && !decl.nameid) { /* NYI: redeclarations are ignored. */ + CType *ct; + CTypeID id; if ((scl & CDF_TYPEDEF)) { /* Create new typedef. */ - CType *ct; - CTypeID tdefid = lj_ctype_new(cp->cts, &ct); + id = lj_ctype_new(cp->cts, &ct); ct->info = CTINFO(CT_TYPEDEF, typeid); - ctype_setname(ct, decl.name); - lj_ctype_addname(cp->cts, ct, tdefid); + goto noredir; } else if (ctype_isfunc(ctype_get(cp->cts, typeid)->info)) { /* Treat both static and extern function declarations as extern. */ - CType *ct = ctype_get(cp->cts, typeid); + ct = ctype_get(cp->cts, typeid); /* We always get new anonymous functions (typedefs are copied). */ lua_assert(gcref(ct->name) == NULL); - ctype_setname(ct, decl.name); /* Just name it. */ - lj_ctype_addname(cp->cts, ct, typeid); + id = typeid; /* Just name it. */ } else if ((scl & CDF_STATIC)) { /* Accept static constants. */ - CType *ct; - CTypeID constid = cp_decl_constinit(cp, &ct, typeid); - ctype_setname(ct, decl.name); - lj_ctype_addname(cp->cts, ct, constid); + id = cp_decl_constinit(cp, &ct, typeid); + goto noredir; } else { /* External references have extern or no storage class. */ - CType *ct; - CTypeID extid = lj_ctype_new(cp->cts, &ct); + id = lj_ctype_new(cp->cts, &ct); ct->info = CTINFO(CT_EXTERN, typeid); - ctype_setname(ct, decl.name); - lj_ctype_addname(cp->cts, ct, extid); } + if (decl.redir) { /* Add attribute for redirected symbol name. */ + CType *cta; + CTypeID aid = lj_ctype_new(cp->cts, &cta); + cta->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_REDIR)); + cta->sib = ct->sib; + ct->sib = aid; + ctype_setname(cta, decl.redir); + } + noredir: + ctype_setname(ct, decl.name); + lj_ctype_addname(cp->cts, ct, id); } if (!cp_opt(cp, ',')) break; cp_decl_reset(&decl); diff --git a/src/lj_ctype.h b/src/lj_ctype.h index 17a6fdc3..555393db 100644 --- a/src/lj_ctype.h +++ b/src/lj_ctype.h @@ -54,7 +54,7 @@ LJ_STATIC_ASSERT(((int)CT_STRUCT & (int)CT_ARRAY) == CT_STRUCT); ** |FIELD cid | offset | field | | name? | ** |BITFIELD B.vcU csz bsz pos | offset | field | | name? | ** |CONSTVAL c cid | value | const | name | name | -** |EXTERN cid | | | name | name | +** |EXTERN cid | | sib? | name | name | ** |KW tok | size | | name | name | ** +----------------------------+--------+-------+-------+-------+-- ** ^^ ^^--- bits used for C type conversion dispatch @@ -126,6 +126,7 @@ enum { CTA_QUAL, /* Unmerged qualifiers. */ CTA_ALIGN, /* Alignment override. */ CTA_SUBTYPE, /* Transparent sub-type. */ + CTA_REDIR, /* Redirected symbol name. */ CTA_BAD, /* To catch bad IDs. */ CTA__MAX };