diff options
| author | Mike Pall <mike> | 2010-12-05 19:49:29 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2010-12-05 21:01:08 +0100 |
| commit | b1fb71fb981c464868e6bc669363658a98ecbd9e (patch) | |
| tree | 88fe921691d957a40c10181c8f13de201a924d31 | |
| parent | 6a7605ec85a6e5f91fc539a9e5c18659d73f3530 (diff) | |
| download | luajit-b1fb71fb981c464868e6bc669363658a98ecbd9e.tar.gz luajit-b1fb71fb981c464868e6bc669363658a98ecbd9e.tar.bz2 luajit-b1fb71fb981c464868e6bc669363658a98ecbd9e.zip | |
Cleanup 64 bit IR type handling.
| -rw-r--r-- | lib/dump.lua | 12 | ||||
| -rw-r--r-- | src/lj_asm.c | 44 | ||||
| -rw-r--r-- | src/lj_def.h | 1 | ||||
| -rw-r--r-- | src/lj_ir.h | 21 |
4 files changed, 48 insertions, 30 deletions
diff --git a/lib/dump.lua b/lib/dump.lua index f567d3d7..3c726484 100644 --- a/lib/dump.lua +++ b/lib/dump.lua | |||
| @@ -129,20 +129,23 @@ local irtype_text = { | |||
| 129 | "tru", | 129 | "tru", |
| 130 | "lud", | 130 | "lud", |
| 131 | "str", | 131 | "str", |
| 132 | "ptr", | 132 | "p32", |
| 133 | "thr", | 133 | "thr", |
| 134 | "pro", | 134 | "pro", |
| 135 | "fun", | 135 | "fun", |
| 136 | "t09", | 136 | "p64", |
| 137 | "cdt", | 137 | "cdt", |
| 138 | "tab", | 138 | "tab", |
| 139 | "udt", | 139 | "udt", |
| 140 | "num", | 140 | "num", |
| 141 | "int", | ||
| 142 | "i8 ", | 141 | "i8 ", |
| 143 | "u8 ", | 142 | "u8 ", |
| 144 | "i16", | 143 | "i16", |
| 145 | "u16", | 144 | "u16", |
| 145 | "int", | ||
| 146 | "u32", | ||
| 147 | "i64", | ||
| 148 | "u64", | ||
| 146 | } | 149 | } |
| 147 | 150 | ||
| 148 | local colortype_ansi = { | 151 | local colortype_ansi = { |
| @@ -165,6 +168,9 @@ local colortype_ansi = { | |||
| 165 | "\027[35m%s\027[m", | 168 | "\027[35m%s\027[m", |
| 166 | "\027[35m%s\027[m", | 169 | "\027[35m%s\027[m", |
| 167 | "\027[35m%s\027[m", | 170 | "\027[35m%s\027[m", |
| 171 | "\027[35m%s\027[m", | ||
| 172 | "\027[35m%s\027[m", | ||
| 173 | "\027[35m%s\027[m", | ||
| 168 | } | 174 | } |
| 169 | 175 | ||
| 170 | local function colorize_text(s, t) | 176 | local function colorize_text(s, t) |
diff --git a/src/lj_asm.c b/src/lj_asm.c index 0dfc7f04..6bb2b8c6 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
| @@ -631,7 +631,7 @@ static int32_t ra_spill(ASMState *as, IRIns *ir) | |||
| 631 | { | 631 | { |
| 632 | int32_t slot = ir->s; | 632 | int32_t slot = ir->s; |
| 633 | if (!ra_hasspill(slot)) { | 633 | if (!ra_hasspill(slot)) { |
| 634 | if (irt_isnum(ir->t) || (LJ_64 && irt_islightud(ir->t))) { | 634 | if (irt_is64(ir->t)) { |
| 635 | slot = as->evenspill; | 635 | slot = as->evenspill; |
| 636 | as->evenspill += 2; | 636 | as->evenspill += 2; |
| 637 | } else if (as->oddspill) { | 637 | } else if (as->oddspill) { |
| @@ -661,14 +661,14 @@ static Reg ra_releasetmp(ASMState *as, IRRef ref) | |||
| 661 | return r; | 661 | return r; |
| 662 | } | 662 | } |
| 663 | 663 | ||
| 664 | /* Use 64 bit operations to handle 64 bit lightuserdata. */ | 664 | /* Use 64 bit operations to handle 64 bit IR types. */ |
| 665 | #define REX_64LU(ir, r) \ | 665 | #define REX_64IR(ir, r) \ |
| 666 | ((r) | ((LJ_64 && irt_islightud((ir)->t)) ? REX_64 : 0)) | 666 | ((r) | ((LJ_64 && irt_is64((ir)->t)) ? REX_64 : 0)) |
| 667 | 667 | ||
| 668 | /* Generic move between two regs. */ | 668 | /* Generic move between two regs. */ |
| 669 | static void ra_movrr(ASMState *as, IRIns *ir, Reg r1, Reg r2) | 669 | static void ra_movrr(ASMState *as, IRIns *ir, Reg r1, Reg r2) |
| 670 | { | 670 | { |
| 671 | emit_rr(as, r1 < RID_MAX_GPR ? XO_MOV : XMM_MOVRR(as), REX_64LU(ir, r1), r2); | 671 | emit_rr(as, r1 < RID_MAX_GPR ? XO_MOV : XMM_MOVRR(as), REX_64IR(ir, r1), r2); |
| 672 | } | 672 | } |
| 673 | 673 | ||
| 674 | /* Restore a register (marked as free). Rematerialize or force a spill. */ | 674 | /* Restore a register (marked as free). Rematerialize or force a spill. */ |
| @@ -687,7 +687,7 @@ static Reg ra_restore(ASMState *as, IRRef ref) | |||
| 687 | ra_modified(as, r); | 687 | ra_modified(as, r); |
| 688 | RA_DBGX((as, "restore $i $r", ir, r)); | 688 | RA_DBGX((as, "restore $i $r", ir, r)); |
| 689 | emit_rmro(as, r < RID_MAX_GPR ? XO_MOV : XMM_MOVRM(as), | 689 | emit_rmro(as, r < RID_MAX_GPR ? XO_MOV : XMM_MOVRM(as), |
| 690 | REX_64LU(ir, r), RID_ESP, ofs); | 690 | REX_64IR(ir, r), RID_ESP, ofs); |
| 691 | } | 691 | } |
| 692 | return r; | 692 | return r; |
| 693 | } | 693 | } |
| @@ -698,7 +698,7 @@ static void ra_save(ASMState *as, IRIns *ir, Reg r) | |||
| 698 | { | 698 | { |
| 699 | RA_DBGX((as, "save $i $r", ir, r)); | 699 | RA_DBGX((as, "save $i $r", ir, r)); |
| 700 | emit_rmro(as, r < RID_MAX_GPR ? XO_MOVto : XO_MOVSDto, | 700 | emit_rmro(as, r < RID_MAX_GPR ? XO_MOVto : XO_MOVSDto, |
| 701 | REX_64LU(ir, r), RID_ESP, sps_scale(ir->s)); | 701 | REX_64IR(ir, r), RID_ESP, sps_scale(ir->s)); |
| 702 | } | 702 | } |
| 703 | 703 | ||
| 704 | #define MINCOST(r) \ | 704 | #define MINCOST(r) \ |
| @@ -1397,7 +1397,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
| 1397 | lj_trace_err(as->J, LJ_TRERR_NYICOAL); | 1397 | lj_trace_err(as->J, LJ_TRERR_NYICOAL); |
| 1398 | r = ra_alloc1(as, args[n], allow & RSET_GPR); | 1398 | r = ra_alloc1(as, args[n], allow & RSET_GPR); |
| 1399 | allow &= ~RID2RSET(r); | 1399 | allow &= ~RID2RSET(r); |
| 1400 | emit_movtomro(as, REX_64LU(ir, r), RID_ESP, ofs); | 1400 | emit_movtomro(as, REX_64IR(ir, r), RID_ESP, ofs); |
| 1401 | } | 1401 | } |
| 1402 | ofs += sizeof(intptr_t); | 1402 | ofs += sizeof(intptr_t); |
| 1403 | } | 1403 | } |
| @@ -1849,7 +1849,7 @@ static void asm_newref(ASMState *as, IRIns *ir) | |||
| 1849 | /* Otherwise use g->tmptv to hold the TValue. */ | 1849 | /* Otherwise use g->tmptv to hold the TValue. */ |
| 1850 | if (!irref_isk(ir->op2)) { | 1850 | if (!irref_isk(ir->op2)) { |
| 1851 | Reg src = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, tmp)); | 1851 | Reg src = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, tmp)); |
| 1852 | emit_movtomro(as, REX_64LU(irkey, src), tmp, 0); | 1852 | emit_movtomro(as, REX_64IR(irkey, src), tmp, 0); |
| 1853 | } else if (!irt_ispri(irkey->t)) { | 1853 | } else if (!irt_ispri(irkey->t)) { |
| 1854 | emit_movmroi(as, tmp, 0, irkey->i); | 1854 | emit_movmroi(as, tmp, 0, irkey->i); |
| 1855 | } | 1855 | } |
| @@ -1918,13 +1918,11 @@ static void asm_fxload(ASMState *as, IRIns *ir) | |||
| 1918 | case IRT_U8: xo = XO_MOVZXb; break; | 1918 | case IRT_U8: xo = XO_MOVZXb; break; |
| 1919 | case IRT_I16: xo = XO_MOVSXw; break; | 1919 | case IRT_I16: xo = XO_MOVSXw; break; |
| 1920 | case IRT_U16: xo = XO_MOVZXw; break; | 1920 | case IRT_U16: xo = XO_MOVZXw; break; |
| 1921 | #if LJ_64 | ||
| 1922 | case IRT_LIGHTUD: | ||
| 1923 | dest |= REX_64; | ||
| 1924 | /* fallthrough */ | ||
| 1925 | #endif | ||
| 1926 | default: | 1921 | default: |
| 1927 | lua_assert(irt_isint(ir->t) || irt_isaddr(ir->t)); | 1922 | if (LJ_64 && irt_is64(ir->t)) |
| 1923 | dest |= REX_64; | ||
| 1924 | else | ||
| 1925 | lua_assert(irt_isint(ir->t) || irt_isu32(ir->t) || irt_isaddr(ir->t)); | ||
| 1928 | xo = XO_MOV; | 1926 | xo = XO_MOV; |
| 1929 | break; | 1927 | break; |
| 1930 | } | 1928 | } |
| @@ -1938,6 +1936,7 @@ static void asm_fstore(ASMState *as, IRIns *ir) | |||
| 1938 | /* The IRT_I16/IRT_U16 stores should never be simplified for constant | 1936 | /* The IRT_I16/IRT_U16 stores should never be simplified for constant |
| 1939 | ** values since mov word [mem], imm16 has a length-changing prefix. | 1937 | ** values since mov word [mem], imm16 has a length-changing prefix. |
| 1940 | */ | 1938 | */ |
| 1939 | lua_assert(!(irref_isk(ir->op2) && irt_is64(ir->t))); /* NYI: KINT64. */ | ||
| 1941 | if (!irref_isk(ir->op2) || irt_isi16(ir->t) || irt_isu16(ir->t)) { | 1940 | if (!irref_isk(ir->op2) || irt_isi16(ir->t) || irt_isu16(ir->t)) { |
| 1942 | RegSet allow8 = (irt_isi8(ir->t) || irt_isu8(ir->t)) ? RSET_GPR8 : RSET_GPR; | 1941 | RegSet allow8 = (irt_isi8(ir->t) || irt_isu8(ir->t)) ? RSET_GPR8 : RSET_GPR; |
| 1943 | src = ra_alloc1(as, ir->op2, allow8); | 1942 | src = ra_alloc1(as, ir->op2, allow8); |
| @@ -1953,7 +1952,10 @@ static void asm_fstore(ASMState *as, IRIns *ir) | |||
| 1953 | case IRT_LIGHTUD: lua_assert(0); /* NYI: mask 64 bit lightuserdata. */ | 1952 | case IRT_LIGHTUD: lua_assert(0); /* NYI: mask 64 bit lightuserdata. */ |
| 1954 | #endif | 1953 | #endif |
| 1955 | default: | 1954 | default: |
| 1956 | lua_assert(irt_isint(ir->t) || irt_isaddr(ir->t)); | 1955 | if (LJ_64 && irt_is64(ir->t)) |
| 1956 | src |= REX_64; | ||
| 1957 | else | ||
| 1958 | lua_assert(irt_isint(ir->t) || irt_isu32(ir->t) || irt_isaddr(ir->t)); | ||
| 1957 | xo = XO_MOVto; | 1959 | xo = XO_MOVto; |
| 1958 | break; | 1960 | break; |
| 1959 | } | 1961 | } |
| @@ -1963,7 +1965,7 @@ static void asm_fstore(ASMState *as, IRIns *ir) | |||
| 1963 | emit_i8(as, IR(ir->op2)->i); | 1965 | emit_i8(as, IR(ir->op2)->i); |
| 1964 | emit_mrm(as, XO_MOVmib, 0, RID_MRM); | 1966 | emit_mrm(as, XO_MOVmib, 0, RID_MRM); |
| 1965 | } else { | 1967 | } else { |
| 1966 | lua_assert(irt_isint(ir->t) || irt_isaddr(ir->t)); | 1968 | lua_assert(irt_isint(ir->t) || irt_isu32(ir->t) || irt_isaddr(ir->t)); |
| 1967 | emit_i32(as, IR(ir->op2)->i); | 1969 | emit_i32(as, IR(ir->op2)->i); |
| 1968 | emit_mrm(as, XO_MOVmi, 0, RID_MRM); | 1970 | emit_mrm(as, XO_MOVmi, 0, RID_MRM); |
| 1969 | } | 1971 | } |
| @@ -2664,7 +2666,7 @@ static void asm_comp_(ASMState *as, IRIns *ir, int cc) | |||
| 2664 | asm_guardcc(as, cc); | 2666 | asm_guardcc(as, cc); |
| 2665 | if (usetest && left != RID_MRM) { | 2667 | if (usetest && left != RID_MRM) { |
| 2666 | /* Use test r,r instead of cmp r,0. */ | 2668 | /* Use test r,r instead of cmp r,0. */ |
| 2667 | emit_rr(as, XO_TEST, REX_64LU(ir, left), left); | 2669 | emit_rr(as, XO_TEST, REX_64IR(ir, left), left); |
| 2668 | if (irl+1 == ir) /* Referencing previous ins? */ | 2670 | if (irl+1 == ir) /* Referencing previous ins? */ |
| 2669 | as->testmcp = as->mcp; /* Set flag to drop test r,r if possible. */ | 2671 | as->testmcp = as->mcp; /* Set flag to drop test r,r if possible. */ |
| 2670 | } else { | 2672 | } else { |
| @@ -2683,7 +2685,7 @@ static void asm_comp_(ASMState *as, IRIns *ir, int cc) | |||
| 2683 | Reg left = ra_alloc1(as, lref, RSET_GPR); | 2685 | Reg left = ra_alloc1(as, lref, RSET_GPR); |
| 2684 | Reg right = asm_fuseload(as, rref, rset_exclude(RSET_GPR, left)); | 2686 | Reg right = asm_fuseload(as, rref, rset_exclude(RSET_GPR, left)); |
| 2685 | asm_guardcc(as, cc); | 2687 | asm_guardcc(as, cc); |
| 2686 | emit_mrm(as, XO_CMP, REX_64LU(ir, left), right); | 2688 | emit_mrm(as, XO_CMP, REX_64IR(ir, left), right); |
| 2687 | } | 2689 | } |
| 2688 | } | 2690 | } |
| 2689 | } | 2691 | } |
| @@ -2762,7 +2764,7 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) | |||
| 2762 | lua_assert(irt_ispri(ir->t) || irt_isaddr(ir->t)); | 2764 | lua_assert(irt_ispri(ir->t) || irt_isaddr(ir->t)); |
| 2763 | if (!irref_isk(ref)) { | 2765 | if (!irref_isk(ref)) { |
| 2764 | Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, RID_BASE)); | 2766 | Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, RID_BASE)); |
| 2765 | emit_movtomro(as, REX_64LU(ir, src), RID_BASE, ofs); | 2767 | emit_movtomro(as, REX_64IR(ir, src), RID_BASE, ofs); |
| 2766 | } else if (!irt_ispri(ir->t)) { | 2768 | } else if (!irt_ispri(ir->t)) { |
| 2767 | emit_movmroi(as, RID_BASE, ofs, ir->i); | 2769 | emit_movmroi(as, RID_BASE, ofs, ir->i); |
| 2768 | } | 2770 | } |
| @@ -3189,7 +3191,7 @@ static void asm_head_side(ASMState *as) | |||
| 3189 | int32_t ofs = sps_scale(regsp_spill(rs)); | 3191 | int32_t ofs = sps_scale(regsp_spill(rs)); |
| 3190 | ra_free(as, r); | 3192 | ra_free(as, r); |
| 3191 | emit_rmro(as, r < RID_MAX_GPR ? XO_MOV : XMM_MOVRM(as), | 3193 | emit_rmro(as, r < RID_MAX_GPR ? XO_MOV : XMM_MOVRM(as), |
| 3192 | REX_64LU(ir, r), RID_ESP, ofs); | 3194 | REX_64IR(ir, r), RID_ESP, ofs); |
| 3193 | checkmclim(as); | 3195 | checkmclim(as); |
| 3194 | } | 3196 | } |
| 3195 | } | 3197 | } |
diff --git a/src/lj_def.h b/src/lj_def.h index bc3ae937..074090af 100644 --- a/src/lj_def.h +++ b/src/lj_def.h | |||
| @@ -89,6 +89,7 @@ typedef unsigned __int32 uintptr_t; | |||
| 89 | #define checku8(x) ((x) == (int32_t)(uint8_t)(x)) | 89 | #define checku8(x) ((x) == (int32_t)(uint8_t)(x)) |
| 90 | #define checki16(x) ((x) == (int32_t)(int16_t)(x)) | 90 | #define checki16(x) ((x) == (int32_t)(int16_t)(x)) |
| 91 | #define checku16(x) ((x) == (int32_t)(uint16_t)(x)) | 91 | #define checku16(x) ((x) == (int32_t)(uint16_t)(x)) |
| 92 | #define checki32(x) ((x) == (int32_t)(x)) | ||
| 92 | #define checkptr32(x) ((uintptr_t)(x) == (uint32_t)(uintptr_t)(x)) | 93 | #define checkptr32(x) ((uintptr_t)(x) == (uint32_t)(uintptr_t)(x)) |
| 93 | 94 | ||
| 94 | /* Every half-decent C compiler transforms this into a rotate instruction. */ | 95 | /* Every half-decent C compiler transforms this into a rotate instruction. */ |
diff --git a/src/lj_ir.h b/src/lj_ir.h index 123d87c8..9d90d69f 100644 --- a/src/lj_ir.h +++ b/src/lj_ir.h | |||
| @@ -315,7 +315,7 @@ typedef enum { | |||
| 315 | IRT_THREAD, | 315 | IRT_THREAD, |
| 316 | IRT_PROTO, | 316 | IRT_PROTO, |
| 317 | IRT_FUNC, | 317 | IRT_FUNC, |
| 318 | IRT_9, /* Unused (map of LJ_TTRACE). */ | 318 | IRT_P64, /* IRT_P64 never escapes the IR (map of LJ_TTRACE). */ |
| 319 | IRT_CDATA, | 319 | IRT_CDATA, |
| 320 | IRT_TAB, | 320 | IRT_TAB, |
| 321 | IRT_UDATA, | 321 | IRT_UDATA, |
| @@ -325,12 +325,15 @@ typedef enum { | |||
| 325 | ** a TValue after implicit or explicit conversion (TONUM). Their types | 325 | ** a TValue after implicit or explicit conversion (TONUM). Their types |
| 326 | ** must be contiguous and next to IRT_NUM (see the typerange macros below). | 326 | ** must be contiguous and next to IRT_NUM (see the typerange macros below). |
| 327 | */ | 327 | */ |
| 328 | IRT_INT, | ||
| 329 | IRT_I8, | 328 | IRT_I8, |
| 330 | IRT_U8, | 329 | IRT_U8, |
| 331 | IRT_I16, | 330 | IRT_I16, |
| 332 | IRT_U16, | 331 | IRT_U16, |
| 333 | /* There is room for 13 more types. */ | 332 | IRT_INT, |
| 333 | IRT_U32, | ||
| 334 | IRT_I64, | ||
| 335 | IRT_U64, | ||
| 336 | /* There is room for 10 more types. */ | ||
| 334 | 337 | ||
| 335 | /* Additional flags. */ | 338 | /* Additional flags. */ |
| 336 | IRT_MARK = 0x20, /* Marker for misc. purposes. */ | 339 | IRT_MARK = 0x20, /* Marker for misc. purposes. */ |
| @@ -370,11 +373,17 @@ typedef struct IRType1 { uint8_t irt; } IRType1; | |||
| 370 | #define irt_isu8(t) (irt_type(t) == IRT_U8) | 373 | #define irt_isu8(t) (irt_type(t) == IRT_U8) |
| 371 | #define irt_isi16(t) (irt_type(t) == IRT_I16) | 374 | #define irt_isi16(t) (irt_type(t) == IRT_I16) |
| 372 | #define irt_isu16(t) (irt_type(t) == IRT_U16) | 375 | #define irt_isu16(t) (irt_type(t) == IRT_U16) |
| 376 | #define irt_isu32(t) (irt_type(t) == IRT_U32) | ||
| 373 | 377 | ||
| 374 | #define irt_isinteger(t) (irt_typerange((t), IRT_INT, IRT_U16)) | 378 | #define irt_isinteger(t) (irt_typerange((t), IRT_I8, IRT_INT)) |
| 375 | #define irt_isgcv(t) (irt_typerange((t), IRT_STR, IRT_UDATA)) | 379 | #define irt_isgcv(t) (irt_typerange((t), IRT_STR, IRT_UDATA)) |
| 376 | #define irt_isaddr(t) (irt_typerange((t), IRT_LIGHTUD, IRT_UDATA)) | 380 | #define irt_isaddr(t) (irt_typerange((t), IRT_LIGHTUD, IRT_UDATA)) |
| 377 | 381 | ||
| 382 | #define IRT_IS64 \ | ||
| 383 | ((1u<<IRT_NUM) | (1u<<IRT_I64) | (1u<<IRT_U64) | (1u<<IRT_P64) | \ | ||
| 384 | (LJ_64 ? (1u<<IRT_LIGHTUD) : 0)) | ||
| 385 | #define irt_is64(t) ((IRT_IS64 >> irt_type(t)) & 1) | ||
| 386 | |||
| 378 | static LJ_AINLINE IRType itype2irt(const TValue *tv) | 387 | static LJ_AINLINE IRType itype2irt(const TValue *tv) |
| 379 | { | 388 | { |
| 380 | if (tvisnum(tv)) | 389 | if (tvisnum(tv)) |
| @@ -469,8 +478,8 @@ typedef uint32_t TRef; | |||
| 469 | #define tref_isbool(tr) (tref_typerange((tr), IRT_FALSE, IRT_TRUE)) | 478 | #define tref_isbool(tr) (tref_typerange((tr), IRT_FALSE, IRT_TRUE)) |
| 470 | #define tref_ispri(tr) (tref_typerange((tr), IRT_NIL, IRT_TRUE)) | 479 | #define tref_ispri(tr) (tref_typerange((tr), IRT_NIL, IRT_TRUE)) |
| 471 | #define tref_istruecond(tr) (!tref_typerange((tr), IRT_NIL, IRT_FALSE)) | 480 | #define tref_istruecond(tr) (!tref_typerange((tr), IRT_NIL, IRT_FALSE)) |
| 472 | #define tref_isinteger(tr) (tref_typerange((tr), IRT_INT, IRT_U16)) | 481 | #define tref_isinteger(tr) (tref_typerange((tr), IRT_I8, IRT_INT)) |
| 473 | #define tref_isnumber(tr) (tref_typerange((tr), IRT_NUM, IRT_U16)) | 482 | #define tref_isnumber(tr) (tref_typerange((tr), IRT_NUM, IRT_INT)) |
| 474 | #define tref_isnumber_str(tr) (tref_isnumber((tr)) || tref_isstr((tr))) | 483 | #define tref_isnumber_str(tr) (tref_isnumber((tr)) || tref_isstr((tr))) |
| 475 | #define tref_isgcv(tr) (tref_typerange((tr), IRT_STR, IRT_UDATA)) | 484 | #define tref_isgcv(tr) (tref_typerange((tr), IRT_STR, IRT_UDATA)) |
| 476 | 485 | ||
