From d2b40ab71fcaa73de57e188116b4778eb0708a2f Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 14:11:26 +0000 Subject: [PATCH 01/15] fix(generator): support PHP 8.5 source layout PHP 8.5 constant expressions may embed a compiled static closure, which the compiler represents as a zend_ast_op_array node carrying a zend_op_array pointer instead of the child pointers the generic AST shape implies. The OpCache payload relocator has to dereference that node, so the type joins both the emitted-types list and the probed layout ground truth. The rest of the generator needed no change for 8.5: every sliceStructs() regex still matches (zend_closure, accel_time_t, zend_early_binding, zend_persistent_script, zend_file_cache_metainfo), the clang include list is unchanged, and FFI validates all 40 layouts against the C compiler. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01HRDZ2XsoVuB5uG4qXKL3ny --- tools/generator/symbols.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/generator/symbols.php b/tools/generator/symbols.php index c3c620e6..5739862c 100644 --- a/tools/generator/symbols.php +++ b/tools/generator/symbols.php @@ -63,6 +63,8 @@ 'zend_ast_decl', 'zend_ast_list', 'zend_ast_zval', + // PHP 8.5: constant expressions may embed a compiled closure body + 'zend_ast_op_array', 'zend_ast_process_t', 'zend_lex_state', 'zend_arena', @@ -294,6 +296,7 @@ 'zend_ast_decl', 'zend_ast_list', 'zend_ast_zval', + 'zend_ast_op_array', 'zend_lex_state', 'zend_closure', 'zend_script', From 055f03019f02e206af883c954e2add2d14e97e45 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 14:11:36 +0000 Subject: [PATCH 02/15] feat: add generated engine definitions for PHP 8.5 (linux-x64-nts) Generated by tools/generator against PHP 8.5.9 NTS x64 (release) from the matching php-src tag, ZEND_MODULE_API_NO 20250925. Layout changes carried by these artifacts: zend_attribute gains validation_error (delayed attribute target validation), zend_object_handlers gains clone_obj_with (the `clone with` rework), zend_constant gains filename and attributes, and zend_executor_globals gains the fatal-error backtrace fields. The opcache structs (zend_persistent_script, zend_early_binding, zend_file_cache_metainfo) and zend_closure are byte-identical to 8.4. include/8.4 stays in the tree untouched: the 8.4 maintenance branch merges up into master, and removing it here would turn every merge-up into a modify/delete conflict. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01HRDZ2XsoVuB5uG4qXKL3ny --- include/8.5/linux-x64-nts/constants.php | 524 ++++++++ include/8.5/linux-x64-nts/engine.h | 1087 ++++++++++++++++ include/8.5/linux-x64-nts/layouts.json | 693 ++++++++++ include/8.5/linux-x64-nts/probe.c | 1533 +++++++++++++++++++++++ 4 files changed, 3837 insertions(+) create mode 100644 include/8.5/linux-x64-nts/constants.php create mode 100644 include/8.5/linux-x64-nts/engine.h create mode 100644 include/8.5/linux-x64-nts/layouts.json create mode 100644 include/8.5/linux-x64-nts/probe.c diff --git a/include/8.5/linux-x64-nts/constants.php b/include/8.5/linux-x64-nts/constants.php new file mode 100644 index 00000000..9319fd08 --- /dev/null +++ b/include/8.5/linux-x64-nts/constants.php @@ -0,0 +1,524 @@ + 1, + 'ZEND_ACC_PROTECTED' => 2, + 'ZEND_ACC_PRIVATE' => 4, + 'ZEND_ACC_CHANGED' => 8, + 'ZEND_ACC_STATIC' => 16, + 'ZEND_ACC_ABSTRACT' => 64, + 'ZEND_ACC_FINAL' => 32, + 'ZEND_ACC_DEPRECATED' => 2048, + 'ZEND_ACC_INTERFACE' => 1, + 'ZEND_ACC_TRAIT' => 2, + 'ZEND_ACC_ANON_CLASS' => 4, + 'ZEND_ACC_ENUM' => 268435456, + 'ZEND_ACC_IMPLICIT_ABSTRACT_CLASS' => 16, + 'ZEND_ACC_LINKED' => 8, + 'ZEND_ACC_IMMUTABLE' => 128, + 'ZEND_ACC_USE_GUARDS' => 1073741824, + 'ZEND_ACC_CONSTANTS_UPDATED' => 4096, + 'ZEND_ACC_NO_DYNAMIC_PROPERTIES' => 8192, + 'ZEND_HAS_STATIC_IN_METHODS' => 16384, + 'ZEND_ACC_TOP_LEVEL' => 512, + 'ZEND_ACC_PRELOADED' => 1024, + 'ZEND_ACC_NOT_SERIALIZABLE' => 536870912, + 'ZEND_ACC_READONLY_CLASS' => 65536, + 'ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES' => 32768, + 'ZEND_ACC_UNRESOLVED_VARIANCE' => 524288, + 'ZEND_ACC_NEARLY_LINKED' => 1048576, + 'ZEND_ACC_RESOLVED_PARENT' => 131072, + 'ZEND_ACC_RESOLVED_INTERFACES' => 262144, + 'ZEND_ACC_EXPLICIT_ABSTRACT_CLASS' => 64, + 'ZEND_ACC_READONLY' => 128, + 'ZEND_ACC_VIRTUAL' => 512, + 'ZEND_ACC_FAKE_CLOSURE' => 8388608, + 'ZEND_ACC_UNINSTANTIABLE' => 268435539, + 'ZEND_ACC_CALL_VIA_TRAMPOLINE' => 262144, + 'ZEND_ACC_NEVER_CACHE' => 524288, + 'ZEND_ACC_TRAIT_CLONE' => 1048576, + 'ZEND_ACC_RETURN_REFERENCE' => 4096, + 'ZEND_ACC_DONE_PASS_TWO' => 33554432, + 'ZEND_ACC_HEAP_RT_CACHE' => 67108864, + 'ZEND_ACC_STRICT_TYPES' => 2147483648, + 'ZEND_ACC_CLOSURE' => 4194304, + 'ZEND_ACC_GENERATOR' => 16777216, + 'ZEND_ACC_HAS_FINALLY_BLOCK' => 32768, + 'ZEND_ACC_EARLY_BINDING' => 65536, + 'ZEND_ACC_USES_THIS' => 131072, + 'ZEND_ACC_CTOR' => 2097152, + 'ZEND_ACC_HAS_TYPE_HINTS' => 256, + 'ZEND_ACC_HAS_RETURN_TYPE' => 8192, + 'ZEND_ACC_VARIADIC' => 16384, + 'ZEND_ACC_CACHED' => 4194304, + 'ZEND_ACC_FILE_CACHED' => 134217728, + 'ZEND_ACC_ARENA_ALLOCATED' => 33554432, + '_ZEND_TYPE_EXTRA_FLAGS_SHIFT' => 25, + '_ZEND_TYPE_MASK' => 33554431, + '_ZEND_TYPE_NAME_BIT' => 16777216, + '_ZEND_TYPE_LITERAL_NAME_BIT' => 8388608, + '_ZEND_TYPE_LIST_BIT' => 4194304, + '_ZEND_TYPE_KIND_MASK' => 29360128, + '_ZEND_TYPE_ITERABLE_BIT' => 2097152, + '_ZEND_TYPE_ARENA_BIT' => 1048576, + '_ZEND_TYPE_INTERSECTION_BIT' => 524288, + '_ZEND_TYPE_UNION_BIT' => 262144, + '_ZEND_TYPE_NULLABLE_BIT' => 2, + '_ZEND_TYPE_MAY_BE_MASK' => 262143, + 'IS_UNDEF' => 0, + 'IS_NULL' => 1, + 'IS_FALSE' => 2, + 'IS_TRUE' => 3, + 'IS_LONG' => 4, + 'IS_DOUBLE' => 5, + 'IS_STRING' => 6, + 'IS_ARRAY' => 7, + 'IS_OBJECT' => 8, + 'IS_RESOURCE' => 9, + 'IS_REFERENCE' => 10, + 'IS_CONSTANT_AST' => 11, + 'IS_CALLABLE' => 12, + 'IS_ITERABLE' => 13, + 'IS_VOID' => 14, + 'IS_STATIC' => 15, + 'IS_MIXED' => 16, + 'IS_NEVER' => 17, + 'IS_INDIRECT' => 12, + 'IS_PTR' => 13, + 'IS_ALIAS_PTR' => 14, + '_IS_ERROR' => 15, + '_IS_BOOL' => 18, + '_IS_NUMBER' => 19, + 'IS_TYPE_REFCOUNTED' => 1, + 'IS_TYPE_COLLECTABLE' => 2, + 'Z_TYPE_MASK' => 255, + 'Z_TYPE_FLAGS_MASK' => 65280, + 'Z_TYPE_FLAGS_SHIFT' => 8, + 'GC_TYPE_MASK' => 15, + 'GC_FLAGS_MASK' => 1008, + 'GC_INFO_MASK' => 4294966272, + 'GC_FLAGS_SHIFT' => 0, + 'GC_INFO_SHIFT' => 10, + 'GC_NULL' => 17, + 'GC_STRING' => 22, + 'GC_ARRAY' => 7, + 'GC_OBJECT' => 8, + 'GC_RESOURCE' => 25, + 'GC_REFERENCE' => 26, + 'GC_CONSTANT_AST' => 27, + 'GC_NOT_COLLECTABLE' => 16, + 'GC_PROTECTED' => 32, + 'GC_IMMUTABLE' => 64, + 'GC_PERSISTENT' => 128, + 'GC_PERSISTENT_LOCAL' => 256, + 'IS_STR_CLASS_NAME_MAP_PTR' => 32, + 'IS_STR_INTERNED' => 64, + 'IS_STR_PERSISTENT' => 128, + 'IS_STR_PERMANENT' => 256, + 'IS_STR_VALID_UTF8' => 512, + 'IS_ARRAY_IMMUTABLE' => 64, + 'IS_ARRAY_PERSISTENT' => 128, + 'IS_OBJ_WEAKLY_REFERENCED' => 128, + 'IS_OBJ_DESTRUCTOR_CALLED' => 256, + 'IS_OBJ_FREE_CALLED' => 512, + 'IS_OBJ_LAZY_UNINITIALIZED' => 2147483648, + 'IS_OBJ_LAZY_PROXY' => 1073741824, + 'HASH_FLAG_CONSISTENCY' => 3, + 'HASH_FLAG_PACKED' => 4, + 'HASH_FLAG_UNINITIALIZED' => 8, + 'HASH_FLAG_STATIC_KEYS' => 16, + 'HASH_FLAG_HAS_EMPTY_IND' => 32, + 'HASH_FLAG_ALLOW_COW_VIOLATION' => 64, + 'HASH_UPDATE' => 1, + 'HASH_ADD' => 2, + 'HASH_UPDATE_INDIRECT' => 4, + 'HASH_ADD_NEW' => 8, + 'HASH_ADD_NEXT' => 16, + 'HT_MIN_MASK' => 4294967294, + 'HT_MIN_SIZE' => 8, + 'ZEND_MODULE_API_NO' => 20250925, + 'MODULE_PERSISTENT' => 1, + 'MODULE_TEMPORARY' => 2, + 'CONST_CS' => 0, + 'CONST_PERSISTENT' => 1, + 'CONST_NO_FILE_CACHE' => 2, + 'CONST_DEPRECATED' => 4, + 'CONST_OWNED' => 8, + 'CONST_RECURSIVE' => 16, + 'PHP_USER_CONSTANT' => 8388607, + 'ZEND_DEBUG' => 0, + 'ZEND_MM_ALIGNMENT' => 8, + 'ZEND_MAX_RESERVED_RESOURCES' => 6, + 'ZEND_INTERNAL_FUNCTION' => 1, + 'ZEND_USER_FUNCTION' => 2, + 'ZEND_EVAL_CODE' => 4, + 'ZEND_COMPILE_EXTENDED_STMT' => 1, + 'ZEND_COMPILE_EXTENDED_FCALL' => 2, + 'ZEND_COMPILE_EXTENDED_INFO' => 3, + 'ZEND_COMPILE_HANDLE_OP_ARRAY' => 4, + 'ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS' => 8, + 'ZEND_COMPILE_DELAYED_BINDING' => 32, + 'ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION' => 64, + 'ZEND_COMPILE_IGNORE_INTERNAL_CLASSES' => 16, + 'ZEND_COMPILE_IGNORE_USER_FUNCTIONS' => 512, + 'ZEND_COMPILE_GUARDS' => 1024, + 'ZEND_COMPILE_NO_BUILTINS' => 2048, + 'ZEND_COMPILE_NO_JUMPTABLES' => 65536, + 'ZEND_COMPILE_PRELOAD' => 32768, + 'ZEND_COMPILE_PRELOAD_IN_CHILD' => 131072, + 'ZEND_COMPILE_WITHOUT_EXECUTION' => 16384, + 'ZEND_CALL_FUNCTION' => 0, + 'ZEND_CALL_CODE' => 65536, + 'ZEND_CALL_NESTED' => 0, + 'ZEND_CALL_TOP' => 131072, + 'ZEND_CALL_HAS_THIS' => 776, + 'ZEND_CALL_FAKE_CLOSURE' => 8388608, + 'ZEND_CALL_CLOSURE' => 4194304, + 'ZEND_ATTRIBUTE_TARGET_CLASS' => 1, + 'ZEND_ATTRIBUTE_TARGET_FUNCTION' => 2, + 'ZEND_ATTRIBUTE_TARGET_METHOD' => 4, + 'ZEND_ATTRIBUTE_TARGET_PROPERTY' => 8, + 'ZEND_ATTRIBUTE_TARGET_CLASS_CONST' => 16, + 'ZEND_ATTRIBUTE_TARGET_PARAMETER' => 32, + 'ZEND_ATTRIBUTE_TARGET_CONST' => 64, + 'ZEND_ATTRIBUTE_TARGET_ALL' => 127, + 'ZEND_ATTRIBUTE_IS_REPEATABLE' => 128, + 'ZEND_ATTRIBUTE_FLAGS' => 255, + 'ZEND_AST_ZVAL' => 64, + 'ZEND_AST_CONSTANT' => 65, + 'ZEND_AST_OP_ARRAY' => 66, + 'ZEND_AST_ZNODE' => 67, + 'ZEND_AST_FUNC_DECL' => 68, + 'ZEND_AST_CLOSURE' => 69, + 'ZEND_AST_METHOD' => 70, + 'ZEND_AST_CLASS' => 71, + 'ZEND_AST_ARROW_FUNC' => 72, + 'ZEND_AST_PROPERTY_HOOK' => 73, + 'ZEND_AST_ARG_LIST' => 128, + 'ZEND_AST_ARRAY' => 129, + 'ZEND_AST_ENCAPS_LIST' => 130, + 'ZEND_AST_EXPR_LIST' => 131, + 'ZEND_AST_STMT_LIST' => 132, + 'ZEND_AST_IF' => 133, + 'ZEND_AST_SWITCH_LIST' => 134, + 'ZEND_AST_CATCH_LIST' => 135, + 'ZEND_AST_PARAM_LIST' => 136, + 'ZEND_AST_CLOSURE_USES' => 137, + 'ZEND_AST_PROP_DECL' => 138, + 'ZEND_AST_CONST_DECL' => 139, + 'ZEND_AST_CLASS_CONST_DECL' => 140, + 'ZEND_AST_NAME_LIST' => 141, + 'ZEND_AST_TRAIT_ADAPTATIONS' => 142, + 'ZEND_AST_USE' => 143, + 'ZEND_AST_TYPE_UNION' => 144, + 'ZEND_AST_TYPE_INTERSECTION' => 145, + 'ZEND_AST_ATTRIBUTE_LIST' => 146, + 'ZEND_AST_ATTRIBUTE_GROUP' => 147, + 'ZEND_AST_MATCH_ARM_LIST' => 148, + 'ZEND_AST_MODIFIER_LIST' => 149, + 'ZEND_AST_MAGIC_CONST' => 0, + 'ZEND_AST_TYPE' => 1, + 'ZEND_AST_CONSTANT_CLASS' => 2, + 'ZEND_AST_CALLABLE_CONVERT' => 3, + 'ZEND_AST_VAR' => 256, + 'ZEND_AST_CONST' => 257, + 'ZEND_AST_UNPACK' => 258, + 'ZEND_AST_UNARY_PLUS' => 259, + 'ZEND_AST_UNARY_MINUS' => 260, + 'ZEND_AST_CAST' => 261, + 'ZEND_AST_CAST_VOID' => 262, + 'ZEND_AST_EMPTY' => 263, + 'ZEND_AST_ISSET' => 264, + 'ZEND_AST_SILENCE' => 265, + 'ZEND_AST_SHELL_EXEC' => 266, + 'ZEND_AST_PRINT' => 267, + 'ZEND_AST_INCLUDE_OR_EVAL' => 268, + 'ZEND_AST_UNARY_OP' => 269, + 'ZEND_AST_PRE_INC' => 270, + 'ZEND_AST_PRE_DEC' => 271, + 'ZEND_AST_POST_INC' => 272, + 'ZEND_AST_POST_DEC' => 273, + 'ZEND_AST_YIELD_FROM' => 274, + 'ZEND_AST_CLASS_NAME' => 275, + 'ZEND_AST_GLOBAL' => 276, + 'ZEND_AST_UNSET' => 277, + 'ZEND_AST_RETURN' => 278, + 'ZEND_AST_LABEL' => 279, + 'ZEND_AST_REF' => 280, + 'ZEND_AST_HALT_COMPILER' => 281, + 'ZEND_AST_ECHO' => 282, + 'ZEND_AST_THROW' => 283, + 'ZEND_AST_GOTO' => 284, + 'ZEND_AST_BREAK' => 285, + 'ZEND_AST_CONTINUE' => 286, + 'ZEND_AST_PROPERTY_HOOK_SHORT_BODY' => 287, + 'ZEND_AST_DIM' => 512, + 'ZEND_AST_PROP' => 513, + 'ZEND_AST_NULLSAFE_PROP' => 514, + 'ZEND_AST_STATIC_PROP' => 515, + 'ZEND_AST_CALL' => 516, + 'ZEND_AST_CLASS_CONST' => 517, + 'ZEND_AST_ASSIGN' => 518, + 'ZEND_AST_ASSIGN_REF' => 519, + 'ZEND_AST_ASSIGN_OP' => 520, + 'ZEND_AST_BINARY_OP' => 521, + 'ZEND_AST_GREATER' => 522, + 'ZEND_AST_GREATER_EQUAL' => 523, + 'ZEND_AST_AND' => 524, + 'ZEND_AST_OR' => 525, + 'ZEND_AST_ARRAY_ELEM' => 526, + 'ZEND_AST_NEW' => 527, + 'ZEND_AST_INSTANCEOF' => 528, + 'ZEND_AST_YIELD' => 529, + 'ZEND_AST_COALESCE' => 530, + 'ZEND_AST_ASSIGN_COALESCE' => 531, + 'ZEND_AST_STATIC' => 532, + 'ZEND_AST_WHILE' => 533, + 'ZEND_AST_DO_WHILE' => 534, + 'ZEND_AST_IF_ELEM' => 535, + 'ZEND_AST_SWITCH' => 536, + 'ZEND_AST_SWITCH_CASE' => 537, + 'ZEND_AST_DECLARE' => 538, + 'ZEND_AST_USE_TRAIT' => 539, + 'ZEND_AST_TRAIT_PRECEDENCE' => 540, + 'ZEND_AST_METHOD_REFERENCE' => 541, + 'ZEND_AST_NAMESPACE' => 542, + 'ZEND_AST_USE_ELEM' => 543, + 'ZEND_AST_TRAIT_ALIAS' => 544, + 'ZEND_AST_GROUP_USE' => 545, + 'ZEND_AST_ATTRIBUTE' => 546, + 'ZEND_AST_MATCH' => 547, + 'ZEND_AST_MATCH_ARM' => 548, + 'ZEND_AST_NAMED_ARG' => 549, + 'ZEND_AST_PARENT_PROPERTY_HOOK_CALL' => 550, + 'ZEND_AST_PIPE' => 551, + 'ZEND_AST_METHOD_CALL' => 768, + 'ZEND_AST_NULLSAFE_METHOD_CALL' => 769, + 'ZEND_AST_STATIC_CALL' => 770, + 'ZEND_AST_CONDITIONAL' => 771, + 'ZEND_AST_TRY' => 772, + 'ZEND_AST_CATCH' => 773, + 'ZEND_AST_PROP_GROUP' => 774, + 'ZEND_AST_CONST_ELEM' => 775, + 'ZEND_AST_CLASS_CONST_GROUP' => 776, + 'ZEND_AST_CONST_ENUM_INIT' => 777, + 'ZEND_AST_FOR' => 1024, + 'ZEND_AST_FOREACH' => 1025, + 'ZEND_AST_ENUM_CASE' => 1026, + 'ZEND_AST_PROP_ELEM' => 1027, + 'ZEND_AST_PARAM' => 1536, + 'ZEND_PROPERTY_HOOK_GET' => 0, + 'ZEND_PROPERTY_HOOK_SET' => 1, + 'ZEND_NOP' => 0, + 'ZEND_ADD' => 1, + 'ZEND_SUB' => 2, + 'ZEND_MUL' => 3, + 'ZEND_DIV' => 4, + 'ZEND_MOD' => 5, + 'ZEND_SL' => 6, + 'ZEND_SR' => 7, + 'ZEND_CONCAT' => 8, + 'ZEND_BW_OR' => 9, + 'ZEND_BW_AND' => 10, + 'ZEND_BW_XOR' => 11, + 'ZEND_POW' => 12, + 'ZEND_BW_NOT' => 13, + 'ZEND_BOOL_NOT' => 14, + 'ZEND_BOOL_XOR' => 15, + 'ZEND_IS_IDENTICAL' => 16, + 'ZEND_IS_NOT_IDENTICAL' => 17, + 'ZEND_IS_EQUAL' => 18, + 'ZEND_IS_NOT_EQUAL' => 19, + 'ZEND_IS_SMALLER' => 20, + 'ZEND_IS_SMALLER_OR_EQUAL' => 21, + 'ZEND_ASSIGN' => 22, + 'ZEND_ASSIGN_DIM' => 23, + 'ZEND_ASSIGN_OBJ' => 24, + 'ZEND_ASSIGN_STATIC_PROP' => 25, + 'ZEND_ASSIGN_OP' => 26, + 'ZEND_ASSIGN_DIM_OP' => 27, + 'ZEND_ASSIGN_OBJ_OP' => 28, + 'ZEND_ASSIGN_STATIC_PROP_OP' => 29, + 'ZEND_ASSIGN_REF' => 30, + 'ZEND_QM_ASSIGN' => 31, + 'ZEND_ASSIGN_OBJ_REF' => 32, + 'ZEND_ASSIGN_STATIC_PROP_REF' => 33, + 'ZEND_PRE_INC' => 34, + 'ZEND_PRE_DEC' => 35, + 'ZEND_POST_INC' => 36, + 'ZEND_POST_DEC' => 37, + 'ZEND_PRE_INC_STATIC_PROP' => 38, + 'ZEND_PRE_DEC_STATIC_PROP' => 39, + 'ZEND_POST_INC_STATIC_PROP' => 40, + 'ZEND_POST_DEC_STATIC_PROP' => 41, + 'ZEND_JMP' => 42, + 'ZEND_JMPZ' => 43, + 'ZEND_JMPNZ' => 44, + 'ZEND_JMPZ_EX' => 46, + 'ZEND_JMPNZ_EX' => 47, + 'ZEND_CASE' => 48, + 'ZEND_CHECK_VAR' => 49, + 'ZEND_SEND_VAR_NO_REF_EX' => 50, + 'ZEND_CAST' => 51, + 'ZEND_BOOL' => 52, + 'ZEND_FAST_CONCAT' => 53, + 'ZEND_ROPE_INIT' => 54, + 'ZEND_ROPE_ADD' => 55, + 'ZEND_ROPE_END' => 56, + 'ZEND_BEGIN_SILENCE' => 57, + 'ZEND_END_SILENCE' => 58, + 'ZEND_INIT_FCALL_BY_NAME' => 59, + 'ZEND_DO_FCALL' => 60, + 'ZEND_INIT_FCALL' => 61, + 'ZEND_RETURN' => 62, + 'ZEND_RECV' => 63, + 'ZEND_RECV_INIT' => 64, + 'ZEND_SEND_VAL' => 65, + 'ZEND_SEND_VAR_EX' => 66, + 'ZEND_SEND_REF' => 67, + 'ZEND_NEW' => 68, + 'ZEND_INIT_NS_FCALL_BY_NAME' => 69, + 'ZEND_FREE' => 70, + 'ZEND_INIT_ARRAY' => 71, + 'ZEND_ADD_ARRAY_ELEMENT' => 72, + 'ZEND_INCLUDE_OR_EVAL' => 73, + 'ZEND_UNSET_VAR' => 74, + 'ZEND_UNSET_DIM' => 75, + 'ZEND_UNSET_OBJ' => 76, + 'ZEND_FE_RESET_R' => 77, + 'ZEND_FE_FETCH_R' => 78, + 'ZEND_FETCH_R' => 80, + 'ZEND_FETCH_DIM_R' => 81, + 'ZEND_FETCH_OBJ_R' => 82, + 'ZEND_FETCH_W' => 83, + 'ZEND_FETCH_DIM_W' => 84, + 'ZEND_FETCH_OBJ_W' => 85, + 'ZEND_FETCH_RW' => 86, + 'ZEND_FETCH_DIM_RW' => 87, + 'ZEND_FETCH_OBJ_RW' => 88, + 'ZEND_FETCH_IS' => 89, + 'ZEND_FETCH_DIM_IS' => 90, + 'ZEND_FETCH_OBJ_IS' => 91, + 'ZEND_FETCH_FUNC_ARG' => 92, + 'ZEND_FETCH_DIM_FUNC_ARG' => 93, + 'ZEND_FETCH_OBJ_FUNC_ARG' => 94, + 'ZEND_FETCH_UNSET' => 95, + 'ZEND_FETCH_DIM_UNSET' => 96, + 'ZEND_FETCH_OBJ_UNSET' => 97, + 'ZEND_FETCH_LIST_R' => 98, + 'ZEND_FETCH_CONSTANT' => 99, + 'ZEND_CHECK_FUNC_ARG' => 100, + 'ZEND_EXT_STMT' => 101, + 'ZEND_EXT_FCALL_BEGIN' => 102, + 'ZEND_EXT_FCALL_END' => 103, + 'ZEND_EXT_NOP' => 104, + 'ZEND_TICKS' => 105, + 'ZEND_SEND_VAR_NO_REF' => 106, + 'ZEND_CATCH' => 107, + 'ZEND_THROW' => 108, + 'ZEND_FETCH_CLASS' => 109, + 'ZEND_CLONE' => 110, + 'ZEND_RETURN_BY_REF' => 111, + 'ZEND_INIT_METHOD_CALL' => 112, + 'ZEND_INIT_STATIC_METHOD_CALL' => 113, + 'ZEND_ISSET_ISEMPTY_VAR' => 114, + 'ZEND_ISSET_ISEMPTY_DIM_OBJ' => 115, + 'ZEND_SEND_VAL_EX' => 116, + 'ZEND_SEND_VAR' => 117, + 'ZEND_INIT_USER_CALL' => 118, + 'ZEND_SEND_ARRAY' => 119, + 'ZEND_SEND_USER' => 120, + 'ZEND_STRLEN' => 121, + 'ZEND_DEFINED' => 122, + 'ZEND_TYPE_CHECK' => 123, + 'ZEND_VERIFY_RETURN_TYPE' => 124, + 'ZEND_FE_RESET_RW' => 125, + 'ZEND_FE_FETCH_RW' => 126, + 'ZEND_FE_FREE' => 127, + 'ZEND_INIT_DYNAMIC_CALL' => 128, + 'ZEND_DO_ICALL' => 129, + 'ZEND_DO_UCALL' => 130, + 'ZEND_DO_FCALL_BY_NAME' => 131, + 'ZEND_PRE_INC_OBJ' => 132, + 'ZEND_PRE_DEC_OBJ' => 133, + 'ZEND_POST_INC_OBJ' => 134, + 'ZEND_POST_DEC_OBJ' => 135, + 'ZEND_ECHO' => 136, + 'ZEND_OP_DATA' => 137, + 'ZEND_INSTANCEOF' => 138, + 'ZEND_GENERATOR_CREATE' => 139, + 'ZEND_MAKE_REF' => 140, + 'ZEND_DECLARE_FUNCTION' => 141, + 'ZEND_DECLARE_LAMBDA_FUNCTION' => 142, + 'ZEND_DECLARE_CONST' => 143, + 'ZEND_DECLARE_CLASS' => 144, + 'ZEND_DECLARE_CLASS_DELAYED' => 145, + 'ZEND_DECLARE_ANON_CLASS' => 146, + 'ZEND_ADD_ARRAY_UNPACK' => 147, + 'ZEND_ISSET_ISEMPTY_PROP_OBJ' => 148, + 'ZEND_HANDLE_EXCEPTION' => 149, + 'ZEND_USER_OPCODE' => 150, + 'ZEND_ASSERT_CHECK' => 151, + 'ZEND_JMP_SET' => 152, + 'ZEND_UNSET_CV' => 153, + 'ZEND_ISSET_ISEMPTY_CV' => 154, + 'ZEND_FETCH_LIST_W' => 155, + 'ZEND_SEPARATE' => 156, + 'ZEND_FETCH_CLASS_NAME' => 157, + 'ZEND_CALL_TRAMPOLINE' => 158, + 'ZEND_DISCARD_EXCEPTION' => 159, + 'ZEND_YIELD' => 160, + 'ZEND_GENERATOR_RETURN' => 161, + 'ZEND_FAST_CALL' => 162, + 'ZEND_FAST_RET' => 163, + 'ZEND_RECV_VARIADIC' => 164, + 'ZEND_SEND_UNPACK' => 165, + 'ZEND_YIELD_FROM' => 166, + 'ZEND_COPY_TMP' => 167, + 'ZEND_BIND_GLOBAL' => 168, + 'ZEND_COALESCE' => 169, + 'ZEND_SPACESHIP' => 170, + 'ZEND_FUNC_NUM_ARGS' => 171, + 'ZEND_FUNC_GET_ARGS' => 172, + 'ZEND_FETCH_STATIC_PROP_R' => 173, + 'ZEND_FETCH_STATIC_PROP_W' => 174, + 'ZEND_FETCH_STATIC_PROP_RW' => 175, + 'ZEND_FETCH_STATIC_PROP_IS' => 176, + 'ZEND_FETCH_STATIC_PROP_FUNC_ARG' => 177, + 'ZEND_FETCH_STATIC_PROP_UNSET' => 178, + 'ZEND_UNSET_STATIC_PROP' => 179, + 'ZEND_ISSET_ISEMPTY_STATIC_PROP' => 180, + 'ZEND_FETCH_CLASS_CONSTANT' => 181, + 'ZEND_BIND_LEXICAL' => 182, + 'ZEND_BIND_STATIC' => 183, + 'ZEND_FETCH_THIS' => 184, + 'ZEND_SEND_FUNC_ARG' => 185, + 'ZEND_ISSET_ISEMPTY_THIS' => 186, + 'ZEND_SWITCH_LONG' => 187, + 'ZEND_SWITCH_STRING' => 188, + 'ZEND_IN_ARRAY' => 189, + 'ZEND_COUNT' => 190, + 'ZEND_GET_CLASS' => 191, + 'ZEND_GET_CALLED_CLASS' => 192, + 'ZEND_GET_TYPE' => 193, + 'ZEND_ARRAY_KEY_EXISTS' => 194, + 'ZEND_MATCH' => 195, + 'ZEND_CASE_STRICT' => 196, + 'ZEND_MATCH_ERROR' => 197, + 'ZEND_JMP_NULL' => 198, + 'ZEND_CHECK_UNDEF_ARGS' => 199, + 'ZEND_FETCH_GLOBALS' => 200, + 'ZEND_VERIFY_NEVER_TYPE' => 201, + 'ZEND_CALLABLE_CONVERT' => 202, + 'ZEND_BIND_INIT_STATIC_OR_JMP' => 203, + 'ZEND_FRAMELESS_ICALL_0' => 204, + 'ZEND_FRAMELESS_ICALL_1' => 205, + 'ZEND_FRAMELESS_ICALL_2' => 206, + 'ZEND_FRAMELESS_ICALL_3' => 207, + 'ZEND_JMP_FRAMELESS' => 208, + 'ZEND_INIT_PARENT_PROPERTY_HOOK_CALL' => 209, + 'ZEND_DECLARE_ATTRIBUTED_CONST' => 210, + 'ZEND_VM_LAST_OPCODE' => 210, +]; diff --git a/include/8.5/linux-x64-nts/engine.h b/include/8.5/linux-x64-nts/engine.h new file mode 100644 index 00000000..228c3ea2 --- /dev/null +++ b/include/8.5/linux-x64-nts/engine.h @@ -0,0 +1,1087 @@ +#define FFI_SCOPE "ZEngine" +/* + * Generated by tools/generator for PHP 8.5 (linux-x64-nts, release) - DO NOT EDIT. + * Regenerate with `composer gen-headers`. + */ +typedef long int __time_t; +typedef __time_t time_t; +typedef struct +{ + unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))]; +} __sigset_t; +struct _IO_FILE; +typedef struct _IO_FILE FILE; +typedef int64_t zend_long; +typedef uint64_t zend_ulong; +typedef enum { + SUCCESS = 0, + FAILURE = -1, +} ZEND_RESULT_CODE; +typedef ZEND_RESULT_CODE zend_result; +typedef struct _zend_object_handlers zend_object_handlers; +typedef struct _zend_class_entry zend_class_entry; +typedef union _zend_function zend_function; +typedef struct _zend_execute_data zend_execute_data; +typedef struct _zval_struct zval; +typedef struct _zend_refcounted zend_refcounted; +typedef struct _zend_string zend_string; +typedef struct _zend_array zend_array; +typedef struct _zend_object zend_object; +typedef struct _zend_resource zend_resource; +typedef struct _zend_reference zend_reference; +typedef struct _zend_ast_ref zend_ast_ref; +typedef struct _zend_ast zend_ast; +typedef void (*dtor_func_t)(zval *pDest); +typedef struct { + void *ptr; + uint32_t type_mask; +} zend_type; +typedef struct { + uint32_t num_types; + zend_type types[1]; +} zend_type_list; +typedef union _zend_value { + zend_long lval; + double dval; + zend_refcounted *counted; + zend_string *str; + zend_array *arr; + zend_object *obj; + zend_resource *res; + zend_reference *ref; + zend_ast_ref *ast; + zval *zv; + void *ptr; + zend_class_entry *ce; + zend_function *func; + struct { + uint32_t w1; + uint32_t w2; + } ww; +} zend_value; +struct _zval_struct { + zend_value value; + union { + uint32_t type_info; + struct { + uint8_t type; uint8_t type_flags; union { uint16_t extra; } u; + } v; + } u1; + union { + uint32_t next; + uint32_t cache_slot; + uint32_t opline_num; + uint32_t lineno; + uint32_t num_args; + uint32_t fe_pos; + uint32_t fe_iter_idx; + uint32_t guard; + uint32_t constant_flags; + uint32_t extra; + } u2; +}; +typedef struct _zend_refcounted_h { + uint32_t refcount; + union { + uint32_t type_info; + } u; +} zend_refcounted_h; +struct _zend_refcounted { + zend_refcounted_h gc; +}; +struct _zend_string { + zend_refcounted_h gc; + zend_ulong h; + size_t len; + char val[1]; +}; +typedef struct _Bucket { + zval val; + zend_ulong h; + zend_string *key; +} Bucket; +typedef struct _zend_array HashTable; +struct _zend_array { + zend_refcounted_h gc; + union { + struct { + uint8_t flags; uint8_t _unused; uint8_t nIteratorsCount; uint8_t _unused2; + } v; + uint32_t flags; + } u; + uint32_t nTableMask; + union { + uint32_t *arHash; + Bucket *arData; + zval *arPacked; + }; + uint32_t nNumUsed; + uint32_t nNumOfElements; + uint32_t nTableSize; + uint32_t nInternalPointer; + zend_long nNextFreeElement; + dtor_func_t pDestructor; +}; +typedef uint32_t HashPosition; +typedef struct _HashTableIterator { + HashTable *ht; + HashPosition pos; + uint32_t next_copy; +} HashTableIterator; +struct _zend_object { + zend_refcounted_h gc; + uint32_t handle; + uint32_t extra_flags; + zend_class_entry *ce; + const zend_object_handlers *handlers; + HashTable *properties; + zval properties_table[1]; +}; +struct _zend_resource { + zend_refcounted_h gc; + zend_long handle; + int type; + void *ptr; +}; +typedef union { + struct _zend_property_info *ptr; + uintptr_t list; +} zend_property_info_source_list; +struct _zend_reference { + zend_refcounted_h gc; + zval val; + zend_property_info_source_list sources; +}; +struct _zend_ast_ref { + zend_refcounted_h gc; +}; +typedef struct _zend_llist_element { + struct _zend_llist_element *next; + struct _zend_llist_element *prev; + char data[1]; +} zend_llist_element; +typedef void (*llist_dtor_func_t)(void *); +typedef struct _zend_llist { + zend_llist_element *head; + zend_llist_element *tail; + size_t count; + size_t size; + llist_dtor_func_t dtor; + unsigned char persistent; + zend_llist_element *traverse_ptr; +} zend_llist; +typedef struct { + zval *cur; + zval *end; + zval *start; +} zend_get_gc_buffer; +typedef uint16_t zend_ast_kind; +typedef uint16_t zend_ast_attr; +struct _zend_ast { + zend_ast_kind kind; + zend_ast_attr attr; + uint32_t lineno; + zend_ast *child[1]; +}; +typedef struct _zend_ast_list { + zend_ast_kind kind; + zend_ast_attr attr; + uint32_t lineno; + uint32_t children; + zend_ast *child[1]; +} zend_ast_list; +typedef struct _zend_ast_zval { + zend_ast_kind kind; + zend_ast_attr attr; + zval val; +} zend_ast_zval; +typedef struct _zend_op_array zend_op_array; +typedef struct _zend_ast_op_array { + zend_ast_kind kind; + zend_ast_attr attr; + uint32_t lineno; + zend_op_array *op_array; +} zend_ast_op_array; +typedef struct _zend_ast_decl { + zend_ast_kind kind; + zend_ast_attr attr; + uint32_t start_lineno; + uint32_t end_lineno; + uint32_t flags; + zend_string *doc_comment; + zend_string *name; + zend_ast *child[5]; +} zend_ast_decl; +typedef void (*zend_ast_process_t)(zend_ast *ast); +typedef struct _zend_object_iterator zend_object_iterator; +typedef struct _zend_object_iterator_funcs { + void (*dtor)(zend_object_iterator *iter); + zend_result (*valid)(zend_object_iterator *iter); + zval *(*get_current_data)(zend_object_iterator *iter); + void (*get_current_key)(zend_object_iterator *iter, zval *key); + void (*move_forward)(zend_object_iterator *iter); + void (*rewind)(zend_object_iterator *iter); + void (*invalidate_current)(zend_object_iterator *iter); + HashTable *(*get_gc)(zend_object_iterator *iter, zval **table, int *n); +} zend_object_iterator_funcs; +struct _zend_object_iterator { + zend_object std; + zval data; + const zend_object_iterator_funcs *funcs; + zend_ulong index; +}; +typedef struct _zend_class_iterator_funcs { + zend_function *zf_new_iterator; + zend_function *zf_valid; + zend_function *zf_current; + zend_function *zf_key; + zend_function *zf_next; + zend_function *zf_rewind; +} zend_class_iterator_funcs; +typedef struct _zend_class_arrayaccess_funcs { + zend_function *zf_offsetget; + zend_function *zf_offsetexists; + zend_function *zf_offsetset; + zend_function *zf_offsetunset; +} zend_class_arrayaccess_funcs; +typedef size_t (*zend_stream_fsizer_t)(void* handle); +typedef ssize_t (*zend_stream_reader_t)(void* handle, char *buf, size_t len); +typedef void (*zend_stream_closer_t)(void* handle); +typedef struct _zend_stream { + void *handle; + int isatty; + zend_stream_reader_t reader; + zend_stream_fsizer_t fsizer; + zend_stream_closer_t closer; +} zend_stream; +typedef struct _zend_file_handle { + union { + FILE *fp; + zend_stream stream; + } handle; + zend_string *filename; + zend_string *opened_path; + uint8_t type; + _Bool primary_script; + _Bool in_list; + char *buf; + size_t len; +} zend_file_handle; +struct _zend_serialize_data; +struct _zend_unserialize_data; +typedef struct _zend_serialize_data zend_serialize_data; +typedef struct _zend_unserialize_data zend_unserialize_data; +typedef struct _zend_class_name { + zend_string *name; + zend_string *lc_name; +} zend_class_name; +typedef struct _zend_trait_method_reference { + zend_string *method_name; + zend_string *class_name; +} zend_trait_method_reference; +typedef struct _zend_trait_precedence { + zend_trait_method_reference trait_method; + uint32_t num_excludes; + zend_string *exclude_class_names[1]; +} zend_trait_precedence; +typedef struct _zend_trait_alias { + zend_trait_method_reference trait_method; + zend_string *alias; + uint32_t modifiers; +} zend_trait_alias; +typedef struct _zend_class_mutable_data { + zval *default_properties_table; + HashTable *constants_table; + uint32_t ce_flags; + HashTable *backed_enum_table; +} zend_class_mutable_data; +typedef struct _zend_class_dependency { + zend_string *name; + zend_class_entry *ce; +} zend_class_dependency; +typedef struct _zend_inheritance_cache_entry zend_inheritance_cache_entry; +typedef struct _zend_error_info { + int type; + uint32_t lineno; + zend_string *filename; + zend_string *message; +} zend_error_info; +struct _zend_inheritance_cache_entry { + zend_inheritance_cache_entry *next; + zend_class_entry *ce; + zend_class_entry *parent; + zend_class_dependency *dependencies; + uint32_t dependencies_count; + uint32_t num_warnings; + zend_error_info **warnings; + zend_class_entry *traits_and_interfaces[1]; +}; +struct _zend_class_entry { + char type; + zend_string *name; + union { + zend_class_entry *parent; + zend_string *parent_name; + }; + int refcount; + uint32_t ce_flags; + int default_properties_count; + int default_static_members_count; + zval *default_properties_table; + zval *default_static_members_table; + zval * static_members_table__ptr; + HashTable function_table; + HashTable properties_info; + HashTable constants_table; + zend_class_mutable_data* mutable_data__ptr; + zend_inheritance_cache_entry *inheritance_cache; + struct _zend_property_info **properties_info_table; + zend_function *constructor; + zend_function *destructor; + zend_function *clone; + zend_function *__get; + zend_function *__set; + zend_function *__unset; + zend_function *__isset; + zend_function *__call; + zend_function *__callstatic; + zend_function *__tostring; + zend_function *__debugInfo; + zend_function *__serialize; + zend_function *__unserialize; + const zend_object_handlers *default_object_handlers; + zend_class_iterator_funcs *iterator_funcs_ptr; + zend_class_arrayaccess_funcs *arrayaccess_funcs_ptr; + union { + zend_object* (*create_object)(zend_class_entry *class_type); + int (*interface_gets_implemented)(zend_class_entry *iface, zend_class_entry *class_type); + }; + zend_object_iterator *(*get_iterator)(zend_class_entry *ce, zval *object, int by_ref); + zend_function *(*get_static_method)(zend_class_entry *ce, zend_string* method); + int (*serialize)(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data); + int (*unserialize)(zval *object, zend_class_entry *ce, const unsigned char *buf, size_t buf_len, zend_unserialize_data *data); + uint32_t num_interfaces; + uint32_t num_traits; + uint32_t num_hooked_props; + uint32_t num_hooked_prop_variance_checks; + union { + zend_class_entry **interfaces; + zend_class_name *interface_names; + }; + zend_class_name *trait_names; + zend_trait_alias **trait_aliases; + zend_trait_precedence **trait_precedences; + HashTable *attributes; + uint32_t enum_backing_type; + HashTable *backed_enum_table; + zend_string *doc_comment; + union { + struct { + zend_string *filename; + uint32_t line_start; + uint32_t line_end; + } user; + struct { + const struct _zend_function_entry *builtin_functions; + struct _zend_module_entry *module; + } internal; + } info; +}; +typedef enum { + EH_NORMAL = 0, + EH_THROW +} zend_error_handling_t; +typedef enum { + ZEND_PROPERTY_HOOK_GET = 0, + ZEND_PROPERTY_HOOK_SET = 1, +} zend_property_hook_kind; +typedef struct _zend_lazy_objects_store { + HashTable infos; +} zend_lazy_objects_store; +typedef struct _zend_property_info zend_property_info; +struct _zend_property_info; +typedef zval *(*zend_object_read_property_t)(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv); +typedef zval *(*zend_object_read_dimension_t)(zend_object *object, zval *offset, int type, zval *rv); +typedef zval *(*zend_object_write_property_t)(zend_object *object, zend_string *member, zval *value, void **cache_slot); +typedef void (*zend_object_write_dimension_t)(zend_object *object, zval *offset, zval *value); +typedef zval *(*zend_object_get_property_ptr_ptr_t)(zend_object *object, zend_string *member, int type, void **cache_slot); +typedef int (*zend_object_has_property_t)(zend_object *object, zend_string *member, int has_set_exists, void **cache_slot); +typedef int (*zend_object_has_dimension_t)(zend_object *object, zval *member, int check_empty); +typedef void (*zend_object_unset_property_t)(zend_object *object, zend_string *member, void **cache_slot); +typedef void (*zend_object_unset_dimension_t)(zend_object *object, zval *offset); +typedef HashTable *(*zend_object_get_properties_t)(zend_object *object); +typedef HashTable *(*zend_object_get_debug_info_t)(zend_object *object, int *is_temp); +typedef enum _zend_prop_purpose { + ZEND_PROP_PURPOSE_DEBUG, + ZEND_PROP_PURPOSE_ARRAY_CAST, + ZEND_PROP_PURPOSE_SERIALIZE, + ZEND_PROP_PURPOSE_VAR_EXPORT, + ZEND_PROP_PURPOSE_JSON, + ZEND_PROP_PURPOSE_GET_OBJECT_VARS, + _ZEND_PROP_PURPOSE_NON_EXHAUSTIVE_ENUM +} zend_prop_purpose; +typedef zend_array *(*zend_object_get_properties_for_t)(zend_object *object, zend_prop_purpose purpose); +typedef zend_function *(*zend_object_get_method_t)(zend_object **object, zend_string *method, const zval *key); +typedef zend_function *(*zend_object_get_constructor_t)(zend_object *object); +typedef void (*zend_object_free_obj_t)(zend_object *object); +typedef void (*zend_object_dtor_obj_t)(zend_object *object); +typedef zend_object* (*zend_object_clone_obj_t)(zend_object *object); +typedef zend_object* (*zend_object_clone_obj_with_t)(zend_object *object, const zend_class_entry *scope, const HashTable *properties); +typedef zend_string *(*zend_object_get_class_name_t)(const zend_object *object); +typedef int (*zend_object_compare_t)(zval *object1, zval *object2); +typedef zend_result (*zend_object_cast_t)(zend_object *readobj, zval *retval, int type); +typedef zend_result (*zend_object_count_elements_t)(zend_object *object, zend_long *count); +typedef zend_result (*zend_object_get_closure_t)(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, _Bool check_only); +typedef HashTable *(*zend_object_get_gc_t)(zend_object *object, zval **table, int *n); +typedef zend_result (*zend_object_do_operation_t)(uint8_t opcode, zval *result, zval *op1, zval *op2); +struct _zend_object_handlers { + int offset; + zend_object_free_obj_t free_obj; + zend_object_dtor_obj_t dtor_obj; + zend_object_clone_obj_t clone_obj; + zend_object_clone_obj_with_t clone_obj_with; + zend_object_read_property_t read_property; + zend_object_write_property_t write_property; + zend_object_read_dimension_t read_dimension; + zend_object_write_dimension_t write_dimension; + zend_object_get_property_ptr_ptr_t get_property_ptr_ptr; + zend_object_has_property_t has_property; + zend_object_unset_property_t unset_property; + zend_object_has_dimension_t has_dimension; + zend_object_unset_dimension_t unset_dimension; + zend_object_get_properties_t get_properties; + zend_object_get_method_t get_method; + zend_object_get_constructor_t get_constructor; + zend_object_get_class_name_t get_class_name; + zend_object_cast_t cast_object; + zend_object_count_elements_t count_elements; + zend_object_get_debug_info_t get_debug_info; + zend_object_get_closure_t get_closure; + zend_object_get_gc_t get_gc; + zend_object_do_operation_t do_operation; + zend_object_compare_t compare; + zend_object_get_properties_for_t get_properties_for; +}; +typedef struct _zend_strtod_bigint zend_strtod_bigint; +typedef struct _zend_strtod_state { + zend_strtod_bigint *freelist[7 +1]; + zend_strtod_bigint *p5s; + char *result; +} zend_strtod_state; +typedef const void* zend_vm_opcode_handler_t; +typedef struct _zend_op zend_op; +typedef struct { + void *handler; + uint32_t num_args; +} zend_frameless_function_info; +typedef union _znode_op { + uint32_t constant; + uint32_t var; + uint32_t num; + uint32_t opline_num; + uint32_t jmp_offset; +} znode_op; +typedef struct _zend_declarables { + zend_long ticks; +} zend_declarables; +typedef struct _zend_file_context { + zend_declarables declarables; + zend_string *current_namespace; + _Bool in_namespace; + _Bool has_bracketed_namespaces; + HashTable *imports; + HashTable *imports_function; + HashTable *imports_const; + HashTable seen_symbols; +} zend_file_context; +typedef int (*user_opcode_handler_t) (zend_execute_data *execute_data); +struct _zend_op { + zend_vm_opcode_handler_t handler; + znode_op op1; + znode_op op2; + znode_op result; + uint32_t extended_value; + uint32_t lineno; + uint8_t opcode; + uint8_t op1_type; + uint8_t op2_type; + uint8_t result_type; +}; +typedef struct _zend_brk_cont_element { + int start; + int cont; + int brk; + int parent; + _Bool is_switch; +} zend_brk_cont_element; +typedef struct _zend_try_catch_element { + uint32_t try_op; + uint32_t catch_op; + uint32_t finally_op; + uint32_t finally_end; +} zend_try_catch_element; +typedef struct _zend_live_range { + uint32_t var; + uint32_t start; + uint32_t end; +} zend_live_range; +typedef struct _zend_oparray_context { + struct _zend_oparray_context *prev; + zend_op_array *op_array; + uint32_t opcodes_size; + int vars_size; + int literals_size; + uint32_t fast_call_var; + uint32_t try_catch_offset; + int current_brk_cont; + int last_brk_cont; + zend_brk_cont_element *brk_cont_array; + HashTable *labels; + zend_string *active_property_info_name; + zend_property_hook_kind active_property_hook_kind; + _Bool in_jmp_frameless_branch; + _Bool has_assigned_to_http_response_header; +} zend_oparray_context; +struct _zend_property_info { + uint32_t offset; + uint32_t flags; + zend_string *name; + zend_string *doc_comment; + HashTable *attributes; + zend_class_entry *ce; + zend_type type; + const zend_property_info *prototype; + zend_function **hooks; +}; +typedef struct _zend_class_constant { + zval value; + zend_string *doc_comment; + HashTable *attributes; + zend_class_entry *ce; + zend_type type; +} zend_class_constant; +typedef struct _zend_internal_arg_info { + const char *name; + zend_type type; + const char *default_value; +} zend_internal_arg_info; +typedef struct _zend_arg_info { + zend_string *name; + zend_type type; + zend_string *default_value; +} zend_arg_info; +struct _zend_op_array { + uint8_t type; + uint8_t arg_flags[3]; + uint32_t fn_flags; + zend_string *function_name; + zend_class_entry *scope; + zend_function *prototype; + uint32_t num_args; + uint32_t required_num_args; + zend_arg_info *arg_info; + HashTable *attributes; + void ** run_time_cache__ptr; + zend_string *doc_comment; + uint32_t T; + const zend_property_info *prop_info; + int cache_size; + int last_var; + uint32_t last; + zend_op *opcodes; + HashTable * static_variables_ptr__ptr; + HashTable *static_variables; + zend_string **vars; + uint32_t *refcount; + int last_live_range; + int last_try_catch; + zend_live_range *live_range; + zend_try_catch_element *try_catch_array; + zend_string *filename; + uint32_t line_start; + uint32_t line_end; + int last_literal; + uint32_t num_dynamic_func_defs; + zval *literals; + zend_op_array **dynamic_func_defs; + void *reserved[6]; +}; +typedef void ( *zif_handler)(zend_execute_data *execute_data, zval *return_value); +typedef struct _zend_internal_function { + uint8_t type; + uint8_t arg_flags[3]; + uint32_t fn_flags; + zend_string* function_name; + zend_class_entry *scope; + zend_function *prototype; + uint32_t num_args; + uint32_t required_num_args; + zend_internal_arg_info *arg_info; + HashTable *attributes; + void ** run_time_cache__ptr; + zend_string *doc_comment; + uint32_t T; + const zend_property_info *prop_info; + zif_handler handler; + struct _zend_module_entry *module; + const zend_frameless_function_info *frameless_function_infos; + void *reserved[6]; +} zend_internal_function; +union _zend_function { + uint8_t type; + uint32_t quick_arg_flags; + struct { + uint8_t type; + uint8_t arg_flags[3]; + uint32_t fn_flags; + zend_string *function_name; + zend_class_entry *scope; + zend_function *prototype; + uint32_t num_args; + uint32_t required_num_args; + zend_arg_info *arg_info; + HashTable *attributes; + void ** run_time_cache__ptr; + zend_string *doc_comment; + uint32_t T; + const zend_property_info *prop_info; + } common; + zend_op_array op_array; + zend_internal_function internal_function; +}; +struct _zend_execute_data { + const zend_op *opline; + zend_execute_data *call; + zval *return_value; + zend_function *func; + zval This; + zend_execute_data *prev_execute_data; + zend_array *symbol_table; + void **run_time_cache; + zend_array *extra_named_params; +}; +typedef long int __jmp_buf[8]; +struct __jmp_buf_tag + { + __jmp_buf __jmpbuf; + int __mask_was_saved; + __sigset_t __saved_mask; + }; +typedef struct __jmp_buf_tag sigjmp_buf[1]; +typedef struct _zend_compiler_globals zend_compiler_globals; +typedef struct _zend_executor_globals zend_executor_globals; +typedef struct zend_atomic_bool_s { + _Bool value; +} zend_atomic_bool; +typedef struct _zend_stack { + int size, top, max; + void *elements; +} zend_stack; +typedef struct _zend_ptr_stack { + int top, max; + void **elements; + void **top_element; + _Bool persistent; +} zend_ptr_stack; +typedef struct _zend_objects_store { + zend_object **object_buckets; + uint32_t top; + uint32_t size; + int free_list_head; +} zend_objects_store; +typedef struct _zend_encoding zend_encoding; +typedef size_t (*zend_encoding_filter)(unsigned char **str, size_t *str_length, const unsigned char *buf, size_t length); +typedef struct _zend_arena zend_arena; +struct _zend_arena { + char *ptr; + char *end; + zend_arena *prev; +}; +typedef struct _zend_call_stack { + void *base; + size_t max_size; +} zend_call_stack; +typedef struct _zend_vm_stack *zend_vm_stack; +typedef struct _zend_ini_entry zend_ini_entry; +typedef struct _zend_fiber_context zend_fiber_context; +typedef struct _zend_fiber zend_fiber; +typedef enum { + ZEND_MEMOIZE_NONE, + ZEND_MEMOIZE_COMPILE, + ZEND_MEMOIZE_FETCH, +} zend_memoize_mode; +struct _zend_compiler_globals { + zend_stack loop_var_stack; + zend_class_entry *active_class_entry; + zend_string *compiled_filename; + int zend_lineno; + zend_op_array *active_op_array; + HashTable *function_table; + HashTable *class_table; + HashTable *auto_globals; + uint8_t parse_error; + _Bool in_compilation; + _Bool short_tags; + _Bool unclean_shutdown; + _Bool ini_parser_unbuffered_errors; + zend_llist open_files; + struct _zend_ini_parser_param *ini_parser_param; + _Bool skip_shebang; + _Bool increment_lineno; + _Bool variable_width_locale; + _Bool ascii_compatible_locale; + zend_string *doc_comment; + uint32_t extra_fn_flags; + uint32_t compiler_options; + zend_oparray_context context; + zend_file_context file_context; + zend_arena *arena; + HashTable interned_strings; + const zend_encoding **script_encoding_list; + size_t script_encoding_list_size; + _Bool multibyte; + _Bool detect_unicode; + _Bool encoding_declared; + zend_ast *ast; + zend_arena *ast_arena; + zend_stack delayed_oplines_stack; + HashTable *memoized_exprs; + zend_memoize_mode memoize_mode; + void *map_ptr_real_base; + void *map_ptr_base; + size_t map_ptr_size; + size_t map_ptr_last; + HashTable *delayed_variance_obligations; + HashTable *delayed_autoloads; + HashTable *unlinked_uses; + zend_class_entry *current_linking_class; + uint32_t rtd_key_counter; + void *internal_run_time_cache; + uint32_t internal_run_time_cache_size; + zend_stack short_circuiting_opnums; +}; +struct _zend_executor_globals { + zval uninitialized_zval; + zval error_zval; + zend_array *symtable_cache[32]; + zend_array **symtable_cache_limit; + zend_array **symtable_cache_ptr; + zend_array symbol_table; + HashTable included_files; + sigjmp_buf *bailout; + int error_reporting; + _Bool fatal_error_backtrace_on; + zval last_fatal_error_backtrace; + int exit_status; + HashTable *function_table; + HashTable *class_table; + HashTable *zend_constants; + zval *vm_stack_top; + zval *vm_stack_end; + zend_vm_stack vm_stack; + size_t vm_stack_page_size; + struct _zend_execute_data *current_execute_data; + const zend_class_entry *fake_scope; + uint32_t jit_trace_num; + zend_execute_data *current_observed_frame; + int ticks_count; + zend_long precision; + uint32_t persistent_constants_count; + uint32_t persistent_functions_count; + uint32_t persistent_classes_count; + _Bool no_extensions; + _Bool full_tables_cleanup; + zend_atomic_bool vm_interrupt; + zend_atomic_bool timed_out; + HashTable *in_autoload; + zend_long hard_timeout; + void *stack_base; + void *stack_limit; + HashTable regular_list; + HashTable persistent_list; + int user_error_handler_error_reporting; + _Bool exception_ignore_args; + zval user_error_handler; + zval user_exception_handler; + zend_stack user_error_handlers_error_reporting; + zend_stack user_error_handlers; + zend_stack user_exception_handlers; + zend_class_entry *exception_class; + zend_error_handling_t error_handling; + int capture_warnings_during_sccp; + zend_long timeout_seconds; + HashTable *ini_directives; + HashTable *modified_ini_directives; + zend_ini_entry *error_reporting_ini_entry; + zend_objects_store objects_store; + zend_lazy_objects_store lazy_objects_store; + zend_object *exception, *prev_exception; + const zend_op *opline_before_exception; + zend_op exception_op[3]; + struct _zend_module_entry *current_module; + _Bool active; + uint8_t flags; + zend_long assertions; + uint32_t ht_iterators_count; + uint32_t ht_iterators_used; + HashTableIterator *ht_iterators; + HashTableIterator ht_iterators_slots[16]; + void *saved_fpu_cw_ptr; + zend_function trampoline; + zend_op call_trampoline_op; + HashTable weakrefs; + zend_long exception_string_param_max_len; + zend_get_gc_buffer get_gc_buffer; + zend_fiber_context *main_fiber_context; + zend_fiber_context *current_fiber_context; + zend_fiber *active_fiber; + size_t fiber_stack_size; + _Bool record_errors; + uint32_t num_errors; + zend_error_info **errors; + zend_string *filename_override; + zend_long lineno_override; + zend_call_stack call_stack; + zend_long max_allowed_stack_size; + zend_ulong reserved_stack_size; + zend_strtod_state strtod_state; + void *reserved[6]; +}; +typedef enum { + ON_TOKEN, + ON_FEEDBACK, + ON_STOP +} zend_php_scanner_event; +typedef struct _zend_module_entry zend_module_entry; +typedef struct _zend_module_dep zend_module_dep; +struct _zend_module_entry { + unsigned short size; + unsigned int zend_api; + unsigned char zend_debug; + unsigned char zts; + const struct _zend_ini_entry *ini_entry; + const struct _zend_module_dep *deps; + const char *name; + const struct _zend_function_entry *functions; + zend_result (*module_startup_func)(int type, int module_number); + zend_result (*module_shutdown_func)(int type, int module_number); + zend_result (*request_startup_func)(int type, int module_number); + zend_result (*request_shutdown_func)(int type, int module_number); + void (*info_func)(zend_module_entry *zend_module); + const char *version; + size_t globals_size; + void* globals_ptr; + void (*globals_ctor)(void *global); + void (*globals_dtor)(void *global); + zend_result (*post_deactivate_func)(void); + int module_started; + unsigned char type; + void *handle; + int module_number; + const char *build_id; +}; +struct _zend_module_dep { + const char *name; + const char *rel; + const char *version; + unsigned char type; +}; +typedef struct _zend_constant { + zval value; + zend_string *name; + zend_string *filename; + HashTable *attributes; +} zend_constant; +struct _zend_vm_stack { + zval *top; + zval *end; + zend_vm_stack prev; +}; +struct _zend_function_entry { + const char *fname; + zif_handler handler; + const struct _zend_internal_arg_info *arg_info; + uint32_t num_args; + uint32_t flags; + const zend_frameless_function_info *frameless_function_infos; + const char *doc_comment; +}; +typedef struct _zend_ini_entry_def { + const char *name; + int (*on_modify)(zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage); + void *mh_arg1; + void *mh_arg2; + void *mh_arg3; + const char *value; + void (*displayer)(zend_ini_entry *ini_entry, int type); + uint32_t value_length; + uint16_t name_length; + uint8_t modifiable; +} zend_ini_entry_def; +struct _zend_ini_entry { + zend_string *name; + int (*on_modify)(zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage); + void *mh_arg1; + void *mh_arg2; + void *mh_arg3; + zend_string *value; + zend_string *orig_value; + void (*displayer)(zend_ini_entry *ini_entry, int type); + int module_number; + uint8_t modifiable; + uint8_t orig_modifiable; + uint8_t modified; + const zend_ini_entry_def *def; +}; +typedef void (*zend_ini_parser_cb_t)(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg); +struct _zend_ini_parser_param { + zend_ini_parser_cb_t ini_parser_cb; + void *arg; +}; +typedef struct { + zend_string *name; + zval value; +} zend_attribute_arg; +typedef struct _zend_attribute { + zend_string *name; + zend_string *lcname; + zend_string *validation_error; + uint32_t flags; + uint32_t lineno; + uint32_t offset; + uint32_t argc; + zend_attribute_arg args[1]; +} zend_attribute; +typedef struct _zend_lex_state { + unsigned int yy_leng; + unsigned char *yy_start; + unsigned char *yy_text; + unsigned char *yy_cursor; + unsigned char *yy_marker; + unsigned char *yy_limit; + int yy_state; + zend_stack state_stack; + zend_ptr_stack heredoc_label_stack; + zend_stack nest_location_stack; + zend_file_handle *in; + uint32_t lineno; + zend_string *filename; + unsigned char *script_org; + size_t script_org_size; + unsigned char *script_filtered; + size_t script_filtered_size; + zend_encoding_filter input_filter; + zend_encoding_filter output_filter; + const zend_encoding *script_encoding; + void (*on_event)( + zend_php_scanner_event event, int token, int line, + const char *text, size_t length, void *context); + void *on_event_context; + zend_ast *ast; + zend_arena *ast_arena; +} zend_lex_state; +typedef struct _zend_script { + zend_string *filename; + zend_op_array main_op_array; + HashTable function_table; + HashTable class_table; +} zend_script; +typedef struct _zend_closure { + zend_object std; + zend_function func; + zval this_ptr; + zend_class_entry *called_scope; + zif_handler orig_internal_handler; +} zend_closure; +typedef time_t accel_time_t; +typedef struct _zend_early_binding { + zend_string *lcname; + zend_string *rtd_key; + zend_string *lc_parent_name; + uint32_t cache_slot; +} zend_early_binding; +typedef struct _zend_persistent_script { + zend_script script; + zend_long compiler_halt_offset; + int ping_auto_globals_mask; + accel_time_t timestamp; + _Bool corrupted; + _Bool is_phar; + _Bool empty; + uint32_t num_warnings; + uint32_t num_early_bindings; + zend_error_info **warnings; + zend_early_binding *early_bindings; + void *mem; + size_t size; + struct zend_persistent_script_dynamic_members { + time_t last_used; + zend_ulong hits; + unsigned int memory_consumption; + time_t revalidate; + } dynamic_members; +} zend_persistent_script; +typedef struct _zend_file_cache_metainfo { + char magic[8]; + char system_id[32]; + size_t mem_size; + size_t str_size; + size_t script_offset; + accel_time_t timestamp; + uint32_t checksum; +} zend_file_cache_metainfo; + +/* Imported functions */ +extern zend_result zend_hash_del(HashTable *, zend_string *); +extern zend_result zend_hash_index_del(HashTable *, zend_ulong); +extern zval * zend_hash_find(const HashTable *, zend_string *); +extern zval * zend_hash_add_or_update(HashTable *, zend_string *, zval *, uint32_t); +extern zval * zend_hash_index_add_or_update(HashTable *, zend_ulong, zval *, uint32_t); +extern zval * zend_hash_index_find(const HashTable *, zend_ulong); +extern void zend_hash_destroy(HashTable *); +extern zend_result zend_set_user_opcode_handler(uint8_t, user_opcode_handler_t); +extern user_opcode_handler_t zend_get_user_opcode_handler(uint8_t); +extern void zend_do_inheritance_ex(zend_class_entry *, zend_class_entry *, _Bool); +extern zend_object * zend_objects_new(zend_class_entry *); +extern void zend_object_std_init(zend_object *, zend_class_entry *); +extern void object_properties_init(zend_object *, zend_class_entry *); +extern void zend_objects_store_put(zend_object *); +extern void zend_save_lexical_state(zend_lex_state *); +extern void zend_restore_lexical_state(zend_lex_state *); +extern void zend_prepare_string_for_scanning(zval *, zend_string *); +extern zend_result zend_lex_tstring(zval *, unsigned char *); +extern int zendparse(void); +extern void zend_ast_destroy(zend_ast *); +extern zend_ast * zend_ast_create_list_0(zend_ast_kind); +extern zend_ast * zend_ast_list_add(zend_ast *, zend_ast *); +extern zend_ast * zend_ast_create_zval_ex(const zval *, zend_ast_attr); +extern zend_ast * zend_ast_create_0(zend_ast_kind); +extern zend_ast * zend_ast_create_1(zend_ast_kind, zend_ast *); +extern zend_ast * zend_ast_create_2(zend_ast_kind, zend_ast *, zend_ast *); +extern zend_ast * zend_ast_create_3(zend_ast_kind, zend_ast *, zend_ast *, zend_ast *); +extern zend_ast * zend_ast_create_4(zend_ast_kind, zend_ast *, zend_ast *, zend_ast *, zend_ast *); +extern zend_ast * zend_ast_create_5(zend_ast_kind, zend_ast *, zend_ast *, zend_ast *, zend_ast *, zend_ast *); +extern zend_ast * zend_ast_create_decl(zend_ast_kind, uint32_t, uint32_t, zend_string *, zend_string *, zend_ast *, zend_ast *, zend_ast *, zend_ast *, zend_ast *); +extern void destroy_op_array(zend_op_array *); +extern void zend_destroy_static_vars(zend_op_array *); +extern void destroy_zend_class(zval *); +extern HashTable * zend_array_dup(const HashTable *); +extern void zend_iterator_init(zend_object_iterator *); +extern zend_module_entry * zend_register_module_ex(zend_module_entry *, int); +extern zend_result zend_startup_module_ex(zend_module_entry *); +extern zend_constant * zend_register_constant(zend_constant *); +extern void zend_clear_exception(void); +extern void zval_ptr_dtor(zval *); +extern void zval_add_ref(zval *); +extern void rc_dtor_func(zend_refcounted *); +extern zend_string * zend_string_concat2(const char *, size_t, const char *, size_t); +extern zend_ulong zend_string_hash_func(zend_string *); +extern void free(void *); + +/* Imported globals */ +extern zend_executor_globals executor_globals; +extern struct _zend_compiler_globals compiler_globals; +extern HashTable module_registry; +extern const zend_object_handlers std_object_handlers; +extern zend_ast_process_t zend_ast_process; +extern char zend_system_id[32]; diff --git a/include/8.5/linux-x64-nts/layouts.json b/include/8.5/linux-x64-nts/layouts.json new file mode 100644 index 00000000..676ef2cb --- /dev/null +++ b/include/8.5/linux-x64-nts/layouts.json @@ -0,0 +1,693 @@ +{ + "meta": { + "php": "8.5", + "api": 20250925, + "zts": 0, + "debug": 0 + }, + "structs": { + "zval": { + "size": 16, + "fields": { + "value": 0, + "u1": 8, + "u2": 12 + } + }, + "zend_refcounted": { + "size": 8, + "fields": { + "gc": 0 + } + }, + "zend_string": { + "size": 32, + "fields": { + "gc": 0, + "h": 8, + "len": 16, + "val": 24 + } + }, + "zend_array": { + "size": 56, + "fields": { + "gc": 0, + "u": 8, + "nTableMask": 12, + "arHash": 16, + "arData": 16, + "arPacked": 16, + "nNumUsed": 24, + "nNumOfElements": 28, + "nTableSize": 32, + "nInternalPointer": 36, + "nNextFreeElement": 40, + "pDestructor": 48 + } + }, + "Bucket": { + "size": 32, + "fields": { + "val": 0, + "h": 16, + "key": 24 + } + }, + "zend_object": { + "size": 56, + "fields": { + "gc": 0, + "handle": 8, + "extra_flags": 12, + "ce": 16, + "handlers": 24, + "properties": 32, + "properties_table": 40 + } + }, + "zend_resource": { + "size": 32, + "fields": { + "gc": 0, + "handle": 8, + "type": 16, + "ptr": 24 + } + }, + "zend_reference": { + "size": 32, + "fields": { + "gc": 0, + "val": 8, + "sources": 24 + } + }, + "zend_class_entry": { + "size": 520, + "fields": { + "type": 0, + "name": 8, + "parent": 16, + "parent_name": 16, + "refcount": 24, + "ce_flags": 28, + "default_properties_count": 32, + "default_static_members_count": 36, + "default_properties_table": 40, + "default_static_members_table": 48, + "static_members_table__ptr": 56, + "function_table": 64, + "properties_info": 120, + "constants_table": 176, + "mutable_data__ptr": 232, + "inheritance_cache": 240, + "properties_info_table": 248, + "constructor": 256, + "destructor": 264, + "clone": 272, + "__get": 280, + "__set": 288, + "__unset": 296, + "__isset": 304, + "__call": 312, + "__callstatic": 320, + "__tostring": 328, + "__debugInfo": 336, + "__serialize": 344, + "__unserialize": 352, + "default_object_handlers": 360, + "iterator_funcs_ptr": 368, + "arrayaccess_funcs_ptr": 376, + "create_object": 384, + "interface_gets_implemented": 384, + "get_iterator": 392, + "get_static_method": 400, + "serialize": 408, + "unserialize": 416, + "num_interfaces": 424, + "num_traits": 428, + "num_hooked_props": 432, + "num_hooked_prop_variance_checks": 436, + "interfaces": 440, + "interface_names": 440, + "trait_names": 448, + "trait_aliases": 456, + "trait_precedences": 464, + "attributes": 472, + "enum_backing_type": 480, + "backed_enum_table": 488, + "doc_comment": 496, + "info": 504 + } + }, + "zend_class_constant": { + "size": 56, + "fields": { + "value": 0, + "doc_comment": 16, + "attributes": 24, + "ce": 32, + "type": 40 + } + }, + "zend_class_name": { + "size": 16, + "fields": { + "name": 0, + "lc_name": 8 + } + }, + "zend_property_info": { + "size": 72, + "fields": { + "offset": 0, + "flags": 4, + "name": 8, + "doc_comment": 16, + "attributes": 24, + "ce": 32, + "type": 40, + "prototype": 56, + "hooks": 64 + } + }, + "zend_type_list": { + "size": 24, + "fields": { + "num_types": 0, + "types": 8 + } + }, + "zend_constant": { + "size": 40, + "fields": { + "value": 0, + "name": 16, + "filename": 24, + "attributes": 32 + } + }, + "zend_attribute": { + "size": 64, + "fields": { + "name": 0, + "lcname": 8, + "validation_error": 16, + "flags": 24, + "lineno": 28, + "offset": 32, + "argc": 36, + "args": 40 + } + }, + "zend_attribute_arg": { + "size": 24, + "fields": { + "name": 0, + "value": 8 + } + }, + "zend_op_array": { + "size": 256, + "fields": { + "type": 0, + "arg_flags": 1, + "fn_flags": 4, + "function_name": 8, + "scope": 16, + "prototype": 24, + "num_args": 32, + "required_num_args": 36, + "arg_info": 40, + "attributes": 48, + "run_time_cache__ptr": 56, + "doc_comment": 64, + "T": 72, + "prop_info": 80, + "cache_size": 88, + "last_var": 92, + "last": 96, + "opcodes": 104, + "static_variables_ptr__ptr": 112, + "static_variables": 120, + "vars": 128, + "refcount": 136, + "last_live_range": 144, + "last_try_catch": 148, + "live_range": 152, + "try_catch_array": 160, + "filename": 168, + "line_start": 176, + "line_end": 180, + "last_literal": 184, + "num_dynamic_func_defs": 188, + "literals": 192, + "dynamic_func_defs": 200, + "reserved": 208 + } + }, + "zend_internal_function": { + "size": 160, + "fields": { + "type": 0, + "arg_flags": 1, + "fn_flags": 4, + "function_name": 8, + "scope": 16, + "prototype": 24, + "num_args": 32, + "required_num_args": 36, + "arg_info": 40, + "attributes": 48, + "run_time_cache__ptr": 56, + "doc_comment": 64, + "T": 72, + "prop_info": 80, + "handler": 88, + "module": 96, + "frameless_function_infos": 104, + "reserved": 112 + } + }, + "zend_op": { + "size": 32, + "fields": { + "handler": 0, + "op1": 8, + "op2": 12, + "result": 16, + "extended_value": 20, + "lineno": 24, + "opcode": 28, + "op1_type": 29, + "op2_type": 30, + "result_type": 31 + } + }, + "zend_execute_data": { + "size": 80, + "fields": { + "opline": 0, + "call": 8, + "return_value": 16, + "func": 24, + "This": 32, + "prev_execute_data": 48, + "symbol_table": 56, + "run_time_cache": 64, + "extra_named_params": 72 + } + }, + "zend_objects_store": { + "size": 24, + "fields": { + "object_buckets": 0, + "top": 8, + "size": 12, + "free_list_head": 16 + } + }, + "zend_executor_globals": { + "size": 1984, + "fields": { + "uninitialized_zval": 0, + "error_zval": 16, + "symtable_cache": 32, + "symtable_cache_limit": 288, + "symtable_cache_ptr": 296, + "symbol_table": 304, + "included_files": 360, + "bailout": 416, + "error_reporting": 424, + "fatal_error_backtrace_on": 428, + "last_fatal_error_backtrace": 432, + "exit_status": 448, + "function_table": 456, + "class_table": 464, + "zend_constants": 472, + "vm_stack_top": 480, + "vm_stack_end": 488, + "vm_stack": 496, + "vm_stack_page_size": 504, + "current_execute_data": 512, + "fake_scope": 520, + "jit_trace_num": 528, + "current_observed_frame": 536, + "ticks_count": 544, + "precision": 552, + "persistent_constants_count": 560, + "persistent_functions_count": 564, + "persistent_classes_count": 568, + "no_extensions": 572, + "full_tables_cleanup": 573, + "vm_interrupt": 574, + "timed_out": 575, + "in_autoload": 576, + "hard_timeout": 584, + "stack_base": 592, + "stack_limit": 600, + "regular_list": 608, + "persistent_list": 664, + "user_error_handler_error_reporting": 720, + "exception_ignore_args": 724, + "user_error_handler": 728, + "user_exception_handler": 744, + "user_error_handlers_error_reporting": 760, + "user_error_handlers": 784, + "user_exception_handlers": 808, + "exception_class": 832, + "error_handling": 840, + "capture_warnings_during_sccp": 844, + "timeout_seconds": 848, + "ini_directives": 856, + "modified_ini_directives": 864, + "error_reporting_ini_entry": 872, + "objects_store": 880, + "lazy_objects_store": 904, + "exception": 960, + "prev_exception": 968, + "opline_before_exception": 976, + "exception_op": 984, + "current_module": 1080, + "active": 1088, + "flags": 1089, + "assertions": 1096, + "ht_iterators_count": 1104, + "ht_iterators_used": 1108, + "ht_iterators": 1112, + "ht_iterators_slots": 1120, + "saved_fpu_cw_ptr": 1376, + "trampoline": 1384, + "call_trampoline_op": 1640, + "weakrefs": 1672, + "exception_string_param_max_len": 1728, + "get_gc_buffer": 1736, + "main_fiber_context": 1760, + "current_fiber_context": 1768, + "active_fiber": 1776, + "fiber_stack_size": 1784, + "record_errors": 1792, + "num_errors": 1796, + "errors": 1800, + "filename_override": 1808, + "lineno_override": 1816, + "call_stack": 1824, + "max_allowed_stack_size": 1840, + "reserved_stack_size": 1848, + "strtod_state": 1856, + "reserved": 1936 + } + }, + "zend_compiler_globals": { + "size": 616, + "fields": { + "loop_var_stack": 0, + "active_class_entry": 24, + "compiled_filename": 32, + "zend_lineno": 40, + "active_op_array": 48, + "function_table": 56, + "class_table": 64, + "auto_globals": 72, + "parse_error": 80, + "in_compilation": 81, + "short_tags": 82, + "unclean_shutdown": 83, + "ini_parser_unbuffered_errors": 84, + "open_files": 88, + "ini_parser_param": 144, + "skip_shebang": 152, + "increment_lineno": 153, + "variable_width_locale": 154, + "ascii_compatible_locale": 155, + "doc_comment": 160, + "extra_fn_flags": 168, + "compiler_options": 172, + "context": 176, + "file_context": 256, + "arena": 360, + "interned_strings": 368, + "script_encoding_list": 424, + "script_encoding_list_size": 432, + "multibyte": 440, + "detect_unicode": 441, + "encoding_declared": 442, + "ast": 448, + "ast_arena": 456, + "delayed_oplines_stack": 464, + "memoized_exprs": 488, + "memoize_mode": 496, + "map_ptr_real_base": 504, + "map_ptr_base": 512, + "map_ptr_size": 520, + "map_ptr_last": 528, + "delayed_variance_obligations": 536, + "delayed_autoloads": 544, + "unlinked_uses": 552, + "current_linking_class": 560, + "rtd_key_counter": 568, + "internal_run_time_cache": 576, + "internal_run_time_cache_size": 584, + "short_circuiting_opnums": 592 + } + }, + "zend_module_entry": { + "size": 168, + "fields": { + "size": 0, + "zend_api": 4, + "zend_debug": 8, + "zts": 9, + "ini_entry": 16, + "deps": 24, + "name": 32, + "functions": 40, + "module_startup_func": 48, + "module_shutdown_func": 56, + "request_startup_func": 64, + "request_shutdown_func": 72, + "info_func": 80, + "version": 88, + "globals_size": 96, + "globals_ptr": 104, + "globals_ctor": 112, + "globals_dtor": 120, + "post_deactivate_func": 128, + "module_started": 136, + "type": 140, + "handle": 144, + "module_number": 152, + "build_id": 160 + } + }, + "zend_module_dep": { + "size": 32, + "fields": { + "name": 0, + "rel": 8, + "version": 16, + "type": 24 + } + }, + "zend_object_handlers": { + "size": 208, + "fields": { + "offset": 0, + "free_obj": 8, + "dtor_obj": 16, + "clone_obj": 24, + "clone_obj_with": 32, + "read_property": 40, + "write_property": 48, + "read_dimension": 56, + "write_dimension": 64, + "get_property_ptr_ptr": 72, + "has_property": 80, + "unset_property": 88, + "has_dimension": 96, + "unset_dimension": 104, + "get_properties": 112, + "get_method": 120, + "get_constructor": 128, + "get_class_name": 136, + "cast_object": 144, + "count_elements": 152, + "get_debug_info": 160, + "get_closure": 168, + "get_gc": 176, + "do_operation": 184, + "compare": 192, + "get_properties_for": 200 + } + }, + "zend_object_iterator": { + "size": 88, + "fields": { + "std": 0, + "data": 56, + "funcs": 72, + "index": 80 + } + }, + "zend_object_iterator_funcs": { + "size": 64, + "fields": { + "dtor": 0, + "valid": 8, + "get_current_data": 16, + "get_current_key": 24, + "move_forward": 32, + "rewind": 40, + "invalidate_current": 48, + "get_gc": 56 + } + }, + "zend_ast": { + "size": 16, + "fields": { + "kind": 0, + "attr": 2, + "lineno": 4, + "child": 8 + } + }, + "zend_ast_decl": { + "size": 72, + "fields": { + "kind": 0, + "attr": 2, + "start_lineno": 4, + "end_lineno": 8, + "flags": 12, + "doc_comment": 16, + "name": 24, + "child": 32 + } + }, + "zend_ast_list": { + "size": 24, + "fields": { + "kind": 0, + "attr": 2, + "lineno": 4, + "children": 8, + "child": 16 + } + }, + "zend_ast_zval": { + "size": 24, + "fields": { + "kind": 0, + "attr": 2, + "val": 8 + } + }, + "zend_ast_op_array": { + "size": 16, + "fields": { + "kind": 0, + "attr": 2, + "lineno": 4, + "op_array": 8 + } + }, + "zend_lex_state": { + "size": 248, + "fields": { + "yy_leng": 0, + "yy_start": 8, + "yy_text": 16, + "yy_cursor": 24, + "yy_marker": 32, + "yy_limit": 40, + "yy_state": 48, + "state_stack": 56, + "heredoc_label_stack": 80, + "nest_location_stack": 112, + "in": 136, + "lineno": 144, + "filename": 152, + "script_org": 160, + "script_org_size": 168, + "script_filtered": 176, + "script_filtered_size": 184, + "input_filter": 192, + "output_filter": 200, + "script_encoding": 208, + "on_event": 216, + "on_event_context": 224, + "ast": 232, + "ast_arena": 240 + } + }, + "zend_closure": { + "size": 344, + "fields": { + "std": 0, + "func": 56, + "this_ptr": 312, + "called_scope": 328, + "orig_internal_handler": 336 + } + }, + "zend_script": { + "size": 376, + "fields": { + "filename": 0, + "main_op_array": 8, + "function_table": 264, + "class_table": 320 + } + }, + "zend_error_info": { + "size": 24, + "fields": { + "type": 0, + "lineno": 4, + "filename": 8, + "message": 16 + } + }, + "zend_early_binding": { + "size": 32, + "fields": { + "lcname": 0, + "rtd_key": 8, + "lc_parent_name": 16, + "cache_slot": 24 + } + }, + "zend_persistent_script": { + "size": 480, + "fields": { + "script": 0, + "compiler_halt_offset": 376, + "ping_auto_globals_mask": 384, + "timestamp": 392, + "corrupted": 400, + "is_phar": 401, + "empty": 402, + "num_warnings": 404, + "num_early_bindings": 408, + "warnings": 416, + "early_bindings": 424, + "mem": 432, + "size": 440, + "dynamic_members": 448 + } + }, + "zend_file_cache_metainfo": { + "size": 80, + "fields": { + "magic": 0, + "system_id": 8, + "mem_size": 40, + "str_size": 48, + "script_offset": 56, + "timestamp": 64, + "checksum": 72 + } + } + } +} diff --git a/include/8.5/linux-x64-nts/probe.c b/include/8.5/linux-x64-nts/probe.c new file mode 100644 index 00000000..d2aa785b --- /dev/null +++ b/include/8.5/linux-x64-nts/probe.c @@ -0,0 +1,1533 @@ +#include "php.h" +#include "zend_ast.h" +#include "zend_attributes.h" +#include "zend_language_scanner.h" +#include "zend_inheritance.h" +#include "zend_hash.h" +#include "zend_modules.h" +#include "zend_arena.h" +#include "zend_exceptions.h" +#include "Optimizer/zend_optimizer.h" +#include "supplement.h" +#include + +int main(void) { + FILE *constants = fopen("constants.php", "w"); + FILE *layouts = fopen("layouts.json", "w"); + if (!constants || !layouts) { return 1; } + fputs(" %lld,\n", (long long)(ZEND_ACC_PUBLIC)); +#endif +#ifdef ZEND_ACC_PROTECTED + fprintf(constants, " 'ZEND_ACC_PROTECTED' => %lld,\n", (long long)(ZEND_ACC_PROTECTED)); +#endif +#ifdef ZEND_ACC_PRIVATE + fprintf(constants, " 'ZEND_ACC_PRIVATE' => %lld,\n", (long long)(ZEND_ACC_PRIVATE)); +#endif +#ifdef ZEND_ACC_CHANGED + fprintf(constants, " 'ZEND_ACC_CHANGED' => %lld,\n", (long long)(ZEND_ACC_CHANGED)); +#endif +#ifdef ZEND_ACC_STATIC + fprintf(constants, " 'ZEND_ACC_STATIC' => %lld,\n", (long long)(ZEND_ACC_STATIC)); +#endif +#ifdef ZEND_ACC_ABSTRACT + fprintf(constants, " 'ZEND_ACC_ABSTRACT' => %lld,\n", (long long)(ZEND_ACC_ABSTRACT)); +#endif +#ifdef ZEND_ACC_FINAL + fprintf(constants, " 'ZEND_ACC_FINAL' => %lld,\n", (long long)(ZEND_ACC_FINAL)); +#endif +#ifdef ZEND_ACC_DEPRECATED + fprintf(constants, " 'ZEND_ACC_DEPRECATED' => %lld,\n", (long long)(ZEND_ACC_DEPRECATED)); +#endif +#ifdef ZEND_ACC_INTERFACE + fprintf(constants, " 'ZEND_ACC_INTERFACE' => %lld,\n", (long long)(ZEND_ACC_INTERFACE)); +#endif +#ifdef ZEND_ACC_TRAIT + fprintf(constants, " 'ZEND_ACC_TRAIT' => %lld,\n", (long long)(ZEND_ACC_TRAIT)); +#endif +#ifdef ZEND_ACC_ANON_CLASS + fprintf(constants, " 'ZEND_ACC_ANON_CLASS' => %lld,\n", (long long)(ZEND_ACC_ANON_CLASS)); +#endif +#ifdef ZEND_ACC_ENUM + fprintf(constants, " 'ZEND_ACC_ENUM' => %lld,\n", (long long)(ZEND_ACC_ENUM)); +#endif +#ifdef ZEND_ACC_IMPLICIT_ABSTRACT_CLASS + fprintf(constants, " 'ZEND_ACC_IMPLICIT_ABSTRACT_CLASS' => %lld,\n", (long long)(ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)); +#endif +#ifdef ZEND_ACC_LINKED + fprintf(constants, " 'ZEND_ACC_LINKED' => %lld,\n", (long long)(ZEND_ACC_LINKED)); +#endif +#ifdef ZEND_ACC_IMMUTABLE + fprintf(constants, " 'ZEND_ACC_IMMUTABLE' => %lld,\n", (long long)(ZEND_ACC_IMMUTABLE)); +#endif +#ifdef ZEND_ACC_USE_GUARDS + fprintf(constants, " 'ZEND_ACC_USE_GUARDS' => %lld,\n", (long long)(ZEND_ACC_USE_GUARDS)); +#endif +#ifdef ZEND_ACC_CONSTANTS_UPDATED + fprintf(constants, " 'ZEND_ACC_CONSTANTS_UPDATED' => %lld,\n", (long long)(ZEND_ACC_CONSTANTS_UPDATED)); +#endif +#ifdef ZEND_ACC_NO_DYNAMIC_PROPERTIES + fprintf(constants, " 'ZEND_ACC_NO_DYNAMIC_PROPERTIES' => %lld,\n", (long long)(ZEND_ACC_NO_DYNAMIC_PROPERTIES)); +#endif +#ifdef ZEND_ACC_HAS_STATIC_IN_METHODS + fprintf(constants, " 'ZEND_ACC_HAS_STATIC_IN_METHODS' => %lld,\n", (long long)(ZEND_ACC_HAS_STATIC_IN_METHODS)); +#endif +#ifdef ZEND_HAS_STATIC_IN_METHODS + fprintf(constants, " 'ZEND_HAS_STATIC_IN_METHODS' => %lld,\n", (long long)(ZEND_HAS_STATIC_IN_METHODS)); +#endif +#ifdef ZEND_ACC_TOP_LEVEL + fprintf(constants, " 'ZEND_ACC_TOP_LEVEL' => %lld,\n", (long long)(ZEND_ACC_TOP_LEVEL)); +#endif +#ifdef ZEND_ACC_PRELOADED + fprintf(constants, " 'ZEND_ACC_PRELOADED' => %lld,\n", (long long)(ZEND_ACC_PRELOADED)); +#endif +#ifdef ZEND_ACC_NOT_SERIALIZABLE + fprintf(constants, " 'ZEND_ACC_NOT_SERIALIZABLE' => %lld,\n", (long long)(ZEND_ACC_NOT_SERIALIZABLE)); +#endif +#ifdef ZEND_ACC_READONLY_CLASS + fprintf(constants, " 'ZEND_ACC_READONLY_CLASS' => %lld,\n", (long long)(ZEND_ACC_READONLY_CLASS)); +#endif +#ifdef ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES + fprintf(constants, " 'ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES' => %lld,\n", (long long)(ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)); +#endif +#ifdef ZEND_ACC_UNRESOLVED_VARIANCE + fprintf(constants, " 'ZEND_ACC_UNRESOLVED_VARIANCE' => %lld,\n", (long long)(ZEND_ACC_UNRESOLVED_VARIANCE)); +#endif +#ifdef ZEND_ACC_NEARLY_LINKED + fprintf(constants, " 'ZEND_ACC_NEARLY_LINKED' => %lld,\n", (long long)(ZEND_ACC_NEARLY_LINKED)); +#endif +#ifdef ZEND_ACC_RESOLVED_PARENT + fprintf(constants, " 'ZEND_ACC_RESOLVED_PARENT' => %lld,\n", (long long)(ZEND_ACC_RESOLVED_PARENT)); +#endif +#ifdef ZEND_ACC_RESOLVED_INTERFACES + fprintf(constants, " 'ZEND_ACC_RESOLVED_INTERFACES' => %lld,\n", (long long)(ZEND_ACC_RESOLVED_INTERFACES)); +#endif +#ifdef ZEND_ACC_HAS_UNLINKED_USES + fprintf(constants, " 'ZEND_ACC_HAS_UNLINKED_USES' => %lld,\n", (long long)(ZEND_ACC_HAS_UNLINKED_USES)); +#endif +#ifdef ZEND_ACC_PROPERTY_TYPES_RESOLVED + fprintf(constants, " 'ZEND_ACC_PROPERTY_TYPES_RESOLVED' => %lld,\n", (long long)(ZEND_ACC_PROPERTY_TYPES_RESOLVED)); +#endif +#ifdef ZEND_ACC_REUSE_GET_ITERATOR + fprintf(constants, " 'ZEND_ACC_REUSE_GET_ITERATOR' => %lld,\n", (long long)(ZEND_ACC_REUSE_GET_ITERATOR)); +#endif +#ifdef ZEND_ACC_EXPLICIT_ABSTRACT_CLASS + fprintf(constants, " 'ZEND_ACC_EXPLICIT_ABSTRACT_CLASS' => %lld,\n", (long long)(ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)); +#endif +#ifdef ZEND_ACC_READONLY + fprintf(constants, " 'ZEND_ACC_READONLY' => %lld,\n", (long long)(ZEND_ACC_READONLY)); +#endif +#ifdef ZEND_ACC_ABSTRACT_METHOD + fprintf(constants, " 'ZEND_ACC_ABSTRACT_METHOD' => %lld,\n", (long long)(ZEND_ACC_ABSTRACT_METHOD)); +#endif +#ifdef ZEND_ACC_VIRTUAL + fprintf(constants, " 'ZEND_ACC_VIRTUAL' => %lld,\n", (long long)(ZEND_ACC_VIRTUAL)); +#endif +#ifdef ZEND_ACC_FAKE_CLOSURE + fprintf(constants, " 'ZEND_ACC_FAKE_CLOSURE' => %lld,\n", (long long)(ZEND_ACC_FAKE_CLOSURE)); +#endif +#ifdef ZEND_ACC_UNINSTANTIABLE + fprintf(constants, " 'ZEND_ACC_UNINSTANTIABLE' => %lld,\n", (long long)(ZEND_ACC_UNINSTANTIABLE)); +#endif +#ifdef ZEND_ACC_CALL_VIA_TRAMPOLINE + fprintf(constants, " 'ZEND_ACC_CALL_VIA_TRAMPOLINE' => %lld,\n", (long long)(ZEND_ACC_CALL_VIA_TRAMPOLINE)); +#endif +#ifdef ZEND_ACC_NEVER_CACHE + fprintf(constants, " 'ZEND_ACC_NEVER_CACHE' => %lld,\n", (long long)(ZEND_ACC_NEVER_CACHE)); +#endif +#ifdef ZEND_ACC_TRAIT_CLONE + fprintf(constants, " 'ZEND_ACC_TRAIT_CLONE' => %lld,\n", (long long)(ZEND_ACC_TRAIT_CLONE)); +#endif +#ifdef ZEND_ACC_RETURN_REFERENCE + fprintf(constants, " 'ZEND_ACC_RETURN_REFERENCE' => %lld,\n", (long long)(ZEND_ACC_RETURN_REFERENCE)); +#endif +#ifdef ZEND_ACC_DONE_PASS_TWO + fprintf(constants, " 'ZEND_ACC_DONE_PASS_TWO' => %lld,\n", (long long)(ZEND_ACC_DONE_PASS_TWO)); +#endif +#ifdef ZEND_ACC_HEAP_RT_CACHE + fprintf(constants, " 'ZEND_ACC_HEAP_RT_CACHE' => %lld,\n", (long long)(ZEND_ACC_HEAP_RT_CACHE)); +#endif +#ifdef ZEND_ACC_STRICT_TYPES + fprintf(constants, " 'ZEND_ACC_STRICT_TYPES' => %lld,\n", (long long)(ZEND_ACC_STRICT_TYPES)); +#endif +#ifdef ZEND_ACC_CLOSURE + fprintf(constants, " 'ZEND_ACC_CLOSURE' => %lld,\n", (long long)(ZEND_ACC_CLOSURE)); +#endif +#ifdef ZEND_ACC_GENERATOR + fprintf(constants, " 'ZEND_ACC_GENERATOR' => %lld,\n", (long long)(ZEND_ACC_GENERATOR)); +#endif +#ifdef ZEND_ACC_HAS_FINALLY_BLOCK + fprintf(constants, " 'ZEND_ACC_HAS_FINALLY_BLOCK' => %lld,\n", (long long)(ZEND_ACC_HAS_FINALLY_BLOCK)); +#endif +#ifdef ZEND_ACC_EARLY_BINDING + fprintf(constants, " 'ZEND_ACC_EARLY_BINDING' => %lld,\n", (long long)(ZEND_ACC_EARLY_BINDING)); +#endif +#ifdef ZEND_ACC_USES_THIS + fprintf(constants, " 'ZEND_ACC_USES_THIS' => %lld,\n", (long long)(ZEND_ACC_USES_THIS)); +#endif +#ifdef ZEND_ACC_CTOR + fprintf(constants, " 'ZEND_ACC_CTOR' => %lld,\n", (long long)(ZEND_ACC_CTOR)); +#endif +#ifdef ZEND_ACC_HAS_TYPE_HINTS + fprintf(constants, " 'ZEND_ACC_HAS_TYPE_HINTS' => %lld,\n", (long long)(ZEND_ACC_HAS_TYPE_HINTS)); +#endif +#ifdef ZEND_ACC_HAS_RETURN_TYPE + fprintf(constants, " 'ZEND_ACC_HAS_RETURN_TYPE' => %lld,\n", (long long)(ZEND_ACC_HAS_RETURN_TYPE)); +#endif +#ifdef ZEND_ACC_VARIADIC + fprintf(constants, " 'ZEND_ACC_VARIADIC' => %lld,\n", (long long)(ZEND_ACC_VARIADIC)); +#endif +#ifdef ZEND_ACC_HAS_UNRESOLVED_INITIALIZERS + fprintf(constants, " 'ZEND_ACC_HAS_UNRESOLVED_INITIALIZERS' => %lld,\n", (long long)(ZEND_ACC_HAS_UNRESOLVED_INITIALIZERS)); +#endif +#ifdef ZEND_ACC_CACHED + fprintf(constants, " 'ZEND_ACC_CACHED' => %lld,\n", (long long)(ZEND_ACC_CACHED)); +#endif +#ifdef ZEND_ACC_FILE_CACHED + fprintf(constants, " 'ZEND_ACC_FILE_CACHED' => %lld,\n", (long long)(ZEND_ACC_FILE_CACHED)); +#endif +#ifdef ZEND_ACC_ARENA_ALLOCATED + fprintf(constants, " 'ZEND_ACC_ARENA_ALLOCATED' => %lld,\n", (long long)(ZEND_ACC_ARENA_ALLOCATED)); +#endif +#ifdef _ZEND_TYPE_EXTRA_FLAGS_SHIFT + fprintf(constants, " '_ZEND_TYPE_EXTRA_FLAGS_SHIFT' => %lld,\n", (long long)(_ZEND_TYPE_EXTRA_FLAGS_SHIFT)); +#endif +#ifdef _ZEND_TYPE_MASK + fprintf(constants, " '_ZEND_TYPE_MASK' => %lld,\n", (long long)(_ZEND_TYPE_MASK)); +#endif +#ifdef _ZEND_TYPE_NAME_BIT + fprintf(constants, " '_ZEND_TYPE_NAME_BIT' => %lld,\n", (long long)(_ZEND_TYPE_NAME_BIT)); +#endif +#ifdef _ZEND_TYPE_LITERAL_NAME_BIT + fprintf(constants, " '_ZEND_TYPE_LITERAL_NAME_BIT' => %lld,\n", (long long)(_ZEND_TYPE_LITERAL_NAME_BIT)); +#endif +#ifdef _ZEND_TYPE_LIST_BIT + fprintf(constants, " '_ZEND_TYPE_LIST_BIT' => %lld,\n", (long long)(_ZEND_TYPE_LIST_BIT)); +#endif +#ifdef _ZEND_TYPE_KIND_MASK + fprintf(constants, " '_ZEND_TYPE_KIND_MASK' => %lld,\n", (long long)(_ZEND_TYPE_KIND_MASK)); +#endif +#ifdef _ZEND_TYPE_ITERABLE_BIT + fprintf(constants, " '_ZEND_TYPE_ITERABLE_BIT' => %lld,\n", (long long)(_ZEND_TYPE_ITERABLE_BIT)); +#endif +#ifdef _ZEND_TYPE_ARENA_BIT + fprintf(constants, " '_ZEND_TYPE_ARENA_BIT' => %lld,\n", (long long)(_ZEND_TYPE_ARENA_BIT)); +#endif +#ifdef _ZEND_TYPE_INTERSECTION_BIT + fprintf(constants, " '_ZEND_TYPE_INTERSECTION_BIT' => %lld,\n", (long long)(_ZEND_TYPE_INTERSECTION_BIT)); +#endif +#ifdef _ZEND_TYPE_UNION_BIT + fprintf(constants, " '_ZEND_TYPE_UNION_BIT' => %lld,\n", (long long)(_ZEND_TYPE_UNION_BIT)); +#endif +#ifdef _ZEND_TYPE_NULLABLE_BIT + fprintf(constants, " '_ZEND_TYPE_NULLABLE_BIT' => %lld,\n", (long long)(_ZEND_TYPE_NULLABLE_BIT)); +#endif +#ifdef _ZEND_TYPE_MAY_BE_MASK + fprintf(constants, " '_ZEND_TYPE_MAY_BE_MASK' => %lld,\n", (long long)(_ZEND_TYPE_MAY_BE_MASK)); +#endif +#ifdef IS_UNDEF + fprintf(constants, " 'IS_UNDEF' => %lld,\n", (long long)(IS_UNDEF)); +#endif +#ifdef IS_NULL + fprintf(constants, " 'IS_NULL' => %lld,\n", (long long)(IS_NULL)); +#endif +#ifdef IS_FALSE + fprintf(constants, " 'IS_FALSE' => %lld,\n", (long long)(IS_FALSE)); +#endif +#ifdef IS_TRUE + fprintf(constants, " 'IS_TRUE' => %lld,\n", (long long)(IS_TRUE)); +#endif +#ifdef IS_LONG + fprintf(constants, " 'IS_LONG' => %lld,\n", (long long)(IS_LONG)); +#endif +#ifdef IS_DOUBLE + fprintf(constants, " 'IS_DOUBLE' => %lld,\n", (long long)(IS_DOUBLE)); +#endif +#ifdef IS_STRING + fprintf(constants, " 'IS_STRING' => %lld,\n", (long long)(IS_STRING)); +#endif +#ifdef IS_ARRAY + fprintf(constants, " 'IS_ARRAY' => %lld,\n", (long long)(IS_ARRAY)); +#endif +#ifdef IS_OBJECT + fprintf(constants, " 'IS_OBJECT' => %lld,\n", (long long)(IS_OBJECT)); +#endif +#ifdef IS_RESOURCE + fprintf(constants, " 'IS_RESOURCE' => %lld,\n", (long long)(IS_RESOURCE)); +#endif +#ifdef IS_REFERENCE + fprintf(constants, " 'IS_REFERENCE' => %lld,\n", (long long)(IS_REFERENCE)); +#endif +#ifdef IS_CONSTANT_AST + fprintf(constants, " 'IS_CONSTANT_AST' => %lld,\n", (long long)(IS_CONSTANT_AST)); +#endif +#ifdef IS_CALLABLE + fprintf(constants, " 'IS_CALLABLE' => %lld,\n", (long long)(IS_CALLABLE)); +#endif +#ifdef IS_ITERABLE + fprintf(constants, " 'IS_ITERABLE' => %lld,\n", (long long)(IS_ITERABLE)); +#endif +#ifdef IS_VOID + fprintf(constants, " 'IS_VOID' => %lld,\n", (long long)(IS_VOID)); +#endif +#ifdef IS_STATIC + fprintf(constants, " 'IS_STATIC' => %lld,\n", (long long)(IS_STATIC)); +#endif +#ifdef IS_MIXED + fprintf(constants, " 'IS_MIXED' => %lld,\n", (long long)(IS_MIXED)); +#endif +#ifdef IS_NEVER + fprintf(constants, " 'IS_NEVER' => %lld,\n", (long long)(IS_NEVER)); +#endif +#ifdef IS_INDIRECT + fprintf(constants, " 'IS_INDIRECT' => %lld,\n", (long long)(IS_INDIRECT)); +#endif +#ifdef IS_PTR + fprintf(constants, " 'IS_PTR' => %lld,\n", (long long)(IS_PTR)); +#endif +#ifdef IS_ALIAS_PTR + fprintf(constants, " 'IS_ALIAS_PTR' => %lld,\n", (long long)(IS_ALIAS_PTR)); +#endif +#ifdef _IS_ERROR + fprintf(constants, " '_IS_ERROR' => %lld,\n", (long long)(_IS_ERROR)); +#endif +#ifdef _IS_BOOL + fprintf(constants, " '_IS_BOOL' => %lld,\n", (long long)(_IS_BOOL)); +#endif +#ifdef _IS_NUMBER + fprintf(constants, " '_IS_NUMBER' => %lld,\n", (long long)(_IS_NUMBER)); +#endif +#ifdef IS_TYPE_REFCOUNTED + fprintf(constants, " 'IS_TYPE_REFCOUNTED' => %lld,\n", (long long)(IS_TYPE_REFCOUNTED)); +#endif +#ifdef IS_TYPE_COLLECTABLE + fprintf(constants, " 'IS_TYPE_COLLECTABLE' => %lld,\n", (long long)(IS_TYPE_COLLECTABLE)); +#endif +#ifdef Z_TYPE_MASK + fprintf(constants, " 'Z_TYPE_MASK' => %lld,\n", (long long)(Z_TYPE_MASK)); +#endif +#ifdef Z_TYPE_FLAGS_MASK + fprintf(constants, " 'Z_TYPE_FLAGS_MASK' => %lld,\n", (long long)(Z_TYPE_FLAGS_MASK)); +#endif +#ifdef Z_TYPE_FLAGS_SHIFT + fprintf(constants, " 'Z_TYPE_FLAGS_SHIFT' => %lld,\n", (long long)(Z_TYPE_FLAGS_SHIFT)); +#endif +#ifdef GC_TYPE_MASK + fprintf(constants, " 'GC_TYPE_MASK' => %lld,\n", (long long)(GC_TYPE_MASK)); +#endif +#ifdef GC_FLAGS_MASK + fprintf(constants, " 'GC_FLAGS_MASK' => %lld,\n", (long long)(GC_FLAGS_MASK)); +#endif +#ifdef GC_INFO_MASK + fprintf(constants, " 'GC_INFO_MASK' => %lld,\n", (long long)(GC_INFO_MASK)); +#endif +#ifdef GC_FLAGS_SHIFT + fprintf(constants, " 'GC_FLAGS_SHIFT' => %lld,\n", (long long)(GC_FLAGS_SHIFT)); +#endif +#ifdef GC_INFO_SHIFT + fprintf(constants, " 'GC_INFO_SHIFT' => %lld,\n", (long long)(GC_INFO_SHIFT)); +#endif +#ifdef GC_NULL + fprintf(constants, " 'GC_NULL' => %lld,\n", (long long)(GC_NULL)); +#endif +#ifdef GC_STRING + fprintf(constants, " 'GC_STRING' => %lld,\n", (long long)(GC_STRING)); +#endif +#ifdef GC_ARRAY + fprintf(constants, " 'GC_ARRAY' => %lld,\n", (long long)(GC_ARRAY)); +#endif +#ifdef GC_OBJECT + fprintf(constants, " 'GC_OBJECT' => %lld,\n", (long long)(GC_OBJECT)); +#endif +#ifdef GC_RESOURCE + fprintf(constants, " 'GC_RESOURCE' => %lld,\n", (long long)(GC_RESOURCE)); +#endif +#ifdef GC_REFERENCE + fprintf(constants, " 'GC_REFERENCE' => %lld,\n", (long long)(GC_REFERENCE)); +#endif +#ifdef GC_CONSTANT_AST + fprintf(constants, " 'GC_CONSTANT_AST' => %lld,\n", (long long)(GC_CONSTANT_AST)); +#endif +#ifdef GC_NOT_COLLECTABLE + fprintf(constants, " 'GC_NOT_COLLECTABLE' => %lld,\n", (long long)(GC_NOT_COLLECTABLE)); +#endif +#ifdef GC_PROTECTED + fprintf(constants, " 'GC_PROTECTED' => %lld,\n", (long long)(GC_PROTECTED)); +#endif +#ifdef GC_IMMUTABLE + fprintf(constants, " 'GC_IMMUTABLE' => %lld,\n", (long long)(GC_IMMUTABLE)); +#endif +#ifdef GC_PERSISTENT + fprintf(constants, " 'GC_PERSISTENT' => %lld,\n", (long long)(GC_PERSISTENT)); +#endif +#ifdef GC_PERSISTENT_LOCAL + fprintf(constants, " 'GC_PERSISTENT_LOCAL' => %lld,\n", (long long)(GC_PERSISTENT_LOCAL)); +#endif +#ifdef IS_STR_CLASS_NAME_MAP_PTR + fprintf(constants, " 'IS_STR_CLASS_NAME_MAP_PTR' => %lld,\n", (long long)(IS_STR_CLASS_NAME_MAP_PTR)); +#endif +#ifdef IS_STR_INTERNED + fprintf(constants, " 'IS_STR_INTERNED' => %lld,\n", (long long)(IS_STR_INTERNED)); +#endif +#ifdef IS_STR_PERSISTENT + fprintf(constants, " 'IS_STR_PERSISTENT' => %lld,\n", (long long)(IS_STR_PERSISTENT)); +#endif +#ifdef IS_STR_PERMANENT + fprintf(constants, " 'IS_STR_PERMANENT' => %lld,\n", (long long)(IS_STR_PERMANENT)); +#endif +#ifdef IS_STR_VALID_UTF8 + fprintf(constants, " 'IS_STR_VALID_UTF8' => %lld,\n", (long long)(IS_STR_VALID_UTF8)); +#endif +#ifdef IS_ARRAY_IMMUTABLE + fprintf(constants, " 'IS_ARRAY_IMMUTABLE' => %lld,\n", (long long)(IS_ARRAY_IMMUTABLE)); +#endif +#ifdef IS_ARRAY_PERSISTENT + fprintf(constants, " 'IS_ARRAY_PERSISTENT' => %lld,\n", (long long)(IS_ARRAY_PERSISTENT)); +#endif +#ifdef IS_OBJ_WEAKLY_REFERENCED + fprintf(constants, " 'IS_OBJ_WEAKLY_REFERENCED' => %lld,\n", (long long)(IS_OBJ_WEAKLY_REFERENCED)); +#endif +#ifdef IS_OBJ_DESTRUCTOR_CALLED + fprintf(constants, " 'IS_OBJ_DESTRUCTOR_CALLED' => %lld,\n", (long long)(IS_OBJ_DESTRUCTOR_CALLED)); +#endif +#ifdef IS_OBJ_FREE_CALLED + fprintf(constants, " 'IS_OBJ_FREE_CALLED' => %lld,\n", (long long)(IS_OBJ_FREE_CALLED)); +#endif +#ifdef IS_OBJ_LAZY_UNINITIALIZED + fprintf(constants, " 'IS_OBJ_LAZY_UNINITIALIZED' => %lld,\n", (long long)(IS_OBJ_LAZY_UNINITIALIZED)); +#endif +#ifdef IS_OBJ_LAZY_PROXY + fprintf(constants, " 'IS_OBJ_LAZY_PROXY' => %lld,\n", (long long)(IS_OBJ_LAZY_PROXY)); +#endif +#ifdef HASH_FLAG_CONSISTENCY + fprintf(constants, " 'HASH_FLAG_CONSISTENCY' => %lld,\n", (long long)(HASH_FLAG_CONSISTENCY)); +#endif +#ifdef HASH_FLAG_PACKED + fprintf(constants, " 'HASH_FLAG_PACKED' => %lld,\n", (long long)(HASH_FLAG_PACKED)); +#endif +#ifdef HASH_FLAG_UNINITIALIZED + fprintf(constants, " 'HASH_FLAG_UNINITIALIZED' => %lld,\n", (long long)(HASH_FLAG_UNINITIALIZED)); +#endif +#ifdef HASH_FLAG_STATIC_KEYS + fprintf(constants, " 'HASH_FLAG_STATIC_KEYS' => %lld,\n", (long long)(HASH_FLAG_STATIC_KEYS)); +#endif +#ifdef HASH_FLAG_HAS_EMPTY_IND + fprintf(constants, " 'HASH_FLAG_HAS_EMPTY_IND' => %lld,\n", (long long)(HASH_FLAG_HAS_EMPTY_IND)); +#endif +#ifdef HASH_FLAG_ALLOW_COW_VIOLATION + fprintf(constants, " 'HASH_FLAG_ALLOW_COW_VIOLATION' => %lld,\n", (long long)(HASH_FLAG_ALLOW_COW_VIOLATION)); +#endif +#ifdef HASH_UPDATE + fprintf(constants, " 'HASH_UPDATE' => %lld,\n", (long long)(HASH_UPDATE)); +#endif +#ifdef HASH_ADD + fprintf(constants, " 'HASH_ADD' => %lld,\n", (long long)(HASH_ADD)); +#endif +#ifdef HASH_UPDATE_INDIRECT + fprintf(constants, " 'HASH_UPDATE_INDIRECT' => %lld,\n", (long long)(HASH_UPDATE_INDIRECT)); +#endif +#ifdef HASH_ADD_NEW + fprintf(constants, " 'HASH_ADD_NEW' => %lld,\n", (long long)(HASH_ADD_NEW)); +#endif +#ifdef HASH_ADD_NEXT + fprintf(constants, " 'HASH_ADD_NEXT' => %lld,\n", (long long)(HASH_ADD_NEXT)); +#endif +#ifdef HT_MIN_MASK + fprintf(constants, " 'HT_MIN_MASK' => %lld,\n", (long long)(HT_MIN_MASK)); +#endif +#ifdef HT_MIN_SIZE + fprintf(constants, " 'HT_MIN_SIZE' => %lld,\n", (long long)(HT_MIN_SIZE)); +#endif +#ifdef ZEND_MODULE_API_NO + fprintf(constants, " 'ZEND_MODULE_API_NO' => %lld,\n", (long long)(ZEND_MODULE_API_NO)); +#endif +#ifdef MODULE_PERSISTENT + fprintf(constants, " 'MODULE_PERSISTENT' => %lld,\n", (long long)(MODULE_PERSISTENT)); +#endif +#ifdef MODULE_TEMPORARY + fprintf(constants, " 'MODULE_TEMPORARY' => %lld,\n", (long long)(MODULE_TEMPORARY)); +#endif +#ifdef CONST_CS + fprintf(constants, " 'CONST_CS' => %lld,\n", (long long)(CONST_CS)); +#endif +#ifdef CONST_PERSISTENT + fprintf(constants, " 'CONST_PERSISTENT' => %lld,\n", (long long)(CONST_PERSISTENT)); +#endif +#ifdef CONST_NO_FILE_CACHE + fprintf(constants, " 'CONST_NO_FILE_CACHE' => %lld,\n", (long long)(CONST_NO_FILE_CACHE)); +#endif +#ifdef CONST_DEPRECATED + fprintf(constants, " 'CONST_DEPRECATED' => %lld,\n", (long long)(CONST_DEPRECATED)); +#endif +#ifdef CONST_OWNED + fprintf(constants, " 'CONST_OWNED' => %lld,\n", (long long)(CONST_OWNED)); +#endif +#ifdef CONST_RECURSIVE + fprintf(constants, " 'CONST_RECURSIVE' => %lld,\n", (long long)(CONST_RECURSIVE)); +#endif +#ifdef PHP_USER_CONSTANT + fprintf(constants, " 'PHP_USER_CONSTANT' => %lld,\n", (long long)(PHP_USER_CONSTANT)); +#endif +#ifdef ZEND_DEBUG + fprintf(constants, " 'ZEND_DEBUG' => %lld,\n", (long long)(ZEND_DEBUG)); +#endif +#ifdef ZEND_MM_ALIGNMENT + fprintf(constants, " 'ZEND_MM_ALIGNMENT' => %lld,\n", (long long)(ZEND_MM_ALIGNMENT)); +#endif +#ifdef ZEND_MAX_RESERVED_RESOURCES + fprintf(constants, " 'ZEND_MAX_RESERVED_RESOURCES' => %lld,\n", (long long)(ZEND_MAX_RESERVED_RESOURCES)); +#endif +#ifdef ZEND_INTERNAL_FUNCTION + fprintf(constants, " 'ZEND_INTERNAL_FUNCTION' => %lld,\n", (long long)(ZEND_INTERNAL_FUNCTION)); +#endif +#ifdef ZEND_USER_FUNCTION + fprintf(constants, " 'ZEND_USER_FUNCTION' => %lld,\n", (long long)(ZEND_USER_FUNCTION)); +#endif +#ifdef ZEND_EVAL_CODE + fprintf(constants, " 'ZEND_EVAL_CODE' => %lld,\n", (long long)(ZEND_EVAL_CODE)); +#endif +#ifdef ZEND_COMPILE_EXTENDED_STMT + fprintf(constants, " 'ZEND_COMPILE_EXTENDED_STMT' => %lld,\n", (long long)(ZEND_COMPILE_EXTENDED_STMT)); +#endif +#ifdef ZEND_COMPILE_EXTENDED_FCALL + fprintf(constants, " 'ZEND_COMPILE_EXTENDED_FCALL' => %lld,\n", (long long)(ZEND_COMPILE_EXTENDED_FCALL)); +#endif +#ifdef ZEND_COMPILE_EXTENDED_INFO + fprintf(constants, " 'ZEND_COMPILE_EXTENDED_INFO' => %lld,\n", (long long)(ZEND_COMPILE_EXTENDED_INFO)); +#endif +#ifdef ZEND_COMPILE_HANDLE_OP_ARRAY + fprintf(constants, " 'ZEND_COMPILE_HANDLE_OP_ARRAY' => %lld,\n", (long long)(ZEND_COMPILE_HANDLE_OP_ARRAY)); +#endif +#ifdef ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS + fprintf(constants, " 'ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS' => %lld,\n", (long long)(ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS)); +#endif +#ifdef ZEND_COMPILE_DELAYED_BINDING + fprintf(constants, " 'ZEND_COMPILE_DELAYED_BINDING' => %lld,\n", (long long)(ZEND_COMPILE_DELAYED_BINDING)); +#endif +#ifdef ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION + fprintf(constants, " 'ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION' => %lld,\n", (long long)(ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)); +#endif +#ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES + fprintf(constants, " 'ZEND_COMPILE_IGNORE_INTERNAL_CLASSES' => %lld,\n", (long long)(ZEND_COMPILE_IGNORE_INTERNAL_CLASSES)); +#endif +#ifdef ZEND_COMPILE_IGNORE_USER_FUNCTIONS + fprintf(constants, " 'ZEND_COMPILE_IGNORE_USER_FUNCTIONS' => %lld,\n", (long long)(ZEND_COMPILE_IGNORE_USER_FUNCTIONS)); +#endif +#ifdef ZEND_COMPILE_GUARDS + fprintf(constants, " 'ZEND_COMPILE_GUARDS' => %lld,\n", (long long)(ZEND_COMPILE_GUARDS)); +#endif +#ifdef ZEND_COMPILE_NO_BUILTINS + fprintf(constants, " 'ZEND_COMPILE_NO_BUILTINS' => %lld,\n", (long long)(ZEND_COMPILE_NO_BUILTINS)); +#endif +#ifdef ZEND_COMPILE_NO_JUMPTABLES + fprintf(constants, " 'ZEND_COMPILE_NO_JUMPTABLES' => %lld,\n", (long long)(ZEND_COMPILE_NO_JUMPTABLES)); +#endif +#ifdef ZEND_COMPILE_PRELOAD + fprintf(constants, " 'ZEND_COMPILE_PRELOAD' => %lld,\n", (long long)(ZEND_COMPILE_PRELOAD)); +#endif +#ifdef ZEND_COMPILE_PRELOAD_IN_CHILD + fprintf(constants, " 'ZEND_COMPILE_PRELOAD_IN_CHILD' => %lld,\n", (long long)(ZEND_COMPILE_PRELOAD_IN_CHILD)); +#endif +#ifdef ZEND_COMPILE_WITHOUT_EXECUTION + fprintf(constants, " 'ZEND_COMPILE_WITHOUT_EXECUTION' => %lld,\n", (long long)(ZEND_COMPILE_WITHOUT_EXECUTION)); +#endif +#ifdef ZEND_CALL_FUNCTION + fprintf(constants, " 'ZEND_CALL_FUNCTION' => %lld,\n", (long long)(ZEND_CALL_FUNCTION)); +#endif +#ifdef ZEND_CALL_CODE + fprintf(constants, " 'ZEND_CALL_CODE' => %lld,\n", (long long)(ZEND_CALL_CODE)); +#endif +#ifdef ZEND_CALL_NESTED + fprintf(constants, " 'ZEND_CALL_NESTED' => %lld,\n", (long long)(ZEND_CALL_NESTED)); +#endif +#ifdef ZEND_CALL_TOP + fprintf(constants, " 'ZEND_CALL_TOP' => %lld,\n", (long long)(ZEND_CALL_TOP)); +#endif +#ifdef ZEND_CALL_HAS_THIS + fprintf(constants, " 'ZEND_CALL_HAS_THIS' => %lld,\n", (long long)(ZEND_CALL_HAS_THIS)); +#endif +#ifdef ZEND_CALL_FAKE_CLOSURE + fprintf(constants, " 'ZEND_CALL_FAKE_CLOSURE' => %lld,\n", (long long)(ZEND_CALL_FAKE_CLOSURE)); +#endif +#ifdef ZEND_CALL_CLOSURE + fprintf(constants, " 'ZEND_CALL_CLOSURE' => %lld,\n", (long long)(ZEND_CALL_CLOSURE)); +#endif +#ifdef ZEND_ATTRIBUTE_TARGET_CLASS + fprintf(constants, " 'ZEND_ATTRIBUTE_TARGET_CLASS' => %lld,\n", (long long)(ZEND_ATTRIBUTE_TARGET_CLASS)); +#endif +#ifdef ZEND_ATTRIBUTE_TARGET_FUNCTION + fprintf(constants, " 'ZEND_ATTRIBUTE_TARGET_FUNCTION' => %lld,\n", (long long)(ZEND_ATTRIBUTE_TARGET_FUNCTION)); +#endif +#ifdef ZEND_ATTRIBUTE_TARGET_METHOD + fprintf(constants, " 'ZEND_ATTRIBUTE_TARGET_METHOD' => %lld,\n", (long long)(ZEND_ATTRIBUTE_TARGET_METHOD)); +#endif +#ifdef ZEND_ATTRIBUTE_TARGET_PROPERTY + fprintf(constants, " 'ZEND_ATTRIBUTE_TARGET_PROPERTY' => %lld,\n", (long long)(ZEND_ATTRIBUTE_TARGET_PROPERTY)); +#endif +#ifdef ZEND_ATTRIBUTE_TARGET_CLASS_CONST + fprintf(constants, " 'ZEND_ATTRIBUTE_TARGET_CLASS_CONST' => %lld,\n", (long long)(ZEND_ATTRIBUTE_TARGET_CLASS_CONST)); +#endif +#ifdef ZEND_ATTRIBUTE_TARGET_PARAMETER + fprintf(constants, " 'ZEND_ATTRIBUTE_TARGET_PARAMETER' => %lld,\n", (long long)(ZEND_ATTRIBUTE_TARGET_PARAMETER)); +#endif +#ifdef ZEND_ATTRIBUTE_TARGET_CONST + fprintf(constants, " 'ZEND_ATTRIBUTE_TARGET_CONST' => %lld,\n", (long long)(ZEND_ATTRIBUTE_TARGET_CONST)); +#endif +#ifdef ZEND_ATTRIBUTE_TARGET_ALL + fprintf(constants, " 'ZEND_ATTRIBUTE_TARGET_ALL' => %lld,\n", (long long)(ZEND_ATTRIBUTE_TARGET_ALL)); +#endif +#ifdef ZEND_ATTRIBUTE_IS_REPEATABLE + fprintf(constants, " 'ZEND_ATTRIBUTE_IS_REPEATABLE' => %lld,\n", (long long)(ZEND_ATTRIBUTE_IS_REPEATABLE)); +#endif +#ifdef ZEND_ATTRIBUTE_FLAGS + fprintf(constants, " 'ZEND_ATTRIBUTE_FLAGS' => %lld,\n", (long long)(ZEND_ATTRIBUTE_FLAGS)); +#endif + fprintf(constants, " 'ZEND_AST_ZVAL' => %lld,\n", (long long)(ZEND_AST_ZVAL)); + fprintf(constants, " 'ZEND_AST_CONSTANT' => %lld,\n", (long long)(ZEND_AST_CONSTANT)); + fprintf(constants, " 'ZEND_AST_OP_ARRAY' => %lld,\n", (long long)(ZEND_AST_OP_ARRAY)); + fprintf(constants, " 'ZEND_AST_ZNODE' => %lld,\n", (long long)(ZEND_AST_ZNODE)); + fprintf(constants, " 'ZEND_AST_FUNC_DECL' => %lld,\n", (long long)(ZEND_AST_FUNC_DECL)); + fprintf(constants, " 'ZEND_AST_CLOSURE' => %lld,\n", (long long)(ZEND_AST_CLOSURE)); + fprintf(constants, " 'ZEND_AST_METHOD' => %lld,\n", (long long)(ZEND_AST_METHOD)); + fprintf(constants, " 'ZEND_AST_CLASS' => %lld,\n", (long long)(ZEND_AST_CLASS)); + fprintf(constants, " 'ZEND_AST_ARROW_FUNC' => %lld,\n", (long long)(ZEND_AST_ARROW_FUNC)); + fprintf(constants, " 'ZEND_AST_PROPERTY_HOOK' => %lld,\n", (long long)(ZEND_AST_PROPERTY_HOOK)); + fprintf(constants, " 'ZEND_AST_ARG_LIST' => %lld,\n", (long long)(ZEND_AST_ARG_LIST)); + fprintf(constants, " 'ZEND_AST_ARRAY' => %lld,\n", (long long)(ZEND_AST_ARRAY)); + fprintf(constants, " 'ZEND_AST_ENCAPS_LIST' => %lld,\n", (long long)(ZEND_AST_ENCAPS_LIST)); + fprintf(constants, " 'ZEND_AST_EXPR_LIST' => %lld,\n", (long long)(ZEND_AST_EXPR_LIST)); + fprintf(constants, " 'ZEND_AST_STMT_LIST' => %lld,\n", (long long)(ZEND_AST_STMT_LIST)); + fprintf(constants, " 'ZEND_AST_IF' => %lld,\n", (long long)(ZEND_AST_IF)); + fprintf(constants, " 'ZEND_AST_SWITCH_LIST' => %lld,\n", (long long)(ZEND_AST_SWITCH_LIST)); + fprintf(constants, " 'ZEND_AST_CATCH_LIST' => %lld,\n", (long long)(ZEND_AST_CATCH_LIST)); + fprintf(constants, " 'ZEND_AST_PARAM_LIST' => %lld,\n", (long long)(ZEND_AST_PARAM_LIST)); + fprintf(constants, " 'ZEND_AST_CLOSURE_USES' => %lld,\n", (long long)(ZEND_AST_CLOSURE_USES)); + fprintf(constants, " 'ZEND_AST_PROP_DECL' => %lld,\n", (long long)(ZEND_AST_PROP_DECL)); + fprintf(constants, " 'ZEND_AST_CONST_DECL' => %lld,\n", (long long)(ZEND_AST_CONST_DECL)); + fprintf(constants, " 'ZEND_AST_CLASS_CONST_DECL' => %lld,\n", (long long)(ZEND_AST_CLASS_CONST_DECL)); + fprintf(constants, " 'ZEND_AST_NAME_LIST' => %lld,\n", (long long)(ZEND_AST_NAME_LIST)); + fprintf(constants, " 'ZEND_AST_TRAIT_ADAPTATIONS' => %lld,\n", (long long)(ZEND_AST_TRAIT_ADAPTATIONS)); + fprintf(constants, " 'ZEND_AST_USE' => %lld,\n", (long long)(ZEND_AST_USE)); + fprintf(constants, " 'ZEND_AST_TYPE_UNION' => %lld,\n", (long long)(ZEND_AST_TYPE_UNION)); + fprintf(constants, " 'ZEND_AST_TYPE_INTERSECTION' => %lld,\n", (long long)(ZEND_AST_TYPE_INTERSECTION)); + fprintf(constants, " 'ZEND_AST_ATTRIBUTE_LIST' => %lld,\n", (long long)(ZEND_AST_ATTRIBUTE_LIST)); + fprintf(constants, " 'ZEND_AST_ATTRIBUTE_GROUP' => %lld,\n", (long long)(ZEND_AST_ATTRIBUTE_GROUP)); + fprintf(constants, " 'ZEND_AST_MATCH_ARM_LIST' => %lld,\n", (long long)(ZEND_AST_MATCH_ARM_LIST)); + fprintf(constants, " 'ZEND_AST_MODIFIER_LIST' => %lld,\n", (long long)(ZEND_AST_MODIFIER_LIST)); + fprintf(constants, " 'ZEND_AST_MAGIC_CONST' => %lld,\n", (long long)(ZEND_AST_MAGIC_CONST)); + fprintf(constants, " 'ZEND_AST_TYPE' => %lld,\n", (long long)(ZEND_AST_TYPE)); + fprintf(constants, " 'ZEND_AST_CONSTANT_CLASS' => %lld,\n", (long long)(ZEND_AST_CONSTANT_CLASS)); + fprintf(constants, " 'ZEND_AST_CALLABLE_CONVERT' => %lld,\n", (long long)(ZEND_AST_CALLABLE_CONVERT)); + fprintf(constants, " 'ZEND_AST_VAR' => %lld,\n", (long long)(ZEND_AST_VAR)); + fprintf(constants, " 'ZEND_AST_CONST' => %lld,\n", (long long)(ZEND_AST_CONST)); + fprintf(constants, " 'ZEND_AST_UNPACK' => %lld,\n", (long long)(ZEND_AST_UNPACK)); + fprintf(constants, " 'ZEND_AST_UNARY_PLUS' => %lld,\n", (long long)(ZEND_AST_UNARY_PLUS)); + fprintf(constants, " 'ZEND_AST_UNARY_MINUS' => %lld,\n", (long long)(ZEND_AST_UNARY_MINUS)); + fprintf(constants, " 'ZEND_AST_CAST' => %lld,\n", (long long)(ZEND_AST_CAST)); + fprintf(constants, " 'ZEND_AST_CAST_VOID' => %lld,\n", (long long)(ZEND_AST_CAST_VOID)); + fprintf(constants, " 'ZEND_AST_EMPTY' => %lld,\n", (long long)(ZEND_AST_EMPTY)); + fprintf(constants, " 'ZEND_AST_ISSET' => %lld,\n", (long long)(ZEND_AST_ISSET)); + fprintf(constants, " 'ZEND_AST_SILENCE' => %lld,\n", (long long)(ZEND_AST_SILENCE)); + fprintf(constants, " 'ZEND_AST_SHELL_EXEC' => %lld,\n", (long long)(ZEND_AST_SHELL_EXEC)); + fprintf(constants, " 'ZEND_AST_PRINT' => %lld,\n", (long long)(ZEND_AST_PRINT)); + fprintf(constants, " 'ZEND_AST_INCLUDE_OR_EVAL' => %lld,\n", (long long)(ZEND_AST_INCLUDE_OR_EVAL)); + fprintf(constants, " 'ZEND_AST_UNARY_OP' => %lld,\n", (long long)(ZEND_AST_UNARY_OP)); + fprintf(constants, " 'ZEND_AST_PRE_INC' => %lld,\n", (long long)(ZEND_AST_PRE_INC)); + fprintf(constants, " 'ZEND_AST_PRE_DEC' => %lld,\n", (long long)(ZEND_AST_PRE_DEC)); + fprintf(constants, " 'ZEND_AST_POST_INC' => %lld,\n", (long long)(ZEND_AST_POST_INC)); + fprintf(constants, " 'ZEND_AST_POST_DEC' => %lld,\n", (long long)(ZEND_AST_POST_DEC)); + fprintf(constants, " 'ZEND_AST_YIELD_FROM' => %lld,\n", (long long)(ZEND_AST_YIELD_FROM)); + fprintf(constants, " 'ZEND_AST_CLASS_NAME' => %lld,\n", (long long)(ZEND_AST_CLASS_NAME)); + fprintf(constants, " 'ZEND_AST_GLOBAL' => %lld,\n", (long long)(ZEND_AST_GLOBAL)); + fprintf(constants, " 'ZEND_AST_UNSET' => %lld,\n", (long long)(ZEND_AST_UNSET)); + fprintf(constants, " 'ZEND_AST_RETURN' => %lld,\n", (long long)(ZEND_AST_RETURN)); + fprintf(constants, " 'ZEND_AST_LABEL' => %lld,\n", (long long)(ZEND_AST_LABEL)); + fprintf(constants, " 'ZEND_AST_REF' => %lld,\n", (long long)(ZEND_AST_REF)); + fprintf(constants, " 'ZEND_AST_HALT_COMPILER' => %lld,\n", (long long)(ZEND_AST_HALT_COMPILER)); + fprintf(constants, " 'ZEND_AST_ECHO' => %lld,\n", (long long)(ZEND_AST_ECHO)); + fprintf(constants, " 'ZEND_AST_THROW' => %lld,\n", (long long)(ZEND_AST_THROW)); + fprintf(constants, " 'ZEND_AST_GOTO' => %lld,\n", (long long)(ZEND_AST_GOTO)); + fprintf(constants, " 'ZEND_AST_BREAK' => %lld,\n", (long long)(ZEND_AST_BREAK)); + fprintf(constants, " 'ZEND_AST_CONTINUE' => %lld,\n", (long long)(ZEND_AST_CONTINUE)); + fprintf(constants, " 'ZEND_AST_PROPERTY_HOOK_SHORT_BODY' => %lld,\n", (long long)(ZEND_AST_PROPERTY_HOOK_SHORT_BODY)); + fprintf(constants, " 'ZEND_AST_DIM' => %lld,\n", (long long)(ZEND_AST_DIM)); + fprintf(constants, " 'ZEND_AST_PROP' => %lld,\n", (long long)(ZEND_AST_PROP)); + fprintf(constants, " 'ZEND_AST_NULLSAFE_PROP' => %lld,\n", (long long)(ZEND_AST_NULLSAFE_PROP)); + fprintf(constants, " 'ZEND_AST_STATIC_PROP' => %lld,\n", (long long)(ZEND_AST_STATIC_PROP)); + fprintf(constants, " 'ZEND_AST_CALL' => %lld,\n", (long long)(ZEND_AST_CALL)); + fprintf(constants, " 'ZEND_AST_CLASS_CONST' => %lld,\n", (long long)(ZEND_AST_CLASS_CONST)); + fprintf(constants, " 'ZEND_AST_ASSIGN' => %lld,\n", (long long)(ZEND_AST_ASSIGN)); + fprintf(constants, " 'ZEND_AST_ASSIGN_REF' => %lld,\n", (long long)(ZEND_AST_ASSIGN_REF)); + fprintf(constants, " 'ZEND_AST_ASSIGN_OP' => %lld,\n", (long long)(ZEND_AST_ASSIGN_OP)); + fprintf(constants, " 'ZEND_AST_BINARY_OP' => %lld,\n", (long long)(ZEND_AST_BINARY_OP)); + fprintf(constants, " 'ZEND_AST_GREATER' => %lld,\n", (long long)(ZEND_AST_GREATER)); + fprintf(constants, " 'ZEND_AST_GREATER_EQUAL' => %lld,\n", (long long)(ZEND_AST_GREATER_EQUAL)); + fprintf(constants, " 'ZEND_AST_AND' => %lld,\n", (long long)(ZEND_AST_AND)); + fprintf(constants, " 'ZEND_AST_OR' => %lld,\n", (long long)(ZEND_AST_OR)); + fprintf(constants, " 'ZEND_AST_ARRAY_ELEM' => %lld,\n", (long long)(ZEND_AST_ARRAY_ELEM)); + fprintf(constants, " 'ZEND_AST_NEW' => %lld,\n", (long long)(ZEND_AST_NEW)); + fprintf(constants, " 'ZEND_AST_INSTANCEOF' => %lld,\n", (long long)(ZEND_AST_INSTANCEOF)); + fprintf(constants, " 'ZEND_AST_YIELD' => %lld,\n", (long long)(ZEND_AST_YIELD)); + fprintf(constants, " 'ZEND_AST_COALESCE' => %lld,\n", (long long)(ZEND_AST_COALESCE)); + fprintf(constants, " 'ZEND_AST_ASSIGN_COALESCE' => %lld,\n", (long long)(ZEND_AST_ASSIGN_COALESCE)); + fprintf(constants, " 'ZEND_AST_STATIC' => %lld,\n", (long long)(ZEND_AST_STATIC)); + fprintf(constants, " 'ZEND_AST_WHILE' => %lld,\n", (long long)(ZEND_AST_WHILE)); + fprintf(constants, " 'ZEND_AST_DO_WHILE' => %lld,\n", (long long)(ZEND_AST_DO_WHILE)); + fprintf(constants, " 'ZEND_AST_IF_ELEM' => %lld,\n", (long long)(ZEND_AST_IF_ELEM)); + fprintf(constants, " 'ZEND_AST_SWITCH' => %lld,\n", (long long)(ZEND_AST_SWITCH)); + fprintf(constants, " 'ZEND_AST_SWITCH_CASE' => %lld,\n", (long long)(ZEND_AST_SWITCH_CASE)); + fprintf(constants, " 'ZEND_AST_DECLARE' => %lld,\n", (long long)(ZEND_AST_DECLARE)); + fprintf(constants, " 'ZEND_AST_USE_TRAIT' => %lld,\n", (long long)(ZEND_AST_USE_TRAIT)); + fprintf(constants, " 'ZEND_AST_TRAIT_PRECEDENCE' => %lld,\n", (long long)(ZEND_AST_TRAIT_PRECEDENCE)); + fprintf(constants, " 'ZEND_AST_METHOD_REFERENCE' => %lld,\n", (long long)(ZEND_AST_METHOD_REFERENCE)); + fprintf(constants, " 'ZEND_AST_NAMESPACE' => %lld,\n", (long long)(ZEND_AST_NAMESPACE)); + fprintf(constants, " 'ZEND_AST_USE_ELEM' => %lld,\n", (long long)(ZEND_AST_USE_ELEM)); + fprintf(constants, " 'ZEND_AST_TRAIT_ALIAS' => %lld,\n", (long long)(ZEND_AST_TRAIT_ALIAS)); + fprintf(constants, " 'ZEND_AST_GROUP_USE' => %lld,\n", (long long)(ZEND_AST_GROUP_USE)); + fprintf(constants, " 'ZEND_AST_ATTRIBUTE' => %lld,\n", (long long)(ZEND_AST_ATTRIBUTE)); + fprintf(constants, " 'ZEND_AST_MATCH' => %lld,\n", (long long)(ZEND_AST_MATCH)); + fprintf(constants, " 'ZEND_AST_MATCH_ARM' => %lld,\n", (long long)(ZEND_AST_MATCH_ARM)); + fprintf(constants, " 'ZEND_AST_NAMED_ARG' => %lld,\n", (long long)(ZEND_AST_NAMED_ARG)); + fprintf(constants, " 'ZEND_AST_PARENT_PROPERTY_HOOK_CALL' => %lld,\n", (long long)(ZEND_AST_PARENT_PROPERTY_HOOK_CALL)); + fprintf(constants, " 'ZEND_AST_PIPE' => %lld,\n", (long long)(ZEND_AST_PIPE)); + fprintf(constants, " 'ZEND_AST_METHOD_CALL' => %lld,\n", (long long)(ZEND_AST_METHOD_CALL)); + fprintf(constants, " 'ZEND_AST_NULLSAFE_METHOD_CALL' => %lld,\n", (long long)(ZEND_AST_NULLSAFE_METHOD_CALL)); + fprintf(constants, " 'ZEND_AST_STATIC_CALL' => %lld,\n", (long long)(ZEND_AST_STATIC_CALL)); + fprintf(constants, " 'ZEND_AST_CONDITIONAL' => %lld,\n", (long long)(ZEND_AST_CONDITIONAL)); + fprintf(constants, " 'ZEND_AST_TRY' => %lld,\n", (long long)(ZEND_AST_TRY)); + fprintf(constants, " 'ZEND_AST_CATCH' => %lld,\n", (long long)(ZEND_AST_CATCH)); + fprintf(constants, " 'ZEND_AST_PROP_GROUP' => %lld,\n", (long long)(ZEND_AST_PROP_GROUP)); + fprintf(constants, " 'ZEND_AST_CONST_ELEM' => %lld,\n", (long long)(ZEND_AST_CONST_ELEM)); + fprintf(constants, " 'ZEND_AST_CLASS_CONST_GROUP' => %lld,\n", (long long)(ZEND_AST_CLASS_CONST_GROUP)); + fprintf(constants, " 'ZEND_AST_CONST_ENUM_INIT' => %lld,\n", (long long)(ZEND_AST_CONST_ENUM_INIT)); + fprintf(constants, " 'ZEND_AST_FOR' => %lld,\n", (long long)(ZEND_AST_FOR)); + fprintf(constants, " 'ZEND_AST_FOREACH' => %lld,\n", (long long)(ZEND_AST_FOREACH)); + fprintf(constants, " 'ZEND_AST_ENUM_CASE' => %lld,\n", (long long)(ZEND_AST_ENUM_CASE)); + fprintf(constants, " 'ZEND_AST_PROP_ELEM' => %lld,\n", (long long)(ZEND_AST_PROP_ELEM)); + fprintf(constants, " 'ZEND_AST_PARAM' => %lld,\n", (long long)(ZEND_AST_PARAM)); + fprintf(constants, " 'ZEND_PROPERTY_HOOK_GET' => %lld,\n", (long long)(ZEND_PROPERTY_HOOK_GET)); + fprintf(constants, " 'ZEND_PROPERTY_HOOK_SET' => %lld,\n", (long long)(ZEND_PROPERTY_HOOK_SET)); + fprintf(constants, " 'ZEND_NOP' => 0,\n"); + fprintf(constants, " 'ZEND_ADD' => 1,\n"); + fprintf(constants, " 'ZEND_SUB' => 2,\n"); + fprintf(constants, " 'ZEND_MUL' => 3,\n"); + fprintf(constants, " 'ZEND_DIV' => 4,\n"); + fprintf(constants, " 'ZEND_MOD' => 5,\n"); + fprintf(constants, " 'ZEND_SL' => 6,\n"); + fprintf(constants, " 'ZEND_SR' => 7,\n"); + fprintf(constants, " 'ZEND_CONCAT' => 8,\n"); + fprintf(constants, " 'ZEND_BW_OR' => 9,\n"); + fprintf(constants, " 'ZEND_BW_AND' => 10,\n"); + fprintf(constants, " 'ZEND_BW_XOR' => 11,\n"); + fprintf(constants, " 'ZEND_POW' => 12,\n"); + fprintf(constants, " 'ZEND_BW_NOT' => 13,\n"); + fprintf(constants, " 'ZEND_BOOL_NOT' => 14,\n"); + fprintf(constants, " 'ZEND_BOOL_XOR' => 15,\n"); + fprintf(constants, " 'ZEND_IS_IDENTICAL' => 16,\n"); + fprintf(constants, " 'ZEND_IS_NOT_IDENTICAL' => 17,\n"); + fprintf(constants, " 'ZEND_IS_EQUAL' => 18,\n"); + fprintf(constants, " 'ZEND_IS_NOT_EQUAL' => 19,\n"); + fprintf(constants, " 'ZEND_IS_SMALLER' => 20,\n"); + fprintf(constants, " 'ZEND_IS_SMALLER_OR_EQUAL' => 21,\n"); + fprintf(constants, " 'ZEND_ASSIGN' => 22,\n"); + fprintf(constants, " 'ZEND_ASSIGN_DIM' => 23,\n"); + fprintf(constants, " 'ZEND_ASSIGN_OBJ' => 24,\n"); + fprintf(constants, " 'ZEND_ASSIGN_STATIC_PROP' => 25,\n"); + fprintf(constants, " 'ZEND_ASSIGN_OP' => 26,\n"); + fprintf(constants, " 'ZEND_ASSIGN_DIM_OP' => 27,\n"); + fprintf(constants, " 'ZEND_ASSIGN_OBJ_OP' => 28,\n"); + fprintf(constants, " 'ZEND_ASSIGN_STATIC_PROP_OP' => 29,\n"); + fprintf(constants, " 'ZEND_ASSIGN_REF' => 30,\n"); + fprintf(constants, " 'ZEND_QM_ASSIGN' => 31,\n"); + fprintf(constants, " 'ZEND_ASSIGN_OBJ_REF' => 32,\n"); + fprintf(constants, " 'ZEND_ASSIGN_STATIC_PROP_REF' => 33,\n"); + fprintf(constants, " 'ZEND_PRE_INC' => 34,\n"); + fprintf(constants, " 'ZEND_PRE_DEC' => 35,\n"); + fprintf(constants, " 'ZEND_POST_INC' => 36,\n"); + fprintf(constants, " 'ZEND_POST_DEC' => 37,\n"); + fprintf(constants, " 'ZEND_PRE_INC_STATIC_PROP' => 38,\n"); + fprintf(constants, " 'ZEND_PRE_DEC_STATIC_PROP' => 39,\n"); + fprintf(constants, " 'ZEND_POST_INC_STATIC_PROP' => 40,\n"); + fprintf(constants, " 'ZEND_POST_DEC_STATIC_PROP' => 41,\n"); + fprintf(constants, " 'ZEND_JMP' => 42,\n"); + fprintf(constants, " 'ZEND_JMPZ' => 43,\n"); + fprintf(constants, " 'ZEND_JMPNZ' => 44,\n"); + fprintf(constants, " 'ZEND_JMPZ_EX' => 46,\n"); + fprintf(constants, " 'ZEND_JMPNZ_EX' => 47,\n"); + fprintf(constants, " 'ZEND_CASE' => 48,\n"); + fprintf(constants, " 'ZEND_CHECK_VAR' => 49,\n"); + fprintf(constants, " 'ZEND_SEND_VAR_NO_REF_EX' => 50,\n"); + fprintf(constants, " 'ZEND_CAST' => 51,\n"); + fprintf(constants, " 'ZEND_BOOL' => 52,\n"); + fprintf(constants, " 'ZEND_FAST_CONCAT' => 53,\n"); + fprintf(constants, " 'ZEND_ROPE_INIT' => 54,\n"); + fprintf(constants, " 'ZEND_ROPE_ADD' => 55,\n"); + fprintf(constants, " 'ZEND_ROPE_END' => 56,\n"); + fprintf(constants, " 'ZEND_BEGIN_SILENCE' => 57,\n"); + fprintf(constants, " 'ZEND_END_SILENCE' => 58,\n"); + fprintf(constants, " 'ZEND_INIT_FCALL_BY_NAME' => 59,\n"); + fprintf(constants, " 'ZEND_DO_FCALL' => 60,\n"); + fprintf(constants, " 'ZEND_INIT_FCALL' => 61,\n"); + fprintf(constants, " 'ZEND_RETURN' => 62,\n"); + fprintf(constants, " 'ZEND_RECV' => 63,\n"); + fprintf(constants, " 'ZEND_RECV_INIT' => 64,\n"); + fprintf(constants, " 'ZEND_SEND_VAL' => 65,\n"); + fprintf(constants, " 'ZEND_SEND_VAR_EX' => 66,\n"); + fprintf(constants, " 'ZEND_SEND_REF' => 67,\n"); + fprintf(constants, " 'ZEND_NEW' => 68,\n"); + fprintf(constants, " 'ZEND_INIT_NS_FCALL_BY_NAME' => 69,\n"); + fprintf(constants, " 'ZEND_FREE' => 70,\n"); + fprintf(constants, " 'ZEND_INIT_ARRAY' => 71,\n"); + fprintf(constants, " 'ZEND_ADD_ARRAY_ELEMENT' => 72,\n"); + fprintf(constants, " 'ZEND_INCLUDE_OR_EVAL' => 73,\n"); + fprintf(constants, " 'ZEND_UNSET_VAR' => 74,\n"); + fprintf(constants, " 'ZEND_UNSET_DIM' => 75,\n"); + fprintf(constants, " 'ZEND_UNSET_OBJ' => 76,\n"); + fprintf(constants, " 'ZEND_FE_RESET_R' => 77,\n"); + fprintf(constants, " 'ZEND_FE_FETCH_R' => 78,\n"); + fprintf(constants, " 'ZEND_FETCH_R' => 80,\n"); + fprintf(constants, " 'ZEND_FETCH_DIM_R' => 81,\n"); + fprintf(constants, " 'ZEND_FETCH_OBJ_R' => 82,\n"); + fprintf(constants, " 'ZEND_FETCH_W' => 83,\n"); + fprintf(constants, " 'ZEND_FETCH_DIM_W' => 84,\n"); + fprintf(constants, " 'ZEND_FETCH_OBJ_W' => 85,\n"); + fprintf(constants, " 'ZEND_FETCH_RW' => 86,\n"); + fprintf(constants, " 'ZEND_FETCH_DIM_RW' => 87,\n"); + fprintf(constants, " 'ZEND_FETCH_OBJ_RW' => 88,\n"); + fprintf(constants, " 'ZEND_FETCH_IS' => 89,\n"); + fprintf(constants, " 'ZEND_FETCH_DIM_IS' => 90,\n"); + fprintf(constants, " 'ZEND_FETCH_OBJ_IS' => 91,\n"); + fprintf(constants, " 'ZEND_FETCH_FUNC_ARG' => 92,\n"); + fprintf(constants, " 'ZEND_FETCH_DIM_FUNC_ARG' => 93,\n"); + fprintf(constants, " 'ZEND_FETCH_OBJ_FUNC_ARG' => 94,\n"); + fprintf(constants, " 'ZEND_FETCH_UNSET' => 95,\n"); + fprintf(constants, " 'ZEND_FETCH_DIM_UNSET' => 96,\n"); + fprintf(constants, " 'ZEND_FETCH_OBJ_UNSET' => 97,\n"); + fprintf(constants, " 'ZEND_FETCH_LIST_R' => 98,\n"); + fprintf(constants, " 'ZEND_FETCH_CONSTANT' => 99,\n"); + fprintf(constants, " 'ZEND_CHECK_FUNC_ARG' => 100,\n"); + fprintf(constants, " 'ZEND_EXT_STMT' => 101,\n"); + fprintf(constants, " 'ZEND_EXT_FCALL_BEGIN' => 102,\n"); + fprintf(constants, " 'ZEND_EXT_FCALL_END' => 103,\n"); + fprintf(constants, " 'ZEND_EXT_NOP' => 104,\n"); + fprintf(constants, " 'ZEND_TICKS' => 105,\n"); + fprintf(constants, " 'ZEND_SEND_VAR_NO_REF' => 106,\n"); + fprintf(constants, " 'ZEND_CATCH' => 107,\n"); + fprintf(constants, " 'ZEND_THROW' => 108,\n"); + fprintf(constants, " 'ZEND_FETCH_CLASS' => 109,\n"); + fprintf(constants, " 'ZEND_CLONE' => 110,\n"); + fprintf(constants, " 'ZEND_RETURN_BY_REF' => 111,\n"); + fprintf(constants, " 'ZEND_INIT_METHOD_CALL' => 112,\n"); + fprintf(constants, " 'ZEND_INIT_STATIC_METHOD_CALL' => 113,\n"); + fprintf(constants, " 'ZEND_ISSET_ISEMPTY_VAR' => 114,\n"); + fprintf(constants, " 'ZEND_ISSET_ISEMPTY_DIM_OBJ' => 115,\n"); + fprintf(constants, " 'ZEND_SEND_VAL_EX' => 116,\n"); + fprintf(constants, " 'ZEND_SEND_VAR' => 117,\n"); + fprintf(constants, " 'ZEND_INIT_USER_CALL' => 118,\n"); + fprintf(constants, " 'ZEND_SEND_ARRAY' => 119,\n"); + fprintf(constants, " 'ZEND_SEND_USER' => 120,\n"); + fprintf(constants, " 'ZEND_STRLEN' => 121,\n"); + fprintf(constants, " 'ZEND_DEFINED' => 122,\n"); + fprintf(constants, " 'ZEND_TYPE_CHECK' => 123,\n"); + fprintf(constants, " 'ZEND_VERIFY_RETURN_TYPE' => 124,\n"); + fprintf(constants, " 'ZEND_FE_RESET_RW' => 125,\n"); + fprintf(constants, " 'ZEND_FE_FETCH_RW' => 126,\n"); + fprintf(constants, " 'ZEND_FE_FREE' => 127,\n"); + fprintf(constants, " 'ZEND_INIT_DYNAMIC_CALL' => 128,\n"); + fprintf(constants, " 'ZEND_DO_ICALL' => 129,\n"); + fprintf(constants, " 'ZEND_DO_UCALL' => 130,\n"); + fprintf(constants, " 'ZEND_DO_FCALL_BY_NAME' => 131,\n"); + fprintf(constants, " 'ZEND_PRE_INC_OBJ' => 132,\n"); + fprintf(constants, " 'ZEND_PRE_DEC_OBJ' => 133,\n"); + fprintf(constants, " 'ZEND_POST_INC_OBJ' => 134,\n"); + fprintf(constants, " 'ZEND_POST_DEC_OBJ' => 135,\n"); + fprintf(constants, " 'ZEND_ECHO' => 136,\n"); + fprintf(constants, " 'ZEND_OP_DATA' => 137,\n"); + fprintf(constants, " 'ZEND_INSTANCEOF' => 138,\n"); + fprintf(constants, " 'ZEND_GENERATOR_CREATE' => 139,\n"); + fprintf(constants, " 'ZEND_MAKE_REF' => 140,\n"); + fprintf(constants, " 'ZEND_DECLARE_FUNCTION' => 141,\n"); + fprintf(constants, " 'ZEND_DECLARE_LAMBDA_FUNCTION' => 142,\n"); + fprintf(constants, " 'ZEND_DECLARE_CONST' => 143,\n"); + fprintf(constants, " 'ZEND_DECLARE_CLASS' => 144,\n"); + fprintf(constants, " 'ZEND_DECLARE_CLASS_DELAYED' => 145,\n"); + fprintf(constants, " 'ZEND_DECLARE_ANON_CLASS' => 146,\n"); + fprintf(constants, " 'ZEND_ADD_ARRAY_UNPACK' => 147,\n"); + fprintf(constants, " 'ZEND_ISSET_ISEMPTY_PROP_OBJ' => 148,\n"); + fprintf(constants, " 'ZEND_HANDLE_EXCEPTION' => 149,\n"); + fprintf(constants, " 'ZEND_USER_OPCODE' => 150,\n"); + fprintf(constants, " 'ZEND_ASSERT_CHECK' => 151,\n"); + fprintf(constants, " 'ZEND_JMP_SET' => 152,\n"); + fprintf(constants, " 'ZEND_UNSET_CV' => 153,\n"); + fprintf(constants, " 'ZEND_ISSET_ISEMPTY_CV' => 154,\n"); + fprintf(constants, " 'ZEND_FETCH_LIST_W' => 155,\n"); + fprintf(constants, " 'ZEND_SEPARATE' => 156,\n"); + fprintf(constants, " 'ZEND_FETCH_CLASS_NAME' => 157,\n"); + fprintf(constants, " 'ZEND_CALL_TRAMPOLINE' => 158,\n"); + fprintf(constants, " 'ZEND_DISCARD_EXCEPTION' => 159,\n"); + fprintf(constants, " 'ZEND_YIELD' => 160,\n"); + fprintf(constants, " 'ZEND_GENERATOR_RETURN' => 161,\n"); + fprintf(constants, " 'ZEND_FAST_CALL' => 162,\n"); + fprintf(constants, " 'ZEND_FAST_RET' => 163,\n"); + fprintf(constants, " 'ZEND_RECV_VARIADIC' => 164,\n"); + fprintf(constants, " 'ZEND_SEND_UNPACK' => 165,\n"); + fprintf(constants, " 'ZEND_YIELD_FROM' => 166,\n"); + fprintf(constants, " 'ZEND_COPY_TMP' => 167,\n"); + fprintf(constants, " 'ZEND_BIND_GLOBAL' => 168,\n"); + fprintf(constants, " 'ZEND_COALESCE' => 169,\n"); + fprintf(constants, " 'ZEND_SPACESHIP' => 170,\n"); + fprintf(constants, " 'ZEND_FUNC_NUM_ARGS' => 171,\n"); + fprintf(constants, " 'ZEND_FUNC_GET_ARGS' => 172,\n"); + fprintf(constants, " 'ZEND_FETCH_STATIC_PROP_R' => 173,\n"); + fprintf(constants, " 'ZEND_FETCH_STATIC_PROP_W' => 174,\n"); + fprintf(constants, " 'ZEND_FETCH_STATIC_PROP_RW' => 175,\n"); + fprintf(constants, " 'ZEND_FETCH_STATIC_PROP_IS' => 176,\n"); + fprintf(constants, " 'ZEND_FETCH_STATIC_PROP_FUNC_ARG' => 177,\n"); + fprintf(constants, " 'ZEND_FETCH_STATIC_PROP_UNSET' => 178,\n"); + fprintf(constants, " 'ZEND_UNSET_STATIC_PROP' => 179,\n"); + fprintf(constants, " 'ZEND_ISSET_ISEMPTY_STATIC_PROP' => 180,\n"); + fprintf(constants, " 'ZEND_FETCH_CLASS_CONSTANT' => 181,\n"); + fprintf(constants, " 'ZEND_BIND_LEXICAL' => 182,\n"); + fprintf(constants, " 'ZEND_BIND_STATIC' => 183,\n"); + fprintf(constants, " 'ZEND_FETCH_THIS' => 184,\n"); + fprintf(constants, " 'ZEND_SEND_FUNC_ARG' => 185,\n"); + fprintf(constants, " 'ZEND_ISSET_ISEMPTY_THIS' => 186,\n"); + fprintf(constants, " 'ZEND_SWITCH_LONG' => 187,\n"); + fprintf(constants, " 'ZEND_SWITCH_STRING' => 188,\n"); + fprintf(constants, " 'ZEND_IN_ARRAY' => 189,\n"); + fprintf(constants, " 'ZEND_COUNT' => 190,\n"); + fprintf(constants, " 'ZEND_GET_CLASS' => 191,\n"); + fprintf(constants, " 'ZEND_GET_CALLED_CLASS' => 192,\n"); + fprintf(constants, " 'ZEND_GET_TYPE' => 193,\n"); + fprintf(constants, " 'ZEND_ARRAY_KEY_EXISTS' => 194,\n"); + fprintf(constants, " 'ZEND_MATCH' => 195,\n"); + fprintf(constants, " 'ZEND_CASE_STRICT' => 196,\n"); + fprintf(constants, " 'ZEND_MATCH_ERROR' => 197,\n"); + fprintf(constants, " 'ZEND_JMP_NULL' => 198,\n"); + fprintf(constants, " 'ZEND_CHECK_UNDEF_ARGS' => 199,\n"); + fprintf(constants, " 'ZEND_FETCH_GLOBALS' => 200,\n"); + fprintf(constants, " 'ZEND_VERIFY_NEVER_TYPE' => 201,\n"); + fprintf(constants, " 'ZEND_CALLABLE_CONVERT' => 202,\n"); + fprintf(constants, " 'ZEND_BIND_INIT_STATIC_OR_JMP' => 203,\n"); + fprintf(constants, " 'ZEND_FRAMELESS_ICALL_0' => 204,\n"); + fprintf(constants, " 'ZEND_FRAMELESS_ICALL_1' => 205,\n"); + fprintf(constants, " 'ZEND_FRAMELESS_ICALL_2' => 206,\n"); + fprintf(constants, " 'ZEND_FRAMELESS_ICALL_3' => 207,\n"); + fprintf(constants, " 'ZEND_JMP_FRAMELESS' => 208,\n"); + fprintf(constants, " 'ZEND_INIT_PARENT_PROPERTY_HOOK_CALL' => 209,\n"); + fprintf(constants, " 'ZEND_DECLARE_ATTRIBUTED_CONST' => 210,\n"); + fprintf(constants, " 'ZEND_VM_LAST_OPCODE' => 210,\n"); + fputs("];\n", constants); + fclose(constants); + + fputs("{\n", layouts); + fprintf(layouts, " \"meta\": {\"php\": \"%d.%d\", \"api\": %d, \"zts\": %d, \"debug\": %d},\n", PHP_MAJOR_VERSION, PHP_MINOR_VERSION, ZEND_MODULE_API_NO, (int)USING_ZTS, (int)ZEND_DEBUG); + fputs(" \"structs\": {\n", layouts); + fputs(" \"zval\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zval)); + fprintf(layouts, "\"value\": %zu", offsetof(zval, value)); + fprintf(layouts, ", \"u1\": %zu", offsetof(zval, u1)); + fprintf(layouts, ", \"u2\": %zu", offsetof(zval, u2)); + fputs("}},\n", layouts); + fputs(" \"zend_refcounted\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_refcounted)); + fprintf(layouts, "\"gc\": %zu", offsetof(zend_refcounted, gc)); + fputs("}},\n", layouts); + fputs(" \"zend_string\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_string)); + fprintf(layouts, "\"gc\": %zu", offsetof(zend_string, gc)); + fprintf(layouts, ", \"h\": %zu", offsetof(zend_string, h)); + fprintf(layouts, ", \"len\": %zu", offsetof(zend_string, len)); + fprintf(layouts, ", \"val\": %zu", offsetof(zend_string, val)); + fputs("}},\n", layouts); + fputs(" \"zend_array\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_array)); + fprintf(layouts, "\"gc\": %zu", offsetof(zend_array, gc)); + fprintf(layouts, ", \"u\": %zu", offsetof(zend_array, u)); + fprintf(layouts, ", \"nTableMask\": %zu", offsetof(zend_array, nTableMask)); + fprintf(layouts, ", \"arHash\": %zu", offsetof(zend_array, arHash)); + fprintf(layouts, ", \"arData\": %zu", offsetof(zend_array, arData)); + fprintf(layouts, ", \"arPacked\": %zu", offsetof(zend_array, arPacked)); + fprintf(layouts, ", \"nNumUsed\": %zu", offsetof(zend_array, nNumUsed)); + fprintf(layouts, ", \"nNumOfElements\": %zu", offsetof(zend_array, nNumOfElements)); + fprintf(layouts, ", \"nTableSize\": %zu", offsetof(zend_array, nTableSize)); + fprintf(layouts, ", \"nInternalPointer\": %zu", offsetof(zend_array, nInternalPointer)); + fprintf(layouts, ", \"nNextFreeElement\": %zu", offsetof(zend_array, nNextFreeElement)); + fprintf(layouts, ", \"pDestructor\": %zu", offsetof(zend_array, pDestructor)); + fputs("}},\n", layouts); + fputs(" \"Bucket\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(Bucket)); + fprintf(layouts, "\"val\": %zu", offsetof(Bucket, val)); + fprintf(layouts, ", \"h\": %zu", offsetof(Bucket, h)); + fprintf(layouts, ", \"key\": %zu", offsetof(Bucket, key)); + fputs("}},\n", layouts); + fputs(" \"zend_object\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_object)); + fprintf(layouts, "\"gc\": %zu", offsetof(zend_object, gc)); + fprintf(layouts, ", \"handle\": %zu", offsetof(zend_object, handle)); + fprintf(layouts, ", \"extra_flags\": %zu", offsetof(zend_object, extra_flags)); + fprintf(layouts, ", \"ce\": %zu", offsetof(zend_object, ce)); + fprintf(layouts, ", \"handlers\": %zu", offsetof(zend_object, handlers)); + fprintf(layouts, ", \"properties\": %zu", offsetof(zend_object, properties)); + fprintf(layouts, ", \"properties_table\": %zu", offsetof(zend_object, properties_table)); + fputs("}},\n", layouts); + fputs(" \"zend_resource\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_resource)); + fprintf(layouts, "\"gc\": %zu", offsetof(zend_resource, gc)); + fprintf(layouts, ", \"handle\": %zu", offsetof(zend_resource, handle)); + fprintf(layouts, ", \"type\": %zu", offsetof(zend_resource, type)); + fprintf(layouts, ", \"ptr\": %zu", offsetof(zend_resource, ptr)); + fputs("}},\n", layouts); + fputs(" \"zend_reference\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_reference)); + fprintf(layouts, "\"gc\": %zu", offsetof(zend_reference, gc)); + fprintf(layouts, ", \"val\": %zu", offsetof(zend_reference, val)); + fprintf(layouts, ", \"sources\": %zu", offsetof(zend_reference, sources)); + fputs("}},\n", layouts); + fputs(" \"zend_class_entry\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_class_entry)); + fprintf(layouts, "\"type\": %zu", offsetof(zend_class_entry, type)); + fprintf(layouts, ", \"name\": %zu", offsetof(zend_class_entry, name)); + fprintf(layouts, ", \"parent\": %zu", offsetof(zend_class_entry, parent)); + fprintf(layouts, ", \"parent_name\": %zu", offsetof(zend_class_entry, parent_name)); + fprintf(layouts, ", \"refcount\": %zu", offsetof(zend_class_entry, refcount)); + fprintf(layouts, ", \"ce_flags\": %zu", offsetof(zend_class_entry, ce_flags)); + fprintf(layouts, ", \"default_properties_count\": %zu", offsetof(zend_class_entry, default_properties_count)); + fprintf(layouts, ", \"default_static_members_count\": %zu", offsetof(zend_class_entry, default_static_members_count)); + fprintf(layouts, ", \"default_properties_table\": %zu", offsetof(zend_class_entry, default_properties_table)); + fprintf(layouts, ", \"default_static_members_table\": %zu", offsetof(zend_class_entry, default_static_members_table)); + fprintf(layouts, ", \"static_members_table__ptr\": %zu", offsetof(zend_class_entry, static_members_table__ptr)); + fprintf(layouts, ", \"function_table\": %zu", offsetof(zend_class_entry, function_table)); + fprintf(layouts, ", \"properties_info\": %zu", offsetof(zend_class_entry, properties_info)); + fprintf(layouts, ", \"constants_table\": %zu", offsetof(zend_class_entry, constants_table)); + fprintf(layouts, ", \"mutable_data__ptr\": %zu", offsetof(zend_class_entry, mutable_data__ptr)); + fprintf(layouts, ", \"inheritance_cache\": %zu", offsetof(zend_class_entry, inheritance_cache)); + fprintf(layouts, ", \"properties_info_table\": %zu", offsetof(zend_class_entry, properties_info_table)); + fprintf(layouts, ", \"constructor\": %zu", offsetof(zend_class_entry, constructor)); + fprintf(layouts, ", \"destructor\": %zu", offsetof(zend_class_entry, destructor)); + fprintf(layouts, ", \"clone\": %zu", offsetof(zend_class_entry, clone)); + fprintf(layouts, ", \"__get\": %zu", offsetof(zend_class_entry, __get)); + fprintf(layouts, ", \"__set\": %zu", offsetof(zend_class_entry, __set)); + fprintf(layouts, ", \"__unset\": %zu", offsetof(zend_class_entry, __unset)); + fprintf(layouts, ", \"__isset\": %zu", offsetof(zend_class_entry, __isset)); + fprintf(layouts, ", \"__call\": %zu", offsetof(zend_class_entry, __call)); + fprintf(layouts, ", \"__callstatic\": %zu", offsetof(zend_class_entry, __callstatic)); + fprintf(layouts, ", \"__tostring\": %zu", offsetof(zend_class_entry, __tostring)); + fprintf(layouts, ", \"__debugInfo\": %zu", offsetof(zend_class_entry, __debugInfo)); + fprintf(layouts, ", \"__serialize\": %zu", offsetof(zend_class_entry, __serialize)); + fprintf(layouts, ", \"__unserialize\": %zu", offsetof(zend_class_entry, __unserialize)); + fprintf(layouts, ", \"default_object_handlers\": %zu", offsetof(zend_class_entry, default_object_handlers)); + fprintf(layouts, ", \"iterator_funcs_ptr\": %zu", offsetof(zend_class_entry, iterator_funcs_ptr)); + fprintf(layouts, ", \"arrayaccess_funcs_ptr\": %zu", offsetof(zend_class_entry, arrayaccess_funcs_ptr)); + fprintf(layouts, ", \"create_object\": %zu", offsetof(zend_class_entry, create_object)); + fprintf(layouts, ", \"interface_gets_implemented\": %zu", offsetof(zend_class_entry, interface_gets_implemented)); + fprintf(layouts, ", \"get_iterator\": %zu", offsetof(zend_class_entry, get_iterator)); + fprintf(layouts, ", \"get_static_method\": %zu", offsetof(zend_class_entry, get_static_method)); + fprintf(layouts, ", \"serialize\": %zu", offsetof(zend_class_entry, serialize)); + fprintf(layouts, ", \"unserialize\": %zu", offsetof(zend_class_entry, unserialize)); + fprintf(layouts, ", \"num_interfaces\": %zu", offsetof(zend_class_entry, num_interfaces)); + fprintf(layouts, ", \"num_traits\": %zu", offsetof(zend_class_entry, num_traits)); + fprintf(layouts, ", \"num_hooked_props\": %zu", offsetof(zend_class_entry, num_hooked_props)); + fprintf(layouts, ", \"num_hooked_prop_variance_checks\": %zu", offsetof(zend_class_entry, num_hooked_prop_variance_checks)); + fprintf(layouts, ", \"interfaces\": %zu", offsetof(zend_class_entry, interfaces)); + fprintf(layouts, ", \"interface_names\": %zu", offsetof(zend_class_entry, interface_names)); + fprintf(layouts, ", \"trait_names\": %zu", offsetof(zend_class_entry, trait_names)); + fprintf(layouts, ", \"trait_aliases\": %zu", offsetof(zend_class_entry, trait_aliases)); + fprintf(layouts, ", \"trait_precedences\": %zu", offsetof(zend_class_entry, trait_precedences)); + fprintf(layouts, ", \"attributes\": %zu", offsetof(zend_class_entry, attributes)); + fprintf(layouts, ", \"enum_backing_type\": %zu", offsetof(zend_class_entry, enum_backing_type)); + fprintf(layouts, ", \"backed_enum_table\": %zu", offsetof(zend_class_entry, backed_enum_table)); + fprintf(layouts, ", \"doc_comment\": %zu", offsetof(zend_class_entry, doc_comment)); + fprintf(layouts, ", \"info\": %zu", offsetof(zend_class_entry, info)); + fputs("}},\n", layouts); + fputs(" \"zend_class_constant\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_class_constant)); + fprintf(layouts, "\"value\": %zu", offsetof(zend_class_constant, value)); + fprintf(layouts, ", \"doc_comment\": %zu", offsetof(zend_class_constant, doc_comment)); + fprintf(layouts, ", \"attributes\": %zu", offsetof(zend_class_constant, attributes)); + fprintf(layouts, ", \"ce\": %zu", offsetof(zend_class_constant, ce)); + fprintf(layouts, ", \"type\": %zu", offsetof(zend_class_constant, type)); + fputs("}},\n", layouts); + fputs(" \"zend_class_name\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_class_name)); + fprintf(layouts, "\"name\": %zu", offsetof(zend_class_name, name)); + fprintf(layouts, ", \"lc_name\": %zu", offsetof(zend_class_name, lc_name)); + fputs("}},\n", layouts); + fputs(" \"zend_property_info\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_property_info)); + fprintf(layouts, "\"offset\": %zu", offsetof(zend_property_info, offset)); + fprintf(layouts, ", \"flags\": %zu", offsetof(zend_property_info, flags)); + fprintf(layouts, ", \"name\": %zu", offsetof(zend_property_info, name)); + fprintf(layouts, ", \"doc_comment\": %zu", offsetof(zend_property_info, doc_comment)); + fprintf(layouts, ", \"attributes\": %zu", offsetof(zend_property_info, attributes)); + fprintf(layouts, ", \"ce\": %zu", offsetof(zend_property_info, ce)); + fprintf(layouts, ", \"type\": %zu", offsetof(zend_property_info, type)); + fprintf(layouts, ", \"prototype\": %zu", offsetof(zend_property_info, prototype)); + fprintf(layouts, ", \"hooks\": %zu", offsetof(zend_property_info, hooks)); + fputs("}},\n", layouts); + fputs(" \"zend_type_list\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_type_list)); + fprintf(layouts, "\"num_types\": %zu", offsetof(zend_type_list, num_types)); + fprintf(layouts, ", \"types\": %zu", offsetof(zend_type_list, types)); + fputs("}},\n", layouts); + fputs(" \"zend_constant\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_constant)); + fprintf(layouts, "\"value\": %zu", offsetof(zend_constant, value)); + fprintf(layouts, ", \"name\": %zu", offsetof(zend_constant, name)); + fprintf(layouts, ", \"filename\": %zu", offsetof(zend_constant, filename)); + fprintf(layouts, ", \"attributes\": %zu", offsetof(zend_constant, attributes)); + fputs("}},\n", layouts); + fputs(" \"zend_attribute\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_attribute)); + fprintf(layouts, "\"name\": %zu", offsetof(zend_attribute, name)); + fprintf(layouts, ", \"lcname\": %zu", offsetof(zend_attribute, lcname)); + fprintf(layouts, ", \"validation_error\": %zu", offsetof(zend_attribute, validation_error)); + fprintf(layouts, ", \"flags\": %zu", offsetof(zend_attribute, flags)); + fprintf(layouts, ", \"lineno\": %zu", offsetof(zend_attribute, lineno)); + fprintf(layouts, ", \"offset\": %zu", offsetof(zend_attribute, offset)); + fprintf(layouts, ", \"argc\": %zu", offsetof(zend_attribute, argc)); + fprintf(layouts, ", \"args\": %zu", offsetof(zend_attribute, args)); + fputs("}},\n", layouts); + fputs(" \"zend_attribute_arg\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_attribute_arg)); + fprintf(layouts, "\"name\": %zu", offsetof(zend_attribute_arg, name)); + fprintf(layouts, ", \"value\": %zu", offsetof(zend_attribute_arg, value)); + fputs("}},\n", layouts); + fputs(" \"zend_op_array\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_op_array)); + fprintf(layouts, "\"type\": %zu", offsetof(zend_op_array, type)); + fprintf(layouts, ", \"arg_flags\": %zu", offsetof(zend_op_array, arg_flags)); + fprintf(layouts, ", \"fn_flags\": %zu", offsetof(zend_op_array, fn_flags)); + fprintf(layouts, ", \"function_name\": %zu", offsetof(zend_op_array, function_name)); + fprintf(layouts, ", \"scope\": %zu", offsetof(zend_op_array, scope)); + fprintf(layouts, ", \"prototype\": %zu", offsetof(zend_op_array, prototype)); + fprintf(layouts, ", \"num_args\": %zu", offsetof(zend_op_array, num_args)); + fprintf(layouts, ", \"required_num_args\": %zu", offsetof(zend_op_array, required_num_args)); + fprintf(layouts, ", \"arg_info\": %zu", offsetof(zend_op_array, arg_info)); + fprintf(layouts, ", \"attributes\": %zu", offsetof(zend_op_array, attributes)); + fprintf(layouts, ", \"run_time_cache__ptr\": %zu", offsetof(zend_op_array, run_time_cache__ptr)); + fprintf(layouts, ", \"doc_comment\": %zu", offsetof(zend_op_array, doc_comment)); + fprintf(layouts, ", \"T\": %zu", offsetof(zend_op_array, T)); + fprintf(layouts, ", \"prop_info\": %zu", offsetof(zend_op_array, prop_info)); + fprintf(layouts, ", \"cache_size\": %zu", offsetof(zend_op_array, cache_size)); + fprintf(layouts, ", \"last_var\": %zu", offsetof(zend_op_array, last_var)); + fprintf(layouts, ", \"last\": %zu", offsetof(zend_op_array, last)); + fprintf(layouts, ", \"opcodes\": %zu", offsetof(zend_op_array, opcodes)); + fprintf(layouts, ", \"static_variables_ptr__ptr\": %zu", offsetof(zend_op_array, static_variables_ptr__ptr)); + fprintf(layouts, ", \"static_variables\": %zu", offsetof(zend_op_array, static_variables)); + fprintf(layouts, ", \"vars\": %zu", offsetof(zend_op_array, vars)); + fprintf(layouts, ", \"refcount\": %zu", offsetof(zend_op_array, refcount)); + fprintf(layouts, ", \"last_live_range\": %zu", offsetof(zend_op_array, last_live_range)); + fprintf(layouts, ", \"last_try_catch\": %zu", offsetof(zend_op_array, last_try_catch)); + fprintf(layouts, ", \"live_range\": %zu", offsetof(zend_op_array, live_range)); + fprintf(layouts, ", \"try_catch_array\": %zu", offsetof(zend_op_array, try_catch_array)); + fprintf(layouts, ", \"filename\": %zu", offsetof(zend_op_array, filename)); + fprintf(layouts, ", \"line_start\": %zu", offsetof(zend_op_array, line_start)); + fprintf(layouts, ", \"line_end\": %zu", offsetof(zend_op_array, line_end)); + fprintf(layouts, ", \"last_literal\": %zu", offsetof(zend_op_array, last_literal)); + fprintf(layouts, ", \"num_dynamic_func_defs\": %zu", offsetof(zend_op_array, num_dynamic_func_defs)); + fprintf(layouts, ", \"literals\": %zu", offsetof(zend_op_array, literals)); + fprintf(layouts, ", \"dynamic_func_defs\": %zu", offsetof(zend_op_array, dynamic_func_defs)); + fprintf(layouts, ", \"reserved\": %zu", offsetof(zend_op_array, reserved)); + fputs("}},\n", layouts); + fputs(" \"zend_internal_function\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_internal_function)); + fprintf(layouts, "\"type\": %zu", offsetof(zend_internal_function, type)); + fprintf(layouts, ", \"arg_flags\": %zu", offsetof(zend_internal_function, arg_flags)); + fprintf(layouts, ", \"fn_flags\": %zu", offsetof(zend_internal_function, fn_flags)); + fprintf(layouts, ", \"function_name\": %zu", offsetof(zend_internal_function, function_name)); + fprintf(layouts, ", \"scope\": %zu", offsetof(zend_internal_function, scope)); + fprintf(layouts, ", \"prototype\": %zu", offsetof(zend_internal_function, prototype)); + fprintf(layouts, ", \"num_args\": %zu", offsetof(zend_internal_function, num_args)); + fprintf(layouts, ", \"required_num_args\": %zu", offsetof(zend_internal_function, required_num_args)); + fprintf(layouts, ", \"arg_info\": %zu", offsetof(zend_internal_function, arg_info)); + fprintf(layouts, ", \"attributes\": %zu", offsetof(zend_internal_function, attributes)); + fprintf(layouts, ", \"run_time_cache__ptr\": %zu", offsetof(zend_internal_function, run_time_cache__ptr)); + fprintf(layouts, ", \"doc_comment\": %zu", offsetof(zend_internal_function, doc_comment)); + fprintf(layouts, ", \"T\": %zu", offsetof(zend_internal_function, T)); + fprintf(layouts, ", \"prop_info\": %zu", offsetof(zend_internal_function, prop_info)); + fprintf(layouts, ", \"handler\": %zu", offsetof(zend_internal_function, handler)); + fprintf(layouts, ", \"module\": %zu", offsetof(zend_internal_function, module)); + fprintf(layouts, ", \"frameless_function_infos\": %zu", offsetof(zend_internal_function, frameless_function_infos)); + fprintf(layouts, ", \"reserved\": %zu", offsetof(zend_internal_function, reserved)); + fputs("}},\n", layouts); + fputs(" \"zend_op\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_op)); + fprintf(layouts, "\"handler\": %zu", offsetof(zend_op, handler)); + fprintf(layouts, ", \"op1\": %zu", offsetof(zend_op, op1)); + fprintf(layouts, ", \"op2\": %zu", offsetof(zend_op, op2)); + fprintf(layouts, ", \"result\": %zu", offsetof(zend_op, result)); + fprintf(layouts, ", \"extended_value\": %zu", offsetof(zend_op, extended_value)); + fprintf(layouts, ", \"lineno\": %zu", offsetof(zend_op, lineno)); + fprintf(layouts, ", \"opcode\": %zu", offsetof(zend_op, opcode)); + fprintf(layouts, ", \"op1_type\": %zu", offsetof(zend_op, op1_type)); + fprintf(layouts, ", \"op2_type\": %zu", offsetof(zend_op, op2_type)); + fprintf(layouts, ", \"result_type\": %zu", offsetof(zend_op, result_type)); + fputs("}},\n", layouts); + fputs(" \"zend_execute_data\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_execute_data)); + fprintf(layouts, "\"opline\": %zu", offsetof(zend_execute_data, opline)); + fprintf(layouts, ", \"call\": %zu", offsetof(zend_execute_data, call)); + fprintf(layouts, ", \"return_value\": %zu", offsetof(zend_execute_data, return_value)); + fprintf(layouts, ", \"func\": %zu", offsetof(zend_execute_data, func)); + fprintf(layouts, ", \"This\": %zu", offsetof(zend_execute_data, This)); + fprintf(layouts, ", \"prev_execute_data\": %zu", offsetof(zend_execute_data, prev_execute_data)); + fprintf(layouts, ", \"symbol_table\": %zu", offsetof(zend_execute_data, symbol_table)); + fprintf(layouts, ", \"run_time_cache\": %zu", offsetof(zend_execute_data, run_time_cache)); + fprintf(layouts, ", \"extra_named_params\": %zu", offsetof(zend_execute_data, extra_named_params)); + fputs("}},\n", layouts); + fputs(" \"zend_objects_store\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_objects_store)); + fprintf(layouts, "\"object_buckets\": %zu", offsetof(zend_objects_store, object_buckets)); + fprintf(layouts, ", \"top\": %zu", offsetof(zend_objects_store, top)); + fprintf(layouts, ", \"size\": %zu", offsetof(zend_objects_store, size)); + fprintf(layouts, ", \"free_list_head\": %zu", offsetof(zend_objects_store, free_list_head)); + fputs("}},\n", layouts); + fputs(" \"zend_executor_globals\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_executor_globals)); + fprintf(layouts, "\"uninitialized_zval\": %zu", offsetof(zend_executor_globals, uninitialized_zval)); + fprintf(layouts, ", \"error_zval\": %zu", offsetof(zend_executor_globals, error_zval)); + fprintf(layouts, ", \"symtable_cache\": %zu", offsetof(zend_executor_globals, symtable_cache)); + fprintf(layouts, ", \"symtable_cache_limit\": %zu", offsetof(zend_executor_globals, symtable_cache_limit)); + fprintf(layouts, ", \"symtable_cache_ptr\": %zu", offsetof(zend_executor_globals, symtable_cache_ptr)); + fprintf(layouts, ", \"symbol_table\": %zu", offsetof(zend_executor_globals, symbol_table)); + fprintf(layouts, ", \"included_files\": %zu", offsetof(zend_executor_globals, included_files)); + fprintf(layouts, ", \"bailout\": %zu", offsetof(zend_executor_globals, bailout)); + fprintf(layouts, ", \"error_reporting\": %zu", offsetof(zend_executor_globals, error_reporting)); + fprintf(layouts, ", \"fatal_error_backtrace_on\": %zu", offsetof(zend_executor_globals, fatal_error_backtrace_on)); + fprintf(layouts, ", \"last_fatal_error_backtrace\": %zu", offsetof(zend_executor_globals, last_fatal_error_backtrace)); + fprintf(layouts, ", \"exit_status\": %zu", offsetof(zend_executor_globals, exit_status)); + fprintf(layouts, ", \"function_table\": %zu", offsetof(zend_executor_globals, function_table)); + fprintf(layouts, ", \"class_table\": %zu", offsetof(zend_executor_globals, class_table)); + fprintf(layouts, ", \"zend_constants\": %zu", offsetof(zend_executor_globals, zend_constants)); + fprintf(layouts, ", \"vm_stack_top\": %zu", offsetof(zend_executor_globals, vm_stack_top)); + fprintf(layouts, ", \"vm_stack_end\": %zu", offsetof(zend_executor_globals, vm_stack_end)); + fprintf(layouts, ", \"vm_stack\": %zu", offsetof(zend_executor_globals, vm_stack)); + fprintf(layouts, ", \"vm_stack_page_size\": %zu", offsetof(zend_executor_globals, vm_stack_page_size)); + fprintf(layouts, ", \"current_execute_data\": %zu", offsetof(zend_executor_globals, current_execute_data)); + fprintf(layouts, ", \"fake_scope\": %zu", offsetof(zend_executor_globals, fake_scope)); + fprintf(layouts, ", \"jit_trace_num\": %zu", offsetof(zend_executor_globals, jit_trace_num)); + fprintf(layouts, ", \"current_observed_frame\": %zu", offsetof(zend_executor_globals, current_observed_frame)); + fprintf(layouts, ", \"ticks_count\": %zu", offsetof(zend_executor_globals, ticks_count)); + fprintf(layouts, ", \"precision\": %zu", offsetof(zend_executor_globals, precision)); + fprintf(layouts, ", \"persistent_constants_count\": %zu", offsetof(zend_executor_globals, persistent_constants_count)); + fprintf(layouts, ", \"persistent_functions_count\": %zu", offsetof(zend_executor_globals, persistent_functions_count)); + fprintf(layouts, ", \"persistent_classes_count\": %zu", offsetof(zend_executor_globals, persistent_classes_count)); + fprintf(layouts, ", \"no_extensions\": %zu", offsetof(zend_executor_globals, no_extensions)); + fprintf(layouts, ", \"full_tables_cleanup\": %zu", offsetof(zend_executor_globals, full_tables_cleanup)); + fprintf(layouts, ", \"vm_interrupt\": %zu", offsetof(zend_executor_globals, vm_interrupt)); + fprintf(layouts, ", \"timed_out\": %zu", offsetof(zend_executor_globals, timed_out)); + fprintf(layouts, ", \"in_autoload\": %zu", offsetof(zend_executor_globals, in_autoload)); + fprintf(layouts, ", \"hard_timeout\": %zu", offsetof(zend_executor_globals, hard_timeout)); + fprintf(layouts, ", \"stack_base\": %zu", offsetof(zend_executor_globals, stack_base)); + fprintf(layouts, ", \"stack_limit\": %zu", offsetof(zend_executor_globals, stack_limit)); + fprintf(layouts, ", \"regular_list\": %zu", offsetof(zend_executor_globals, regular_list)); + fprintf(layouts, ", \"persistent_list\": %zu", offsetof(zend_executor_globals, persistent_list)); + fprintf(layouts, ", \"user_error_handler_error_reporting\": %zu", offsetof(zend_executor_globals, user_error_handler_error_reporting)); + fprintf(layouts, ", \"exception_ignore_args\": %zu", offsetof(zend_executor_globals, exception_ignore_args)); + fprintf(layouts, ", \"user_error_handler\": %zu", offsetof(zend_executor_globals, user_error_handler)); + fprintf(layouts, ", \"user_exception_handler\": %zu", offsetof(zend_executor_globals, user_exception_handler)); + fprintf(layouts, ", \"user_error_handlers_error_reporting\": %zu", offsetof(zend_executor_globals, user_error_handlers_error_reporting)); + fprintf(layouts, ", \"user_error_handlers\": %zu", offsetof(zend_executor_globals, user_error_handlers)); + fprintf(layouts, ", \"user_exception_handlers\": %zu", offsetof(zend_executor_globals, user_exception_handlers)); + fprintf(layouts, ", \"exception_class\": %zu", offsetof(zend_executor_globals, exception_class)); + fprintf(layouts, ", \"error_handling\": %zu", offsetof(zend_executor_globals, error_handling)); + fprintf(layouts, ", \"capture_warnings_during_sccp\": %zu", offsetof(zend_executor_globals, capture_warnings_during_sccp)); + fprintf(layouts, ", \"timeout_seconds\": %zu", offsetof(zend_executor_globals, timeout_seconds)); + fprintf(layouts, ", \"ini_directives\": %zu", offsetof(zend_executor_globals, ini_directives)); + fprintf(layouts, ", \"modified_ini_directives\": %zu", offsetof(zend_executor_globals, modified_ini_directives)); + fprintf(layouts, ", \"error_reporting_ini_entry\": %zu", offsetof(zend_executor_globals, error_reporting_ini_entry)); + fprintf(layouts, ", \"objects_store\": %zu", offsetof(zend_executor_globals, objects_store)); + fprintf(layouts, ", \"lazy_objects_store\": %zu", offsetof(zend_executor_globals, lazy_objects_store)); + fprintf(layouts, ", \"exception\": %zu", offsetof(zend_executor_globals, exception)); + fprintf(layouts, ", \"prev_exception\": %zu", offsetof(zend_executor_globals, prev_exception)); + fprintf(layouts, ", \"opline_before_exception\": %zu", offsetof(zend_executor_globals, opline_before_exception)); + fprintf(layouts, ", \"exception_op\": %zu", offsetof(zend_executor_globals, exception_op)); + fprintf(layouts, ", \"current_module\": %zu", offsetof(zend_executor_globals, current_module)); + fprintf(layouts, ", \"active\": %zu", offsetof(zend_executor_globals, active)); + fprintf(layouts, ", \"flags\": %zu", offsetof(zend_executor_globals, flags)); + fprintf(layouts, ", \"assertions\": %zu", offsetof(zend_executor_globals, assertions)); + fprintf(layouts, ", \"ht_iterators_count\": %zu", offsetof(zend_executor_globals, ht_iterators_count)); + fprintf(layouts, ", \"ht_iterators_used\": %zu", offsetof(zend_executor_globals, ht_iterators_used)); + fprintf(layouts, ", \"ht_iterators\": %zu", offsetof(zend_executor_globals, ht_iterators)); + fprintf(layouts, ", \"ht_iterators_slots\": %zu", offsetof(zend_executor_globals, ht_iterators_slots)); + fprintf(layouts, ", \"saved_fpu_cw_ptr\": %zu", offsetof(zend_executor_globals, saved_fpu_cw_ptr)); + fprintf(layouts, ", \"trampoline\": %zu", offsetof(zend_executor_globals, trampoline)); + fprintf(layouts, ", \"call_trampoline_op\": %zu", offsetof(zend_executor_globals, call_trampoline_op)); + fprintf(layouts, ", \"weakrefs\": %zu", offsetof(zend_executor_globals, weakrefs)); + fprintf(layouts, ", \"exception_string_param_max_len\": %zu", offsetof(zend_executor_globals, exception_string_param_max_len)); + fprintf(layouts, ", \"get_gc_buffer\": %zu", offsetof(zend_executor_globals, get_gc_buffer)); + fprintf(layouts, ", \"main_fiber_context\": %zu", offsetof(zend_executor_globals, main_fiber_context)); + fprintf(layouts, ", \"current_fiber_context\": %zu", offsetof(zend_executor_globals, current_fiber_context)); + fprintf(layouts, ", \"active_fiber\": %zu", offsetof(zend_executor_globals, active_fiber)); + fprintf(layouts, ", \"fiber_stack_size\": %zu", offsetof(zend_executor_globals, fiber_stack_size)); + fprintf(layouts, ", \"record_errors\": %zu", offsetof(zend_executor_globals, record_errors)); + fprintf(layouts, ", \"num_errors\": %zu", offsetof(zend_executor_globals, num_errors)); + fprintf(layouts, ", \"errors\": %zu", offsetof(zend_executor_globals, errors)); + fprintf(layouts, ", \"filename_override\": %zu", offsetof(zend_executor_globals, filename_override)); + fprintf(layouts, ", \"lineno_override\": %zu", offsetof(zend_executor_globals, lineno_override)); + fprintf(layouts, ", \"call_stack\": %zu", offsetof(zend_executor_globals, call_stack)); + fprintf(layouts, ", \"max_allowed_stack_size\": %zu", offsetof(zend_executor_globals, max_allowed_stack_size)); + fprintf(layouts, ", \"reserved_stack_size\": %zu", offsetof(zend_executor_globals, reserved_stack_size)); + fprintf(layouts, ", \"strtod_state\": %zu", offsetof(zend_executor_globals, strtod_state)); + fprintf(layouts, ", \"reserved\": %zu", offsetof(zend_executor_globals, reserved)); + fputs("}},\n", layouts); + fputs(" \"zend_compiler_globals\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_compiler_globals)); + fprintf(layouts, "\"loop_var_stack\": %zu", offsetof(zend_compiler_globals, loop_var_stack)); + fprintf(layouts, ", \"active_class_entry\": %zu", offsetof(zend_compiler_globals, active_class_entry)); + fprintf(layouts, ", \"compiled_filename\": %zu", offsetof(zend_compiler_globals, compiled_filename)); + fprintf(layouts, ", \"zend_lineno\": %zu", offsetof(zend_compiler_globals, zend_lineno)); + fprintf(layouts, ", \"active_op_array\": %zu", offsetof(zend_compiler_globals, active_op_array)); + fprintf(layouts, ", \"function_table\": %zu", offsetof(zend_compiler_globals, function_table)); + fprintf(layouts, ", \"class_table\": %zu", offsetof(zend_compiler_globals, class_table)); + fprintf(layouts, ", \"auto_globals\": %zu", offsetof(zend_compiler_globals, auto_globals)); + fprintf(layouts, ", \"parse_error\": %zu", offsetof(zend_compiler_globals, parse_error)); + fprintf(layouts, ", \"in_compilation\": %zu", offsetof(zend_compiler_globals, in_compilation)); + fprintf(layouts, ", \"short_tags\": %zu", offsetof(zend_compiler_globals, short_tags)); + fprintf(layouts, ", \"unclean_shutdown\": %zu", offsetof(zend_compiler_globals, unclean_shutdown)); + fprintf(layouts, ", \"ini_parser_unbuffered_errors\": %zu", offsetof(zend_compiler_globals, ini_parser_unbuffered_errors)); + fprintf(layouts, ", \"open_files\": %zu", offsetof(zend_compiler_globals, open_files)); + fprintf(layouts, ", \"ini_parser_param\": %zu", offsetof(zend_compiler_globals, ini_parser_param)); + fprintf(layouts, ", \"skip_shebang\": %zu", offsetof(zend_compiler_globals, skip_shebang)); + fprintf(layouts, ", \"increment_lineno\": %zu", offsetof(zend_compiler_globals, increment_lineno)); + fprintf(layouts, ", \"variable_width_locale\": %zu", offsetof(zend_compiler_globals, variable_width_locale)); + fprintf(layouts, ", \"ascii_compatible_locale\": %zu", offsetof(zend_compiler_globals, ascii_compatible_locale)); + fprintf(layouts, ", \"doc_comment\": %zu", offsetof(zend_compiler_globals, doc_comment)); + fprintf(layouts, ", \"extra_fn_flags\": %zu", offsetof(zend_compiler_globals, extra_fn_flags)); + fprintf(layouts, ", \"compiler_options\": %zu", offsetof(zend_compiler_globals, compiler_options)); + fprintf(layouts, ", \"context\": %zu", offsetof(zend_compiler_globals, context)); + fprintf(layouts, ", \"file_context\": %zu", offsetof(zend_compiler_globals, file_context)); + fprintf(layouts, ", \"arena\": %zu", offsetof(zend_compiler_globals, arena)); + fprintf(layouts, ", \"interned_strings\": %zu", offsetof(zend_compiler_globals, interned_strings)); + fprintf(layouts, ", \"script_encoding_list\": %zu", offsetof(zend_compiler_globals, script_encoding_list)); + fprintf(layouts, ", \"script_encoding_list_size\": %zu", offsetof(zend_compiler_globals, script_encoding_list_size)); + fprintf(layouts, ", \"multibyte\": %zu", offsetof(zend_compiler_globals, multibyte)); + fprintf(layouts, ", \"detect_unicode\": %zu", offsetof(zend_compiler_globals, detect_unicode)); + fprintf(layouts, ", \"encoding_declared\": %zu", offsetof(zend_compiler_globals, encoding_declared)); + fprintf(layouts, ", \"ast\": %zu", offsetof(zend_compiler_globals, ast)); + fprintf(layouts, ", \"ast_arena\": %zu", offsetof(zend_compiler_globals, ast_arena)); + fprintf(layouts, ", \"delayed_oplines_stack\": %zu", offsetof(zend_compiler_globals, delayed_oplines_stack)); + fprintf(layouts, ", \"memoized_exprs\": %zu", offsetof(zend_compiler_globals, memoized_exprs)); + fprintf(layouts, ", \"memoize_mode\": %zu", offsetof(zend_compiler_globals, memoize_mode)); + fprintf(layouts, ", \"map_ptr_real_base\": %zu", offsetof(zend_compiler_globals, map_ptr_real_base)); + fprintf(layouts, ", \"map_ptr_base\": %zu", offsetof(zend_compiler_globals, map_ptr_base)); + fprintf(layouts, ", \"map_ptr_size\": %zu", offsetof(zend_compiler_globals, map_ptr_size)); + fprintf(layouts, ", \"map_ptr_last\": %zu", offsetof(zend_compiler_globals, map_ptr_last)); + fprintf(layouts, ", \"delayed_variance_obligations\": %zu", offsetof(zend_compiler_globals, delayed_variance_obligations)); + fprintf(layouts, ", \"delayed_autoloads\": %zu", offsetof(zend_compiler_globals, delayed_autoloads)); + fprintf(layouts, ", \"unlinked_uses\": %zu", offsetof(zend_compiler_globals, unlinked_uses)); + fprintf(layouts, ", \"current_linking_class\": %zu", offsetof(zend_compiler_globals, current_linking_class)); + fprintf(layouts, ", \"rtd_key_counter\": %zu", offsetof(zend_compiler_globals, rtd_key_counter)); + fprintf(layouts, ", \"internal_run_time_cache\": %zu", offsetof(zend_compiler_globals, internal_run_time_cache)); + fprintf(layouts, ", \"internal_run_time_cache_size\": %zu", offsetof(zend_compiler_globals, internal_run_time_cache_size)); + fprintf(layouts, ", \"short_circuiting_opnums\": %zu", offsetof(zend_compiler_globals, short_circuiting_opnums)); + fputs("}},\n", layouts); + fputs(" \"zend_module_entry\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_module_entry)); + fprintf(layouts, "\"size\": %zu", offsetof(zend_module_entry, size)); + fprintf(layouts, ", \"zend_api\": %zu", offsetof(zend_module_entry, zend_api)); + fprintf(layouts, ", \"zend_debug\": %zu", offsetof(zend_module_entry, zend_debug)); + fprintf(layouts, ", \"zts\": %zu", offsetof(zend_module_entry, zts)); + fprintf(layouts, ", \"ini_entry\": %zu", offsetof(zend_module_entry, ini_entry)); + fprintf(layouts, ", \"deps\": %zu", offsetof(zend_module_entry, deps)); + fprintf(layouts, ", \"name\": %zu", offsetof(zend_module_entry, name)); + fprintf(layouts, ", \"functions\": %zu", offsetof(zend_module_entry, functions)); + fprintf(layouts, ", \"module_startup_func\": %zu", offsetof(zend_module_entry, module_startup_func)); + fprintf(layouts, ", \"module_shutdown_func\": %zu", offsetof(zend_module_entry, module_shutdown_func)); + fprintf(layouts, ", \"request_startup_func\": %zu", offsetof(zend_module_entry, request_startup_func)); + fprintf(layouts, ", \"request_shutdown_func\": %zu", offsetof(zend_module_entry, request_shutdown_func)); + fprintf(layouts, ", \"info_func\": %zu", offsetof(zend_module_entry, info_func)); + fprintf(layouts, ", \"version\": %zu", offsetof(zend_module_entry, version)); + fprintf(layouts, ", \"globals_size\": %zu", offsetof(zend_module_entry, globals_size)); + fprintf(layouts, ", \"globals_ptr\": %zu", offsetof(zend_module_entry, globals_ptr)); + fprintf(layouts, ", \"globals_ctor\": %zu", offsetof(zend_module_entry, globals_ctor)); + fprintf(layouts, ", \"globals_dtor\": %zu", offsetof(zend_module_entry, globals_dtor)); + fprintf(layouts, ", \"post_deactivate_func\": %zu", offsetof(zend_module_entry, post_deactivate_func)); + fprintf(layouts, ", \"module_started\": %zu", offsetof(zend_module_entry, module_started)); + fprintf(layouts, ", \"type\": %zu", offsetof(zend_module_entry, type)); + fprintf(layouts, ", \"handle\": %zu", offsetof(zend_module_entry, handle)); + fprintf(layouts, ", \"module_number\": %zu", offsetof(zend_module_entry, module_number)); + fprintf(layouts, ", \"build_id\": %zu", offsetof(zend_module_entry, build_id)); + fputs("}},\n", layouts); + fputs(" \"zend_module_dep\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_module_dep)); + fprintf(layouts, "\"name\": %zu", offsetof(zend_module_dep, name)); + fprintf(layouts, ", \"rel\": %zu", offsetof(zend_module_dep, rel)); + fprintf(layouts, ", \"version\": %zu", offsetof(zend_module_dep, version)); + fprintf(layouts, ", \"type\": %zu", offsetof(zend_module_dep, type)); + fputs("}},\n", layouts); + fputs(" \"zend_object_handlers\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_object_handlers)); + fprintf(layouts, "\"offset\": %zu", offsetof(zend_object_handlers, offset)); + fprintf(layouts, ", \"free_obj\": %zu", offsetof(zend_object_handlers, free_obj)); + fprintf(layouts, ", \"dtor_obj\": %zu", offsetof(zend_object_handlers, dtor_obj)); + fprintf(layouts, ", \"clone_obj\": %zu", offsetof(zend_object_handlers, clone_obj)); + fprintf(layouts, ", \"clone_obj_with\": %zu", offsetof(zend_object_handlers, clone_obj_with)); + fprintf(layouts, ", \"read_property\": %zu", offsetof(zend_object_handlers, read_property)); + fprintf(layouts, ", \"write_property\": %zu", offsetof(zend_object_handlers, write_property)); + fprintf(layouts, ", \"read_dimension\": %zu", offsetof(zend_object_handlers, read_dimension)); + fprintf(layouts, ", \"write_dimension\": %zu", offsetof(zend_object_handlers, write_dimension)); + fprintf(layouts, ", \"get_property_ptr_ptr\": %zu", offsetof(zend_object_handlers, get_property_ptr_ptr)); + fprintf(layouts, ", \"has_property\": %zu", offsetof(zend_object_handlers, has_property)); + fprintf(layouts, ", \"unset_property\": %zu", offsetof(zend_object_handlers, unset_property)); + fprintf(layouts, ", \"has_dimension\": %zu", offsetof(zend_object_handlers, has_dimension)); + fprintf(layouts, ", \"unset_dimension\": %zu", offsetof(zend_object_handlers, unset_dimension)); + fprintf(layouts, ", \"get_properties\": %zu", offsetof(zend_object_handlers, get_properties)); + fprintf(layouts, ", \"get_method\": %zu", offsetof(zend_object_handlers, get_method)); + fprintf(layouts, ", \"get_constructor\": %zu", offsetof(zend_object_handlers, get_constructor)); + fprintf(layouts, ", \"get_class_name\": %zu", offsetof(zend_object_handlers, get_class_name)); + fprintf(layouts, ", \"cast_object\": %zu", offsetof(zend_object_handlers, cast_object)); + fprintf(layouts, ", \"count_elements\": %zu", offsetof(zend_object_handlers, count_elements)); + fprintf(layouts, ", \"get_debug_info\": %zu", offsetof(zend_object_handlers, get_debug_info)); + fprintf(layouts, ", \"get_closure\": %zu", offsetof(zend_object_handlers, get_closure)); + fprintf(layouts, ", \"get_gc\": %zu", offsetof(zend_object_handlers, get_gc)); + fprintf(layouts, ", \"do_operation\": %zu", offsetof(zend_object_handlers, do_operation)); + fprintf(layouts, ", \"compare\": %zu", offsetof(zend_object_handlers, compare)); + fprintf(layouts, ", \"get_properties_for\": %zu", offsetof(zend_object_handlers, get_properties_for)); + fputs("}},\n", layouts); + fputs(" \"zend_object_iterator\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_object_iterator)); + fprintf(layouts, "\"std\": %zu", offsetof(zend_object_iterator, std)); + fprintf(layouts, ", \"data\": %zu", offsetof(zend_object_iterator, data)); + fprintf(layouts, ", \"funcs\": %zu", offsetof(zend_object_iterator, funcs)); + fprintf(layouts, ", \"index\": %zu", offsetof(zend_object_iterator, index)); + fputs("}},\n", layouts); + fputs(" \"zend_object_iterator_funcs\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_object_iterator_funcs)); + fprintf(layouts, "\"dtor\": %zu", offsetof(zend_object_iterator_funcs, dtor)); + fprintf(layouts, ", \"valid\": %zu", offsetof(zend_object_iterator_funcs, valid)); + fprintf(layouts, ", \"get_current_data\": %zu", offsetof(zend_object_iterator_funcs, get_current_data)); + fprintf(layouts, ", \"get_current_key\": %zu", offsetof(zend_object_iterator_funcs, get_current_key)); + fprintf(layouts, ", \"move_forward\": %zu", offsetof(zend_object_iterator_funcs, move_forward)); + fprintf(layouts, ", \"rewind\": %zu", offsetof(zend_object_iterator_funcs, rewind)); + fprintf(layouts, ", \"invalidate_current\": %zu", offsetof(zend_object_iterator_funcs, invalidate_current)); + fprintf(layouts, ", \"get_gc\": %zu", offsetof(zend_object_iterator_funcs, get_gc)); + fputs("}},\n", layouts); + fputs(" \"zend_ast\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_ast)); + fprintf(layouts, "\"kind\": %zu", offsetof(zend_ast, kind)); + fprintf(layouts, ", \"attr\": %zu", offsetof(zend_ast, attr)); + fprintf(layouts, ", \"lineno\": %zu", offsetof(zend_ast, lineno)); + fprintf(layouts, ", \"child\": %zu", offsetof(zend_ast, child)); + fputs("}},\n", layouts); + fputs(" \"zend_ast_decl\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_ast_decl)); + fprintf(layouts, "\"kind\": %zu", offsetof(zend_ast_decl, kind)); + fprintf(layouts, ", \"attr\": %zu", offsetof(zend_ast_decl, attr)); + fprintf(layouts, ", \"start_lineno\": %zu", offsetof(zend_ast_decl, start_lineno)); + fprintf(layouts, ", \"end_lineno\": %zu", offsetof(zend_ast_decl, end_lineno)); + fprintf(layouts, ", \"flags\": %zu", offsetof(zend_ast_decl, flags)); + fprintf(layouts, ", \"doc_comment\": %zu", offsetof(zend_ast_decl, doc_comment)); + fprintf(layouts, ", \"name\": %zu", offsetof(zend_ast_decl, name)); + fprintf(layouts, ", \"child\": %zu", offsetof(zend_ast_decl, child)); + fputs("}},\n", layouts); + fputs(" \"zend_ast_list\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_ast_list)); + fprintf(layouts, "\"kind\": %zu", offsetof(zend_ast_list, kind)); + fprintf(layouts, ", \"attr\": %zu", offsetof(zend_ast_list, attr)); + fprintf(layouts, ", \"lineno\": %zu", offsetof(zend_ast_list, lineno)); + fprintf(layouts, ", \"children\": %zu", offsetof(zend_ast_list, children)); + fprintf(layouts, ", \"child\": %zu", offsetof(zend_ast_list, child)); + fputs("}},\n", layouts); + fputs(" \"zend_ast_zval\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_ast_zval)); + fprintf(layouts, "\"kind\": %zu", offsetof(zend_ast_zval, kind)); + fprintf(layouts, ", \"attr\": %zu", offsetof(zend_ast_zval, attr)); + fprintf(layouts, ", \"val\": %zu", offsetof(zend_ast_zval, val)); + fputs("}},\n", layouts); + fputs(" \"zend_ast_op_array\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_ast_op_array)); + fprintf(layouts, "\"kind\": %zu", offsetof(zend_ast_op_array, kind)); + fprintf(layouts, ", \"attr\": %zu", offsetof(zend_ast_op_array, attr)); + fprintf(layouts, ", \"lineno\": %zu", offsetof(zend_ast_op_array, lineno)); + fprintf(layouts, ", \"op_array\": %zu", offsetof(zend_ast_op_array, op_array)); + fputs("}},\n", layouts); + fputs(" \"zend_lex_state\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_lex_state)); + fprintf(layouts, "\"yy_leng\": %zu", offsetof(zend_lex_state, yy_leng)); + fprintf(layouts, ", \"yy_start\": %zu", offsetof(zend_lex_state, yy_start)); + fprintf(layouts, ", \"yy_text\": %zu", offsetof(zend_lex_state, yy_text)); + fprintf(layouts, ", \"yy_cursor\": %zu", offsetof(zend_lex_state, yy_cursor)); + fprintf(layouts, ", \"yy_marker\": %zu", offsetof(zend_lex_state, yy_marker)); + fprintf(layouts, ", \"yy_limit\": %zu", offsetof(zend_lex_state, yy_limit)); + fprintf(layouts, ", \"yy_state\": %zu", offsetof(zend_lex_state, yy_state)); + fprintf(layouts, ", \"state_stack\": %zu", offsetof(zend_lex_state, state_stack)); + fprintf(layouts, ", \"heredoc_label_stack\": %zu", offsetof(zend_lex_state, heredoc_label_stack)); + fprintf(layouts, ", \"nest_location_stack\": %zu", offsetof(zend_lex_state, nest_location_stack)); + fprintf(layouts, ", \"in\": %zu", offsetof(zend_lex_state, in)); + fprintf(layouts, ", \"lineno\": %zu", offsetof(zend_lex_state, lineno)); + fprintf(layouts, ", \"filename\": %zu", offsetof(zend_lex_state, filename)); + fprintf(layouts, ", \"script_org\": %zu", offsetof(zend_lex_state, script_org)); + fprintf(layouts, ", \"script_org_size\": %zu", offsetof(zend_lex_state, script_org_size)); + fprintf(layouts, ", \"script_filtered\": %zu", offsetof(zend_lex_state, script_filtered)); + fprintf(layouts, ", \"script_filtered_size\": %zu", offsetof(zend_lex_state, script_filtered_size)); + fprintf(layouts, ", \"input_filter\": %zu", offsetof(zend_lex_state, input_filter)); + fprintf(layouts, ", \"output_filter\": %zu", offsetof(zend_lex_state, output_filter)); + fprintf(layouts, ", \"script_encoding\": %zu", offsetof(zend_lex_state, script_encoding)); + fprintf(layouts, ", \"on_event\": %zu", offsetof(zend_lex_state, on_event)); + fprintf(layouts, ", \"on_event_context\": %zu", offsetof(zend_lex_state, on_event_context)); + fprintf(layouts, ", \"ast\": %zu", offsetof(zend_lex_state, ast)); + fprintf(layouts, ", \"ast_arena\": %zu", offsetof(zend_lex_state, ast_arena)); + fputs("}},\n", layouts); + fputs(" \"zend_closure\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_closure)); + fprintf(layouts, "\"std\": %zu", offsetof(zend_closure, std)); + fprintf(layouts, ", \"func\": %zu", offsetof(zend_closure, func)); + fprintf(layouts, ", \"this_ptr\": %zu", offsetof(zend_closure, this_ptr)); + fprintf(layouts, ", \"called_scope\": %zu", offsetof(zend_closure, called_scope)); + fprintf(layouts, ", \"orig_internal_handler\": %zu", offsetof(zend_closure, orig_internal_handler)); + fputs("}},\n", layouts); + fputs(" \"zend_script\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_script)); + fprintf(layouts, "\"filename\": %zu", offsetof(zend_script, filename)); + fprintf(layouts, ", \"main_op_array\": %zu", offsetof(zend_script, main_op_array)); + fprintf(layouts, ", \"function_table\": %zu", offsetof(zend_script, function_table)); + fprintf(layouts, ", \"class_table\": %zu", offsetof(zend_script, class_table)); + fputs("}},\n", layouts); + fputs(" \"zend_error_info\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_error_info)); + fprintf(layouts, "\"type\": %zu", offsetof(zend_error_info, type)); + fprintf(layouts, ", \"lineno\": %zu", offsetof(zend_error_info, lineno)); + fprintf(layouts, ", \"filename\": %zu", offsetof(zend_error_info, filename)); + fprintf(layouts, ", \"message\": %zu", offsetof(zend_error_info, message)); + fputs("}},\n", layouts); + fputs(" \"zend_early_binding\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_early_binding)); + fprintf(layouts, "\"lcname\": %zu", offsetof(zend_early_binding, lcname)); + fprintf(layouts, ", \"rtd_key\": %zu", offsetof(zend_early_binding, rtd_key)); + fprintf(layouts, ", \"lc_parent_name\": %zu", offsetof(zend_early_binding, lc_parent_name)); + fprintf(layouts, ", \"cache_slot\": %zu", offsetof(zend_early_binding, cache_slot)); + fputs("}},\n", layouts); + fputs(" \"zend_persistent_script\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_persistent_script)); + fprintf(layouts, "\"script\": %zu", offsetof(zend_persistent_script, script)); + fprintf(layouts, ", \"compiler_halt_offset\": %zu", offsetof(zend_persistent_script, compiler_halt_offset)); + fprintf(layouts, ", \"ping_auto_globals_mask\": %zu", offsetof(zend_persistent_script, ping_auto_globals_mask)); + fprintf(layouts, ", \"timestamp\": %zu", offsetof(zend_persistent_script, timestamp)); + fprintf(layouts, ", \"corrupted\": %zu", offsetof(zend_persistent_script, corrupted)); + fprintf(layouts, ", \"is_phar\": %zu", offsetof(zend_persistent_script, is_phar)); + fprintf(layouts, ", \"empty\": %zu", offsetof(zend_persistent_script, empty)); + fprintf(layouts, ", \"num_warnings\": %zu", offsetof(zend_persistent_script, num_warnings)); + fprintf(layouts, ", \"num_early_bindings\": %zu", offsetof(zend_persistent_script, num_early_bindings)); + fprintf(layouts, ", \"warnings\": %zu", offsetof(zend_persistent_script, warnings)); + fprintf(layouts, ", \"early_bindings\": %zu", offsetof(zend_persistent_script, early_bindings)); + fprintf(layouts, ", \"mem\": %zu", offsetof(zend_persistent_script, mem)); + fprintf(layouts, ", \"size\": %zu", offsetof(zend_persistent_script, size)); + fprintf(layouts, ", \"dynamic_members\": %zu", offsetof(zend_persistent_script, dynamic_members)); + fputs("}},\n", layouts); + fputs(" \"zend_file_cache_metainfo\": {", layouts); + fprintf(layouts, "\"size\": %zu, \"fields\": {", sizeof(zend_file_cache_metainfo)); + fprintf(layouts, "\"magic\": %zu", offsetof(zend_file_cache_metainfo, magic)); + fprintf(layouts, ", \"system_id\": %zu", offsetof(zend_file_cache_metainfo, system_id)); + fprintf(layouts, ", \"mem_size\": %zu", offsetof(zend_file_cache_metainfo, mem_size)); + fprintf(layouts, ", \"str_size\": %zu", offsetof(zend_file_cache_metainfo, str_size)); + fprintf(layouts, ", \"script_offset\": %zu", offsetof(zend_file_cache_metainfo, script_offset)); + fprintf(layouts, ", \"timestamp\": %zu", offsetof(zend_file_cache_metainfo, timestamp)); + fprintf(layouts, ", \"checksum\": %zu", offsetof(zend_file_cache_metainfo, checksum)); + fputs("}}\n", layouts); + fputs(" }\n}\n", layouts); + fclose(layouts); + return 0; +} From b057d0f11603143c35b99c87c8db7bfa2f0acd47 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 14:12:00 +0000 Subject: [PATCH 03/15] feat: update hand-written engine constants for PHP 8.5 ZEND_ACC_USE_GUARDS moved from 0x800 to 1 << 30 (0x40000000): 0x800 now means only ZEND_ACC_DEPRECATED, so the stale value would have silently mis-read every class with magic property accessors. OpCode gains DECLARE_ATTRIBUTED_CONST (210), which PHP 8.5 emits instead of DECLARE_CONST when a global const carries attributes. No opcode was renumbered. NodeKind is regenerated from the 8.5 enum: AST_OP_ARRAY, AST_CAST_VOID and AST_PIPE are new, AST_CLONE and AST_EXIT are gone (both constructs now compile to a ZEND_AST_CALL on the construct name), and 32 kinds shift as a result. Neither removed kind was referenced outside the table. LiveRange and ArgumentEntry were verified against Zend/zend_compile.h by hand - no engine export exists for those macros - and are unchanged in 8.5. OpCache: three file-cache serializer changes needed a matching port. Attributes carry the new validation_error string; constant-expression ASTs may hold a ZEND_AST_OP_ARRAY node (a compiled static closure) whose op_array pointer must be relocated and walked, or a ZEND_AST_CALLABLE_CONVERT node that only touches execution-only ZEND_MAP_PTR state; and an attributed global constant hangs its attribute table off a ZEND_OP_DATA operand as an IS_PTR literal, which the ordinary literal walk skips. Note that the operand is resolved as a literal index rather than through the engine's RT_CONSTANT() byte-offset math: opcache stores IS_CONST operands as indexes in the file cache and only converts them on load, and this port keeps every opline in its serialized form. The binary format itself is unchanged in 8.5 - same metainfo, same adler32 checksum, same system_id stamp, same bin path layout - so CacheMetaInfo, BinaryCacheFile and SystemId needed no change. The opcache fixture now compiles both new node shapes into the cached binary, so the relocator walks them on every round trip. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01HRDZ2XsoVuB5uG4qXKL3ny --- src/AbstractSyntaxTree/NodeKind.php | 71 ++++++++-------- src/Core.php | 8 +- src/OpCache/PayloadRelocator.php | 119 ++++++++++++++++++++++++--- src/Reflection/FunctionLikeTrait.php | 2 +- src/System/OpCode.php | 1 + src/Type/ArgumentEntry.php | 2 +- src/Type/LiveRange.php | 2 +- tests/OpCache/fixtures/answer.php | 24 +++++- 8 files changed, 175 insertions(+), 54 deletions(-) diff --git a/src/AbstractSyntaxTree/NodeKind.php b/src/AbstractSyntaxTree/NodeKind.php index 790eb05d..810b0162 100644 --- a/src/AbstractSyntaxTree/NodeKind.php +++ b/src/AbstractSyntaxTree/NodeKind.php @@ -24,16 +24,17 @@ class NodeKind private const AST_IS_LIST_SHIFT = 7; private const AST_NUM_CHILDREN_SHIFT = 8; - /* Generated for PHP 8.4 from enum _zend_ast_kind; EngineConstantsTest guards these values */ + /* Generated for PHP 8.5 from enum _zend_ast_kind; EngineConstantsTest guards these values */ public const AST_ZVAL = 64; public const AST_CONSTANT = 65; - public const AST_ZNODE = 66; - public const AST_FUNC_DECL = 67; - public const AST_CLOSURE = 68; - public const AST_METHOD = 69; - public const AST_CLASS = 70; - public const AST_ARROW_FUNC = 71; - public const AST_PROPERTY_HOOK = 72; + public const AST_OP_ARRAY = 66; + public const AST_ZNODE = 67; + public const AST_FUNC_DECL = 68; + public const AST_CLOSURE = 69; + public const AST_METHOD = 70; + public const AST_CLASS = 71; + public const AST_ARROW_FUNC = 72; + public const AST_PROPERTY_HOOK = 73; public const AST_ARG_LIST = 128; public const AST_ARRAY = 129; public const AST_ENCAPS_LIST = 130; @@ -66,33 +67,32 @@ class NodeKind public const AST_UNARY_PLUS = 259; public const AST_UNARY_MINUS = 260; public const AST_CAST = 261; - public const AST_EMPTY = 262; - public const AST_ISSET = 263; - public const AST_SILENCE = 264; - public const AST_SHELL_EXEC = 265; - public const AST_CLONE = 266; - public const AST_EXIT = 267; - public const AST_PRINT = 268; - public const AST_INCLUDE_OR_EVAL = 269; - public const AST_UNARY_OP = 270; - public const AST_PRE_INC = 271; - public const AST_PRE_DEC = 272; - public const AST_POST_INC = 273; - public const AST_POST_DEC = 274; - public const AST_YIELD_FROM = 275; - public const AST_CLASS_NAME = 276; - public const AST_GLOBAL = 277; - public const AST_UNSET = 278; - public const AST_RETURN = 279; - public const AST_LABEL = 280; - public const AST_REF = 281; - public const AST_HALT_COMPILER = 282; - public const AST_ECHO = 283; - public const AST_THROW = 284; - public const AST_GOTO = 285; - public const AST_BREAK = 286; - public const AST_CONTINUE = 287; - public const AST_PROPERTY_HOOK_SHORT_BODY = 288; + public const AST_CAST_VOID = 262; + public const AST_EMPTY = 263; + public const AST_ISSET = 264; + public const AST_SILENCE = 265; + public const AST_SHELL_EXEC = 266; + public const AST_PRINT = 267; + public const AST_INCLUDE_OR_EVAL = 268; + public const AST_UNARY_OP = 269; + public const AST_PRE_INC = 270; + public const AST_PRE_DEC = 271; + public const AST_POST_INC = 272; + public const AST_POST_DEC = 273; + public const AST_YIELD_FROM = 274; + public const AST_CLASS_NAME = 275; + public const AST_GLOBAL = 276; + public const AST_UNSET = 277; + public const AST_RETURN = 278; + public const AST_LABEL = 279; + public const AST_REF = 280; + public const AST_HALT_COMPILER = 281; + public const AST_ECHO = 282; + public const AST_THROW = 283; + public const AST_GOTO = 284; + public const AST_BREAK = 285; + public const AST_CONTINUE = 286; + public const AST_PROPERTY_HOOK_SHORT_BODY = 287; public const AST_DIM = 512; public const AST_PROP = 513; public const AST_NULLSAFE_PROP = 514; @@ -132,6 +132,7 @@ class NodeKind public const AST_MATCH_ARM = 548; public const AST_NAMED_ARG = 549; public const AST_PARENT_PROPERTY_HOOK_CALL = 550; + public const AST_PIPE = 551; public const AST_METHOD_CALL = 768; public const AST_NULLSAFE_METHOD_CALL = 769; public const AST_STATIC_CALL = 770; diff --git a/src/Core.php b/src/Core.php index 3be2b8df..5c2e6452 100644 --- a/src/Core.php +++ b/src/Core.php @@ -59,7 +59,7 @@ class Core { /** - * Class, method, property and constant flags (ZEND_ACC_*) for PHP 8.4. + * Class, method, property and constant flags (ZEND_ACC_*) for PHP 8.5. * * Ground truth lives in the generated include///constants.php; * EngineConstantsTest asserts these values match it exactly, so any drift @@ -88,7 +88,6 @@ class Core public const ZEND_ACC_LINKED = 0x8; public const ZEND_ACC_IMPLICIT_ABSTRACT_CLASS = 0x10; public const ZEND_ACC_EXPLICIT_ABSTRACT_CLASS = 0x40; - public const ZEND_ACC_USE_GUARDS = 0x800; public const ZEND_ACC_CONSTANTS_UPDATED = 0x1000; public const ZEND_ACC_NO_DYNAMIC_PROPERTIES = 0x2000; public const ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES = 0x8000; @@ -99,6 +98,7 @@ class Core public const ZEND_ACC_NEARLY_LINKED = 0x100000; public const ZEND_ACC_ENUM = 0x10000000; public const ZEND_ACC_NOT_SERIALIZABLE = 0x20000000; + public const ZEND_ACC_USE_GUARDS = 0x40000000; // was 0x800 before PHP 8.5 public const ZEND_ACC_UNINSTANTIABLE = 0x10000053; /* Property flags */ @@ -188,7 +188,7 @@ class Core * anything else is memory corruption, not a degraded mode - hence the hard * boot guard. See AGENTS.md ("Version matching is non-negotiable"). */ - private const SUPPORTED_PHP_VERSION_ID = [80400, 80500]; + private const SUPPORTED_PHP_VERSION_ID = [80500, 80600]; /** * Stores an internal instance of low-level FFI binding @@ -354,7 +354,7 @@ private static function assertSupportedEnvironment(): void } /** - * Platform selector for the generated per-ABI artifacts, e.g. "8.4/linux-x64-nts" + * Platform selector for the generated per-ABI artifacts, e.g. "8.5/linux-x64-nts" */ private static function platformKey(): string { diff --git a/src/OpCache/PayloadRelocator.php b/src/OpCache/PayloadRelocator.php index c08e87ce..ef7bc990 100644 --- a/src/OpCache/PayloadRelocator.php +++ b/src/OpCache/PayloadRelocator.php @@ -55,10 +55,23 @@ final class PayloadRelocator private const ZEND_ACC_HAS_RETURN_TYPE = 0x2000; private const ZEND_ACC_VARIADIC = 0x4000; - private const ZEND_AST_ZVAL = 64; - private const ZEND_AST_CONSTANT = 65; - private const ZEND_AST_IS_LIST_SHIFT = 7; - private const ZEND_AST_CHILDREN_SHIFT = 8; + /** + * AST node kinds the walk special-cases. PHP 8.5 added two node shapes that can + * appear in a constant expression: ZEND_AST_OP_ARRAY (a static closure compiled + * into the expression, carrying a zend_op_array pointer) and ZEND_AST_CALLABLE_CONVERT + * (first-class callable syntax, whose zend_ast_fcc holds only a ZEND_MAP_PTR slot). + */ + private const ZEND_AST_ZVAL = 64; + private const ZEND_AST_CONSTANT = 65; + private const ZEND_AST_OP_ARRAY = 66; + private const ZEND_AST_CALLABLE_CONVERT = 3; + private const ZEND_AST_IS_LIST_SHIFT = 7; + private const ZEND_AST_CHILDREN_SHIFT = 8; + + /** Opcodes whose operands carry file-cache state the opline walk must convert (PHP 8.5) */ + private const ZEND_DECLARE_ATTRIBUTED_CONST = 210; + private const ZEND_OP_DATA = 137; + private const IS_CONST = 1; /** zend_type bit layout (zend_types.h) - list/name discriminators */ private const TYPE_LIST_BIT = 4194304; // _ZEND_TYPE_LIST_BIT @@ -400,6 +413,22 @@ private function unserializeAst(int $astAddress): void return; } + if ($kind === self::ZEND_AST_OP_ARRAY) { + // PHP 8.5 constant expressions may hold a compiled static closure; the + // embedded body is stored the same way a function-table entry is + $node = Core::pointerAtAddress('zend_ast_op_array *', $astAddress); + if (!$this->isUnserialized($this->ptrValue($node, 'op_array'))) { + $address = $this->unPtr($node, 'op_array'); + $this->unserializeOpArray(Core::pointerAtAddress('zend_op_array *', $address)); + } + + return; + } + if ($kind === self::ZEND_AST_CALLABLE_CONVERT) { + // zend_ast_fcc holds only a ZEND_MAP_PTR slot, which is execution-only + // state this port preserves verbatim (see class docblock) + return; + } if (($kind >> self::ZEND_AST_IS_LIST_SHIFT & 1) !== 0) { $list = Core::pointerAtAddress('zend_ast_list *', $astAddress); $childBase = $astAddress + Core::sizeof(Core::type('zend_ast_list')) - PHP_INT_SIZE; @@ -427,6 +456,18 @@ private function serializeAst(int $astAddress): void return; } + if ($kind === self::ZEND_AST_OP_ARRAY) { + $node = Core::pointerAtAddress('zend_ast_op_array *', $astAddress); + if (!$this->isSerialized($this->ptrValue($node, 'op_array'))) { + $address = $this->serPtr($node, 'op_array'); + $this->serializeOpArray(Core::pointerAtAddress('zend_op_array *', $address)); + } + + return; + } + if ($kind === self::ZEND_AST_CALLABLE_CONVERT) { + return; + } if (($kind >> self::ZEND_AST_IS_LIST_SHIFT & 1) !== 0) { $list = Core::pointerAtAddress('zend_ast_list *', $astAddress); $childBase = $astAddress + Core::sizeof(Core::type('zend_ast_list')) - PHP_INT_SIZE; @@ -478,6 +519,8 @@ private function unserializeAttribute(CData $zval): void $attr = Core::pointerAtAddress('zend_attribute *', $this->unPtr($zval->value, 'ptr')); $this->unStr($attr, 'name'); $this->unStr($attr, 'lcname'); + // PHP 8.5: delayed target validation stores the pending error message here + $this->unStr($attr, 'validation_error'); $argSize = Core::sizeof(Core::type('zend_attribute_arg')); $argBase = Core::addressOf($attr->args); for ($i = 0; $i < $attr->argc; $i++) { @@ -493,6 +536,7 @@ private function serializeAttribute(CData $zval): void $attr = Core::pointerAtAddress('zend_attribute *', $address); $this->serStr($attr, 'name'); $this->serStr($attr, 'lcname'); + $this->serStr($attr, 'validation_error'); $argSize = Core::sizeof(Core::type('zend_attribute_arg')); $argBase = Core::addressOf($attr->args); for ($i = 0; $i < $attr->argc; $i++) { @@ -570,17 +614,20 @@ private function unserializeOpArray(CData $opArray): void $address = $this->unPtr($opArray, 'static_variables'); $this->unserializeHash(Core::pointerAtAddress('zend_array *', $address), $this->unserializeZval(...)); } + $literals = 0; if ($this->ptrValue($opArray, 'literals') !== 0) { - $address = $this->unPtr($opArray, 'literals'); + $literals = $this->unPtr($opArray, 'literals'); $zvalSize = Core::sizeof(Core::type('zval')); for ($i = 0; $i < $opArray->last_literal; $i++) { - $this->unserializeZval(Core::pointerAtAddress('zval *', $address + $i * $zvalSize)); + $this->unserializeZval(Core::pointerAtAddress('zval *', $literals + $i * $zvalSize)); } } // opcodes: only the array pointer is relocated; per-opline operands and // handlers are literal indexes/relative jumps on this platform and are - // preserved verbatim (see class docblock) - $this->unPtr($opArray, 'opcodes'); + // preserved verbatim (see class docblock). The one exception is the PHP 8.5 + // attributed-constant payload hanging off an ZEND_OP_DATA operand. + $opcodes = $this->unPtr($opArray, 'opcodes'); + $this->walkAttributedConstOplines($opcodes, $literals, (int) $opArray->last, false); $this->unPtr($opArray, 'scope'); $this->unserializeArgInfo($opArray); $this->unserializeVars($opArray); @@ -630,14 +677,16 @@ private function serializeOpArray(CData $opArray): void $address = $this->serPtr($opArray, 'static_variables'); $this->serializeHash(Core::pointerAtAddress('zend_array *', $address), $this->serializeZval(...)); } + $literals = 0; if ($this->ptrValue($opArray, 'literals') !== 0) { - $address = $this->serPtr($opArray, 'literals'); + $literals = $this->serPtr($opArray, 'literals'); $zvalSize = Core::sizeof(Core::type('zval')); for ($i = 0; $i < $opArray->last_literal; $i++) { - $this->serializeZval(Core::pointerAtAddress('zval *', $address + $i * $zvalSize)); + $this->serializeZval(Core::pointerAtAddress('zval *', $literals + $i * $zvalSize)); } } - $this->serPtr($opArray, 'opcodes'); + $opcodes = $this->serPtr($opArray, 'opcodes'); + $this->walkAttributedConstOplines($opcodes, $literals, (int) $opArray->last, true); $this->serializeArgInfo($opArray); $this->serializeVars($opArray); if ($opArray->num_dynamic_func_defs !== 0) { @@ -654,6 +703,54 @@ private function serializeOpArray(CData $opArray): void $this->serPtr($opArray, 'prop_info'); } + /** + * Converts the attribute tables reachable from ZEND_DECLARE_ATTRIBUTED_CONST oplines. + * + * PHP 8.5 emits ZEND_DECLARE_ATTRIBUTED_CONST (instead of ZEND_DECLARE_CONST) for a + * global `const` carrying attributes, followed by a ZEND_OP_DATA whose op1 literal is + * an IS_PTR zval holding the compiled attribute HashTable. Because the zval type is + * IS_PTR the ordinary literal walk skips it, so opcache converts it from the opline + * loop - and so must this port, otherwise the table keeps a raw offset (read path) or + * a live address (write path) and the written binary is unloadable. + * + * The operand is read as a LITERAL INDEX, not as the run-time byte offset the engine's + * RT_CONSTANT() macro expects: opcache stores IS_CONST operands as indexes in the file + * cache (ZEND_PASS_TWO_UNDO_CONSTANT) and only converts them back on load, while this + * port keeps every opline in its serialized form (see class docblock). Everything else + * about the opline - handlers, jump offsets, the other operands - stays untouched. + * + * @param int $opcodes Address of the (already converted) opcodes array, 0 when null + * @param int $literals Address of the (already converted) literals array, 0 when null + * @param int $count Number of oplines (op_array.last) + * @param bool $serialized True on the write path, false on the read path + */ + private function walkAttributedConstOplines(int $opcodes, int $literals, int $count, bool $serialized): void + { + if ($opcodes === 0 || $literals === 0 || $count < 2) { + return; + } + $oplineSize = Core::sizeof(Core::type('zend_op')); + $zvalSize = Core::sizeof(Core::type('zval')); + // The pair is (DECLARE_ATTRIBUTED_CONST, OP_DATA), so the scan starts at index 1 + for ($i = 1; $i < $count; $i++) { + $address = $opcodes + $i * $oplineSize; + $opline = Core::pointerAtAddress('zend_op *', $address); + if ($opline->opcode !== self::ZEND_OP_DATA || $opline->op1_type !== self::IS_CONST) { + continue; + } + $previous = Core::pointerAtAddress('zend_op *', $address - $oplineSize); + if ($previous->opcode !== self::ZEND_DECLARE_ATTRIBUTED_CONST) { + continue; + } + $literal = Core::pointerAtAddress('zval *', $literals + (int) $opline->op1->constant * $zvalSize); + if ($serialized) { + $this->serializeAttributes($literal->value, 'ptr'); + } else { + $this->unserializeAttributes($literal->value, 'ptr'); + } + } + } + /** * @return array{int, int} [start index, end index) for the arg_info walk */ diff --git a/src/Reflection/FunctionLikeTrait.php b/src/Reflection/FunctionLikeTrait.php index 498445e8..37789075 100644 --- a/src/Reflection/FunctionLikeTrait.php +++ b/src/Reflection/FunctionLikeTrait.php @@ -427,7 +427,7 @@ public function getArgumentInfo(int $index): ArgumentEntry /** * Returns the static variables table of this function (borrowed engine view) * - * On PHP 8.4 the engine keeps two tables: op_array.static_variables holds the default + * On PHP 8.4+ the engine keeps two tables: op_array.static_variables holds the default * values from the declaration, while the map pointer static_variables_ptr points to * the live table once it was materialized (on the first ZEND_BIND_STATIC execution, * or already at creation time for closures). The live table is returned whenever it diff --git a/src/System/OpCode.php b/src/System/OpCode.php index 6c3a6ef5..bdf8a420 100644 --- a/src/System/OpCode.php +++ b/src/System/OpCode.php @@ -230,6 +230,7 @@ final class OpCode public const FRAMELESS_ICALL_3 = 207; public const JMP_FRAMELESS = 208; public const INIT_PARENT_PROPERTY_HOOK_CALL = 209; + public const DECLARE_ATTRIBUTED_CONST = 210; // PHP 8.5: DECLARE_CONST with attributes /** * Reversed class constants, containing names by number diff --git a/src/Type/ArgumentEntry.php b/src/Type/ArgumentEntry.php index 349e0672..00f70e62 100644 --- a/src/Type/ArgumentEntry.php +++ b/src/Type/ArgumentEntry.php @@ -27,7 +27,7 @@ * * The zend_type.type_mask field packs the allowed-type bits together with several * argument-passing flags; the bit layout below mirrors zend_types.h/zend_compile.h - * for PHP 8.4 (there is no exported engine constant for these internal macros). + * for PHP 8.5 (there is no exported engine constant for these internal macros). */ class ArgumentEntry { diff --git a/src/Type/LiveRange.php b/src/Type/LiveRange.php index e8623997..042e4ac2 100644 --- a/src/Type/LiveRange.php +++ b/src/Type/LiveRange.php @@ -25,7 +25,7 @@ * A live range tells the executor which temporary variables must be destroyed when an * exception unwinds through the [start, end) opcode window. The var field packs the * variable operand offset together with a kind tag in its low bits; the KIND_* values - * mirror the ZEND_LIVE_* macros of zend_compile.h for PHP 8.4. + * mirror the ZEND_LIVE_* macros of zend_compile.h for PHP 8.5. */ class LiveRange { diff --git a/tests/OpCache/fixtures/answer.php b/tests/OpCache/fixtures/answer.php index 839e7c1a..b975374a 100644 --- a/tests/OpCache/fixtures/answer.php +++ b/tests/OpCache/fixtures/answer.php @@ -5,7 +5,8 @@ * * Deliberately exercises walker breadth: a global function, a class with a * constant, a typed property with a default, a static variable, an attribute, - * a try/catch block and a string literal that patch tests rewrite. + * a try/catch block and a string literal that patch tests rewrite, plus the two + * node shapes PHP 8.5 introduced into the file-cache format (see below). */ declare(strict_types=1); @@ -40,3 +41,24 @@ public static function describe(int $times): string } } } + +#[\Attribute(\Attribute::TARGET_ALL)] +class ZEngineBinConstMarker {} + +/* + * PHP 8.5 shape #1: an attributed global constant compiles to + * ZEND_DECLARE_ATTRIBUTED_CONST + ZEND_OP_DATA, whose IS_CONST operand points at + * a literal of type IS_PTR holding the attribute table. The literal walk skips + * IS_PTR zvals, so the table is only reachable through the opline pair. + */ +#[ZEngineBinConstMarker] +const ZENGINE_BIN_FLAG = 'on'; + +/* + * PHP 8.5 shape #2: a static closure inside a constant expression compiles to a + * ZEND_AST_OP_ARRAY node, which carries a zend_op_array pointer instead of the + * child pointers the generic AST walk expects. + */ +const ZENGINE_BIN_CALLBACK = static function (): int { + return 5; +}; From 119b177e465a3329faf6b6e052d4df89f3fb1f57 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 14:12:15 +0000 Subject: [PATCH 04/15] feat: target PHP 8.5 master now builds against PHP 8.5; the 8.4 line lives on its own maintenance branch. Core's boot guard, the composer platform requirement, the CI matrix, both Dockerfiles and the PHPStan php version move together, since running z-engine against a PHP minor it was not generated for is memory corruption rather than a degraded mode. The generator keeps 8.4 in its default target list even though master targets 8.5: the 8.4 branch merges up into master, and dropping include/8.4 from the regenerated set would turn every merge-up into a modify/delete conflict. PHPStan: the single baseline entry that spelled out ZEND_ACC_USE_GUARDS' old numeric value is updated in place. A full baseline regeneration was rejected - it rewrites ~540 lines on the untouched 8.4 master too, so the churn is pre-existing drift and unrelated to this change. Verified that regenerating on 8.4 master and on this branch differ in exactly that one line, i.e. these edits introduce no new static-analysis errors. PHP 8.5 deprecates the report_memleaks directive; the test-suite calls that use it to suppress leak reports for immortal-by-design allocations are silenced, as it remains the only switch for that behaviour. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01HRDZ2XsoVuB5uG4qXKL3ny --- .github/workflows/ci.yml | 4 ++-- composer.json | 7 ++++++- phpstan-baseline.neon | 2 +- phpstan.dist.neon | 2 +- tests/Performance/GeneratedFunctionBenchmarkTest.php | 2 +- tests/Reflection/ReflectionClassTest.php | 2 +- .../Reflection/ReflectionClassTraitConfigurationTest.php | 4 ++-- tests/Reflection/ReflectionFunctionTest.php | 2 +- tools/docker/php-debug.Dockerfile | 2 +- tools/generator/Dockerfile | 2 +- tools/generator/generate.php | 9 +++++++-- 11 files changed, 24 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 644826bd..ab600c3e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,9 +7,9 @@ on: - '[0-9].[0-9]' pull_request: -# This branch targets PHP 8.4 only - engine structures are version-specific. +# This branch targets PHP 8.5 only - engine structures are version-specific. env: - PHP_MINOR: '8.4' + PHP_MINOR: '8.5' jobs: tests: diff --git a/composer.json b/composer.json index 676e2ba2..02f49eae 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ } ], "require": { - "php": "~8.4.0", + "php": "~8.5.0", "ext-ffi": "*" }, "require-dev": { @@ -52,5 +52,10 @@ }, "config": { "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-master": "8.5.x-dev" + } } } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index af901c1c..172df327 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -955,7 +955,7 @@ parameters: path: src/Reflection/ReflectionClass.php - - message: '#^Binary operation "&" between mixed and 2048 results in an error\.$#' + message: '#^Binary operation "&" between mixed and 1073741824 results in an error\.$#' identifier: binaryOp.invalid count: 1 path: src/Reflection/ReflectionClass.php diff --git a/phpstan.dist.neon b/phpstan.dist.neon index 3b4e460c..86f93a71 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -3,7 +3,7 @@ includes: parameters: level: max - phpVersion: 80400 + phpVersion: 80500 paths: - src - tests diff --git a/tests/Performance/GeneratedFunctionBenchmarkTest.php b/tests/Performance/GeneratedFunctionBenchmarkTest.php index ce4b2bef..824bebcf 100644 --- a/tests/Performance/GeneratedFunctionBenchmarkTest.php +++ b/tests/Performance/GeneratedFunctionBenchmarkTest.php @@ -42,7 +42,7 @@ class GeneratedFunctionBenchmarkTest extends TestCase public function testGeneratedFunctionMatchesDeclaredSpeed(): void { // The generated function keeps its body alive until request end (immortal-by-design) - ini_set('report_memleaks', '0'); + @ini_set('report_memleaks', '0'); // deprecated in PHP 8.5, still the only leak-report switch $generatedName = 'zengine_benchmark_twice'; ReflectionFunction::addFunction($generatedName, static fn(int $x): int => $x * 2); diff --git a/tests/Reflection/ReflectionClassTest.php b/tests/Reflection/ReflectionClassTest.php index 0055b5d4..a37a90c2 100644 --- a/tests/Reflection/ReflectionClassTest.php +++ b/tests/Reflection/ReflectionClassTest.php @@ -63,7 +63,7 @@ public function testAddMethod() // Immortal-by-design: addMethod() keeps the closure body alive until the class // entry is destroyed at the very end of the request (see docs/long-running.md), // so the debug-build shutdown report would flag it although nothing is wrong - ini_set('report_memleaks', '0'); + @ini_set('report_memleaks', '0'); // deprecated in PHP 8.5, still the only leak-report switch $methodName = 'newMethod'; $refMethod = $this->refClass->addMethod($methodName, function (string $argument): string { return $argument; diff --git a/tests/Reflection/ReflectionClassTraitConfigurationTest.php b/tests/Reflection/ReflectionClassTraitConfigurationTest.php index 0fc6f816..f77208b5 100644 --- a/tests/Reflection/ReflectionClassTraitConfigurationTest.php +++ b/tests/Reflection/ReflectionClassTraitConfigurationTest.php @@ -188,7 +188,7 @@ public function testRemoveTraitAliasReleasesCompileTimeEntries(): void // Bounded residual: replacing the engine-original (compiler-emalloc'd) alias list // leaves that list allocated until the request ends (see docs/long-running.md); // the debug-build shutdown report would flag it although nothing is wrong - ini_set('report_memleaks', '0'); + @ini_set('report_memleaks', '0'); // deprecated in PHP 8.5, still the only leak-report switch $refClass = new ReflectionClass(TestTraitConfiguredClass::class); $refClass->removeTraitAlias('secondConflicting'); @@ -208,7 +208,7 @@ public function testRemoveTraitPrecedenceReleasesCompileTimeEntries(): void { // Bounded residual: the replaced engine-original precedence list stays allocated // (see docs/long-running.md), which the debug-build shutdown report would flag - ini_set('report_memleaks', '0'); + @ini_set('report_memleaks', '0'); // deprecated in PHP 8.5, still the only leak-report switch $refClass = new ReflectionClass(TestTraitConfiguredClass::class); $refClass->removeTraitPrecedence(TestFirstConflictTrait::class . '::conflicting'); diff --git a/tests/Reflection/ReflectionFunctionTest.php b/tests/Reflection/ReflectionFunctionTest.php index 3093e463..5d2c7fcb 100644 --- a/tests/Reflection/ReflectionFunctionTest.php +++ b/tests/Reflection/ReflectionFunctionTest.php @@ -119,7 +119,7 @@ public function testAddFunction(): void // request (the published zend_function lives inside the closure object, see // docs/memory-model.md), so the debug-build shutdown report would flag it although // nothing is wrong - ini_set('report_memleaks', '0'); + @ini_set('report_memleaks', '0'); // deprecated in PHP 8.5, still the only leak-report switch $functionName = 'zengine_generated_twice'; $refFunction = ReflectionFunction::addFunction($functionName, fn(int $x): int => $x * 2); diff --git a/tools/docker/php-debug.Dockerfile b/tools/docker/php-debug.Dockerfile index 631e185b..7315f6c3 100644 --- a/tools/docker/php-debug.Dockerfile +++ b/tools/docker/php-debug.Dockerfile @@ -11,7 +11,7 @@ # the base image's release-ABI ffi.so) plus the extensions PHPUnit needs at # runtime (dom/xml/xmlwriter from libxml, mbstring). Build locally with: # docker build -f tools/docker/php-debug.Dockerfile -t z-engine-php:debug . -ARG PHP_VERSION=8.4 +ARG PHP_VERSION=8.5 FROM php:${PHP_VERSION}-cli AS build # Build dependencies for the default-enabled extensions (which the official diff --git a/tools/generator/Dockerfile b/tools/generator/Dockerfile index 1a7ce769..cf9c9435 100644 --- a/tools/generator/Dockerfile +++ b/tools/generator/Dockerfile @@ -3,7 +3,7 @@ # (engine.h, constants.php, layouts.json) via the scratch stage. # # Driven by tools/generator/generate.php - do not run by hand unless debugging. -ARG BASE_IMAGE=php:8.4-cli +ARG BASE_IMAGE=php:8.5-cli FROM ${BASE_IMAGE} AS build WORKDIR /gen diff --git a/tools/generator/generate.php b/tools/generator/generate.php index 6651d7ea..21bebb94 100644 --- a/tools/generator/generate.php +++ b/tools/generator/generate.php @@ -7,7 +7,7 @@ * * Usage: * php tools/generator/generate.php # all targets of this branch - * php tools/generator/generate.php --php=8.4 --ts=nts + * php tools/generator/generate.php --php=8.5 --ts=nts * * Requires docker (with buildx). Invoked via `composer gen-headers`. */ @@ -20,16 +20,21 @@ * Version/TS targets maintained on this branch. Extend when a new platform * or thread-safety mode becomes supported (see AGENTS.md). * + * master targets PHP 8.5, but it keeps regenerating the 8.4 artifacts as well: + * the maintenance branch `8.4` merges up into master, and dropping include/8.4 + * here would turn every such merge into a modify/delete conflict. + * * @var list $defaultTargets */ $defaultTargets = [ ['php' => '8.4', 'ts' => 'nts'], + ['php' => '8.5', 'ts' => 'nts'], ]; $options = getopt('', ['php:', 'ts:']); $targets = $defaultTargets; if (isset($options['php']) || isset($options['ts'])) { - $php = is_string($options['php'] ?? null) ? $options['php'] : '8.4'; + $php = is_string($options['php'] ?? null) ? $options['php'] : '8.5'; $ts = is_string($options['ts'] ?? null) ? $options['ts'] : 'nts'; $targets = [['php' => $php, 'ts' => $ts]]; } From 8aec47fad2d6176fa9c04b0c81b85d64f7d96ba5 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 14:12:33 +0000 Subject: [PATCH 05/15] docs: update README support matrix and issue template for PHP 8.5 master is now the PHP 8.5 line; 8.4 keeps its own maintenance branch and stays supported. The bug-report template asks for an 8.5 `php -v` line and spells out which branch each version lives on, so reports land against the right one. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01HRDZ2XsoVuB5uG4qXKL3ny --- .github/ISSUE_TEMPLATE/bug_report.yml | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 22a0cca8..2804b1e4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -11,7 +11,7 @@ body: id: php-version attributes: label: PHP version (full `php -v` first line) - placeholder: 'PHP 8.4.3 (cli) (built: ...) (NTS)' + placeholder: 'PHP 8.5.3 (cli) (built: ...) (NTS)' validations: required: true - type: dropdown @@ -34,7 +34,7 @@ body: id: z-engine-version attributes: label: z-engine version / branch - placeholder: 'dev-master, or the 8.4 branch' + placeholder: 'dev-master (PHP 8.5), or the 8.4 branch' validations: required: true - type: textarea diff --git a/README.md b/README.md index 34818871..017706d1 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Engine memory layouts change between every PHP minor version, so each PHP minor | PHP | OS / Arch / TS | Branch | Status | |-----|----------------|--------|--------| -| 8.5 | linux-x64-nts | `master` | 🚧 in progress | +| 8.5 | linux-x64-nts | `master` | ✅ supported | | 8.4 | linux-x64-nts | `8.4` | ✅ supported | | 8.0 | linux-x64-nts | `8.0` | 🧊 frozen (legacy) | | macOS / Windows / ZTS | — | — | 📋 [tracked in issues](https://github.com/lisachenko/z-engine/issues) | From a2ed9aa4bfc814578b40a3e43543611fe6f2b536 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 14:20:43 +0000 Subject: [PATCH 06/15] fix(ci): make generator manifest and debug image work on both 8.4 and 8.5 The dual-target gen-headers run broke on the 8.4 image: zend_ast_op_array only exists since PHP 8.5, so gate the manifest entries on the running PHP version (symbols.php executes inside the target container). The debug image build required an opcache.so, but since PHP 8.5 opcache is linked statically - emit the zend_extension line only when the shared extension exists and rely on the existing extension_loaded sanity check. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01HRDZ2XsoVuB5uG4qXKL3ny --- tools/docker/php-debug.Dockerfile | 12 ++++++++---- tools/generator/symbols.php | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tools/docker/php-debug.Dockerfile b/tools/docker/php-debug.Dockerfile index 7315f6c3..53e4a9cd 100644 --- a/tools/docker/php-debug.Dockerfile +++ b/tools/docker/php-debug.Dockerfile @@ -61,14 +61,18 @@ RUN rm -f /usr/local/etc/php/conf.d/docker-php-ext-*.ini # explicitly in the child processes that exercise shared memory - which is where # a debug build turns the shared-memory corruption of issue #41 into a loud # zend_function_dtor() assertion instead of a silent wrong result. -# opcache is a shared zend_extension here (the debug build installs its own -# ABI-tagged extension directory), so it is loaded by absolute path - a bare +# Up to PHP 8.4 opcache is a shared zend_extension (the debug build installs +# its own ABI-tagged extension directory), loaded by absolute path - a bare # file name resolves against whatever extension_dir the base image left behind. +# Since PHP 8.5 opcache is linked statically into the binary: no opcache.so +# exists and no zend_extension line is needed. The sanity check below asserts +# the extension is present either way. RUN set -eux; \ extension_dir="$(php-config --extension-dir)"; \ - test -f "${extension_dir}/opcache.so"; \ { \ - echo "zend_extension=${extension_dir}/opcache.so"; \ + if [ -f "${extension_dir}/opcache.so" ]; then \ + echo "zend_extension=${extension_dir}/opcache.so"; \ + fi; \ echo 'ffi.enable=1'; \ echo 'zend.assertions=1'; \ echo 'report_memleaks=1'; \ diff --git a/tools/generator/symbols.php b/tools/generator/symbols.php index 5739862c..f424187a 100644 --- a/tools/generator/symbols.php +++ b/tools/generator/symbols.php @@ -63,8 +63,8 @@ 'zend_ast_decl', 'zend_ast_list', 'zend_ast_zval', - // PHP 8.5: constant expressions may embed a compiled closure body - 'zend_ast_op_array', + // PHP 8.5+: constant expressions may embed a compiled closure body + ...(PHP_VERSION_ID >= 80500 ? ['zend_ast_op_array'] : []), 'zend_ast_process_t', 'zend_lex_state', 'zend_arena', @@ -296,7 +296,7 @@ 'zend_ast_decl', 'zend_ast_list', 'zend_ast_zval', - 'zend_ast_op_array', + ...(PHP_VERSION_ID >= 80500 ? ['zend_ast_op_array'] : []), 'zend_lex_state', 'zend_closure', 'zend_script', From 44663dca10a322cbb05bcae91ea759c9bd99d119 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 14:38:12 +0000 Subject: [PATCH 07/15] chore(generator): target only PHP 8.5 on master Review feedback on #134: include/8.4 artifacts are maintained on the 8.4 branch and flow into master via the cascade merge-up, so master's gen-headers run (and the header-drift job) only needs the 8.5 target. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01HRDZ2XsoVuB5uG4qXKL3ny --- tools/generator/generate.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/generator/generate.php b/tools/generator/generate.php index 21bebb94..7091725c 100644 --- a/tools/generator/generate.php +++ b/tools/generator/generate.php @@ -20,14 +20,13 @@ * Version/TS targets maintained on this branch. Extend when a new platform * or thread-safety mode becomes supported (see AGENTS.md). * - * master targets PHP 8.5, but it keeps regenerating the 8.4 artifacts as well: - * the maintenance branch `8.4` merges up into master, and dropping include/8.4 - * here would turn every such merge into a modify/delete conflict. + * master targets PHP 8.5 only. The committed include/8.4 artifacts are + * maintained on the `8.4` branch (its own gen-headers run regenerates them) + * and arrive here through the cascade merge-up. * * @var list $defaultTargets */ $defaultTargets = [ - ['php' => '8.4', 'ts' => 'nts'], ['php' => '8.5', 'ts' => 'nts'], ]; From 8c2fc073c547dcd410a0fce73c2a9c09b935a26d Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 14:38:51 +0000 Subject: [PATCH 08/15] chore(generator): drop the version gate around zend_ast_op_array Review feedback on #134: master's generator only ever runs against PHP 8.5 now, so the manifest can list the type unconditionally. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01HRDZ2XsoVuB5uG4qXKL3ny --- tools/generator/symbols.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/generator/symbols.php b/tools/generator/symbols.php index f424187a..5739862c 100644 --- a/tools/generator/symbols.php +++ b/tools/generator/symbols.php @@ -63,8 +63,8 @@ 'zend_ast_decl', 'zend_ast_list', 'zend_ast_zval', - // PHP 8.5+: constant expressions may embed a compiled closure body - ...(PHP_VERSION_ID >= 80500 ? ['zend_ast_op_array'] : []), + // PHP 8.5: constant expressions may embed a compiled closure body + 'zend_ast_op_array', 'zend_ast_process_t', 'zend_lex_state', 'zend_arena', @@ -296,7 +296,7 @@ 'zend_ast_decl', 'zend_ast_list', 'zend_ast_zval', - ...(PHP_VERSION_ID >= 80500 ? ['zend_ast_op_array'] : []), + 'zend_ast_op_array', 'zend_lex_state', 'zend_closure', 'zend_script', From 82145029a151d0f331cc6391e2b072d24f842afd Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 14:54:01 +0000 Subject: [PATCH 09/15] fix: stop duplicating static-variable defaults on redefine The debug-build leak gate caught redefine-churn losing three blocks per cycle on PHP 8.5 (a zend_array, its arData and one key string - a whole static-variables table), leak-free on 8.4. PHP 8.5 changed who owns a closure's static variables. zend_create_closure_ex() used to duplicate the prototype defaults into the closure's OWN op_array.static_variables field; it now duplicates them into the ZEND_MAP_PTR slot only and leaves the struct field aliasing the prototype's table, whose single destroy is tied to the body refcount. The two releases that used to compensate went away with it: zend_closure_free_storage() no longer nulls static_variables, and destroy_op_array() no longer unconditionally frees the static_variables of a dying op_array's closure prototypes. The swap assumed the old model and minted the entry an independent duplicate, overwriting op_array.static_variables. On 8.5 that field is the only handle through which the entry's body reference could still reach the prototype's table, so once it was replaced nothing freed the original: the eval'd op_array had already returned early on the shared refcount, and the entry's own destroy_op_array went on to free the duplicate instead. No donor kind owns that table on 8.5, so the duplication is not merely unnecessary but actively wrong - the body refcount already guards it and the last holder frees it exactly once. Dropping it takes the whole minted-defaults bookkeeping with it (the registry, the rollback restore records and the duplicateStatics parameter, whose only `true` caller was redefine()). The live per-entry table is still unshared by dropping the ZEND_MAP_PTR slot, so statics keep materializing lazily from the defaults on first ZEND_BIND_STATIC. Verified against a locally built PHP 8.5.9 --enable-debug: all 25 leak scenarios report no leaks (redefine-churn was 300), and the internal group runs 138 tests with only 2 skips instead of 27, since the leak gates actually execute on a debug build. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01HRDZ2XsoVuB5uG4qXKL3ny --- src/HotSwap/ClassDelta.php | 10 +-- src/Reflection/FunctionBodySwap.php | 125 +++++++++------------------ src/Reflection/FunctionLikeTrait.php | 2 - src/Reflection/PendingBodySwap.php | 12 +-- 4 files changed, 41 insertions(+), 108 deletions(-) diff --git a/src/HotSwap/ClassDelta.php b/src/HotSwap/ClassDelta.php index 35bad071..a373f299 100644 --- a/src/HotSwap/ClassDelta.php +++ b/src/HotSwap/ClassDelta.php @@ -313,8 +313,6 @@ public function apply(): void $donorMethod, // The new source is authoritative for the declaration as well preserveDeclaration: false, - // The donor body refcount guards the statics defaults table - duplicateStatics: false, destroyPrevious: true, publishedShares: FunctionBodySwap::countPublishedShares($entry), ); @@ -535,13 +533,7 @@ private static function releaseAdoptedContainer(CData $container): void assert($namePointer instanceof CData); StringEntry::fromCData($namePointer)->releaseReference(); - FunctionBodySwap::releaseSwappedInBody( - $containerFunction, - $containerFunction->getAddress(), - 1, - false, - null, - ); + FunctionBodySwap::releaseSwappedInBody($containerFunction, 1); Core::untrackAndFree(Core::addr($container)); } } diff --git a/src/Reflection/FunctionBodySwap.php b/src/Reflection/FunctionBodySwap.php index 9ed3320b..00c5b256 100644 --- a/src/Reflection/FunctionBodySwap.php +++ b/src/Reflection/FunctionBodySwap.php @@ -33,10 +33,11 @@ * scope-dependent and owned by the donor; the engine frees a heap cache together * with the entry (destroy_op_array), and every subsequent swap releases the * previous one, so repeated swaps stay memory-flat. - * - Static variables never stay shared with a donor that owns them: a closure - * destroys its own static table when it dies, so the entry duplicates the - * defaults; the live per-entry table materializes lazily on the first - * ZEND_BIND_STATIC, exactly like a plain compiled function. + * - The entry never shares the donor's LIVE static-variables table: its ZEND_MAP_PTR + * slot is dropped so the table materializes lazily on the first ZEND_BIND_STATIC, + * exactly like a plain compiled function. The defaults table behind it stays + * shared and is guarded by the body refcount alone - no donor kind owns it, see + * unshareStaticVariables() for the PHP 8.5 ownership rules. * - The previous body is destroyed with engine semantics (destroy_op_array) when * the swap is committed - unless it lives in opcache shared memory, which is * never freed. The entry keeps its owned reference on the function name; @@ -74,17 +75,6 @@ final class FunctionBodySwap | Core::ZEND_ACC_STRICT_TYPES | Core::ZEND_ACC_IMMUTABLE; - /** - * Static-variable defaults tables minted by swaps, keyed by entry address - * - * A minted table is exclusively owned by its entry, so the next swap of the same - * entry may release it eagerly even while the body arrays themselves are still - * shared with a live template op_array (whose own defaults pointer differs). - * - * @var array Entry address => defaults table address - */ - private static array $mintedStaticDefaults = []; - /** * This is an utility class, no instances needed */ @@ -106,10 +96,6 @@ private function __construct() {} * adopts the donor's declaration (the ClassDelta contract, * where the new source is authoritative). The entry always * keeps its own function name and class scope. - * @param bool $duplicateStatics True when the donor keeps ownership of its static-variables - * table (closure donors destroy theirs on death); false when - * the table's lifetime is guarded by the body refcount alone - * (method donors about to be released via destroy_zend_class) * @param bool $destroyPrevious False when the previous body must stay allocated on commit * (opcache shared memory is never freed) * @param int $publishedShares Number of table buckets pointing at this entry structure, @@ -121,7 +107,6 @@ public static function swapUserFunctionBody( FunctionLikeInterface $entryFunction, FunctionLikeInterface $donorFunction, bool $preserveDeclaration, - bool $duplicateStatics, bool $destroyPrevious = true, int $publishedShares = 1, ): PendingBodySwap { @@ -168,8 +153,7 @@ public static function swapUserFunctionBody( self::addBodyReference($entryFunction); } self::installFreshRunTimeCache($entryFunction); - $previousMintedRecord = self::$mintedStaticDefaults[$entryAddress] ?? null; - $mintedDefaults = self::unshareStaticVariables($entryFunction, $duplicateStatics, $entryAddress); + self::unshareStaticVariables($entryFunction); return new PendingBodySwap( $entryFunction, @@ -177,8 +161,6 @@ public static function swapUserFunctionBody( $entryAddress, $publishedShares, $destroyPrevious, - $mintedDefaults, - $previousMintedRecord, ); } @@ -262,7 +244,7 @@ public static function adoptFunctionForPublishing(CData $container, FunctionLike self::addBodyReference($containerFunction); self::installFreshRunTimeCache($containerFunction); - self::unshareStaticVariables($containerFunction, false, $containerFunction->getAddress()); + self::unshareStaticVariables($containerFunction); } /** @@ -371,46 +353,41 @@ private static function installFreshRunTimeCache(FunctionLikeInterface $entryFun } /** - * Detaches the entry's static variables from the donor + * Detaches the entry's live static-variables table from the donor * - * The live per-entry table always materializes lazily (first ZEND_BIND_STATIC dup - * of the defaults), exactly like a plain compiled function; the engine destroys it - * through its regular shutdown walks. When the donor owns the defaults table (a - * closure destroys its own on death), the entry gets an independent duplicate, - * recorded so the next swap can release it eagerly. + * Only the LIVE table is unshared: dropping the ZEND_MAP_PTR slot makes it + * materialize lazily on the first ZEND_BIND_STATIC, from the defaults, exactly + * like a plain compiled function. * - * @return bool True when an own defaults duplicate was minted for the entry + * The defaults table itself stays shared with the donor's other body holders. No + * donor kind owns it: since PHP 8.5 zend_create_closure_ex() duplicates the + * prototype defaults into the closure's ZEND_MAP_PTR slot only and leaves + * op_array.static_variables aliasing the prototype's table, whose single destroy + * is tied to the body refcount that destroy_op_array decrements. The entry holds + * one such reference per published bucket, so the last holder - whichever it turns + * out to be - frees the table exactly once. + * + * Duplicating it here instead would be a leak: the swap would replace the only + * field through which this entry's body reference could still reach the original, + * while PHP 8.5 also dropped the unconditional release destroy_op_array used to + * perform for the closure prototypes of a dying op_array. */ - private static function unshareStaticVariables( - FunctionLikeInterface $entryFunction, - bool $duplicateStatics, - int $entryAddress, - ): bool { + private static function unshareStaticVariables(FunctionLikeInterface $entryFunction): void + { $opArray = $entryFunction->getOpArrayPointer(); $opArray->static_variables_ptr__ptr = null; - $defaultsTable = $opArray->static_variables; - if ($defaultsTable !== null) { - // The engine's shutdown walk destroys per-method live static tables only - // for classes flagged as having statics - a swapped-in body with statics - // must set the flag or its materialized table leaks at request end - $entryScope = $entryFunction->getCommonPointer()->scope; - if ($entryScope !== null) { - ReflectionClass::fromCData($entryScope) - ->markHasStaticInMethods(); - } + if ($opArray->static_variables === null) { + return; } - if ($defaultsTable === null || !$duplicateStatics) { - return false; + // The engine's shutdown walk destroys per-method live static tables only + // for classes flagged as having statics - a swapped-in body with statics + // must set the flag or its materialized table leaks at request end + $entryScope = $entryFunction->getCommonPointer()->scope; + if ($entryScope !== null) { + ReflectionClass::fromCData($entryScope) + ->markHasStaticInMethods(); } - // Core::call() proxies a variadic engine symbol, its result stays untyped - $ownDefaults = Core::call('zend_array_dup', $defaultsTable); - assert($ownDefaults instanceof CData); - $opArray->static_variables = $ownDefaults; - - self::$mintedStaticDefaults[$entryAddress] = Core::addressOf($ownDefaults); - - return true; } /** @@ -466,19 +443,9 @@ public static function destroyPreviousBody(CData $previousBody, int $entryAddres Core::call('zend_destroy_static_vars', $rawOpArray); } - // A minted defaults duplicate belongs exclusively to this entry: release it - // eagerly when the shared body arrays themselves are not freed below - $defaultsTable = $previousOpArray->static_variables; - if ($defaultsTable !== null) { - $isMintedTable = (self::$mintedStaticDefaults[$entryAddress] ?? null) === Core::addressOf($defaultsTable); - if ($isMintedTable) { - if (!$isLastHolder) { - Core::call('rc_dtor_func', Core::cast('zend_refcounted *', $defaultsTable)); - $previousOpArray->static_variables = null; - } - unset(self::$mintedStaticDefaults[$entryAddress]); - } - } + // The defaults table needs no handling of its own: it is shared with the other + // holders of this body and destroy_op_array below frees it exactly when this + // entry drops the final reference // The entry keeps the single owned reference on the name - the snapshot must // not release it @@ -516,10 +483,7 @@ private static function hasLiveFrame(int $entryAddress): bool */ public static function releaseSwappedInBody( FunctionLikeInterface $entryFunction, - int $entryAddress, int $publishedShares, - bool $mintedDefaults, - ?int $previousMintedRecord, ): void { // The fresh run-time cache was installed by the swap and is not published anywhere $opArray = $entryFunction->getOpArrayPointer(); @@ -528,19 +492,8 @@ public static function releaseSwappedInBody( if (($entryFlags & Core::ZEND_ACC_HEAP_RT_CACHE) !== 0 && $cachePointer !== null) { Core::free($cachePointer); } - - if ($mintedDefaults) { - $defaultsTable = $opArray->static_variables; - if ($defaultsTable !== null) { - Core::call('rc_dtor_func', Core::cast('zend_refcounted *', $defaultsTable)); - } - // Restore the bookkeeping of the previous (still committed) swap, if any - if ($previousMintedRecord !== null) { - self::$mintedStaticDefaults[$entryAddress] = $previousMintedRecord; - } else { - unset(self::$mintedStaticDefaults[$entryAddress]); - } - } + // The defaults table was never duplicated, so the rollback owes nothing for it: + // restoring the previous body puts the entry's own pointer back in place self::dropBodyReferences($entryFunction, $publishedShares); } diff --git a/src/Reflection/FunctionLikeTrait.php b/src/Reflection/FunctionLikeTrait.php index 37789075..f81b51a4 100644 --- a/src/Reflection/FunctionLikeTrait.php +++ b/src/Reflection/FunctionLikeTrait.php @@ -150,8 +150,6 @@ public function redefine(\Closure $newCode): void $entryFunction, $donorFunction, preserveDeclaration: true, - // The donor closure owns (and destroys) its static-variables table - duplicateStatics: true, // A shared-memory body is immortal by definition and must not be freed destroyPrevious: !$isSharedMemoryEntry, // Subclass method tables may share this very structure - every such diff --git a/src/Reflection/PendingBodySwap.php b/src/Reflection/PendingBodySwap.php index 138e35ca..2b5c7967 100644 --- a/src/Reflection/PendingBodySwap.php +++ b/src/Reflection/PendingBodySwap.php @@ -40,8 +40,6 @@ final class PendingBodySwap * @param int $entryAddress Numeric identity of the entry * @param int $publishedShares Bucket shares held on both the previous and the new body * @param bool $destroyPrevious False for shared-memory previous bodies (never freed) - * @param bool $mintedDefaults True when the swap minted an own statics defaults duplicate - * @param ?int $previousMintedRecord Bookkeeping record of the previous committed swap, if any */ public function __construct( private FunctionLikeInterface $entry, @@ -49,8 +47,6 @@ public function __construct( private int $entryAddress, private int $publishedShares, private bool $destroyPrevious, - private bool $mintedDefaults, - private ?int $previousMintedRecord, ) {} /** @@ -76,13 +72,7 @@ public function rollback(): void { $this->assertUnresolved(); $this->isResolved = true; - FunctionBodySwap::releaseSwappedInBody( - $this->entry, - $this->entryAddress, - $this->publishedShares, - $this->mintedDefaults, - $this->previousMintedRecord, - ); + FunctionBodySwap::releaseSwappedInBody($this->entry, $this->publishedShares); Core::memcpy($this->entry->getEntryPointer(), Core::addr($this->previousBody), Core::sizeof($this->previousBody)); } From 22a70b1a7b3ace9a69f281c8ad7690311adc8b3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 04:44:33 +0000 Subject: [PATCH 10/15] chore(deps-dev): update phpunit/phpunit requirement || ^13.0 Updates the requirements on [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) to permit the latest version. - [Release notes](https://github.com/sebastianbergmann/phpunit/releases) - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/13.2.6/ChangeLog-13.2.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/12.2.0...13.2.6) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-version: 13.2.6 dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 02f49eae..3646cb49 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "ext-ffi": "*" }, "require-dev": { - "phpunit/phpunit": "^12.2", + "phpunit/phpunit": "^12.2 || ^13.0", "phpstan/phpstan": "^2.1", "friendsofphp/php-cs-fixer": "^3.75" }, From 7c83b37645366455c98f9d33d625da42afd67c52 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 7 Aug 2026 09:35:14 +0000 Subject: [PATCH 11/15] fix(test): restore swapped $this so the live frame stays heap-safe on PHP 8.5 testGetThis swaps the running frame's $this to a stdClass to demonstrate the capability, but left the foreign object in the frame's This slot. At frame cleanup the engine releases whatever sits there while the original object is still referenced elsewhere, and PHP 8.5's stricter allocator reports the resulting imbalance as 'zend_mm_heap corrupted' + SIGABRT (PHP 8.4 tolerated it silently). The fix restores the original $this before the frame unwinds: swapping is a real capability, not cleaning up after it in a *live* frame was the bug. Pre-existing on master; surfaced by the 8.4->master cascade running its suite on 8.5.9. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01M1Cp8nVraSrjYe3NvKP7af --- tests/System/ExecutionDataTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/System/ExecutionDataTest.php b/tests/System/ExecutionDataTest.php index 9388e160..45a82ea0 100644 --- a/tests/System/ExecutionDataTest.php +++ b/tests/System/ExecutionDataTest.php @@ -211,6 +211,14 @@ public function testGetThis() $self = $this; // Save current $this to call method on it later $thisValue->setNativeValue(new \stdClass()); $self->assertInstanceOf(\stdClass::class, $this); + + // Restore the original $this before the frame unwinds: leaving a foreign object + // in the running frame's This slot desyncs the object the engine releases at + // frame cleanup from the one still referenced elsewhere, which corrupts the heap + // on stricter allocators (PHP 8.5). Swapping is a real capability; not cleaning + // up after it in the *live* frame is the bug. + Core::$executor->getExecutionState()->getThis()->setNativeValue($self); + $self->assertSame($self, $this); } public function testGetFunction() From d73bd7ac5e375b8e30badf724b91dbce2aae3555 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 7 Aug 2026 19:34:21 +0000 Subject: [PATCH 12/15] feat(core): support PHP 8.4 and 8.5 in parallel from one codebase Engine definitions for both minors are bundled (include/8.4, include/8.5) and Core::init() already selects the set of the running interpreter; this widens the boot guard to [8.4, 8.6) and turns every hand-declared value that moved between minors into a PHP_VERSION_ID conditional: - Core::ZEND_ACC_USE_GUARDS moved from 0x800 to 0x40000000 in 8.5 - NodeKind AST_* kinds shifted when 8.5 inserted AST_OP_ARRAY and AST_CAST_VOID, added AST_PIPE and removed AST_CLONE/AST_EXIT; kinds absent on the running minor carry a negative sentinel and the name() reverse map only indexes real (non-negative, public) kinds - PayloadRelocator matches ZEND_AST_OP_ARRAY only on 8.5 (66 is AST_ZNODE on 8.4) and walks zend_attribute.validation_error and the DECLARE_ATTRIBUTED_CONST opline pair only where they exist - FunctionBodySwap restores the 8.4 statics-defaults duplication for closure donors (which own their table and destroy it on death there) while keeping the 8.5 rule of never duplicating (the table is guarded by the body refcount alone since zend_create_closure_ex changed); the ownership rules are documented on unshareStaticVariables() The 8.5-only file-cache shapes (attributed constants, const closures) use 8.5-only syntax, so they move out of the shared answer.php fixture into answer-php85.php with their own opcache-php85 test group, keeping the opcache group skip-free on every supported minor. Verified: full suite green on release 8.4.24 and 8.5.9, internal and opcache groups green on a debug 8.4 build, both header sets regenerate byte-identical. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_0184AgTjKVX4S6qmvRsdM6dt --- phpstan-baseline.neon | 2 +- src/AbstractSyntaxTree/NodeKind.php | 91 +++++++------ src/Core.php | 38 ++++-- src/HotSwap/ClassDelta.php | 10 +- src/OpCache/PayloadRelocator.php | 20 ++- src/Reflection/FunctionBodySwap.php | 140 ++++++++++++++------ src/Reflection/FunctionLikeTrait.php | 3 + src/Reflection/PendingBodySwap.php | 12 +- src/Type/ArgumentEntry.php | 3 +- src/Type/LiveRange.php | 2 +- tests/OpCache/Php85SerializerShapesTest.php | 80 +++++++++++ tests/OpCache/fixtures/answer-php85.php | 36 +++++ tests/OpCache/fixtures/answer.php | 27 +--- 13 files changed, 342 insertions(+), 122 deletions(-) create mode 100644 tests/OpCache/Php85SerializerShapesTest.php create mode 100644 tests/OpCache/fixtures/answer-php85.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 172df327..ec2d4437 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -955,7 +955,7 @@ parameters: path: src/Reflection/ReflectionClass.php - - message: '#^Binary operation "&" between mixed and 1073741824 results in an error\.$#' + message: '#^Binary operation "&" between mixed and 2048\|1073741824 results in an error\.$#' identifier: binaryOp.invalid count: 1 path: src/Reflection/ReflectionClass.php diff --git a/src/AbstractSyntaxTree/NodeKind.php b/src/AbstractSyntaxTree/NodeKind.php index 810b0162..91d77696 100644 --- a/src/AbstractSyntaxTree/NodeKind.php +++ b/src/AbstractSyntaxTree/NodeKind.php @@ -24,17 +24,26 @@ class NodeKind private const AST_IS_LIST_SHIFT = 7; private const AST_NUM_CHILDREN_SHIFT = 8; - /* Generated for PHP 8.5 from enum _zend_ast_kind; EngineConstantsTest guards these values */ + /** + * The kind values are version-dependent: PHP 8.5 inserted AST_OP_ARRAY and + * AST_CAST_VOID into enum _zend_ast_kind (shifting every later member), added + * AST_PIPE and removed AST_CLONE/AST_EXIT. A kind that does not exist on the + * running version is declared with a negative sentinel so it never matches a + * real node and never collides in the reversed name() map. + */ + private const IS_PHP85 = PHP_VERSION_ID >= 80500; + + /* Generated from enum _zend_ast_kind (8.4 and 8.5); EngineConstantsTest guards these values */ public const AST_ZVAL = 64; public const AST_CONSTANT = 65; - public const AST_OP_ARRAY = 66; - public const AST_ZNODE = 67; - public const AST_FUNC_DECL = 68; - public const AST_CLOSURE = 69; - public const AST_METHOD = 70; - public const AST_CLASS = 71; - public const AST_ARROW_FUNC = 72; - public const AST_PROPERTY_HOOK = 73; + public const AST_OP_ARRAY = self::IS_PHP85 ? 66 : -66; // PHP 8.5+ + public const AST_ZNODE = self::IS_PHP85 ? 67 : 66; + public const AST_FUNC_DECL = self::IS_PHP85 ? 68 : 67; + public const AST_CLOSURE = self::IS_PHP85 ? 69 : 68; + public const AST_METHOD = self::IS_PHP85 ? 70 : 69; + public const AST_CLASS = self::IS_PHP85 ? 71 : 70; + public const AST_ARROW_FUNC = self::IS_PHP85 ? 72 : 71; + public const AST_PROPERTY_HOOK = self::IS_PHP85 ? 73 : 72; public const AST_ARG_LIST = 128; public const AST_ARRAY = 129; public const AST_ENCAPS_LIST = 130; @@ -67,32 +76,34 @@ class NodeKind public const AST_UNARY_PLUS = 259; public const AST_UNARY_MINUS = 260; public const AST_CAST = 261; - public const AST_CAST_VOID = 262; - public const AST_EMPTY = 263; - public const AST_ISSET = 264; - public const AST_SILENCE = 265; - public const AST_SHELL_EXEC = 266; - public const AST_PRINT = 267; - public const AST_INCLUDE_OR_EVAL = 268; - public const AST_UNARY_OP = 269; - public const AST_PRE_INC = 270; - public const AST_PRE_DEC = 271; - public const AST_POST_INC = 272; - public const AST_POST_DEC = 273; - public const AST_YIELD_FROM = 274; - public const AST_CLASS_NAME = 275; - public const AST_GLOBAL = 276; - public const AST_UNSET = 277; - public const AST_RETURN = 278; - public const AST_LABEL = 279; - public const AST_REF = 280; - public const AST_HALT_COMPILER = 281; - public const AST_ECHO = 282; - public const AST_THROW = 283; - public const AST_GOTO = 284; - public const AST_BREAK = 285; - public const AST_CONTINUE = 286; - public const AST_PROPERTY_HOOK_SHORT_BODY = 287; + public const AST_CAST_VOID = self::IS_PHP85 ? 262 : -262; // PHP 8.5+ + public const AST_EMPTY = self::IS_PHP85 ? 263 : 262; + public const AST_ISSET = self::IS_PHP85 ? 264 : 263; + public const AST_SILENCE = self::IS_PHP85 ? 265 : 264; + public const AST_SHELL_EXEC = self::IS_PHP85 ? 266 : 265; + public const AST_CLONE = self::IS_PHP85 ? -266 : 266; // kind removed in PHP 8.5 + public const AST_EXIT = self::IS_PHP85 ? -267 : 267; // kind removed in PHP 8.5 + public const AST_PRINT = self::IS_PHP85 ? 267 : 268; + public const AST_INCLUDE_OR_EVAL = self::IS_PHP85 ? 268 : 269; + public const AST_UNARY_OP = self::IS_PHP85 ? 269 : 270; + public const AST_PRE_INC = self::IS_PHP85 ? 270 : 271; + public const AST_PRE_DEC = self::IS_PHP85 ? 271 : 272; + public const AST_POST_INC = self::IS_PHP85 ? 272 : 273; + public const AST_POST_DEC = self::IS_PHP85 ? 273 : 274; + public const AST_YIELD_FROM = self::IS_PHP85 ? 274 : 275; + public const AST_CLASS_NAME = self::IS_PHP85 ? 275 : 276; + public const AST_GLOBAL = self::IS_PHP85 ? 276 : 277; + public const AST_UNSET = self::IS_PHP85 ? 277 : 278; + public const AST_RETURN = self::IS_PHP85 ? 278 : 279; + public const AST_LABEL = self::IS_PHP85 ? 279 : 280; + public const AST_REF = self::IS_PHP85 ? 280 : 281; + public const AST_HALT_COMPILER = self::IS_PHP85 ? 281 : 282; + public const AST_ECHO = self::IS_PHP85 ? 282 : 283; + public const AST_THROW = self::IS_PHP85 ? 283 : 284; + public const AST_GOTO = self::IS_PHP85 ? 284 : 285; + public const AST_BREAK = self::IS_PHP85 ? 285 : 286; + public const AST_CONTINUE = self::IS_PHP85 ? 286 : 287; + public const AST_PROPERTY_HOOK_SHORT_BODY = self::IS_PHP85 ? 287 : 288; public const AST_DIM = 512; public const AST_PROP = 513; public const AST_NULLSAFE_PROP = 514; @@ -132,7 +143,7 @@ class NodeKind public const AST_MATCH_ARM = 548; public const AST_NAMED_ARG = 549; public const AST_PARENT_PROPERTY_HOOK_CALL = 550; - public const AST_PIPE = 551; + public const AST_PIPE = self::IS_PHP85 ? 551 : -551; // PHP 8.5+ public const AST_METHOD_CALL = 768; public const AST_NULLSAFE_METHOD_CALL = 769; public const AST_STATIC_CALL = 770; @@ -198,7 +209,13 @@ public static function childrenCount(int $astKind): int public static function name(int $astKind): string { if (empty(self::$constantNames)) { - self::$constantNames = array_flip((new \ReflectionClass(self::class))->getConstants()); + // Only the public AST_* kinds take part in the reverse map: the private + // helpers and the negative other-version sentinels are not node kinds + foreach ((new \ReflectionClass(self::class))->getConstants(\ReflectionClassConstant::IS_PUBLIC) as $name => $value) { + if (is_int($value) && $value >= 0) { + self::$constantNames[$value] = $name; + } + } } if (!isset(self::$constantNames[$astKind])) { diff --git a/src/Core.php b/src/Core.php index 02cd5532..f7e12360 100644 --- a/src/Core.php +++ b/src/Core.php @@ -61,11 +61,14 @@ class Core { /** - * Class, method, property and constant flags (ZEND_ACC_*) for PHP 8.5. + * Class, method, property and constant flags (ZEND_ACC_*) for PHP 8.4/8.5. * * Ground truth lives in the generated include///constants.php; - * EngineConstantsTest asserts these values match it exactly, so any drift - * in a future engine version fails CI instead of corrupting memory. + * EngineConstantsTest asserts these values match it exactly on every supported + * minor, so any drift in a future engine version fails CI instead of + * corrupting memory. A flag whose value moved between minors is declared as a + * PHP_VERSION_ID conditional, so the constant is always right for the + * running engine. */ /* Visibility flags (methods, properties, constants) */ @@ -100,7 +103,7 @@ class Core public const ZEND_ACC_NEARLY_LINKED = 0x100000; public const ZEND_ACC_ENUM = 0x10000000; public const ZEND_ACC_NOT_SERIALIZABLE = 0x20000000; - public const ZEND_ACC_USE_GUARDS = 0x40000000; // was 0x800 before PHP 8.5 + public const ZEND_ACC_USE_GUARDS = PHP_VERSION_ID >= 80500 ? 0x40000000 : 0x800; // moved in PHP 8.5 public const ZEND_ACC_UNINSTANTIABLE = 0x10000053; /* Property flags */ @@ -185,12 +188,15 @@ class Core /** * PHP version range supported by this branch: [min, max). * - * Engine memory structures differ between minor PHP versions, therefore a - * branch of z-engine works with exactly one minor version. Running against - * anything else is memory corruption, not a degraded mode - hence the hard - * boot guard. See AGENTS.md ("Version matching is non-negotiable"). + * Engine memory structures differ between minor PHP versions. z-engine hides + * that from consumers by bundling generated definitions per minor version + * (include///) and selecting the right set at boot, together + * with PHP_VERSION_ID conditionals in the few places where a hand-declared + * value moved between minors. Running on a minor OUTSIDE this range is memory + * corruption, not a degraded mode - hence the hard boot guard. See AGENTS.md + * ("Version matching is non-negotiable"). */ - private const SUPPORTED_PHP_VERSION_ID = [80500, 80600]; + private const SUPPORTED_PHP_VERSION_ID = [80400, 80600]; /** * Stores an internal instance of low-level FFI binding @@ -331,13 +337,16 @@ private static function assertSupportedEnvironment(): void [$minVersionId, $maxVersionId] = self::SUPPORTED_PHP_VERSION_ID; if (PHP_VERSION_ID < $minVersionId || PHP_VERSION_ID >= $maxVersionId) { - $supported = sprintf('%d.%d', intdiv($minVersionId, 10000), intdiv($minVersionId % 10000, 100)); + $supportedMinors = []; + for ($versionId = $minVersionId; $versionId < $maxVersionId; $versionId += 100) { + $supportedMinors[] = sprintf('%d.%d', intdiv($versionId, 10000), intdiv($versionId % 10000, 100)); + } throw new RuntimeException(sprintf( - 'z-engine (branch %1$s) supports PHP %1$s only, but you are running PHP %2$s. ' . + 'This z-engine release supports PHP %1$s, but you are running PHP %2$s. ' . 'Engine memory structures differ between minor versions: running a mismatched version ' . 'would corrupt memory and crash PHP. Install the z-engine release matching your PHP minor ' . - 'version (e.g. the "%1$s" branch for PHP %1$s, "8.0" for legacy PHP 8.0).', - $supported, + 'version (e.g. "8.0" for legacy PHP 8.0), or wait for a release adding support for a newer one.', + implode(' and ', $supportedMinors), PHP_VERSION, )); } @@ -356,7 +365,8 @@ private static function assertSupportedEnvironment(): void } /** - * Platform selector for the generated per-ABI artifacts, e.g. "8.5/linux-x64-nts" + * Platform selector for the generated per-ABI artifacts, e.g. "8.4/linux-x64-nts" + * or "8.5/linux-x64-nts" - the running PHP minor picks its own definitions */ private static function platformKey(): string { diff --git a/src/HotSwap/ClassDelta.php b/src/HotSwap/ClassDelta.php index a373f299..35bad071 100644 --- a/src/HotSwap/ClassDelta.php +++ b/src/HotSwap/ClassDelta.php @@ -313,6 +313,8 @@ public function apply(): void $donorMethod, // The new source is authoritative for the declaration as well preserveDeclaration: false, + // The donor body refcount guards the statics defaults table + duplicateStatics: false, destroyPrevious: true, publishedShares: FunctionBodySwap::countPublishedShares($entry), ); @@ -533,7 +535,13 @@ private static function releaseAdoptedContainer(CData $container): void assert($namePointer instanceof CData); StringEntry::fromCData($namePointer)->releaseReference(); - FunctionBodySwap::releaseSwappedInBody($containerFunction, 1); + FunctionBodySwap::releaseSwappedInBody( + $containerFunction, + $containerFunction->getAddress(), + 1, + false, + null, + ); Core::untrackAndFree(Core::addr($container)); } } diff --git a/src/OpCache/PayloadRelocator.php b/src/OpCache/PayloadRelocator.php index ef7bc990..5a29f791 100644 --- a/src/OpCache/PayloadRelocator.php +++ b/src/OpCache/PayloadRelocator.php @@ -60,10 +60,14 @@ final class PayloadRelocator * appear in a constant expression: ZEND_AST_OP_ARRAY (a static closure compiled * into the expression, carrying a zend_op_array pointer) and ZEND_AST_CALLABLE_CONVERT * (first-class callable syntax, whose zend_ast_fcc holds only a ZEND_MAP_PTR slot). + * + * ZEND_AST_OP_ARRAY carries a sentinel on PHP 8.4, where kind 66 is + * ZEND_AST_ZNODE (a compile-time-only node that never reaches a payload) - + * matching it there would misread the node as an embedded op_array. */ private const ZEND_AST_ZVAL = 64; private const ZEND_AST_CONSTANT = 65; - private const ZEND_AST_OP_ARRAY = 66; + private const ZEND_AST_OP_ARRAY = PHP_VERSION_ID >= 80500 ? 66 : -66; private const ZEND_AST_CALLABLE_CONVERT = 3; private const ZEND_AST_IS_LIST_SHIFT = 7; private const ZEND_AST_CHILDREN_SHIFT = 8; @@ -519,8 +523,11 @@ private function unserializeAttribute(CData $zval): void $attr = Core::pointerAtAddress('zend_attribute *', $this->unPtr($zval->value, 'ptr')); $this->unStr($attr, 'name'); $this->unStr($attr, 'lcname'); - // PHP 8.5: delayed target validation stores the pending error message here - $this->unStr($attr, 'validation_error'); + if (PHP_VERSION_ID >= 80500) { + // Delayed target validation stores the pending error message here; + // the field does not exist in the PHP 8.4 zend_attribute struct + $this->unStr($attr, 'validation_error'); + } $argSize = Core::sizeof(Core::type('zend_attribute_arg')); $argBase = Core::addressOf($attr->args); for ($i = 0; $i < $attr->argc; $i++) { @@ -536,7 +543,9 @@ private function serializeAttribute(CData $zval): void $attr = Core::pointerAtAddress('zend_attribute *', $address); $this->serStr($attr, 'name'); $this->serStr($attr, 'lcname'); - $this->serStr($attr, 'validation_error'); + if (PHP_VERSION_ID >= 80500) { + $this->serStr($attr, 'validation_error'); + } $argSize = Core::sizeof(Core::type('zend_attribute_arg')); $argBase = Core::addressOf($attr->args); for ($i = 0; $i < $attr->argc; $i++) { @@ -726,7 +735,8 @@ private function serializeOpArray(CData $opArray): void */ private function walkAttributedConstOplines(int $opcodes, int $literals, int $count, bool $serialized): void { - if ($opcodes === 0 || $literals === 0 || $count < 2) { + // ZEND_DECLARE_ATTRIBUTED_CONST exists only since PHP 8.5 (8.4 tops out at 209) + if (PHP_VERSION_ID < 80500 || $opcodes === 0 || $literals === 0 || $count < 2) { return; } $oplineSize = Core::sizeof(Core::type('zend_op')); diff --git a/src/Reflection/FunctionBodySwap.php b/src/Reflection/FunctionBodySwap.php index 00c5b256..5608e93e 100644 --- a/src/Reflection/FunctionBodySwap.php +++ b/src/Reflection/FunctionBodySwap.php @@ -33,11 +33,11 @@ * scope-dependent and owned by the donor; the engine frees a heap cache together * with the entry (destroy_op_array), and every subsequent swap releases the * previous one, so repeated swaps stay memory-flat. - * - The entry never shares the donor's LIVE static-variables table: its ZEND_MAP_PTR - * slot is dropped so the table materializes lazily on the first ZEND_BIND_STATIC, - * exactly like a plain compiled function. The defaults table behind it stays - * shared and is guarded by the body refcount alone - no donor kind owns it, see - * unshareStaticVariables() for the PHP 8.5 ownership rules. + * - Static variables never stay shared with a donor that owns them: the entry's + * ZEND_MAP_PTR slot is dropped so the live table materializes lazily on the + * first ZEND_BIND_STATIC, exactly like a plain compiled function. Whether the + * DEFAULTS table must additionally be duplicated depends on the running engine + * version - see unshareStaticVariables() for the per-version ownership rules. * - The previous body is destroyed with engine semantics (destroy_op_array) when * the swap is committed - unless it lives in opcache shared memory, which is * never freed. The entry keeps its owned reference on the function name; @@ -75,6 +75,17 @@ final class FunctionBodySwap | Core::ZEND_ACC_STRICT_TYPES | Core::ZEND_ACC_IMMUTABLE; + /** + * Static-variable defaults tables minted by swaps, keyed by entry address + * + * A minted table is exclusively owned by its entry, so the next swap of the same + * entry may release it eagerly even while the body arrays themselves are still + * shared with a live template op_array (whose own defaults pointer differs). + * + * @var array Entry address => defaults table address + */ + private static array $mintedStaticDefaults = []; + /** * This is an utility class, no instances needed */ @@ -96,6 +107,12 @@ private function __construct() {} * adopts the donor's declaration (the ClassDelta contract, * where the new source is authoritative). The entry always * keeps its own function name and class scope. + * @param bool $duplicateStatics True when the donor keeps ownership of its static-variables + * table (closure donors destroy theirs on death - a PHP 8.4 + * rule, ignored on 8.5+ where the table is guarded by the + * body refcount for every donor kind); false when the table's + * lifetime is guarded by the body refcount alone (method + * donors about to be released via destroy_zend_class) * @param bool $destroyPrevious False when the previous body must stay allocated on commit * (opcache shared memory is never freed) * @param int $publishedShares Number of table buckets pointing at this entry structure, @@ -107,6 +124,7 @@ public static function swapUserFunctionBody( FunctionLikeInterface $entryFunction, FunctionLikeInterface $donorFunction, bool $preserveDeclaration, + bool $duplicateStatics, bool $destroyPrevious = true, int $publishedShares = 1, ): PendingBodySwap { @@ -153,7 +171,8 @@ public static function swapUserFunctionBody( self::addBodyReference($entryFunction); } self::installFreshRunTimeCache($entryFunction); - self::unshareStaticVariables($entryFunction); + $previousMintedRecord = self::$mintedStaticDefaults[$entryAddress] ?? null; + $mintedDefaults = self::unshareStaticVariables($entryFunction, $duplicateStatics, $entryAddress); return new PendingBodySwap( $entryFunction, @@ -161,6 +180,8 @@ public static function swapUserFunctionBody( $entryAddress, $publishedShares, $destroyPrevious, + $mintedDefaults, + $previousMintedRecord, ); } @@ -244,7 +265,7 @@ public static function adoptFunctionForPublishing(CData $container, FunctionLike self::addBodyReference($containerFunction); self::installFreshRunTimeCache($containerFunction); - self::unshareStaticVariables($containerFunction); + self::unshareStaticVariables($containerFunction, false, $containerFunction->getAddress()); } /** @@ -353,41 +374,60 @@ private static function installFreshRunTimeCache(FunctionLikeInterface $entryFun } /** - * Detaches the entry's live static-variables table from the donor + * Detaches the entry's static variables from the donor * - * Only the LIVE table is unshared: dropping the ZEND_MAP_PTR slot makes it - * materialize lazily on the first ZEND_BIND_STATIC, from the defaults, exactly - * like a plain compiled function. + * The live per-entry table always materializes lazily (first ZEND_BIND_STATIC dup + * of the defaults), exactly like a plain compiled function; the engine destroys it + * through its regular shutdown walks. * - * The defaults table itself stays shared with the donor's other body holders. No - * donor kind owns it: since PHP 8.5 zend_create_closure_ex() duplicates the - * prototype defaults into the closure's ZEND_MAP_PTR slot only and leaves - * op_array.static_variables aliasing the prototype's table, whose single destroy - * is tied to the body refcount that destroy_op_array decrements. The entry holds - * one such reference per published bucket, so the last holder - whichever it turns - * out to be - frees the table exactly once. + * The defaults table ownership rules changed with the engine version, and the + * version split below is load-bearing in both directions: * - * Duplicating it here instead would be a leak: the swap would replace the only - * field through which this entry's body reference could still reach the original, - * while PHP 8.5 also dropped the unconditional release destroy_op_array used to - * perform for the closure prototypes of a dying op_array. + * - On PHP 8.4 a closure donor owns its defaults table and destroys it on death, + * so the entry gets an independent duplicate ($duplicateStatics), recorded so + * the next swap can release it eagerly. Skipping the duplicate would leave the + * entry pointing into freed memory once the donor dies. + * - Since PHP 8.5 no donor kind owns it: zend_create_closure_ex() duplicates the + * prototype defaults into the closure's ZEND_MAP_PTR slot only and leaves + * op_array.static_variables aliasing the prototype's table, whose single + * destroy is tied to the body refcount that destroy_op_array decrements. The + * entry holds one such reference per published bucket, so the last holder + * frees the table exactly once - and duplicating it here would be a leak, + * because the swap would replace the only field through which this entry's + * body reference could still reach the original. + * + * @return bool True when an own defaults duplicate was minted for the entry */ - private static function unshareStaticVariables(FunctionLikeInterface $entryFunction): void - { + private static function unshareStaticVariables( + FunctionLikeInterface $entryFunction, + bool $duplicateStatics, + int $entryAddress, + ): bool { $opArray = $entryFunction->getOpArrayPointer(); $opArray->static_variables_ptr__ptr = null; - if ($opArray->static_variables === null) { - return; + $defaultsTable = $opArray->static_variables; + if ($defaultsTable !== null) { + // The engine's shutdown walk destroys per-method live static tables only + // for classes flagged as having statics - a swapped-in body with statics + // must set the flag or its materialized table leaks at request end + $entryScope = $entryFunction->getCommonPointer()->scope; + if ($entryScope !== null) { + ReflectionClass::fromCData($entryScope) + ->markHasStaticInMethods(); + } } - // The engine's shutdown walk destroys per-method live static tables only - // for classes flagged as having statics - a swapped-in body with statics - // must set the flag or its materialized table leaks at request end - $entryScope = $entryFunction->getCommonPointer()->scope; - if ($entryScope !== null) { - ReflectionClass::fromCData($entryScope) - ->markHasStaticInMethods(); + if ($defaultsTable === null || !$duplicateStatics || PHP_VERSION_ID >= 80500) { + return false; } + // Core::call() proxies a variadic engine symbol, its result stays untyped + $ownDefaults = Core::call('zend_array_dup', $defaultsTable); + assert($ownDefaults instanceof CData); + $opArray->static_variables = $ownDefaults; + + self::$mintedStaticDefaults[$entryAddress] = Core::addressOf($ownDefaults); + + return true; } /** @@ -443,9 +483,19 @@ public static function destroyPreviousBody(CData $previousBody, int $entryAddres Core::call('zend_destroy_static_vars', $rawOpArray); } - // The defaults table needs no handling of its own: it is shared with the other - // holders of this body and destroy_op_array below frees it exactly when this - // entry drops the final reference + // A minted defaults duplicate belongs exclusively to this entry: release it + // eagerly when the shared body arrays themselves are not freed below + $defaultsTable = $previousOpArray->static_variables; + if ($defaultsTable !== null) { + $isMintedTable = (self::$mintedStaticDefaults[$entryAddress] ?? null) === Core::addressOf($defaultsTable); + if ($isMintedTable) { + if (!$isLastHolder) { + Core::call('rc_dtor_func', Core::cast('zend_refcounted *', $defaultsTable)); + $previousOpArray->static_variables = null; + } + unset(self::$mintedStaticDefaults[$entryAddress]); + } + } // The entry keeps the single owned reference on the name - the snapshot must // not release it @@ -483,7 +533,10 @@ private static function hasLiveFrame(int $entryAddress): bool */ public static function releaseSwappedInBody( FunctionLikeInterface $entryFunction, + int $entryAddress, int $publishedShares, + bool $mintedDefaults, + ?int $previousMintedRecord, ): void { // The fresh run-time cache was installed by the swap and is not published anywhere $opArray = $entryFunction->getOpArrayPointer(); @@ -492,8 +545,19 @@ public static function releaseSwappedInBody( if (($entryFlags & Core::ZEND_ACC_HEAP_RT_CACHE) !== 0 && $cachePointer !== null) { Core::free($cachePointer); } - // The defaults table was never duplicated, so the rollback owes nothing for it: - // restoring the previous body puts the entry's own pointer back in place + + if ($mintedDefaults) { + $defaultsTable = $opArray->static_variables; + if ($defaultsTable !== null) { + Core::call('rc_dtor_func', Core::cast('zend_refcounted *', $defaultsTable)); + } + // Restore the bookkeeping of the previous (still committed) swap, if any + if ($previousMintedRecord !== null) { + self::$mintedStaticDefaults[$entryAddress] = $previousMintedRecord; + } else { + unset(self::$mintedStaticDefaults[$entryAddress]); + } + } self::dropBodyReferences($entryFunction, $publishedShares); } diff --git a/src/Reflection/FunctionLikeTrait.php b/src/Reflection/FunctionLikeTrait.php index f0635ee3..2e0e336b 100644 --- a/src/Reflection/FunctionLikeTrait.php +++ b/src/Reflection/FunctionLikeTrait.php @@ -151,6 +151,9 @@ public function redefine(\Closure $newCode): void $entryFunction, $donorFunction, preserveDeclaration: true, + // The donor closure owns (and destroys) its static-variables table on + // PHP 8.4; on 8.5+ the flag is ignored (body refcount guards the table) + duplicateStatics: true, // A shared-memory body is immortal by definition and must not be freed destroyPrevious: !$isSharedMemoryEntry, // Subclass method tables may share this very structure - every such diff --git a/src/Reflection/PendingBodySwap.php b/src/Reflection/PendingBodySwap.php index 2b5c7967..138e35ca 100644 --- a/src/Reflection/PendingBodySwap.php +++ b/src/Reflection/PendingBodySwap.php @@ -40,6 +40,8 @@ final class PendingBodySwap * @param int $entryAddress Numeric identity of the entry * @param int $publishedShares Bucket shares held on both the previous and the new body * @param bool $destroyPrevious False for shared-memory previous bodies (never freed) + * @param bool $mintedDefaults True when the swap minted an own statics defaults duplicate + * @param ?int $previousMintedRecord Bookkeeping record of the previous committed swap, if any */ public function __construct( private FunctionLikeInterface $entry, @@ -47,6 +49,8 @@ public function __construct( private int $entryAddress, private int $publishedShares, private bool $destroyPrevious, + private bool $mintedDefaults, + private ?int $previousMintedRecord, ) {} /** @@ -72,7 +76,13 @@ public function rollback(): void { $this->assertUnresolved(); $this->isResolved = true; - FunctionBodySwap::releaseSwappedInBody($this->entry, $this->publishedShares); + FunctionBodySwap::releaseSwappedInBody( + $this->entry, + $this->entryAddress, + $this->publishedShares, + $this->mintedDefaults, + $this->previousMintedRecord, + ); Core::memcpy($this->entry->getEntryPointer(), Core::addr($this->previousBody), Core::sizeof($this->previousBody)); } diff --git a/src/Type/ArgumentEntry.php b/src/Type/ArgumentEntry.php index 00f70e62..9d083155 100644 --- a/src/Type/ArgumentEntry.php +++ b/src/Type/ArgumentEntry.php @@ -27,7 +27,8 @@ * * The zend_type.type_mask field packs the allowed-type bits together with several * argument-passing flags; the bit layout below mirrors zend_types.h/zend_compile.h - * for PHP 8.5 (there is no exported engine constant for these internal macros). + * (identical on PHP 8.4 and 8.5; there is no exported engine constant for these + * internal macros). */ class ArgumentEntry { diff --git a/src/Type/LiveRange.php b/src/Type/LiveRange.php index 042e4ac2..3eb4ec39 100644 --- a/src/Type/LiveRange.php +++ b/src/Type/LiveRange.php @@ -25,7 +25,7 @@ * A live range tells the executor which temporary variables must be destroyed when an * exception unwinds through the [start, end) opcode window. The var field packs the * variable operand offset together with a kind tag in its low bits; the KIND_* values - * mirror the ZEND_LIVE_* macros of zend_compile.h for PHP 8.5. + * mirror the ZEND_LIVE_* macros of zend_compile.h (identical on PHP 8.4 and 8.5). */ class LiveRange { diff --git a/tests/OpCache/Php85SerializerShapesTest.php b/tests/OpCache/Php85SerializerShapesTest.php new file mode 100644 index 00000000..9cd1bda3 --- /dev/null +++ b/tests/OpCache/Php85SerializerShapesTest.php @@ -0,0 +1,80 @@ + + * + * This source file is subject to the license that is bundled + * with this source code in the file LICENSE. + * + */ +declare(strict_types=1); + +namespace ZEngine\OpCache; + +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\RequiresPhp; +use PHPUnit\Framework\TestCase; +use ZEngine\Core; + +/** + * The node shapes PHP 8.5 introduced into the file-cache format: an attributed + * global constant (ZEND_DECLARE_ATTRIBUTED_CONST + ZEND_OP_DATA carrying an + * IS_PTR attribute-table literal) and a static closure compiled into a constant + * expression (ZEND_AST_OP_ARRAY). + * + * The fixture uses 8.5-only syntax, so these tests carry their own group + * (`opcache-php85`) instead of `opcache`: the `opcache` group runs under + * --fail-on-skipped on EVERY supported minor, while this group is asserted + * skip-free by `composer test:opcache85` on the minors that have the syntax. + */ +#[Group('opcache-php85')] +#[RequiresPhp('>= 8.5.0')] +final class Php85SerializerShapesTest extends TestCase +{ + use FileCacheFixture; + + protected function tearDown(): void + { + self::removeCacheDir(); + } + + public function testConstantShapesRoundTripByteIdentical(): void + { + $binPath = self::compileFixture(self::php85FixturePath()); + $payload = substr((string) file_get_contents($binPath), CacheMetaInfo::byteSize()); + $meta = CacheMetaInfo::parse((string) file_get_contents($binPath), $binPath); + + $length = strlen($payload); + $buffer = Core::new("char[{$length}]", false); + Core::memcpy($buffer, $payload, $length); + $relocator = new PayloadRelocator($buffer, $meta); + $relocator->relocate(); + + self::assertSame($payload, $relocator->derelocate(), 'The 8.5 node shapes must survive an untouched round trip byte-for-byte'); + } + + public function testConstantShapesExecuteAfterResave(): void + { + $fixture = self::php85FixturePath(); + $file = BinaryCacheFile::read(self::compileFixture($fixture), $fixture); + $file->getReflection(); // relocate + $file->save(); // re-serialize unchanged + + self::assertTrue(BinaryCacheFile::read($file->binPath())->verifyChecksum()); + self::assertSame('on5', self::runFromCache($fixture, 'zengine_bin_php85', self::$cacheDir)); + } + + /** + * The attributed-constant and const-closure shapes exist only since PHP 8.5 and + * use 8.5-only syntax, so they live in their own fixture the 8.4 runs never parse + */ + private static function php85FixturePath(): string + { + $path = realpath(__DIR__ . '/fixtures/answer-php85.php'); + self::assertIsString($path); + + return $path; + } +} diff --git a/tests/OpCache/fixtures/answer-php85.php b/tests/OpCache/fixtures/answer-php85.php new file mode 100644 index 00000000..9a10e4e4 --- /dev/null +++ b/tests/OpCache/fixtures/answer-php85.php @@ -0,0 +1,36 @@ + Date: Fri, 7 Aug 2026 19:34:31 +0000 Subject: [PATCH 13/15] chore(ci): build matrix and generator targets for PHP 8.4 + 8.5 - composer.json widens php to ~8.4.0 || ~8.5.0 and gains the test:opcache85 script for the version-gated file-cache shape tests - generate.php defaults to BOTH minors, so a symbol change regenerates every bundled definition set and header-drift checks the whole tree - symbols.php restores the PHP_VERSION_ID gate around zend_ast_op_array (the struct does not exist in 8.4 headers) - CI runs tests, PHPStan and the debug internal/opcache groups on a {8.4, 8.5} matrix; the opcache-php85 group is asserted skip-free on 8.5 only Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_0184AgTjKVX4S6qmvRsdM6dt --- .github/workflows/ci.yml | 45 ++++++++++++++++++++++++++---------- composer.json | 4 +++- tools/generator/generate.php | 11 +++++---- tools/generator/symbols.php | 6 ++--- 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab600c3e..0299321d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,14 +7,17 @@ on: - '[0-9].[0-9]' pull_request: -# This branch targets PHP 8.5 only - engine structures are version-specific. -env: - PHP_MINOR: '8.5' - +# This branch supports PHP 8.4 and 8.5 in parallel: Core selects the generated +# engine definitions of the RUNNING minor at boot, so every engine-touching job +# runs against both minors. jobs: tests: - name: Tests (release, NTS) + name: Tests (release, NTS, PHP ${{ matrix.php }}) runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: ['8.4', '8.5'] steps: - uses: actions/checkout@v4 @@ -29,7 +32,7 @@ jobs: # (AGENTS.md). uses: shivammathur/setup-php@v2 with: - php-version: ${{ env.PHP_MINOR }} + php-version: ${{ matrix.php }} extensions: ffi, opcache ini-values: ffi.enable=1, zend.assertions=1, opcache.enable=1, opcache.enable_cli=0, opcache.jit=off, opcache.jit_buffer_size=0 coverage: none @@ -52,17 +55,29 @@ jobs: - name: Opcache/SHM coverage must not silently skip run: composer test:opcache + # The PHP 8.5 file-cache shapes (attributed constants, const closures) use + # 8.5-only syntax; their group is asserted skip-free only where it applies. + - name: PHP 8.5 file-cache shapes must not silently skip + if: matrix.php != '8.4' + run: composer test:opcache85 + - name: Worker-loop soak (flat memory after warm-up) run: php -d ffi.enable=1 -d zend.assertions=1 -d opcache.jit=off tools/examples/worker-loop.php static-analysis: - name: PHPStan (level max) + name: PHPStan (level max, PHP ${{ matrix.php }}) runs-on: ubuntu-latest + # The analysis runs per minor: the version-dependent constants and the + # PHP_VERSION_ID branches resolve differently on 8.4 and 8.5. + strategy: + fail-fast: false + matrix: + php: ['8.4', '8.5'] steps: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: - php-version: ${{ env.PHP_MINOR }} + php-version: ${{ matrix.php }} extensions: ffi ini-values: ffi.enable=1 coverage: none @@ -76,15 +91,19 @@ jobs: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: - php-version: ${{ env.PHP_MINOR }} + php-version: '8.5' extensions: ffi coverage: none - uses: ramsey/composer-install@v3 - run: composer cs:check tests-internal-debug: - name: Internal group (debug build) + name: Internal group (debug build, PHP ${{ matrix.php }}) runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: ['8.4', '8.5'] # The segfault-prone destructive tests run only against a --enable-debug # PHP build, where corruption surfaces as assertion failures. There is no # official debug PHP image, so we build one here from the official image's @@ -99,7 +118,7 @@ jobs: - name: Set up PHP uses: shivammathur/setup-php@v2 with: - php-version: ${{ env.PHP_MINOR }} + php-version: ${{ matrix.php }} extensions: ffi coverage: none @@ -110,7 +129,7 @@ jobs: run: | docker build \ -f tools/docker/php-debug.Dockerfile \ - --build-arg "PHP_VERSION=${PHP_MINOR}" \ + --build-arg "PHP_VERSION=${{ matrix.php }}" \ -t z-engine-php:debug . - name: Run internal group with process isolation @@ -130,6 +149,8 @@ jobs: header-drift: name: Generated headers up to date runs-on: ubuntu-latest + # A single job regenerates every default target (8.4 and 8.5) - the drift + # check must prove the WHOLE committed include/ tree matches the pipeline. steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx diff --git a/composer.json b/composer.json index 3646cb49..c3505358 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ } ], "require": { - "php": "~8.5.0", + "php": "~8.4.0 || ~8.5.0", "ext-ffi": "*" }, "require-dev": { @@ -36,6 +36,7 @@ "test": "phpunit", "test:internal": "phpunit --group internal --process-isolation", "test:opcache": "phpunit --group opcache --fail-on-skipped", + "test:opcache85": "phpunit --group opcache-php85 --fail-on-skipped", "phpstan": "phpstan analyse", "cs:check": "php-cs-fixer fix --dry-run --diff", "cs:fix": "php-cs-fixer fix", @@ -45,6 +46,7 @@ "test": "Run the test suite (segfault-prone internal group excluded)", "test:internal": "Run the segfault-prone internal test group with process isolation (use a debug PHP build)", "test:opcache": "Run the opcache/shared-memory tests and FAIL if any of them skipped (they are self-skipping when opcache is unavailable)", + "test:opcache85": "Run the PHP 8.5-only file-cache shape tests and FAIL if any skipped (run this on PHP 8.5+)", "phpstan": "Run static analysis at the maximum level", "cs:check": "Check coding standards without fixing", "cs:fix": "Fix coding standards", diff --git a/tools/generator/generate.php b/tools/generator/generate.php index 7091725c..63c45ab3 100644 --- a/tools/generator/generate.php +++ b/tools/generator/generate.php @@ -17,16 +17,17 @@ error_reporting(E_ALL); /** - * Version/TS targets maintained on this branch. Extend when a new platform - * or thread-safety mode becomes supported (see AGENTS.md). + * Version/TS targets maintained on this branch. Extend when a new platform, + * PHP minor or thread-safety mode becomes supported (see AGENTS.md). * - * master targets PHP 8.5 only. The committed include/8.4 artifacts are - * maintained on the `8.4` branch (its own gen-headers run regenerates them) - * and arrive here through the cascade merge-up. + * This branch supports PHP 8.4 and 8.5 in parallel: Core resolves the artifact + * set of the RUNNING minor at boot, so both include/8.4 and include/8.5 are + * maintained (and drift-checked) here. * * @var list $defaultTargets */ $defaultTargets = [ + ['php' => '8.4', 'ts' => 'nts'], ['php' => '8.5', 'ts' => 'nts'], ]; diff --git a/tools/generator/symbols.php b/tools/generator/symbols.php index 24155ed8..e593ec7f 100644 --- a/tools/generator/symbols.php +++ b/tools/generator/symbols.php @@ -63,8 +63,8 @@ 'zend_ast_decl', 'zend_ast_list', 'zend_ast_zval', - // PHP 8.5: constant expressions may embed a compiled closure body - 'zend_ast_op_array', + // PHP 8.5+: constant expressions may embed a compiled closure body + ...(PHP_VERSION_ID >= 80500 ? ['zend_ast_op_array'] : []), 'zend_ast_process_t', 'zend_lex_state', 'zend_arena', @@ -306,7 +306,7 @@ 'zend_ast_decl', 'zend_ast_list', 'zend_ast_zval', - 'zend_ast_op_array', + ...(PHP_VERSION_ID >= 80500 ? ['zend_ast_op_array'] : []), 'zend_lex_state', 'zend_closure', 'zend_script', From e6f18f2dae190857b77aad52fda4bd31adea82be Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 7 Aug 2026 19:34:32 +0000 Subject: [PATCH 14/15] docs: describe the parallel PHP 8.4 + 8.5 support model README support matrix, AGENTS.md version-matching and branch-model sections, CONTRIBUTING and the bug-report template now describe one line supporting both minors, with z-engine owning all header/version complexity. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_0184AgTjKVX4S6qmvRsdM6dt --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- AGENTS.md | 50 ++++++++++++++++++--------- CONTRIBUTING.md | 9 ++--- README.md | 9 +++-- 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 2804b1e4..cdb42e56 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -34,7 +34,7 @@ body: id: z-engine-version attributes: label: z-engine version / branch - placeholder: 'dev-master (PHP 8.5), or the 8.4 branch' + placeholder: 'dev-master or the 8.4 branch (both support PHP 8.4 + 8.5)' validations: required: true - type: textarea diff --git a/AGENTS.md b/AGENTS.md index 03f1dc80..4b604627 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,19 +8,33 @@ human contributors and automated agents alike. ## The one rule that is non-negotiable: version matching -**Never run z-engine code or tests against a PHP minor version other than the -one the current branch targets.** The engine's C structures change between -every minor version (`zend_class_entry` alone changed size in 8.1, 8.3 and -8.4). z-engine reads those structures by offset. Run it on a mismatched +**Never run z-engine code or tests against a PHP minor version the current +branch has no bundled definitions for.** The engine's C structures change +between every minor version (`zend_class_entry` alone changed size in 8.1, 8.3 +and 8.4). z-engine reads those structures by offset. Run it on an unsupported version and you are reading and writing the wrong memory — the result is a crash, or worse, silent corruption. -- `master` targets the newest supported PHP minor (currently **8.5**). -- Branch `8.4` targets **PHP 8.4**. +The current line supports **PHP 8.4 and 8.5 in parallel**: both minors have +generated definitions bundled (`include/8.4/`, `include/8.5/`), `Core::init()` +selects the set matching the *running* interpreter, and the few hand-declared +values that moved between minors (`Core::ZEND_ACC_USE_GUARDS`, the +`NodeKind::AST_*` kinds, the statics-ownership rules in `FunctionBodySwap`) +are `PHP_VERSION_ID` conditionals. z-engine owns ALL of that complexity — +consumers never deal with version-dependent headers. + +- Branch `8.4` (default) and `master` both carry the parallel 8.4 + 8.5 + support; `master` is where support for the next minor lands first. - Branch `8.0` is the frozen legacy line for PHP 8.0. -`Core::init()` enforces this at runtime and refuses to boot on the wrong minor. -Do not try to defeat that guard. +`Core::init()` enforces the supported range at runtime and refuses to boot on +any other minor. Do not try to defeat that guard. + +When you add or change version-dependent behavior, it must work on EVERY minor +the branch supports: express the difference as a `PHP_VERSION_ID` conditional +(constants included — a kind that exists on only one minor gets a negative +sentinel on the others, see `NodeKind`), and make sure CI's matrix exercises +both sides of the branch you introduced. ## Branch model @@ -30,13 +44,14 @@ never cherry-picked downward. The succession is declared in which opens a merge-up PR when a version branch is pushed. ``` -8.0 (frozen) 8.4 ──► master (8.5) +8.0 (frozen) 8.4 (default, PHP 8.4 + 8.5) ──► master (PHP 8.4 + 8.5) ``` -So a bug that exists in both 8.4 and 8.5 is fixed on `8.4`, and the cascade -carries it into `master`. A bug that only exists on 8.5 is fixed on `master` -directly. When resolving a merge-up conflict inside `include/`, do **not** -merge the generated headers textually — regenerate them on the target branch +Since the 8.4/8.5 unification both `8.4` and `master` support the same two +minors; fixes land on `8.4` and the cascade carries them into `master`, which +is also where support for the NEXT minor (8.6) will be added first. When +resolving a merge-up conflict inside `include/`, do **not** merge the +generated headers textually — regenerate them on the target branch (`composer gen-headers`) instead. ## Generated engine definitions — never hand-edit @@ -53,13 +68,16 @@ Everything under `include//--/` is generated: Regenerate them with: ```bash -composer gen-headers # all targets for this branch (needs Docker) +composer gen-headers # all targets for this branch: 8.4 AND 8.5 (needs Docker) ``` The generator (`tools/generator/`) runs inside the official `php:` Docker -image so the artifacts always match a real build. Regenerate whenever you: +image so the artifacts always match a real build. The default target list in +`tools/generator/generate.php` covers every supported minor — a symbol change +regenerates all of them, never just the minor you happen to be running. +Regenerate whenever you: -- bump the branch to a new PHP minor, +- add a new PHP minor to the branch, - add or remove an engine symbol in `tools/generator/symbols.php`, - or CI's `header-drift` job goes red. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3543cc2f..7f536ba9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,9 +7,10 @@ humans and automated tools, and this document is the short human version. ## Before you start -- **Match your PHP version to the branch.** `master` targets the newest - supported PHP minor, branch `8.4` targets PHP 8.4, and so on. Running against - the wrong minor crashes PHP — this is the single most important rule. +- **Run only supported PHP minors.** The current line supports PHP 8.4 and + 8.5 in parallel (both branch `8.4` and `master`); branch `8.0` is the frozen + legacy line. Running against an unsupported minor crashes PHP — this is the + single most important rule. - Develop against a **debug PHP build** when you can (`--enable-debug`, FFI enabled). It turns silent memory corruption into loud assertion failures. A ready-made image lives in `tools/docker/php-debug.Dockerfile`. @@ -46,7 +47,7 @@ composer test:internal ## Pull request checklist - [ ] Targets the correct branch for the PHP version affected -- [ ] `composer test` passes on the matching PHP minor +- [ ] `composer test` passes on every supported PHP minor (CI runs 8.4 and 8.5) - [ ] `composer phpstan` and `composer cs:check` are green - [ ] Generated `include/` artifacts regenerated if engine symbols changed - [ ] Tests added or updated diff --git a/README.md b/README.md index 8380cc0c..3b11a27e 100644 --- a/README.md +++ b/README.md @@ -40,16 +40,15 @@ FFI lets PHP load shared libraries, call C functions, and read C structures with - PHP with the **FFI** extension enabled - **x64, non-thread-safe (NTS)** builds -Engine memory layouts change between every PHP minor version, so each PHP minor has its own generated definitions and its own branch. +Engine memory layouts change between every PHP minor version. Z-Engine hides that complexity from you: it bundles generated, version-exact definitions for **every supported minor in parallel** (`include/8.4/`, `include/8.5/`) and `Core::init()` selects the set matching the *running* interpreter at boot. Install one release, run it on PHP 8.4 or 8.5 — no per-version branch juggling in your application. | PHP | OS / Arch / TS | Branch | Status | |-----|----------------|--------|--------| -| 8.5 | linux-x64-nts | `master` | ✅ supported | -| 8.4 | linux-x64-nts | `8.4` | ✅ supported | +| 8.4 + 8.5 | linux-x64-nts | `8.4` / `master` | ✅ supported in parallel | | 8.0 | linux-x64-nts | `8.0` | 🧊 frozen (legacy) | | macOS / Windows / ZTS | — | — | 📋 [tracked in issues](https://github.com/lisachenko/z-engine/issues) | -> **Version matching is not optional.** Running Z-Engine against a PHP minor it was not built for corrupts memory. `Core::init()` enforces the match and aborts with a clear message rather than letting you crash. +> **Version matching is not optional.** Running Z-Engine against a PHP minor it has no bundled definitions for corrupts memory. `Core::init()` enforces the match and aborts with a clear message rather than letting you crash. ## Memory safety & long-running PHP @@ -275,7 +274,7 @@ These libraries are built entirely on Z-Engine and make good, real-world reading ## Contributing -Z-Engine has a couple of unusual rules — most importantly, **match your PHP version to the branch** and develop against a debug build. See **[CONTRIBUTING.md](CONTRIBUTING.md)** and **[AGENTS.md](AGENTS.md)** (the full contract for humans and automated tools). Engine definitions are generated from the PHP source by `tools/generator/` and never hand-edited. +Z-Engine has a couple of unusual rules — most importantly, **run only PHP minors the branch bundles definitions for** (currently 8.4 and 8.5) and develop against a debug build. See **[CONTRIBUTING.md](CONTRIBUTING.md)** and **[AGENTS.md](AGENTS.md)** (the full contract for humans and automated tools). Engine definitions are generated from the PHP source by `tools/generator/` and never hand-edited. ```bash composer test # safe suite From ae0fbc9ec81d75bbeab816e98c4e6bf4dbac2399 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 7 Aug 2026 19:39:06 +0000 Subject: [PATCH 15/15] fix(ci): exclude the 8.5-only fixture from PHPStan analysis ConstantAttributesRule refuses to check attributed constants unless the RUNTIME is PHP 8.5, so the 8.4 matrix leg failed on answer-php85.php. The file is opcache fixture payload, not library code - excluded like answer.php. Also documents why phpVersion stays pinned to the newest supported minor instead of the [8.4, 8.5] range: the range folds the out-of-range boot guard into an always-false branch at level max. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_0184AgTjKVX4S6qmvRsdM6dt --- phpstan.dist.neon | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/phpstan.dist.neon b/phpstan.dist.neon index 9d098335..9538dd13 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -3,6 +3,11 @@ includes: parameters: level: max + # The branch supports PHP 8.4 and 8.5 in parallel; analysis is pinned to the + # newest supported minor rather than the [8.4, 8.5] range because the range + # would fold Core::init()'s out-of-range boot guard into "always false" - + # the guard exists precisely for interpreters the analysis says cannot occur. + # CI runs this config on both matrix runtimes. phpVersion: 80500 paths: - src @@ -16,6 +21,9 @@ parameters: # Compiled into the opcache file cache by child processes; the static # counter and attribute usage are fixture payload, not library code - tests/OpCache/fixtures/answer.php + # Same, plus 8.5-only syntax that an analysis run on a PHP 8.4 runtime + # cannot even parse/check (ConstantAttributesRule refuses non-8.5 runtimes) + - tests/OpCache/fixtures/answer-php85.php # Child driver invoked in a subprocess; calls a dynamic global/method # target passed on argv, which is not statically typeable - tests/OpCache/scripts/run-cached.php