From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id B23EA6EC63; Thu, 25 Jun 2026 23:30:44 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org B23EA6EC63 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1782419444; bh=2gpSs+IlQjpQa8i/JChtfEnF3St8VZSuV6QRDwDHvW8=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=uoAyYYP2Pq7T8m4PwmA0yCqXvn9dYTB/zW7KQlWJJw4enVdiEcIkxGwmj/WCRAFmZ tLud+JLc6qlq7PsOzRuYzv93L68qTpX56N6A0rCgf0ux/lQTjbhh7pqxt48ZKihz8K a14cVQ+hq3Mu82bdXFYxpf691Ln2i9OlTDZz2MHM= Received: from send105.i.mail.ru (send105.i.mail.ru [89.221.237.200]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id B8C686EC63 for ; Thu, 25 Jun 2026 23:29:44 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org B8C686EC63 Received: by exim-smtp-78b8b8c574-5xgpx with esmtpa (envelope-from ) id 1wcqhj-00000000ErT-2WZl; Thu, 25 Jun 2026 23:29:44 +0300 To: Sergey Bronnikov , Evgeniy Temirgaleev Date: Thu, 25 Jun 2026 23:29:02 +0300 Message-ID: <20260625202903.3157425-3-skaplun@tarantool.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260625202903.3157425-1-skaplun@tarantool.org> References: <20260625202903.3157425-1-skaplun@tarantool.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Mailru-Src: smtp X-4EC0790: 10 X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD918D6BB028DF8CB61A65939FAA1DDFE7B14086D303B91705C182A05F538085040D314C6F2271242233DE06ABAFEAF67059C1AD625BC99B29D068316178BC98E66DC39866218C5191E X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE75B37E0A1C175363BEA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637AC83A81C8FD4AD23D82A6BABE6F325AC2E85FA5F3EDFCBAA7353EFBB5533756637495F66AF669A39C1BCA7A5BF0B888D47292893F3A5C3AEA995A5F569C67D4A389733CBF5DBD5E913377AFFFEAFD269176DF2183F8FC7C084ED00A64A654CBE8941B15DA834481FCF19DD082D7633A0EF3E4896CB9E6436389733CBF5DBD5E9D5E8D9A59859A8B6BAA8CD687FCDB2EBCC7F00164DA146DA6F5DAA56C3B73B237318B6A418E8EAB86D1867E19FE14079C09775C1D3CA48CF17B107DEF921CE791DD303D21008E298D5E8D9A59859A8B6B372FE9A2E580EFC725E5C173C3A84C3C9BE88FFEDFA497A35872C767BF85DA2F004C90652538430E4A6367B16DE6309 X-C1DE0DAB: 0D63561A33F958A5E0F051640BE1A4905002B1117B3ED6960A19B255D620EFFED57BAD45EC4C5DE1823CB91A9FED034534781492E4B8EEADCDAE96973654FA85C79554A2A72441328621D336A7BC284946AD531847A6065A535571D14F44ED41 X-C8649E89: 1C3962B70DF3F0AD73CAD6646DEDE191716CD42B3DD1D34CAB70F9BE574AE9C625B6776AC983F447FC0B9F89525902EE6F57B2FD27647F25E66C117BDB76D65998BC3468D10D85470C2C456C8ED5C2EED4E5A5C8B5AC88A532205F6A47827378579BCDAA6EED9F32B8341EE9D5BE9A0AF2DAB1D351A09C4FC5CAD4167DE3ECCCA3B557EFBCA9F54FC7CEAA0681F5848F4C41F94D744909CECFA6C6B0C050A61A8CAF69B82BA93681CD72808BE417F3B9E0E7457915DAA85F X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu53w8ahmwBjZKM/YPHZyZHvz5uv+WouB9+ObcCpyrx6l7KImUglyhkEat/+ysWwi0gdhEs0JGjl6ggRWTy1haxBpVdbIX1nthFXMZebaIdHP2ghjoIc/363UZI6Kf1ptIMVRSZSJkMhZtMYdyQLJcXhas= X-DA7885C5: F200B2E96E29B7B8F255D290C0D534F9A85E2087C76AC36A2B0DFA882B40B04A2976ABFF975FDE6C5B1A4C17EAA7BC4BEF2421ABFA55128DAF83EF9164C44C7E X-Mailru-Sender: 689FA8AB762F7393520AF17B8A65FDE24E9ADF66D4223D702317B2BD31D3A78653F60596AC210871E49D44BB4BD9522A059A1ED8796F048DB274557F927329BE89D5A3BC2B10C37545BD1C3CC395C826B4A721A3011E896F X-Mras: Ok Subject: [Tarantool-patches] [PATCH luajit 2/3] dbg: introduce lj-ctype command, extend cdata dump X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Sergey Kaplun via Tarantool-patches Reply-To: Sergey Kaplun Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" This patch extends dumped information for the given cdata object. Now it resolves the given `CType` and prints it in the format similar to the `__tostring` metamethod. The `lj-ctype` command is introduced to dump this information where there is only the `CType` pointer but no cdata associated with it. `__or__` and `__ror__` metamethods are monkey-patched for the LLDB value object. In `__sub__` metamethod for LLDB pointers `GetPointeeType()` is used to get the pointee type instead of the incorrectly used `GetDereferencedType()` which always returns the same type with size 8. Casting from negative values to the unsigned values is supported to check `CTF_UCHAR`. Part of tarantool/tarantool#4808 --- src/luajit_dbg.py | 333 +++++++++++++++++- .../debug-extension-tests.py | 208 ++++++++++- 2 files changed, 535 insertions(+), 6 deletions(-) diff --git a/src/luajit_dbg.py b/src/luajit_dbg.py index fd6ca8a5..62cd65d5 100644 --- a/src/luajit_dbg.py +++ b/src/luajit_dbg.py @@ -386,6 +386,8 @@ class _LLDBDebugger(Debugger): pack_flag = 'size holds the actual size. +CT_FUNC = 6 # Function. +CT_TYPEDEF = 7 # Typedef. +CT_ATTRIB = 8 # Miscellaneous attributes. + +# Common types. +CTID_CTYPEID = 21 + +# C type info flags. +CTF_BOOL = 0x08000000 # Boolean: NUM, BITFIELD. +CTF_FP = 0x04000000 # Floating-point: NUM. +CTF_CONST = 0x02000000 # Const qualifier. +CTF_VOLATILE = 0x01000000 # Volatile qualifier. +CTF_UNSIGNED = 0x00800000 # Unsigned: NUM, BITFIELD. +CTF_LONG = 0x00400000 # Long: NUM. +CTF_VLA = 0x00100000 # Variable-length: ARRAY, STRUCT. +CTF_REF = 0x00800000 # Reference: PTR. +CTF_VECTOR = 0x08000000 # Vector: ARRAY. +CTF_COMPLEX = 0x04000000 # Complex: ARRAY. +CTF_UNION = 0x00800000 # Union: STRUCT. +CTF_VARARG = 0x00800000 # Vararg: FUNC. +CTF_SSEREGPARM = 0x00400000 # SSE register parameters: FUNC. + +CTF_UCHAR = CTF_UNSIGNED if int(dbg.cast('char', -1)) > 0 else 0 + +CTMASK_ATTRIB = 255 # Max. 256 attributes. +CTSHIFT_ATTRIB = 16 + +# Attribute numbers. +CTA_QUAL = 1 # Unmerged qualifiers. + +CTSHIFT_NUM = 28 +CTMASK_CID = 0x0000ffff +CTMASK_NUM = 0xf0000000 # Max. 16 type numbers. + +# Special sizes. +CTSIZE_INVALID = 0xffffffff +DWORDSZ = 4 +QWORDSZ = 8 + + +def ctype_type(info): + return info >> CTSHIFT_NUM + + +def ctype_attrib(info): + return (info >> CTSHIFT_ATTRIB) & CTMASK_ATTRIB + + +def ctinfo(ct, flags): + return (tou32(ct) << CTSHIFT_NUM) + flags + + +def ctype_isptr(info): + return ctype_type(info) == CT_PTR + + +def ctype_iscomplex(info): + return (info & (CTMASK_NUM | CTF_COMPLEX)) == ctinfo(CT_ARRAY, CTF_COMPLEX) + + +def ctype_isinteger(info): + return (info & (CTMASK_NUM | CTF_BOOL | CTF_FP)) == ctinfo(CT_NUM, 0) + + +def ctype_isrefarray(info): + return (info & (CTMASK_NUM | CTF_VECTOR | CTF_COMPLEX)) == \ + ctinfo(CT_ARRAY, 0) + + +def ctype_cid(info): + return info & CTMASK_CID + + +def ctype_child(cts, ctype): + return ctype_get(cts, ctype_cid(ctype['info'])) + + +def cdataptr(cd): + return dbg.cast('void *', (cd + 1)) + + +def cdata_getptr(p, size): + if LJ_64 and size == 4: + return dbg.cast('void *', dbg.cast('uint32_t *', p)[0]) + else: + return dbg.cast('void *', dbg.cast('uint64_t *', p)[0]) + + +# Get C type ID for a C type. +def ctype_typeid(cts, ct): + return ct - cts['tab'] + + # JIT engine. @@ -1951,7 +2071,26 @@ def dump_lj_gco_trace(gcobj): def dump_lj_gco_cdata(gcobj): - return 'cdata @ {}'.format(strx64(gcobj)) + cdata = dbg.cast('struct GCcdata *', gcobj) + cts = ctype_ctsG(G(L())) + cid = cdata['ctypeid'] + ctype = ctype_get(cts, cid) + info = ctype['info'] + size = ctype['size'] + value = '' + if ctype_iscomplex(info): + value = cdata_val_complex(cdata, ctype) + elif size == 8 and ctype_isinteger(info): + value = cdata_val_int64(cdata, ctype) + else: + value = cdataptr(cdata) + if ctype_isptr(info): + value = cdata_getptr(value, size) + return 'cdata @ {addr} {ctype} {value}'.format( + addr=strx64(gcobj), + ctype=dump_ctype(ctype), + value=value, + ) def dump_lj_gco_tab(gcobj): @@ -2281,6 +2420,176 @@ def dump_func(func): return 'fast function #{}\n'.format(int(ffid)) +# FFI dumpers. + + +def cdata_val_int64(cdata, ctype): + info = ctype['info'] + isunsigned = info & CTF_UNSIGNED + cdataval = cdataptr(cdata) + valueptr = None + usuffix = '' + if isunsigned: + usuffix = 'U' + valueptr = dbg.cast('uint64_t *', cdataval) + else: + valueptr = dbg.cast('int64_t *', cdataval) + return str(valueptr[0]) + usuffix + 'LL' + + +def cdata_val_complex(cdata, ctype): + size = ctype['size'] + cdataval = cdataptr(cdata) + casttype = None + if size == QWORDSZ * 2: + casttype = 'double *' + else: + assert size == DWORDSZ * 2, 'bad (complex float) size' + casttype = 'float *' + re = dbg.cast(casttype, cdataval)[0] + im = dbg.cast(casttype, cdataval)[1] + sign = '+' if im > 0 else '' + return '{re}{sign}{im}i'.format(re=re, im=im, sign=sign) + + +def ctype_preplit(ctypestr, lit): + # Prevent extra space in the end of the string. + space = ' ' if ctypestr != '' else '' + return lit + space + ctypestr + + +def ctype_prepqual(ctypestr, info): + if (info & CTF_VOLATILE): + ctypestr = ctype_preplit(ctypestr, 'volatile') + if (info & CTF_CONST): + ctypestr = ctype_preplit(ctypestr, 'const') + return ctypestr + + +def ctype_preptype(cts, ctypestr, ctype, qual, tp): + nameref = gcref(ctype['name']) + if nameref: + ctypestr = ctype_preplit(ctypestr, re.sub('"', '', strdata(nameref))) + else: + ctypestr = ctype_preplit(ctypestr, str(ctype_typeid(cts, ctype))) + ctypestr = ctype_preplit(ctypestr, tp) + ctypestr = ctype_prepqual(ctypestr, qual) + return ctypestr + + +def ctype_prepnum(ctypestr, info, size): + if info & CTF_BOOL: + ctypestr = ctype_preplit(ctypestr, 'bool') + elif info & CTF_FP: + if size == QWORDSZ: + ctypestr = ctype_preplit(ctypestr, 'double') + elif size == DWORDSZ: + ctypestr = ctype_preplit(ctypestr, 'float') + else: + assert size == QWORDSZ * 2, 'bad (long double) size' + ctypestr = ctype_preplit(ctypestr, 'long double') + elif size == 1: + if not ((info ^ CTF_UCHAR) & CTF_UNSIGNED): + ctypestr = ctype_preplit(ctypestr, 'char') + elif CTF_UCHAR: + ctypestr = ctype_preplit(ctypestr, 'signed char') + else: + ctypestr = ctype_preplit(ctypestr, 'unsigned char') + elif size < 8: + if size == 4: + ctypestr = ctype_preplit(ctypestr, 'int') + else: + assert size == DWORDSZ // 2, 'bad (short) size' + ctypestr = ctype_preplit(ctypestr, 'short') + if info & CTF_UNSIGNED: + ctypestr = ctype_preplit(ctypestr, 'unsigned') + else: + size_t = '{u}int{sz}_t'.format( + u='u' if info & CTF_UNSIGNED else '', + sz=size * 8, + ) + ctypestr = ctype_preplit(ctypestr, size_t) + return ctypestr + + +def ctype_repr(cts, id): + ctype = ctype_get(cts, id) + ctypestr = '' + qual = 0 + ptrto = 0 + while True: + info = ctype['info'] + size = ctype['size'] + ctp = ctype_type(info) + if ctp == CT_NUM: + ctypestr = ctype_prepnum(ctypestr, info, size) + return ctype_prepqual(ctypestr, qual | info) + elif ctp == CT_VOID: + ctypestr = ctype_preplit(ctypestr, 'void') + return ctype_prepqual(ctypestr, qual | info) + elif ctp == CT_STRUCT: + tp = 'union' if (info & CTF_UNION) else 'struct' + return ctype_preptype(cts, ctypestr, ctype, qual, tp) + elif ctp == CT_ENUM: + if id == CTID_CTYPEID: + return ctype_preplit(ctypestr, 'ctype') + return ctype_preptype(cts, ctypestr, ctype, qual, 'enum') + elif ctp == CT_ATTRIB: + if ctype_attrib(info) == CTA_QUAL: + qual |= size + elif ctp == CT_PTR: + if info & CTF_REF: + ctypestr = ctype_preplit(ctypestr, '&') + else: + ctypestr = ctype_prepqual(ctypestr, qual | info) + if LJ_64 and size == 4: + ctypestr = ctype_preplit(ctypestr, '__ptr32') + ctypestr = ctype_preplit(ctypestr, '*') + qual = 0 + ptrto = 1 + elif ctp == CT_ARRAY: + if ctype_isrefarray(info): + if ptrto: + ptrto = 0 + ctypestr = '(' + ctypestr + ')' + arrsize = '' + if size != CTSIZE_INVALID: + child_size = ctype_child(cts, ctype)['size'] + arrsize = str(int(size / child_size) if child_size > 0 + else 0) + elif info & CTF_VLA: + arrsize = '?' + ctypestr = ctypestr + '[{}]'.format(arrsize) + elif ctype_iscomplex(info): + if size == DWORDSZ * 2: + ctypestr = ctype_preplit(ctypestr, 'float') + else: + assert size == QWORDSZ * 2, 'bad (complex double) size' + return ctype_preplit(ctypestr, 'complex') + else: + ctypestr = ctype_preplit( + ctypestr, + '__attribute__((vector_size({})))'.format(size) + ) + elif ctp == CT_FUNC: + if ptrto: + ptrto = 0 + ctypestr = '(' + ctypestr + ')' + ctypestr += '()' + ctype = ctype_child(cts, ctype) + return 'NYI' + + +def dump_ctype(ct): + cts = ctype_ctsG(G(L())) + cid = ctype_typeid(cts, ct) + name = ctype_repr(cts, cid) + return '[{id}] <{name}>'.format( + id=cid, + name=name, + ) + + # JIT dumpers. @@ -2294,7 +2603,8 @@ def dump_call_func(trace, callop): assert IRS[cdt_idx_irk['o']] == 'KINT', \ 'unexpected IR for ctype storage' ctype_idx = cdt_idx_irk['i'] - ctype = 'ctype: {}'.format(ctype_idx) + cts = ctype_ctsG(G(L())) + ctype = 'ctype: {}'.format(dump_ctype(ctype_get(cts, ctype_idx))) func_str = '' if callop < 0: @@ -2652,6 +2962,20 @@ https://github.com/tarantool/tarantool/wiki/LuaJIT-Bytecodes. )) +class LJDumpCType(dbg.LJBase): + ''' +lj-ctype + +The command receives a pointer of the corresponding CType +and dumps the ID and the name for this C data type. + ''' + + def execute(self, arg): + dbg.write('{}\n'.format( + dump_ctype(dbg.cast('CType *', dbg.eval(arg))) + )) + + class LJDumpFunc(dbg.LJBase): ''' lj-func @@ -2979,6 +3303,7 @@ def load(event=None): dbg.initialize_extension({ 'lj-arch': LJDumpArch, 'lj-bc': LJDumpBC, + 'lj-ctype': LJDumpCType, 'lj-func': LJDumpFunc, 'lj-gc': LJGC, 'lj-gco': LJDumpGCobj, diff --git a/test/tarantool-debugger-tests/debug-extension-tests.py b/test/tarantool-debugger-tests/debug-extension-tests.py index 76543daa..fc5d2c7b 100644 --- a/test/tarantool-debugger-tests/debug-extension-tests.py +++ b/test/tarantool-debugger-tests/debug-extension-tests.py @@ -227,6 +227,7 @@ class TestLoad(TestCaseBase): pattern = ( r'lj-arch command initialized\n' r'lj-bc command initialized\n' + r'lj-ctype command initialized\n' r'lj-func command initialized\n' r'lj-gc command initialized\n' r'lj-gco command initialized\n' @@ -331,7 +332,7 @@ GCO_RX = ( r'Lua function @ ' + RX_ADDR + r', [0-9]+ upvalues, .+:[0-9]+\n' r'C function @ ' + RX_ADDR + r'\n' r'fast function #[0-9]+\n' - r'cdata @ ' + RX_ADDR + r'\n' + r'cdata @ ' + RX_ADDR + r' \[\d+\] 0x0\n' r'table @ ' + RX_ADDR + r' \(asize: \d+, hmask: ' + RX_HASH + r'\)\n' r'userdata @ ' + RX_ADDR + r'\n' ) @@ -817,7 +818,9 @@ class TestLJIRCallXSCType(TestCaseBase): 'trace()\n' 'print()\n' ) - pattern = r'int CALLXS .* [' + RX_ADDR + r'\]\(.*\) ctype: \d+' + pattern = ( + r'int CALLXS .* [' + RX_ADDR + r'\]\(.*\) ctype: \[\d+\] ' + ) class TestLJJSlotsBase(TestCaseBase): @@ -838,6 +841,207 @@ class TestLJJSlotsBase(TestCaseBase): ) +def cdata_rx(tpstr, suffix=None): + return r'cdata @ ' + RX_ADDR + r' \[\d+\] <' + tpstr + '> ' + ( + RX_ADDR if not suffix else suffix + ) + + +CHAR_SIGNED = machine in ['arm64', 'aarch64'] and sys.platform != 'darwin' +HAS_LONG_DOUBLE = not (machine in ['arm64', 'aarch64'] and + sys.platform == 'darwin') + + +class TestLJCTypePrim(TestCaseBase): + location = 'lj_cf_print' + extension_cmds = ( + 'n\n' # Load L. + 'lj-tv L->base\n' + 'lj-tv L->base + 1\n' + 'lj-tv L->base + 2\n' + 'lj-tv L->base + 3\n' + 'lj-tv L->base + 4\n' + 'lj-tv L->base + 5\n' + 'lj-tv L->base + 6\n' + 'lj-tv L->base + 7\n' + 'lj-tv L->base + 8\n' + 'lj-tv L->base + 9\n' + 'lj-tv L->base + 10\n' + 'lj-tv L->base + 11\n' + 'lj-tv L->base + 12\n' + 'lj-tv L->base + 13\n' + 'lj-tv L->base + 14\n' + 'lj-tv L->base + 15\n' + 'lj-tv L->base + 16\n' + 'lj-tv L->base + 17\n' + 'lj-tv L->base + 18\n' + 'lj-tv L->base + 19\n' + 'lj-tv L->base + 20\n' + 'lj-tv L->base + 21\n' + 'lj-tv L->base + 22\n' + ) + lua_script = ( + 'local ffi = require("ffi")\n' + 'print(\n' + ' ffi.new("bool"),\n' + ' ffi.new("char"),\n' + ' ffi.new("signed char"),\n' + ' ffi.new("unsigned char"),\n' + ' ffi.new("int"),\n' + ' ffi.new("short"),\n' + ' ffi.new("unsigned"),\n' + ' ffi.new("int8_t"),\n' + ' ffi.new("int16_t"),\n' + ' ffi.new("int32_t"),\n' + ' ffi.new("int64_t"),\n' + ' ffi.new("uint8_t"),\n' + ' ffi.new("uint64_t"),\n' + ' ffi.new("float"),\n' + ' ffi.new("double"),\n' + ' ffi.new("long double"),\n' + ' 1i,\n' + ' ffi.new("complex float", 1, -2),\n' + ' ffi.new("const volatile int"),\n' + ' ffi.new("void *"),\n' + ' ffi.new("void * __ptr32"),\n' + ' ffi.new("int &"),\n' + ' ffi.typeof(1LL)\n' + ')\n' + ) + pattern = ( + cdata_rx('bool') + r'\n' + + cdata_rx('char') + r'\n' + + cdata_rx(('signed ' if CHAR_SIGNED else '') + 'char') + r'\n' + + cdata_rx(('unsigned ' if not CHAR_SIGNED else '') + 'char') + r'\n' + + cdata_rx('int') + r'\n' + + cdata_rx('short') + r'\n' + + cdata_rx('unsigned int') + r'\n' + + cdata_rx(('signed ' if CHAR_SIGNED else '') + 'char') + r'\n' + + cdata_rx('short') + r'\n' + + cdata_rx('int') + r'\n' + + cdata_rx('int64_t', '0LL') + r'\n' + + cdata_rx(('unsigned ' if not CHAR_SIGNED else '') + 'char') + r'\n' + + cdata_rx('uint64_t', '0ULL') + r'\n' + + cdata_rx('float') + r'\n' + + cdata_rx('double') + r'\n' + + cdata_rx(('long ' if HAS_LONG_DOUBLE else '') + 'double') + r'\n' + + cdata_rx('complex', r'0\+1i') + r'\n' + + cdata_rx('complex float', '1-2i') + r'\n' + + cdata_rx('const volatile int') + r'\n' + + cdata_rx(r'void \*') + r'\n' + + cdata_rx(r'void \* __ptr32') + r'\n' + + cdata_rx('int &') + r'\n' + + cdata_rx('ctype') + r'\n' + ) + + +class TestLJCTypeStructUnionEnum(TestCaseBase): + location = 'lj_cf_print' + extension_cmds = ( + 'n\n' # Load L. + 'lj-tv L->base\n' + 'lj-tv L->base + 1\n' + 'lj-tv L->base + 2\n' + 'lj-tv L->base + 3\n' + ) + lua_script = ( + 'local ffi = require("ffi")\n' + 'ffi.cdef[[\n' + ' struct test {int a;};\n' + ']]\n' + 'print(\n' + ' ffi.new("struct test"),\n' + ' ffi.new("struct {int a;}"),\n' + ' ffi.new("union {int a;}"),\n' + ' ffi.new("enum {ENUM1}")\n' + ')\n' + ) + pattern = ( + cdata_rx('struct test') + r'\n' + + cdata_rx(r'struct \d+') + r'\n' + + cdata_rx(r'union \d+') + r'\n' + + cdata_rx(r'enum \d+') + r'\n' + ) + + +class TestLJCTypeArray(TestCaseBase): + location = 'lj_cf_print' + extension_cmds = ( + 'n\n' # Load L. + 'lj-tv L->base\n' + 'lj-tv L->base + 1\n' + 'lj-tv L->base + 2\n' + 'lj-tv L->base + 3\n' + 'lj-tv L->base + 4\n' + 'lj-tv L->base + 5\n' + 'lj-tv L->base + 6\n' + ) + lua_script = ( + 'local ffi = require("ffi")\n' + 'print(\n' + ' ffi.new("char [0]"),\n' + ' ffi.new("int [1]"),\n' + ' ffi.new("complex [2]"),\n' + ' ffi.new("complex float [3]"),\n' + ' ffi.new("float __attribute__((vector_size(4)))"),\n' + ' ffi.new("int (&)[5]"),\n' + ' ffi.new("int[?]", 6)\n' + ')\n' + ) + pattern = ( + cdata_rx(r'char \[0\]') + r'\n' + + cdata_rx(r'int \[1\]') + r'\n' + + cdata_rx(r'complex \[2\]') + r'\n' + + cdata_rx(r'complex float \[3\]') + r'\n' + + cdata_rx(r'float __attribute__\(\(vector_size\(4\)\)\)') + r'\n' + + cdata_rx(r'int \(&\)\[5\]') + r'\n' + + cdata_rx(r'int \[\?\]') + r'\n' + ) + + +class TestLJCTypeFunc(TestCaseBase): + location = 'lj_cf_print' + extension_cmds = ( + 'n\n' # Load L. + 'lj-tv L->base\n' + 'lj-tv L->base + 1\n' + 'lj-tv L->base + 2\n' + ) + lua_script = ( + 'local ffi = require("ffi")\n' + 'ffi.cdef[[void getpid(void);]]\n' + 'print(\n' + ' ffi.C.getpid,\n' + ' ffi.new("int (*)()"),\n' + ' ffi.new("int (*(*)(void))[2]")\n' + ')\n' + ) + pattern = ( + cdata_rx(r'void \(\)') + r'\n' + + cdata_rx(r'int \(\*\)\(\)') + r'\n' + + cdata_rx(r'int \(\* \(\*\)\(\)\)\[2\]') + r'\n' + ) + + +class TestLJCTypeBase(TestCaseBase): + location = 'lj_cf_ffi_new' + extension_cmds = ( + # Load `ct`. Skip inlined functions for LLDB. + 'n\n' + 'n\n' + 'n\n' + 'n\n' + 'n\n' + 'n\n' + 'lj-ctype ct\n' + ) + lua_script = ( + 'local ffi = require("ffi")\n' + 'ffi.new("int")\n' + ) + pattern = r'\[\d+\] ' + + for test_cls in TestCaseBase.__subclasses__(): test_cls.test = lambda self: self.check() -- 2.54.0