+// area_size is either a byte_size or an elements_count?&
+static int compare_heap_area_with_type(struct s_mm_diff *state, void *real_area1, void *real_area2, void *area1, void *area2,
+ xbt_dynar_t previous, mc_object_info_t info, mc_object_info_t other_info, char *type_id,
+ int area_size, int check_ignore, int pointer_level){
+
+ if(is_stack(real_area1) && is_stack(real_area2))
+ return 0;
+
+ ssize_t ignore1, ignore2;
+
+ if((check_ignore > 0) && ((ignore1 = heap_comparison_ignore_size(state->to_ignore1, real_area1)) > 0) && ((ignore2 = heap_comparison_ignore_size(state->to_ignore2, real_area2)) == ignore1)){
+ return 0;
+ }
+
+ dw_type_t type = xbt_dict_get_or_null(info->types, type_id);
+ dw_type_t subtype, subsubtype;
+ int res, elm_size, i, switch_types = 0;
+ unsigned int cursor = 0;
+ dw_type_t member;
+ void *addr_pointed1, *addr_pointed2;;
+
+ switch(type->type){
+ case DW_TAG_base_type:
+ if(type->name!=NULL && strcmp(type->name, "char") == 0){ /* String, hence random (arbitrary ?) size */
+ if(real_area1 == real_area2)
+ return -1;
+ else
+ return (memcmp(area1, area2, area_size) != 0);
+ }else{
+ if(area_size != -1 && type->byte_size != area_size)
+ return -1;
+ else{
+ return (memcmp(area1, area2, type->byte_size) != 0);
+ }
+ }
+ break;
+ case DW_TAG_enumeration_type:
+ if(area_size != -1 && type->byte_size != area_size)
+ return -1;
+ else
+ return (memcmp(area1, area2, type->byte_size) != 0);
+ break;
+ case DW_TAG_typedef:
+ case DW_TAG_const_type:
+ case DW_TAG_volatile_type:
+ return compare_heap_area_with_type(state, real_area1, real_area2, area1, area2, previous, info, other_info, type->dw_type_id, area_size, check_ignore, pointer_level);
+ break;
+ case DW_TAG_array_type:
+ subtype = xbt_dict_get_or_null(info->types, type->dw_type_id);
+ switch(subtype->type){
+ case DW_TAG_base_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_rvalue_reference_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ if(subtype->byte_size == 0){ /*declaration of the type, need the complete description */
+ subtype = xbt_dict_get_or_null(other_info->types_by_name, subtype->name);
+ switch_types = 1;
+ }
+ elm_size = subtype->byte_size;
+ break;
+ // TODO, just remove the type indirection?
+ case DW_TAG_const_type:
+ case DW_TAG_typedef:
+ case DW_TAG_volatile_type:
+ subsubtype = subtype->subtype;
+ if(subsubtype->byte_size == 0){ /*declaration of the type, need the complete description */
+ subsubtype = xbt_dict_get_or_null(other_info->types_by_name, subtype->name);
+ switch_types = 1;
+ }
+ elm_size = subsubtype->byte_size;
+ break;
+ default :
+ return 0;
+ break;
+ }
+ for(i=0; i<type->element_count; i++){
+ // TODO, add support for variable stride (DW_AT_byte_stride)
+ if(switch_types)
+ res = compare_heap_area_with_type(state, (char *)real_area1 + (i*elm_size), (char *)real_area2 + (i*elm_size), (char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), previous, other_info, info, type->dw_type_id, subtype->byte_size, check_ignore, pointer_level);
+ else
+ res = compare_heap_area_with_type(state, (char *)real_area1 + (i*elm_size), (char *)real_area2 + (i*elm_size), (char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), previous, info, other_info, type->dw_type_id, subtype->byte_size, check_ignore, pointer_level);
+ if(res == 1)
+ return res;
+ }
+ break;
+ case DW_TAG_reference_type:
+ case DW_TAG_rvalue_reference_type:
+ case DW_TAG_pointer_type:
+ if(type->dw_type_id && ((dw_type_t)xbt_dict_get_or_null(info->types, type->dw_type_id))->type == DW_TAG_subroutine_type){
+ addr_pointed1 = *((void **)(area1));
+ addr_pointed2 = *((void **)(area2));
+ return (addr_pointed1 != addr_pointed2);;
+ }else{
+ pointer_level++;
+ if(pointer_level > 1){ /* Array of pointers */
+ for(i=0; i<(area_size/sizeof(void *)); i++){
+ addr_pointed1 = *((void **)((char *)area1 + (i*sizeof(void *))));
+ addr_pointed2 = *((void **)((char *)area2 + (i*sizeof(void *))));
+ if(addr_pointed1 > state->s_heap && (char *)addr_pointed1 < (char*) state->s_heap + STD_HEAP_SIZE && addr_pointed2 > state->s_heap && (char *)addr_pointed2 < (char*) state->s_heap + STD_HEAP_SIZE)
+ res = compare_heap_area(addr_pointed1, addr_pointed2, previous, info, other_info, type->dw_type_id, pointer_level);
+ else
+ res = (addr_pointed1 != addr_pointed2);
+ if(res == 1)
+ return res;
+ }
+ }else{
+ addr_pointed1 = *((void **)(area1));
+ addr_pointed2 = *((void **)(area2));
+ if(addr_pointed1 > state->s_heap && (char *)addr_pointed1 < (char*) state->s_heap + STD_HEAP_SIZE && addr_pointed2 > state->s_heap && (char *)addr_pointed2 < (char*) state->s_heap + STD_HEAP_SIZE)
+ return compare_heap_area(addr_pointed1, addr_pointed2, previous, info, other_info, type->dw_type_id, pointer_level);
+ else
+ return (addr_pointed1 != addr_pointed2);
+ }
+ }
+ break;
+ case DW_TAG_structure_type:
+ if(type->byte_size == 0){ /*declaration of the structure, need the complete description */
+ dw_type_t full_type = xbt_dict_get_or_null(info->types_by_name, type->name);
+ if(full_type){
+ type = full_type;
+ }else{
+ type = xbt_dict_get_or_null(other_info->types_by_name, type->name);
+ switch_types = 1;
+ }
+ }
+ if(area_size != -1 && type->byte_size != area_size){
+ if(area_size>type->byte_size && area_size%type->byte_size == 0){
+ for(i=0; i<(area_size/type->byte_size); i++){
+ if(switch_types)
+ res = compare_heap_area_with_type(state, (char *)real_area1 + (i*type->byte_size), (char *)real_area2 + (i*type->byte_size), (char *)area1 + (i*type->byte_size), (char *)area2 + (i*type->byte_size), previous, other_info, info, type_id, -1, check_ignore, 0);
+ else
+ res = compare_heap_area_with_type(state, (char *)real_area1 + (i*type->byte_size), (char *)real_area2 + (i*type->byte_size), (char *)area1 + (i*type->byte_size), (char *)area2 + (i*type->byte_size), previous, info, other_info, type_id, -1, check_ignore, 0);
+ if(res == 1)
+ return res;
+ }
+ }else{
+ return -1;
+ }