PHP_METHOD(Struct, getOffset) { zval *zoffset; php_jit_struct_t *pstruct; zend_ulong of = 0; if (php_jit_parameters("z", &zoffset) != SUCCESS || !zoffset) { php_jit_exception("unexpected parameters, expected (string|integer field)"); return; } pstruct = PHP_JIT_FETCH_STRUCT(getThis()); switch (Z_TYPE_P(zoffset)) { case IS_STRING: if (!pstruct->names) { php_jit_exception("no names available"); } of = jit_type_find_name (pstruct->type, Z_STRVAL_P(zoffset)); break; case IS_LONG: of = Z_LVAL_P(zoffset); break; default: php_jit_exception("unexpected parameters, expected (string|integer field)"); return; } if (of < pstruct->nfields) { RETURN_LONG(jit_type_get_offset(pstruct->type, of)); } php_jit_exception("failed to find offset of requested field"); }
/* * On X86_64 the alignment of native types matches their size. * This leads to the result that all types except nfloats and aggregates * (structs and unions) must start and end in an eightbyte (or the part * we are looking at). */ static int _jit_classify_structpart(jit_type_t struct_type, unsigned int start, unsigned int start_offset, unsigned int end_offset) { int arg_class = X86_64_ARG_NO_CLASS; unsigned int num_fields = jit_type_num_fields(struct_type); unsigned int current_field; for(current_field = 0; current_field < num_fields; ++current_field) { jit_nuint field_offset = jit_type_get_offset(struct_type, current_field); if(field_offset <= end_offset) { /* The field starts at a place that's inerresting for us */ jit_type_t field_type = jit_type_get_field(struct_type, current_field); jit_nuint field_size = jit_type_get_size(field_type); if(field_offset + field_size > start_offset) { /* The field is at least partially in the part we are */ /* looking at */ int arg_class2 = X86_64_ARG_NO_CLASS; if(is_struct_or_union(field_type)) { /* We have to check this struct recursively */ unsigned int current_start; unsigned int nested_struct_start; unsigned int nested_struct_end; current_start = start + start_offset; if(field_offset < current_start) { nested_struct_start = current_start - field_offset; } else { nested_struct_start = 0; } if(field_offset + field_size - 1 > end_offset) { /* The struct ends beyond the part we are looking at */ nested_struct_end = field_offset + field_size - (nested_struct_start + 1); } else { nested_struct_end = field_size - 1; } arg_class2 = _jit_classify_structpart(field_type, start + field_offset, nested_struct_start, nested_struct_end); } else { if((start + start_offset) & (field_size - 1)) { /* The field is misaligned */ return X86_64_ARG_MEMORY; } arg_class2 = _jit_classify_arg(field_type, 0); } if(arg_class == X86_64_ARG_NO_CLASS) { arg_class = arg_class2; } else if(arg_class != arg_class2) { if(arg_class == X86_64_ARG_MEMORY || arg_class2 == X86_64_ARG_MEMORY) { arg_class = X86_64_ARG_MEMORY; } else if(arg_class == X86_64_ARG_INTEGER || arg_class2 == X86_64_ARG_INTEGER) { arg_class = X86_64_ARG_INTEGER; } else if(arg_class == X86_64_ARG_X87 || arg_class2 == X86_64_ARG_X87) { arg_class = X86_64_ARG_MEMORY; } else { arg_class = X86_64_ARG_SSE; } } } } } return arg_class; }