lj_cdata.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. ** C data management.
  3. ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
  4. */
  5. #include "lj_obj.h"
  6. #if LJ_HASFFI
  7. #include "lj_gc.h"
  8. #include "lj_err.h"
  9. #include "lj_tab.h"
  10. #include "lj_ctype.h"
  11. #include "lj_cconv.h"
  12. #include "lj_cdata.h"
  13. /* -- C data allocation --------------------------------------------------- */
  14. /* Allocate a new C data object holding a reference to another object. */
  15. GCcdata *lj_cdata_newref(CTState *cts, const void *p, CTypeID id)
  16. {
  17. CTypeID refid = lj_ctype_intern(cts, CTINFO_REF(id), CTSIZE_PTR);
  18. GCcdata *cd = lj_cdata_new(cts, refid, CTSIZE_PTR);
  19. *(const void **)cdataptr(cd) = p;
  20. return cd;
  21. }
  22. /* Allocate variable-sized or specially aligned C data object. */
  23. GCcdata *lj_cdata_newv(lua_State *L, CTypeID id, CTSize sz, CTSize align)
  24. {
  25. global_State *g;
  26. MSize extra = sizeof(GCcdataVar) + sizeof(GCcdata) +
  27. (align > CT_MEMALIGN ? (1u<<align) - (1u<<CT_MEMALIGN) : 0);
  28. char *p = lj_mem_newt(L, extra + sz, char);
  29. uintptr_t adata = (uintptr_t)p + sizeof(GCcdataVar) + sizeof(GCcdata);
  30. uintptr_t almask = (1u << align) - 1u;
  31. GCcdata *cd = (GCcdata *)(((adata + almask) & ~almask) - sizeof(GCcdata));
  32. lj_assertL((char *)cd - p < 65536, "excessive cdata alignment");
  33. cdatav(cd)->offset = (uint16_t)((char *)cd - p);
  34. cdatav(cd)->extra = extra;
  35. cdatav(cd)->len = sz;
  36. g = G(L);
  37. setgcrefr(cd->nextgc, g->gc.root);
  38. setgcref(g->gc.root, obj2gco(cd));
  39. newwhite(g, obj2gco(cd));
  40. cd->marked |= 0x80;
  41. cd->gct = ~LJ_TCDATA;
  42. cd->ctypeid = id;
  43. return cd;
  44. }
  45. /* Allocate arbitrary C data object. */
  46. GCcdata *lj_cdata_newx(CTState *cts, CTypeID id, CTSize sz, CTInfo info)
  47. {
  48. if (!(info & CTF_VLA) && ctype_align(info) <= CT_MEMALIGN)
  49. return lj_cdata_new(cts, id, sz);
  50. else
  51. return lj_cdata_newv(cts->L, id, sz, ctype_align(info));
  52. }
  53. /* Free a C data object. */
  54. void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd)
  55. {
  56. if (LJ_UNLIKELY(cd->marked & LJ_GC_CDATA_FIN)) {
  57. GCobj *root;
  58. makewhite(g, obj2gco(cd));
  59. markfinalized(obj2gco(cd));
  60. if ((root = gcref(g->gc.mmudata)) != NULL) {
  61. setgcrefr(cd->nextgc, root->gch.nextgc);
  62. setgcref(root->gch.nextgc, obj2gco(cd));
  63. setgcref(g->gc.mmudata, obj2gco(cd));
  64. } else {
  65. setgcref(cd->nextgc, obj2gco(cd));
  66. setgcref(g->gc.mmudata, obj2gco(cd));
  67. }
  68. } else if (LJ_LIKELY(!cdataisv(cd))) {
  69. CType *ct = ctype_raw(ctype_ctsG(g), cd->ctypeid);
  70. CTSize sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_PTR;
  71. lj_assertG(ctype_hassize(ct->info) || ctype_isfunc(ct->info) ||
  72. ctype_isextern(ct->info), "free of ctype without a size");
  73. lj_mem_free(g, cd, sizeof(GCcdata) + sz);
  74. } else {
  75. lj_mem_free(g, memcdatav(cd), sizecdatav(cd));
  76. }
  77. }
  78. void lj_cdata_setfin(lua_State *L, GCcdata *cd, GCobj *obj, uint32_t it)
  79. {
  80. GCtab *t = ctype_ctsG(G(L))->finalizer;
  81. if (gcref(t->metatable)) {
  82. /* Add cdata to finalizer table, if still enabled. */
  83. TValue *tv, tmp;
  84. setcdataV(L, &tmp, cd);
  85. lj_gc_anybarriert(L, t);
  86. tv = lj_tab_set(L, t, &tmp);
  87. if (it == LJ_TNIL) {
  88. setnilV(tv);
  89. cd->marked &= ~LJ_GC_CDATA_FIN;
  90. } else {
  91. setgcV(L, tv, obj, it);
  92. cd->marked |= LJ_GC_CDATA_FIN;
  93. }
  94. }
  95. }
  96. /* -- C data indexing ----------------------------------------------------- */
  97. /* Index C data by a TValue. Return CType and pointer. */
  98. CType *lj_cdata_index(CTState *cts, GCcdata *cd, cTValue *key, uint8_t **pp,
  99. CTInfo *qual)
  100. {
  101. uint8_t *p = (uint8_t *)cdataptr(cd);
  102. CType *ct = ctype_get(cts, cd->ctypeid);
  103. ptrdiff_t idx;
  104. /* Resolve reference for cdata object. */
  105. if (ctype_isref(ct->info)) {
  106. lj_assertCTS(ct->size == CTSIZE_PTR, "ref is not pointer-sized");
  107. p = *(uint8_t **)p;
  108. ct = ctype_child(cts, ct);
  109. }
  110. collect_attrib:
  111. /* Skip attributes and collect qualifiers. */
  112. while (ctype_isattrib(ct->info)) {
  113. if (ctype_attrib(ct->info) == CTA_QUAL) *qual |= ct->size;
  114. ct = ctype_child(cts, ct);
  115. }
  116. /* Interning rejects refs to refs. */
  117. lj_assertCTS(!ctype_isref(ct->info), "bad ref of ref");
  118. if (tvisint(key)) {
  119. idx = (ptrdiff_t)intV(key);
  120. goto integer_key;
  121. } else if (tvisnum(key)) { /* Numeric key. */
  122. #ifdef _MSC_VER
  123. /* Workaround for MSVC bug. */
  124. volatile
  125. #endif
  126. lua_Number n = numV(key);
  127. idx = LJ_64 ? (ptrdiff_t)n : (ptrdiff_t)lj_num2int(n);
  128. integer_key:
  129. if (ctype_ispointer(ct->info)) {
  130. CTSize sz = lj_ctype_size(cts, ctype_cid(ct->info)); /* Element size. */
  131. if (sz == CTSIZE_INVALID)
  132. lj_err_caller(cts->L, LJ_ERR_FFI_INVSIZE);
  133. if (ctype_isptr(ct->info)) {
  134. p = (uint8_t *)cdata_getptr(p, ct->size);
  135. } else if ((ct->info & (CTF_VECTOR|CTF_COMPLEX))) {
  136. if ((ct->info & CTF_COMPLEX)) idx &= 1;
  137. *qual |= CTF_CONST; /* Valarray elements are constant. */
  138. }
  139. *pp = p + idx*(int32_t)sz;
  140. return ct;
  141. }
  142. } else if (tviscdata(key)) { /* Integer cdata key. */
  143. GCcdata *cdk = cdataV(key);
  144. CType *ctk = ctype_raw(cts, cdk->ctypeid);
  145. if (ctype_isenum(ctk->info)) ctk = ctype_child(cts, ctk);
  146. if (ctype_isinteger(ctk->info)) {
  147. lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), ctk,
  148. (uint8_t *)&idx, cdataptr(cdk), 0);
  149. goto integer_key;
  150. }
  151. } else if (tvisstr(key)) { /* String key. */
  152. GCstr *name = strV(key);
  153. if (ctype_isstruct(ct->info)) {
  154. CTSize ofs;
  155. CType *fct = lj_ctype_getfieldq(cts, ct, name, &ofs, qual);
  156. if (fct) {
  157. *pp = p + ofs;
  158. return fct;
  159. }
  160. } else if (ctype_iscomplex(ct->info)) {
  161. if (name->len == 2) {
  162. *qual |= CTF_CONST; /* Complex fields are constant. */
  163. if (strdata(name)[0] == 'r' && strdata(name)[1] == 'e') {
  164. *pp = p;
  165. return ct;
  166. } else if (strdata(name)[0] == 'i' && strdata(name)[1] == 'm') {
  167. *pp = p + (ct->size >> 1);
  168. return ct;
  169. }
  170. }
  171. } else if (cd->ctypeid == CTID_CTYPEID) {
  172. /* Allow indexing a (pointer to) struct constructor to get constants. */
  173. CType *sct = ctype_raw(cts, *(CTypeID *)p);
  174. if (ctype_isptr(sct->info))
  175. sct = ctype_rawchild(cts, sct);
  176. if (ctype_isstruct(sct->info)) {
  177. CTSize ofs;
  178. CType *fct = lj_ctype_getfield(cts, sct, name, &ofs);
  179. if (fct && ctype_isconstval(fct->info))
  180. return fct;
  181. }
  182. ct = sct; /* Allow resolving metamethods for constructors, too. */
  183. }
  184. }
  185. if (ctype_isptr(ct->info)) { /* Automatically perform '->'. */
  186. if (ctype_isstruct(ctype_rawchild(cts, ct)->info)) {
  187. p = (uint8_t *)cdata_getptr(p, ct->size);
  188. ct = ctype_child(cts, ct);
  189. goto collect_attrib;
  190. }
  191. }
  192. *qual |= 1; /* Lookup failed. */
  193. return ct; /* But return the resolved raw type. */
  194. }
  195. /* -- C data getters ------------------------------------------------------ */
  196. /* Get constant value and convert to TValue. */
  197. static void cdata_getconst(CTState *cts, TValue *o, CType *ct)
  198. {
  199. CType *ctt = ctype_child(cts, ct);
  200. lj_assertCTS(ctype_isinteger(ctt->info) && ctt->size <= 4,
  201. "only 32 bit const supported"); /* NYI */
  202. /* Constants are already zero-extended/sign-extended to 32 bits. */
  203. if ((ctt->info & CTF_UNSIGNED) && (int32_t)ct->size < 0)
  204. setnumV(o, (lua_Number)(uint32_t)ct->size);
  205. else
  206. setintV(o, (int32_t)ct->size);
  207. }
  208. /* Get C data value and convert to TValue. */
  209. int lj_cdata_get(CTState *cts, CType *s, TValue *o, uint8_t *sp)
  210. {
  211. CTypeID sid;
  212. if (ctype_isconstval(s->info)) {
  213. cdata_getconst(cts, o, s);
  214. return 0; /* No GC step needed. */
  215. } else if (ctype_isbitfield(s->info)) {
  216. return lj_cconv_tv_bf(cts, s, o, sp);
  217. }
  218. /* Get child type of pointer/array/field. */
  219. lj_assertCTS(ctype_ispointer(s->info) || ctype_isfield(s->info),
  220. "pointer or field expected");
  221. sid = ctype_cid(s->info);
  222. s = ctype_get(cts, sid);
  223. /* Resolve reference for field. */
  224. if (ctype_isref(s->info)) {
  225. lj_assertCTS(s->size == CTSIZE_PTR, "ref is not pointer-sized");
  226. sp = *(uint8_t **)sp;
  227. sid = ctype_cid(s->info);
  228. s = ctype_get(cts, sid);
  229. }
  230. /* Skip attributes. */
  231. while (ctype_isattrib(s->info))
  232. s = ctype_child(cts, s);
  233. return lj_cconv_tv_ct(cts, s, sid, o, sp);
  234. }
  235. /* -- C data setters ------------------------------------------------------ */
  236. /* Convert TValue and set C data value. */
  237. void lj_cdata_set(CTState *cts, CType *d, uint8_t *dp, TValue *o, CTInfo qual)
  238. {
  239. if (ctype_isconstval(d->info)) {
  240. goto err_const;
  241. } else if (ctype_isbitfield(d->info)) {
  242. if (((d->info|qual) & CTF_CONST)) goto err_const;
  243. lj_cconv_bf_tv(cts, d, dp, o);
  244. return;
  245. }
  246. /* Get child type of pointer/array/field. */
  247. lj_assertCTS(ctype_ispointer(d->info) || ctype_isfield(d->info),
  248. "pointer or field expected");
  249. d = ctype_child(cts, d);
  250. /* Resolve reference for field. */
  251. if (ctype_isref(d->info)) {
  252. lj_assertCTS(d->size == CTSIZE_PTR, "ref is not pointer-sized");
  253. dp = *(uint8_t **)dp;
  254. d = ctype_child(cts, d);
  255. }
  256. /* Skip attributes and collect qualifiers. */
  257. for (;;) {
  258. if (ctype_isattrib(d->info)) {
  259. if (ctype_attrib(d->info) == CTA_QUAL) qual |= d->size;
  260. } else {
  261. break;
  262. }
  263. d = ctype_child(cts, d);
  264. }
  265. lj_assertCTS(ctype_hassize(d->info), "store to ctype without size");
  266. lj_assertCTS(!ctype_isvoid(d->info), "store to void type");
  267. if (((d->info|qual) & CTF_CONST)) {
  268. err_const:
  269. lj_err_caller(cts->L, LJ_ERR_FFI_WRCONST);
  270. }
  271. lj_cconv_ct_tv(cts, d, dp, o, 0);
  272. }
  273. #endif