tree gfc_build_wide_string_const (int kind, int length, const gfc_char_t *string) { int i; tree str, len; size_t size; char *s; i = gfc_validate_kind (BT_CHARACTER, kind, false); size = length * gfc_character_kinds[i].bit_size / 8; s = XCNEWVAR (char, size); gfc_encode_character (kind, length, string, (unsigned char *) s, size); str = build_string (size, s); free (s); len = size_int (length); TREE_TYPE (str) = build_array_type (gfc_get_char_type (kind), build_range_type (gfc_charlen_type_node, size_one_node, len)); TYPE_STRING_FLAG (TREE_TYPE (str)) = 1; return str; }
static void pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr) { /* for VECTOR_TYPE, TYPE_MODE reevaluates the mode using target_flags not necessary valid in a global context. Use the raw value previously set by layout_type. */ bp_pack_machine_mode (bp, TYPE_MODE_RAW (expr)); bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1); /* TYPE_NO_FORCE_BLK is private to stor-layout and need no streaming. */ bp_pack_value (bp, TYPE_NEEDS_CONSTRUCTING (expr), 1); bp_pack_value (bp, TYPE_PACKED (expr), 1); bp_pack_value (bp, TYPE_RESTRICT (expr), 1); bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1); bp_pack_value (bp, TYPE_READONLY (expr), 1); /* We used to stream TYPE_ALIAS_SET == 0 information to let frontends mark types that are opaque for TBAA. This however did not work as intended, becuase TYPE_ALIAS_SET == 0 was regularly lost in type merging. */ if (RECORD_OR_UNION_TYPE_P (expr)) { bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1); bp_pack_value (bp, TYPE_FINAL_P (expr), 1); } else if (TREE_CODE (expr) == ARRAY_TYPE) bp_pack_value (bp, TYPE_NONALIASED_COMPONENT (expr), 1); bp_pack_var_len_unsigned (bp, TYPE_PRECISION (expr)); bp_pack_var_len_unsigned (bp, TYPE_ALIGN (expr)); }
static void unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr) { machine_mode mode; mode = bp_unpack_machine_mode (bp); SET_TYPE_MODE (expr, mode); TYPE_STRING_FLAG (expr) = (unsigned) bp_unpack_value (bp, 1); /* TYPE_NO_FORCE_BLK is private to stor-layout and need no streaming. */ TYPE_NEEDS_CONSTRUCTING (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1); if (RECORD_OR_UNION_TYPE_P (expr)) { TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_FINAL_P (expr) = (unsigned) bp_unpack_value (bp, 1); } else if (TREE_CODE (expr) == ARRAY_TYPE) TYPE_NONALIASED_COMPONENT (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_PRECISION (expr) = bp_unpack_var_len_unsigned (bp); TYPE_ALIGN (expr) = bp_unpack_var_len_unsigned (bp); #ifdef ACCEL_COMPILER if (TYPE_ALIGN (expr) > targetm.absolute_biggest_alignment) TYPE_ALIGN (expr) = targetm.absolute_biggest_alignment; #endif }
static void pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr) { bp_pack_enum (bp, machine_mode, MAX_MACHINE_MODE, TYPE_MODE (expr)); bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1); bp_pack_value (bp, TYPE_NO_FORCE_BLK (expr), 1); bp_pack_value (bp, TYPE_NEEDS_CONSTRUCTING (expr), 1); if (RECORD_OR_UNION_TYPE_P (expr)) { bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1); bp_pack_value (bp, TYPE_FINAL_P (expr), 1); } else if (TREE_CODE (expr) == ARRAY_TYPE) bp_pack_value (bp, TYPE_NONALIASED_COMPONENT (expr), 1); bp_pack_value (bp, TYPE_PACKED (expr), 1); bp_pack_value (bp, TYPE_RESTRICT (expr), 1); bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1); bp_pack_value (bp, TYPE_READONLY (expr), 1); bp_pack_var_len_unsigned (bp, TYPE_PRECISION (expr)); bp_pack_var_len_unsigned (bp, TYPE_ALIGN (expr)); /* Make sure to preserve the fact whether the frontend would assign alias-set zero to this type. */ bp_pack_var_len_int (bp, (TYPE_ALIAS_SET (expr) == 0 || (!in_lto_p && get_alias_set (expr) == 0)) ? 0 : -1); }
static void unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr) { machine_mode mode; mode = bp_unpack_enum (bp, machine_mode, MAX_MACHINE_MODE); SET_TYPE_MODE (expr, mode); TYPE_STRING_FLAG (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_NO_FORCE_BLK (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_NEEDS_CONSTRUCTING (expr) = (unsigned) bp_unpack_value (bp, 1); if (RECORD_OR_UNION_TYPE_P (expr)) { TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_FINAL_P (expr) = (unsigned) bp_unpack_value (bp, 1); } else if (TREE_CODE (expr) == ARRAY_TYPE) TYPE_NONALIASED_COMPONENT (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_PRECISION (expr) = bp_unpack_var_len_unsigned (bp); TYPE_ALIGN (expr) = bp_unpack_var_len_unsigned (bp); TYPE_ALIAS_SET (expr) = bp_unpack_var_len_int (bp); }
tree gfc_build_string_const (int length, const char *s) { tree str; tree len; str = build_string (length, s); len = size_int (length); TREE_TYPE (str) = build_array_type (gfc_character1_type_node, build_range_type (gfc_charlen_type_node, size_one_node, len)); TYPE_STRING_FLAG (TREE_TYPE (str)) = 1; return str; }
static void pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr) { bp_pack_enum (bp, machine_mode, MAX_MACHINE_MODE, TYPE_MODE (expr)); bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1); bp_pack_value (bp, TYPE_NO_FORCE_BLK (expr), 1); bp_pack_value (bp, TYPE_NEEDS_CONSTRUCTING (expr), 1); if (RECORD_OR_UNION_TYPE_P (expr)) bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1); bp_pack_value (bp, TYPE_PACKED (expr), 1); bp_pack_value (bp, TYPE_RESTRICT (expr), 1); bp_pack_value (bp, TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr), 2); bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1); bp_pack_value (bp, TYPE_READONLY (expr), 1); bp_pack_var_len_unsigned (bp, TYPE_PRECISION (expr)); bp_pack_var_len_unsigned (bp, TYPE_ALIGN (expr)); bp_pack_var_len_int (bp, TYPE_ALIAS_SET (expr) == 0 ? 0 : -1); }
tree gfc_build_array_ref (tree base, tree offset, tree decl) { tree type = TREE_TYPE (base); tree tmp; gcc_assert (TREE_CODE (type) == ARRAY_TYPE); type = TREE_TYPE (type); if (DECL_P (base)) TREE_ADDRESSABLE (base) = 1; /* Strip NON_LVALUE_EXPR nodes. */ STRIP_TYPE_NOPS (offset); /* If the array reference is to a pointer, whose target contains a subreference, use the span that is stored with the backend decl and reference the element with pointer arithmetic. */ if (decl && (TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL) && GFC_DECL_SUBREF_ARRAY_P (decl) && !integer_zerop (GFC_DECL_SPAN(decl))) { offset = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, offset, GFC_DECL_SPAN(decl)); tmp = gfc_build_addr_expr (pvoid_type_node, base); tmp = fold_build2_loc (input_location, POINTER_PLUS_EXPR, pvoid_type_node, tmp, fold_convert (sizetype, offset)); tmp = fold_convert (build_pointer_type (type), tmp); if (!TYPE_STRING_FLAG (type)) tmp = build_fold_indirect_ref_loc (input_location, tmp); return tmp; } else /* Otherwise use a straightforward array reference. */ return build4_loc (input_location, ARRAY_REF, type, base, offset, NULL_TREE, NULL_TREE); }
bool useless_type_conversion_p (tree outer_type, tree inner_type) { /* Do the following before stripping toplevel qualifiers. */ if (POINTER_TYPE_P (inner_type) && POINTER_TYPE_P (outer_type)) { /* Do not lose casts between pointers to different address spaces. */ if (TYPE_ADDR_SPACE (TREE_TYPE (outer_type)) != TYPE_ADDR_SPACE (TREE_TYPE (inner_type))) return false; /* Do not lose casts to function pointer types. */ if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE) && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE)) return false; } /* From now on qualifiers on value types do not matter. */ inner_type = TYPE_MAIN_VARIANT (inner_type); outer_type = TYPE_MAIN_VARIANT (outer_type); if (inner_type == outer_type) return true; /* Changes in machine mode are never useless conversions because the RTL middle-end expects explicit conversions between modes. */ if (TYPE_MODE (inner_type) != TYPE_MODE (outer_type)) return false; /* If both the inner and outer types are integral types, then the conversion is not necessary if they have the same mode and signedness and precision, and both or neither are boolean. */ if (INTEGRAL_TYPE_P (inner_type) && INTEGRAL_TYPE_P (outer_type)) { /* Preserve changes in signedness or precision. */ if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type) || TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type)) return false; /* Preserve conversions to/from BOOLEAN_TYPE if types are not of precision one. */ if (((TREE_CODE (inner_type) == BOOLEAN_TYPE) != (TREE_CODE (outer_type) == BOOLEAN_TYPE)) && TYPE_PRECISION (outer_type) != 1) return false; /* We don't need to preserve changes in the types minimum or maximum value in general as these do not generate code unless the types precisions are different. */ return true; } /* Scalar floating point types with the same mode are compatible. */ else if (SCALAR_FLOAT_TYPE_P (inner_type) && SCALAR_FLOAT_TYPE_P (outer_type)) return true; /* Fixed point types with the same mode are compatible. */ else if (FIXED_POINT_TYPE_P (inner_type) && FIXED_POINT_TYPE_P (outer_type)) return true; /* We need to take special care recursing to pointed-to types. */ else if (POINTER_TYPE_P (inner_type) && POINTER_TYPE_P (outer_type)) { /* We do not care for const qualification of the pointed-to types as const qualification has no semantic value to the middle-end. */ /* Otherwise pointers/references are equivalent. */ return true; } /* Recurse for complex types. */ else if (TREE_CODE (inner_type) == COMPLEX_TYPE && TREE_CODE (outer_type) == COMPLEX_TYPE) return useless_type_conversion_p (TREE_TYPE (outer_type), TREE_TYPE (inner_type)); /* Recurse for vector types with the same number of subparts. */ else if (TREE_CODE (inner_type) == VECTOR_TYPE && TREE_CODE (outer_type) == VECTOR_TYPE && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type)) return useless_type_conversion_p (TREE_TYPE (outer_type), TREE_TYPE (inner_type)); else if (TREE_CODE (inner_type) == ARRAY_TYPE && TREE_CODE (outer_type) == ARRAY_TYPE) { /* Preserve various attributes. */ if (TYPE_REVERSE_STORAGE_ORDER (inner_type) != TYPE_REVERSE_STORAGE_ORDER (outer_type)) return false; if (TYPE_STRING_FLAG (inner_type) != TYPE_STRING_FLAG (outer_type)) return false; /* Conversions from array types with unknown extent to array types with known extent are not useless. */ if (!TYPE_DOMAIN (inner_type) && TYPE_DOMAIN (outer_type)) return false; /* Nor are conversions from array types with non-constant size to array types with constant size or to different size. */ if (TYPE_SIZE (outer_type) && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST && (!TYPE_SIZE (inner_type) || TREE_CODE (TYPE_SIZE (inner_type)) != INTEGER_CST || !tree_int_cst_equal (TYPE_SIZE (outer_type), TYPE_SIZE (inner_type)))) return false; /* Check conversions between arrays with partially known extents. If the array min/max values are constant they have to match. Otherwise allow conversions to unknown and variable extents. In particular this declares conversions that may change the mode to BLKmode as useless. */ if (TYPE_DOMAIN (inner_type) && TYPE_DOMAIN (outer_type) && TYPE_DOMAIN (inner_type) != TYPE_DOMAIN (outer_type)) { tree inner_min = TYPE_MIN_VALUE (TYPE_DOMAIN (inner_type)); tree outer_min = TYPE_MIN_VALUE (TYPE_DOMAIN (outer_type)); tree inner_max = TYPE_MAX_VALUE (TYPE_DOMAIN (inner_type)); tree outer_max = TYPE_MAX_VALUE (TYPE_DOMAIN (outer_type)); /* After gimplification a variable min/max value carries no additional information compared to a NULL value. All that matters has been lowered to be part of the IL. */ if (inner_min && TREE_CODE (inner_min) != INTEGER_CST) inner_min = NULL_TREE; if (outer_min && TREE_CODE (outer_min) != INTEGER_CST) outer_min = NULL_TREE; if (inner_max && TREE_CODE (inner_max) != INTEGER_CST) inner_max = NULL_TREE; if (outer_max && TREE_CODE (outer_max) != INTEGER_CST) outer_max = NULL_TREE; /* Conversions NULL / variable <- cst are useless, but not the other way around. */ if (outer_min && (!inner_min || !tree_int_cst_equal (inner_min, outer_min))) return false; if (outer_max && (!inner_max || !tree_int_cst_equal (inner_max, outer_max))) return false; } /* Recurse on the element check. */ return useless_type_conversion_p (TREE_TYPE (outer_type), TREE_TYPE (inner_type)); } else if ((TREE_CODE (inner_type) == FUNCTION_TYPE || TREE_CODE (inner_type) == METHOD_TYPE) && TREE_CODE (inner_type) == TREE_CODE (outer_type)) { tree outer_parm, inner_parm; /* If the return types are not compatible bail out. */ if (!useless_type_conversion_p (TREE_TYPE (outer_type), TREE_TYPE (inner_type))) return false; /* Method types should belong to a compatible base class. */ if (TREE_CODE (inner_type) == METHOD_TYPE && !useless_type_conversion_p (TYPE_METHOD_BASETYPE (outer_type), TYPE_METHOD_BASETYPE (inner_type))) return false; /* A conversion to an unprototyped argument list is ok. */ if (!prototype_p (outer_type)) return true; /* If the unqualified argument types are compatible the conversion is useless. */ if (TYPE_ARG_TYPES (outer_type) == TYPE_ARG_TYPES (inner_type)) return true; for (outer_parm = TYPE_ARG_TYPES (outer_type), inner_parm = TYPE_ARG_TYPES (inner_type); outer_parm && inner_parm; outer_parm = TREE_CHAIN (outer_parm), inner_parm = TREE_CHAIN (inner_parm)) if (!useless_type_conversion_p (TYPE_MAIN_VARIANT (TREE_VALUE (outer_parm)), TYPE_MAIN_VARIANT (TREE_VALUE (inner_parm)))) return false; /* If there is a mismatch in the number of arguments the functions are not compatible. */ if (outer_parm || inner_parm) return false; /* Defer to the target if necessary. */ if (TYPE_ATTRIBUTES (inner_type) || TYPE_ATTRIBUTES (outer_type)) return comp_type_attributes (outer_type, inner_type) != 0; return true; } /* For aggregates we rely on TYPE_CANONICAL exclusively and require explicit conversions for types involving to be structurally compared types. */ else if (AGGREGATE_TYPE_P (inner_type) && TREE_CODE (inner_type) == TREE_CODE (outer_type)) return TYPE_CANONICAL (inner_type) && TYPE_CANONICAL (inner_type) == TYPE_CANONICAL (outer_type); else if (TREE_CODE (inner_type) == OFFSET_TYPE && TREE_CODE (outer_type) == OFFSET_TYPE) return useless_type_conversion_p (TREE_TYPE (outer_type), TREE_TYPE (inner_type)) && useless_type_conversion_p (TYPE_OFFSET_BASETYPE (outer_type), TYPE_OFFSET_BASETYPE (inner_type)); return false; }
void print_node (FILE *file, const char *prefix, tree node, int indent) { int hash; struct bucket *b; machine_mode mode; enum tree_code_class tclass; int len; int i; expanded_location xloc; enum tree_code code; if (node == 0) return; code = TREE_CODE (node); tclass = TREE_CODE_CLASS (code); /* Don't get too deep in nesting. If the user wants to see deeper, it is easy to use the address of a lowest-level node as an argument in another call to debug_tree. */ if (indent > 24) { print_node_brief (file, prefix, node, indent); return; } if (indent > 8 && (tclass == tcc_type || tclass == tcc_declaration)) { print_node_brief (file, prefix, node, indent); return; } /* It is unsafe to look at any other fields of an ERROR_MARK node. */ if (code == ERROR_MARK) { print_node_brief (file, prefix, node, indent); return; } /* Allow this function to be called if the table is not there. */ if (table) { hash = ((uintptr_t) node) % HASH_SIZE; /* If node is in the table, just mention its address. */ for (b = table[hash]; b; b = b->next) if (b->node == node) { print_node_brief (file, prefix, node, indent); return; } /* Add this node to the table. */ b = XNEW (struct bucket); b->node = node; b->next = table[hash]; table[hash] = b; } /* Indent to the specified column, since this is the long form. */ indent_to (file, indent); /* Print the slot this node is in, and its code, and address. */ fprintf (file, "%s <%s", prefix, get_tree_code_name (code)); dump_addr (file, " ", node); /* Print the name, if any. */ if (tclass == tcc_declaration) { if (DECL_NAME (node)) fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node))); else if (code == LABEL_DECL && LABEL_DECL_UID (node) != -1) { if (dump_flags & TDF_NOUID) fprintf (file, " L.xxxx"); else fprintf (file, " L.%d", (int) LABEL_DECL_UID (node)); } else { if (dump_flags & TDF_NOUID) fprintf (file, " %c.xxxx", code == CONST_DECL ? 'C' : 'D'); else fprintf (file, " %c.%u", code == CONST_DECL ? 'C' : 'D', DECL_UID (node)); } } else if (tclass == tcc_type) { if (TYPE_NAME (node)) { if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE) fprintf (file, " %s", IDENTIFIER_POINTER (TYPE_NAME (node))); else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL && DECL_NAME (TYPE_NAME (node))) fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node)))); } } if (code == IDENTIFIER_NODE) fprintf (file, " %s", IDENTIFIER_POINTER (node)); if (code == INTEGER_CST) { if (indent <= 4) print_node_brief (file, "type", TREE_TYPE (node), indent + 4); } else if (CODE_CONTAINS_STRUCT (code, TS_TYPED)) { print_node (file, "type", TREE_TYPE (node), indent + 4); if (TREE_TYPE (node)) indent_to (file, indent + 3); } if (!TYPE_P (node) && TREE_SIDE_EFFECTS (node)) fputs (" side-effects", file); if (TYPE_P (node) ? TYPE_READONLY (node) : TREE_READONLY (node)) fputs (" readonly", file); if (TYPE_P (node) && TYPE_ATOMIC (node)) fputs (" atomic", file); if (!TYPE_P (node) && TREE_CONSTANT (node)) fputs (" constant", file); else if (TYPE_P (node) && TYPE_SIZES_GIMPLIFIED (node)) fputs (" sizes-gimplified", file); if (TYPE_P (node) && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (node))) fprintf (file, " address-space-%d", TYPE_ADDR_SPACE (node)); if (TREE_ADDRESSABLE (node)) fputs (" addressable", file); if (TREE_THIS_VOLATILE (node)) fputs (" volatile", file); if (TREE_ASM_WRITTEN (node)) fputs (" asm_written", file); if (TREE_USED (node)) fputs (" used", file); if (TREE_NOTHROW (node)) fputs (" nothrow", file); if (TREE_PUBLIC (node)) fputs (" public", file); if (TREE_PRIVATE (node)) fputs (" private", file); if (TREE_PROTECTED (node)) fputs (" protected", file); if (TREE_STATIC (node)) fputs (code == CALL_EXPR ? " must-tail-call" : " static", file); if (TREE_DEPRECATED (node)) fputs (" deprecated", file); if (TREE_VISITED (node)) fputs (" visited", file); if (code != TREE_VEC && code != INTEGER_CST && code != SSA_NAME) { if (TREE_LANG_FLAG_0 (node)) fputs (" tree_0", file); if (TREE_LANG_FLAG_1 (node)) fputs (" tree_1", file); if (TREE_LANG_FLAG_2 (node)) fputs (" tree_2", file); if (TREE_LANG_FLAG_3 (node)) fputs (" tree_3", file); if (TREE_LANG_FLAG_4 (node)) fputs (" tree_4", file); if (TREE_LANG_FLAG_5 (node)) fputs (" tree_5", file); if (TREE_LANG_FLAG_6 (node)) fputs (" tree_6", file); } /* DECL_ nodes have additional attributes. */ switch (TREE_CODE_CLASS (code)) { case tcc_declaration: if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) { if (DECL_UNSIGNED (node)) fputs (" unsigned", file); if (DECL_IGNORED_P (node)) fputs (" ignored", file); if (DECL_ABSTRACT_P (node)) fputs (" abstract", file); if (DECL_EXTERNAL (node)) fputs (" external", file); if (DECL_NONLOCAL (node)) fputs (" nonlocal", file); } if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) { if (DECL_WEAK (node)) fputs (" weak", file); if (DECL_IN_SYSTEM_HEADER (node)) fputs (" in_system_header", file); } if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL) && code != LABEL_DECL && code != FUNCTION_DECL && DECL_REGISTER (node)) fputs (" regdecl", file); if (code == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node)) fputs (" suppress-debug", file); if (code == FUNCTION_DECL && DECL_FUNCTION_SPECIFIC_TARGET (node)) fputs (" function-specific-target", file); if (code == FUNCTION_DECL && DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node)) fputs (" function-specific-opt", file); if (code == FUNCTION_DECL && DECL_DECLARED_INLINE_P (node)) fputs (" autoinline", file); if (code == FUNCTION_DECL && DECL_BUILT_IN (node)) fputs (" built-in", file); if (code == FUNCTION_DECL && DECL_STATIC_CHAIN (node)) fputs (" static-chain", file); if (TREE_CODE (node) == FUNCTION_DECL && decl_is_tm_clone (node)) fputs (" tm-clone", file); if (code == FIELD_DECL && DECL_PACKED (node)) fputs (" packed", file); if (code == FIELD_DECL && DECL_BIT_FIELD (node)) fputs (" bit-field", file); if (code == FIELD_DECL && DECL_NONADDRESSABLE_P (node)) fputs (" nonaddressable", file); if (code == LABEL_DECL && EH_LANDING_PAD_NR (node)) fprintf (file, " landing-pad:%d", EH_LANDING_PAD_NR (node)); if (code == VAR_DECL && DECL_IN_TEXT_SECTION (node)) fputs (" in-text-section", file); if (code == VAR_DECL && DECL_IN_CONSTANT_POOL (node)) fputs (" in-constant-pool", file); if (code == VAR_DECL && DECL_COMMON (node)) fputs (" common", file); if (code == VAR_DECL && DECL_THREAD_LOCAL_P (node)) { fputs (" ", file); fputs (tls_model_names[DECL_TLS_MODEL (node)], file); } if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) { if (DECL_VIRTUAL_P (node)) fputs (" virtual", file); if (DECL_PRESERVE_P (node)) fputs (" preserve", file); if (DECL_LANG_FLAG_0 (node)) fputs (" decl_0", file); if (DECL_LANG_FLAG_1 (node)) fputs (" decl_1", file); if (DECL_LANG_FLAG_2 (node)) fputs (" decl_2", file); if (DECL_LANG_FLAG_3 (node)) fputs (" decl_3", file); if (DECL_LANG_FLAG_4 (node)) fputs (" decl_4", file); if (DECL_LANG_FLAG_5 (node)) fputs (" decl_5", file); if (DECL_LANG_FLAG_6 (node)) fputs (" decl_6", file); if (DECL_LANG_FLAG_7 (node)) fputs (" decl_7", file); mode = DECL_MODE (node); fprintf (file, " %s", GET_MODE_NAME (mode)); } if ((code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL) && DECL_BY_REFERENCE (node)) fputs (" passed-by-reference", file); if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS) && DECL_DEFER_OUTPUT (node)) fputs (" defer-output", file); xloc = expand_location (DECL_SOURCE_LOCATION (node)); fprintf (file, " file %s line %d col %d", xloc.file, xloc.line, xloc.column); if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) { print_node (file, "size", DECL_SIZE (node), indent + 4); print_node (file, "unit size", DECL_SIZE_UNIT (node), indent + 4); if (code != FUNCTION_DECL || DECL_BUILT_IN (node)) indent_to (file, indent + 3); if (DECL_USER_ALIGN (node)) fprintf (file, " user"); fprintf (file, " align %d", DECL_ALIGN (node)); if (code == FIELD_DECL) fprintf (file, " offset_align " HOST_WIDE_INT_PRINT_UNSIGNED, DECL_OFFSET_ALIGN (node)); if (code == FUNCTION_DECL && DECL_BUILT_IN (node)) { if (DECL_BUILT_IN_CLASS (node) == BUILT_IN_MD) fprintf (file, " built-in BUILT_IN_MD %d", DECL_FUNCTION_CODE (node)); else fprintf (file, " built-in %s:%s", built_in_class_names[(int) DECL_BUILT_IN_CLASS (node)], built_in_names[(int) DECL_FUNCTION_CODE (node)]); } } if (code == FIELD_DECL) { print_node (file, "offset", DECL_FIELD_OFFSET (node), indent + 4); print_node (file, "bit offset", DECL_FIELD_BIT_OFFSET (node), indent + 4); if (DECL_BIT_FIELD_TYPE (node)) print_node (file, "bit_field_type", DECL_BIT_FIELD_TYPE (node), indent + 4); } print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4); if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) { print_node_brief (file, "attributes", DECL_ATTRIBUTES (node), indent + 4); if (code != PARM_DECL) print_node_brief (file, "initial", DECL_INITIAL (node), indent + 4); } if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL)) { print_node_brief (file, "abstract_origin", DECL_ABSTRACT_ORIGIN (node), indent + 4); } if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON)) { print_node (file, "result", DECL_RESULT_FLD (node), indent + 4); } lang_hooks.print_decl (file, node, indent); if (DECL_RTL_SET_P (node)) { indent_to (file, indent + 4); print_rtl (file, DECL_RTL (node)); } if (code == PARM_DECL) { print_node (file, "arg-type", DECL_ARG_TYPE (node), indent + 4); if (DECL_INCOMING_RTL (node) != 0) { indent_to (file, indent + 4); fprintf (file, "incoming-rtl "); print_rtl (file, DECL_INCOMING_RTL (node)); } } else if (code == FUNCTION_DECL && DECL_STRUCT_FUNCTION (node) != 0) { print_node (file, "arguments", DECL_ARGUMENTS (node), indent + 4); indent_to (file, indent + 4); dump_addr (file, "struct-function ", DECL_STRUCT_FUNCTION (node)); } if ((code == VAR_DECL || code == PARM_DECL) && DECL_HAS_VALUE_EXPR_P (node)) print_node (file, "value-expr", DECL_VALUE_EXPR (node), indent + 4); /* Print the decl chain only if decl is at second level. */ if (indent == 4) print_node (file, "chain", TREE_CHAIN (node), indent + 4); else print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4); break; case tcc_type: if (TYPE_UNSIGNED (node)) fputs (" unsigned", file); if (TYPE_NO_FORCE_BLK (node)) fputs (" no-force-blk", file); if (TYPE_STRING_FLAG (node)) fputs (" string-flag", file); if (TYPE_NEEDS_CONSTRUCTING (node)) fputs (" needs-constructing", file); if ((code == RECORD_TYPE || code == UNION_TYPE || code == QUAL_UNION_TYPE || code == ARRAY_TYPE) && TYPE_REVERSE_STORAGE_ORDER (node)) fputs (" reverse-storage-order", file); /* The transparent-union flag is used for different things in different nodes. */ if ((code == UNION_TYPE || code == RECORD_TYPE) && TYPE_TRANSPARENT_AGGR (node)) fputs (" transparent-aggr", file); else if (code == ARRAY_TYPE && TYPE_NONALIASED_COMPONENT (node)) fputs (" nonaliased-component", file); if (TYPE_PACKED (node)) fputs (" packed", file); if (TYPE_RESTRICT (node)) fputs (" restrict", file); if (TYPE_LANG_FLAG_0 (node)) fputs (" type_0", file); if (TYPE_LANG_FLAG_1 (node)) fputs (" type_1", file); if (TYPE_LANG_FLAG_2 (node)) fputs (" type_2", file); if (TYPE_LANG_FLAG_3 (node)) fputs (" type_3", file); if (TYPE_LANG_FLAG_4 (node)) fputs (" type_4", file); if (TYPE_LANG_FLAG_5 (node)) fputs (" type_5", file); if (TYPE_LANG_FLAG_6 (node)) fputs (" type_6", file); if (TYPE_LANG_FLAG_7 (node)) fputs (" type_7", file); mode = TYPE_MODE (node); fprintf (file, " %s", GET_MODE_NAME (mode)); print_node (file, "size", TYPE_SIZE (node), indent + 4); print_node (file, "unit size", TYPE_SIZE_UNIT (node), indent + 4); indent_to (file, indent + 3); if (TYPE_USER_ALIGN (node)) fprintf (file, " user"); fprintf (file, " align %d symtab %d alias set " HOST_WIDE_INT_PRINT_DEC, TYPE_ALIGN (node), TYPE_SYMTAB_ADDRESS (node), (HOST_WIDE_INT) TYPE_ALIAS_SET (node)); if (TYPE_STRUCTURAL_EQUALITY_P (node)) fprintf (file, " structural equality"); else dump_addr (file, " canonical type ", TYPE_CANONICAL (node)); print_node (file, "attributes", TYPE_ATTRIBUTES (node), indent + 4); if (INTEGRAL_TYPE_P (node) || code == REAL_TYPE || code == FIXED_POINT_TYPE) { fprintf (file, " precision %d", TYPE_PRECISION (node)); print_node_brief (file, "min", TYPE_MIN_VALUE (node), indent + 4); print_node_brief (file, "max", TYPE_MAX_VALUE (node), indent + 4); } if (code == ENUMERAL_TYPE) print_node (file, "values", TYPE_VALUES (node), indent + 4); else if (code == ARRAY_TYPE) print_node (file, "domain", TYPE_DOMAIN (node), indent + 4); else if (code == VECTOR_TYPE) fprintf (file, " nunits %d", (int) TYPE_VECTOR_SUBPARTS (node)); else if (code == RECORD_TYPE || code == UNION_TYPE || code == QUAL_UNION_TYPE) print_node (file, "fields", TYPE_FIELDS (node), indent + 4); else if (code == FUNCTION_TYPE || code == METHOD_TYPE) { if (TYPE_METHOD_BASETYPE (node)) print_node_brief (file, "method basetype", TYPE_METHOD_BASETYPE (node), indent + 4); print_node (file, "arg-types", TYPE_ARG_TYPES (node), indent + 4); } else if (code == OFFSET_TYPE) print_node_brief (file, "basetype", TYPE_OFFSET_BASETYPE (node), indent + 4); if (TYPE_CONTEXT (node)) print_node_brief (file, "context", TYPE_CONTEXT (node), indent + 4); lang_hooks.print_type (file, node, indent); if (TYPE_POINTER_TO (node) || TREE_CHAIN (node)) indent_to (file, indent + 3); print_node_brief (file, "pointer_to_this", TYPE_POINTER_TO (node), indent + 4); print_node_brief (file, "reference_to_this", TYPE_REFERENCE_TO (node), indent + 4); print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4); break; case tcc_expression: case tcc_comparison: case tcc_unary: case tcc_binary: case tcc_reference: case tcc_statement: case tcc_vl_exp: if (code == BIND_EXPR) { print_node (file, "vars", TREE_OPERAND (node, 0), indent + 4); print_node (file, "body", TREE_OPERAND (node, 1), indent + 4); print_node (file, "block", TREE_OPERAND (node, 2), indent + 4); break; } if (code == CALL_EXPR) { call_expr_arg_iterator iter; tree arg; print_node (file, "fn", CALL_EXPR_FN (node), indent + 4); print_node (file, "static_chain", CALL_EXPR_STATIC_CHAIN (node), indent + 4); i = 0; FOR_EACH_CALL_EXPR_ARG (arg, iter, node) { char temp[10]; sprintf (temp, "arg %d", i); print_node (file, temp, arg, indent + 4); i++; } }
tree gfc_build_array_ref (tree base, tree offset, tree decl) { tree type = TREE_TYPE (base); tree tmp; tree span; if (GFC_ARRAY_TYPE_P (type) && GFC_TYPE_ARRAY_RANK (type) == 0) { gcc_assert (GFC_TYPE_ARRAY_CORANK (type) > 0); return fold_convert (TYPE_MAIN_VARIANT (type), base); } /* Scalar coarray, there is nothing to do. */ if (TREE_CODE (type) != ARRAY_TYPE) { gcc_assert (decl == NULL_TREE); gcc_assert (integer_zerop (offset)); return base; } type = TREE_TYPE (type); if (DECL_P (base)) TREE_ADDRESSABLE (base) = 1; /* Strip NON_LVALUE_EXPR nodes. */ STRIP_TYPE_NOPS (offset); /* If the array reference is to a pointer, whose target contains a subreference, use the span that is stored with the backend decl and reference the element with pointer arithmetic. */ if (decl && (TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL) && ((GFC_DECL_SUBREF_ARRAY_P (decl) && !integer_zerop (GFC_DECL_SPAN(decl))) || GFC_DECL_CLASS (decl))) { if (GFC_DECL_CLASS (decl)) { /* Allow for dummy arguments and other good things. */ if (POINTER_TYPE_P (TREE_TYPE (decl))) decl = build_fold_indirect_ref_loc (input_location, decl); /* Check if '_data' is an array descriptor. If it is not, the array must be one of the components of the class object, so return a normal array reference. */ if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_class_data_get (decl)))) return build4_loc (input_location, ARRAY_REF, type, base, offset, NULL_TREE, NULL_TREE); span = gfc_vtable_size_get (decl); } else if (GFC_DECL_SUBREF_ARRAY_P (decl)) span = GFC_DECL_SPAN(decl); else gcc_unreachable (); offset = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, offset, span); tmp = gfc_build_addr_expr (pvoid_type_node, base); tmp = fold_build_pointer_plus_loc (input_location, tmp, offset); tmp = fold_convert (build_pointer_type (type), tmp); if (!TYPE_STRING_FLAG (type)) tmp = build_fold_indirect_ref_loc (input_location, tmp); return tmp; } else /* Otherwise use a straightforward array reference. */ return build4_loc (input_location, ARRAY_REF, type, base, offset, NULL_TREE, NULL_TREE); }