Browse Source

FFI: Add symbol name redirection.

This works like the GCC extension, e.g.:
FILE *fopen(const char *fn, const char *mode) __asm__("" "fopen64");
Mike Pall 14 years ago
parent
commit
1b75ec22c8
4 changed files with 58 additions and 21 deletions
  1. 9 1
      src/lj_ccall.c
  2. 15 3
      src/lj_clib.c
  3. 32 16
      src/lj_cparse.c
  4. 2 1
      src/lj_ctype.h

+ 9 - 1
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;

+ 15 - 3
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);
 	}

+ 32 - 16
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);

+ 2 - 1
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
 };