static tree ubsan_type_descriptor_type (void) { static const char *field_names[3] = { "__typekind", "__typeinfo", "__typename" }; tree fields[3], ret; tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE); tree flex_arr_type = build_array_type (char_type_node, itype); ret = make_node (RECORD_TYPE); for (int i = 0; i < 3; i++) { fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, get_identifier (field_names[i]), (i == 2) ? flex_arr_type : short_unsigned_type_node); DECL_CONTEXT (fields[i]) = ret; if (i) DECL_CHAIN (fields[i - 1]) = fields[i]; } TYPE_FIELDS (ret) = fields[0]; TYPE_NAME (ret) = get_identifier ("__ubsan_type_descriptor"); layout_type (ret); return ret; }
static tree ubsan_source_location (location_t loc) { expanded_location xloc; tree type = ubsan_source_location_type (); xloc = expand_location (loc); if (xloc.file == NULL) xloc.file = "<unknown>"; /* Fill in the values from LOC. */ size_t len = strlen (xloc.file); tree str = build_string (len + 1, xloc.file); TREE_TYPE (str) = build_array_type (char_type_node, build_index_type (size_int (len))); TREE_READONLY (str) = 1; TREE_STATIC (str) = 1; str = build_fold_addr_expr (str); tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE, build_int_cst (unsigned_type_node, xloc.line), NULL_TREE, build_int_cst (unsigned_type_node, xloc.column)); TREE_CONSTANT (ctor) = 1; TREE_STATIC (ctor) = 1; return ctor; }
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 tree make_fname_decl () { const char *name = lang_hooks.decl_printable_name (current_function_decl, 0); tree decl, type, init; size_t length = strlen (name); type = build_array_type (build_type_variant (char_type_node, true, false), build_index_type (size_int (length))); decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier ("__function_name__"), type); TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; DECL_ARTIFICIAL (decl) = 1; init = build_string (length + 1, name); TREE_TYPE (init) = type; TREE_READONLY (init) = 1; DECL_READ_P (decl) = 1; DECL_INITIAL (decl) = init; TREE_USED (decl) = 1; TREE_ADDRESSABLE (decl) = 1; DECL_CONTEXT (decl) = current_function_decl; return decl; }
tree build_capture_proxy (tree member) { tree var, object, fn, closure, name, lam, type; if (PACK_EXPANSION_P (member)) member = PACK_EXPANSION_PATTERN (member); closure = DECL_CONTEXT (member); fn = lambda_function (closure); lam = CLASSTYPE_LAMBDA_EXPR (closure); /* The proxy variable forwards to the capture field. */ object = build_fold_indirect_ref (DECL_ARGUMENTS (fn)); object = finish_non_static_data_member (member, object, NULL_TREE); if (REFERENCE_REF_P (object)) object = TREE_OPERAND (object, 0); /* Remove the __ inserted by add_capture. */ if (DECL_NORMAL_CAPTURE_P (member)) name = get_identifier (IDENTIFIER_POINTER (DECL_NAME (member)) + 2); else name = DECL_NAME (member); type = lambda_proxy_type (object); if (DECL_VLA_CAPTURE_P (member)) { /* Rebuild the VLA type from the pointer and maxindex. */ tree field = next_initializable_field (TYPE_FIELDS (type)); tree ptr = build_simple_component_ref (object, field); field = next_initializable_field (DECL_CHAIN (field)); tree max = build_simple_component_ref (object, field); type = build_array_type (TREE_TYPE (TREE_TYPE (ptr)), build_index_type (max)); type = build_reference_type (type); REFERENCE_VLA_OK (type) = true; object = convert (type, ptr); } var = build_decl (input_location, VAR_DECL, name, type); SET_DECL_VALUE_EXPR (var, object); DECL_HAS_VALUE_EXPR_P (var) = 1; DECL_ARTIFICIAL (var) = 1; TREE_USED (var) = 1; DECL_CONTEXT (var) = fn; if (name == this_identifier) { gcc_assert (LAMBDA_EXPR_THIS_CAPTURE (lam) == member); LAMBDA_EXPR_THIS_CAPTURE (lam) = var; } if (fn == current_function_decl) insert_capture_proxy (var); else vec_safe_push (LAMBDA_EXPR_PENDING_PROXIES (lam), var); return var; }
static tree create_struct_type(tree decl, size_t front_rz_size, size_t rear_rz_size) { // TODO make this dynamic rather than static char type_name[50]; tree fieldfront, orig_var, fieldrear, struct_type; gcc_assert(front_rz_size % 8 == 0 && rear_rz_size % 8 == 0); struct_type = mf_mark(make_node (RECORD_TYPE)); // Build the front red zone tree front_array_idx = build_index_type (size_int (front_rz_size / sizeof(unsigned int))); tree front_rz_array = build_array_type (unsigned_type_node, front_array_idx); fieldfront = build_decl (UNKNOWN_LOCATION, FIELD_DECL, get_identifier ("rz_front"), front_rz_array); DECL_ALIGN(fieldfront) = 8; DECL_CONTEXT (fieldfront) = struct_type; // orig variable orig_var = build_decl (UNKNOWN_LOCATION, FIELD_DECL, get_identifier("orig_var"), TREE_TYPE(decl)); DECL_CONTEXT (orig_var) = struct_type; // Look at comments above DECL_CHAIN (fieldfront) = orig_var; // Rear zone if (COMPLETE_TYPE_P(decl)){ tree rear_array_idx = build_index_type (size_int (rear_rz_size / sizeof(unsigned int))); tree rear_rz_array = build_array_type (unsigned_type_node, rear_array_idx); fieldrear = build_decl (UNKNOWN_LOCATION, FIELD_DECL, get_identifier ("rz_rear"), rear_rz_array); DECL_ALIGN(fieldrear) = 8; DECL_CONTEXT (fieldrear) = struct_type; DECL_CHAIN (orig_var) = fieldrear; } TYPE_FIELDS (struct_type) = fieldfront; strcpy(type_name, "rz_"); strcat(type_name, get_name(decl)); strcat(type_name, "_type"); TYPE_NAME (struct_type) = get_identifier (type_name); layout_type (struct_type); return struct_type; }
datatype_t* ensure_good_scanred_type(datatype_t* pdt) { datatype_t* basetype; datatype_t* newtype; switch (D_CLASS(pdt)) { case DT_CHAR: case DT_BOOLEAN: case DT_SIGNED_BYTE: case DT_INTEGER: case DT_SHORT: return pdtINT; break; case DT_UNSIGNED_BYTE: case DT_UNSIGNED_SHORT: case DT_UNSIGNED_INT: return pdtUNSIGNED_INT; break; case DT_LONG: return pdtLONG; break; case DT_UNSIGNED_LONG: return pdtUNSIGNED_LONG; break; case DT_REAL: return pdtFLOAT; break; case DT_DOUBLE: return pdtDOUBLE; break; case DT_QUAD: return pdtQUAD; break; case DT_COMPLEX: return pdtCOMPLEX; break; case DT_DCOMPLEX: return pdtDCOMPLEX; break; case DT_QCOMPLEX: return pdtQCOMPLEX; break; case DT_ARRAY: basetype = D_ARR_TYPE(pdt); newtype = ensure_good_scanred_type(basetype); if (newtype == basetype) { return pdt; } else { /* sharing dimension list */ return build_array_type(D_ARR_DIM(pdt),newtype); } break; default: INT_FATAL(NULL, "Unexpected datatype in ensure_good_scanred_type(): %d", D_CLASS(pdt)); } return NULL; }
/* Initialize the global tree nodes that correspond to mf-runtime.h declarations. */ void mudflap_init (void) { static bool done = false; tree mf_const_string_type; tree mf_cache_array_type; tree mf_check_register_fntype; tree mf_unregister_fntype; tree mf_init_fntype; tree mf_set_options_fntype; if (done) return; done = true; mf_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode, /*unsignedp=*/true); mf_const_string_type = build_pointer_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST)); mf_cache_struct_type = mf_make_mf_cache_struct_type (mf_uintptr_type); mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type); mf_cache_array_type = build_array_type (mf_cache_struct_type, 0); mf_check_register_fntype = build_function_type_list (void_type_node, ptr_type_node, size_type_node, integer_type_node, mf_const_string_type, NULL_TREE); mf_unregister_fntype = build_function_type_list (void_type_node, ptr_type_node, size_type_node, integer_type_node, NULL_TREE); mf_init_fntype = build_function_type_list (void_type_node, NULL_TREE); mf_set_options_fntype = build_function_type_list (integer_type_node, mf_const_string_type, NULL_TREE); mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache", mf_cache_array_type); mf_cache_shift_decl = mf_make_builtin (VAR_DECL, "__mf_lc_shift", unsigned_char_type_node); mf_cache_mask_decl = mf_make_builtin (VAR_DECL, "__mf_lc_mask", mf_uintptr_type); /* Don't process these in mudflap_enqueue_decl, should they come by there for some reason. */ mf_mark (mf_cache_array_decl); mf_mark (mf_cache_shift_decl); mf_mark (mf_cache_mask_decl); mf_check_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_check", mf_check_register_fntype); mf_register_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_register", mf_check_register_fntype); mf_unregister_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_unregister", mf_unregister_fntype); mf_init_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_init", mf_init_fntype); mf_set_options_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_set_options", mf_set_options_fntype); }
tree build_prim_array_type (tree element_type, HOST_WIDE_INT length) { tree index = NULL; if (length != -1) { tree max_index = build_int_cst (sizetype, length - 1); index = build_index_type (max_index); } return build_array_type (element_type, index); }
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)); return str; }
/* Build a reference to a literal string. */ static tree mf_build_string (const char *string) { size_t len = strlen (string); tree result = mf_mark (build_string (len + 1, string)); TREE_TYPE (result) = build_array_type (char_type_node, build_index_type (size_int (len))); TREE_CONSTANT (result) = 1; TREE_READONLY (result) = 1; TREE_STATIC (result) = 1; result = build1 (ADDR_EXPR, build_pointer_type (char_type_node), result); return mf_mark (result); }
bool AstArrTypeNode::translate( tree& t, tree ctx, SymTable& symTable ) const { tree elemType; if( !mElemType->translate( elemType, ctx, symTable ) ) return false; t = build_array_type( elemType, build_index_type( size_int( mEnd - mBegin ) ) ); return true; }
static void build_one_array (gimple swtch, int num, tree arr_index_type, gimple phi, tree tidx) { tree array_type, ctor, decl, value_type, name, fetch; gimple load; gimple_stmt_iterator gsi; gcc_assert (info.default_values[num]); value_type = TREE_TYPE (info.default_values[num]); array_type = build_array_type (value_type, arr_index_type); ctor = build_constructor (array_type, info.constructors[num]); TREE_CONSTANT (ctor) = true; decl = build_decl (VAR_DECL, NULL_TREE, array_type); TREE_STATIC (decl) = 1; DECL_INITIAL (decl) = ctor; DECL_NAME (decl) = create_tmp_var_name ("CSWTCH"); DECL_ARTIFICIAL (decl) = 1; TREE_CONSTANT (decl) = 1; add_referenced_var (decl); varpool_mark_needed_node (varpool_node (decl)); varpool_finalize_decl (decl); mark_sym_for_renaming (decl); name = make_ssa_name (SSA_NAME_VAR (PHI_RESULT (phi)), NULL); info.target_inbound_names[num] = name; fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE, NULL_TREE); load = gimple_build_assign (name, fetch); SSA_NAME_DEF_STMT (name) = load; gsi = gsi_for_stmt (swtch); gsi_insert_before (&gsi, load, GSI_SAME_STMT); mark_symbols_for_renaming (load); info.arr_ref_last = load; }
static tree build_type () { tree ret_type, i_type, a_type, field_decl; ret_type = make_node (RECORD_TYPE); i_type = build_index_type (size_int (sizeof (CTrace) - 1)); a_type = build_array_type (char_type_node, i_type); field_decl = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, a_type); TYPE_FIELDS (ret_type) = field_decl; TYPE_SIZE_UNIT (ret_type) = build_int_cst (integer_type_node, sizeof (CTrace)); TYPE_NAME (ret_type) = get_identifier ("__CtraceStruct__"); if (dump_file) { fprintf (dump_file, "begin print built type:\n"); print_generic_stmt (dump_file, ret_type, TDF_VERBOSE); fprintf (dump_file, "end print built type:\n"); } return ret_type; }
static tree start_handler_array () { tree handler_array_type, decl; push_obstacks_nochange (); end_temporary_allocation (); handler_array_type = build_array_type (handler_element_type, NULL_TREE); decl = build_lang_decl (VAR_DECL, get_unique_identifier ("handler_table"), handler_array_type); /* TREE_TYPE (decl) = handler_array_type;*/ TREE_READONLY (decl) = 1; TREE_STATIC (decl) = 1; DECL_INITIAL (decl) = error_mark_node; pushdecl (decl); make_decl_rtl (decl, NULL_PTR, 0); current_handler->handler_array_decl = decl; return decl; }
tree build_descriptor_table_initializer (tree type, tree entries) { vec<constructor_elt, va_gc> *inits = NULL; do { vec<constructor_elt, va_gc> *elts = NULL; CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, build_selector (METHOD_SEL_NAME (entries))); CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, add_objc_string (METHOD_ENCODING (entries), meth_var_types)); CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, objc_build_constructor (type, elts)); entries = DECL_CHAIN (entries); } while (entries); return objc_build_constructor (build_array_type (type, 0), inits); }
tree build_dispatch_table_initializer (tree type, tree entries) { vec<constructor_elt, va_gc> *inits = NULL; do { vec<constructor_elt, va_gc> *elems = NULL; tree expr; CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE, build_selector (METHOD_SEL_NAME (entries))); /* Generate the method encoding if we don't have one already. */ if (! METHOD_ENCODING (entries)) METHOD_ENCODING (entries) = encode_method_prototype (entries); CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE, add_objc_string (METHOD_ENCODING (entries), meth_var_types)); expr = convert (ptr_type_node, build_unary_op (input_location, ADDR_EXPR, METHOD_DEFINITION (entries), 1)); CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE, expr); CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, objc_build_constructor (type, elems)); entries = DECL_CHAIN (entries); } while (entries); return objc_build_constructor (build_array_type (type, 0), inits); }
tree build_ivar_list_initializer (tree type, tree field_decl) { vec<constructor_elt, va_gc> *inits = NULL; do { vec<constructor_elt, va_gc> *ivar = NULL; tree id; /* Set name. */ if (DECL_NAME (field_decl)) CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, add_objc_string (DECL_NAME (field_decl), meth_var_names)); else /* Unnamed bit-field ivar (yuck). */ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, build_int_cst (NULL_TREE, 0)); /* Set type. */ id = add_objc_string (encode_field_decl (field_decl), meth_var_types); CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id); /* Set offset. */ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, byte_position (field_decl)); CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, objc_build_constructor (type, ivar)); do field_decl = DECL_CHAIN (field_decl); while (field_decl && TREE_CODE (field_decl) != FIELD_DECL); } while (field_decl); return objc_build_constructor (build_array_type (type, 0), inits); }
tree ubsan_type_descriptor (tree type) { /* See through any typedefs. */ type = TYPE_MAIN_VARIANT (type); tree decl = decl_for_type_lookup (type); if (decl != NULL_TREE) return decl; tree dtype = ubsan_type_descriptor_type (); const char *tname; unsigned short tkind, tinfo; /* At least for INTEGER_TYPE/REAL_TYPE/COMPLEX_TYPE, this should work. ??? For e.g. type_unsigned_for (type), the TYPE_NAME would be NULL. */ if (TYPE_NAME (type) != NULL) tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); else tname = "<unknown>"; if (TREE_CODE (type) == INTEGER_TYPE) { /* For INTEGER_TYPE, this is 0x0000. */ tkind = 0x000; tinfo = get_ubsan_type_info_for_type (type); } else if (TREE_CODE (type) == REAL_TYPE) /* We don't have float support yet. */ gcc_unreachable (); else gcc_unreachable (); /* Create a new VAR_DECL of type descriptor. */ char tmp_name[32]; static unsigned int type_var_id_num; ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++); decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name), dtype); TREE_STATIC (decl) = 1; TREE_PUBLIC (decl) = 0; DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; DECL_EXTERNAL (decl) = 0; size_t len = strlen (tname); tree str = build_string (len + 1, tname); TREE_TYPE (str) = build_array_type (char_type_node, build_index_type (size_int (len))); TREE_READONLY (str) = 1; TREE_STATIC (str) = 1; tree ctor = build_constructor_va (dtype, 3, NULL_TREE, build_int_cst (short_unsigned_type_node, tkind), NULL_TREE, build_int_cst (short_unsigned_type_node, tinfo), NULL_TREE, str); TREE_CONSTANT (ctor) = 1; TREE_STATIC (ctor) = 1; DECL_INITIAL (decl) = ctor; rest_of_decl_compilation (decl, 1, 0); /* Save the address of the VAR_DECL into the pointer map. */ decl = build_fold_addr_expr (decl); decl_for_type_insert (type, decl); return decl; }
static gimple input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in, struct function *fn, enum LTO_tags tag) { gimple stmt; enum gimple_code code; unsigned HOST_WIDE_INT num_ops; size_t i; struct bitpack_d bp; bool has_hist; code = lto_tag_to_gimple_code (tag); /* Read the tuple header. */ bp = streamer_read_bitpack (ib); num_ops = bp_unpack_var_len_unsigned (&bp); stmt = gimple_alloc (code, num_ops); stmt->gsbase.no_warning = bp_unpack_value (&bp, 1); if (is_gimple_assign (stmt)) stmt->gsbase.nontemporal_move = bp_unpack_value (&bp, 1); stmt->gsbase.has_volatile_ops = bp_unpack_value (&bp, 1); has_hist = bp_unpack_value (&bp, 1); stmt->gsbase.subcode = bp_unpack_var_len_unsigned (&bp); /* Read location information. */ gimple_set_location (stmt, stream_input_location (&bp, data_in)); /* Read lexical block reference. */ gimple_set_block (stmt, stream_read_tree (ib, data_in)); /* Read in all the operands. */ switch (code) { case GIMPLE_RESX: gimple_resx_set_region (stmt, streamer_read_hwi (ib)); break; case GIMPLE_EH_MUST_NOT_THROW: gimple_eh_must_not_throw_set_fndecl (stmt, stream_read_tree (ib, data_in)); break; case GIMPLE_EH_DISPATCH: gimple_eh_dispatch_set_region (stmt, streamer_read_hwi (ib)); break; case GIMPLE_ASM: { /* FIXME lto. Move most of this into a new gimple_asm_set_string(). */ tree str; stmt->gimple_asm.ni = streamer_read_uhwi (ib); stmt->gimple_asm.no = streamer_read_uhwi (ib); stmt->gimple_asm.nc = streamer_read_uhwi (ib); stmt->gimple_asm.nl = streamer_read_uhwi (ib); str = streamer_read_string_cst (data_in, ib); stmt->gimple_asm.string = TREE_STRING_POINTER (str); } /* Fallthru */ case GIMPLE_ASSIGN: case GIMPLE_CALL: case GIMPLE_RETURN: case GIMPLE_SWITCH: case GIMPLE_LABEL: case GIMPLE_COND: case GIMPLE_GOTO: case GIMPLE_DEBUG: for (i = 0; i < num_ops; i++) { tree *opp, op = stream_read_tree (ib, data_in); gimple_set_op (stmt, i, op); if (!op) continue; opp = gimple_op_ptr (stmt, i); if (TREE_CODE (*opp) == ADDR_EXPR) opp = &TREE_OPERAND (*opp, 0); while (handled_component_p (*opp)) { if (TREE_CODE (*opp) == COMPONENT_REF) { /* Fixup FIELD_DECLs in COMPONENT_REFs, they are not handled by decl merging. */ tree field, type, tem; tree closest_match = NULL_TREE; field = TREE_OPERAND (*opp, 1); type = DECL_CONTEXT (field); for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem)) { if (TREE_CODE (tem) != FIELD_DECL) continue; if (tem == field) break; if (DECL_NONADDRESSABLE_P (tem) == DECL_NONADDRESSABLE_P (field) && gimple_compare_field_offset (tem, field)) { if (types_compatible_p (TREE_TYPE (tem), TREE_TYPE (field))) break; else closest_match = tem; } } /* In case of type mismatches across units we can fail to unify some types and thus not find a proper field-decl here. */ if (tem == NULL_TREE) { /* Thus, emit a ODR violation warning. */ if (warning_at (gimple_location (stmt), 0, "use of type %<%E%> with two mismatching " "declarations at field %<%E%>", type, TREE_OPERAND (*opp, 1))) { if (TYPE_FIELDS (type)) inform (DECL_SOURCE_LOCATION (TYPE_FIELDS (type)), "original type declared here"); inform (DECL_SOURCE_LOCATION (TREE_OPERAND (*opp, 1)), "field in mismatching type declared here"); if (TYPE_NAME (TREE_TYPE (field)) && (TREE_CODE (TYPE_NAME (TREE_TYPE (field))) == TYPE_DECL)) inform (DECL_SOURCE_LOCATION (TYPE_NAME (TREE_TYPE (field))), "type of field declared here"); if (closest_match && TYPE_NAME (TREE_TYPE (closest_match)) && (TREE_CODE (TYPE_NAME (TREE_TYPE (closest_match))) == TYPE_DECL)) inform (DECL_SOURCE_LOCATION (TYPE_NAME (TREE_TYPE (closest_match))), "type of mismatching field declared here"); } /* And finally fixup the types. */ TREE_OPERAND (*opp, 0) = build1 (VIEW_CONVERT_EXPR, type, TREE_OPERAND (*opp, 0)); } else TREE_OPERAND (*opp, 1) = tem; } else if ((TREE_CODE (*opp) == ARRAY_REF || TREE_CODE (*opp) == ARRAY_RANGE_REF) && (TREE_CODE (TREE_TYPE (TREE_OPERAND (*opp, 0))) != ARRAY_TYPE)) { /* And ARRAY_REFs to objects that had mismatched types during symbol merging to avoid ICEs. */ TREE_OPERAND (*opp, 0) = build1 (VIEW_CONVERT_EXPR, build_array_type (TREE_TYPE (*opp), NULL_TREE), TREE_OPERAND (*opp, 0)); } opp = &TREE_OPERAND (*opp, 0); } /* At LTO output time we wrap all global decls in MEM_REFs to allow seamless replacement with prevailing decls. Undo this here if the prevailing decl allows for this. ??? Maybe we should simply fold all stmts. */ if (TREE_CODE (*opp) == MEM_REF && TREE_CODE (TREE_OPERAND (*opp, 0)) == ADDR_EXPR && integer_zerop (TREE_OPERAND (*opp, 1)) && (TREE_THIS_VOLATILE (*opp) == TREE_THIS_VOLATILE (TREE_OPERAND (TREE_OPERAND (*opp, 0), 0))) && !TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (*opp, 1))) && (TREE_TYPE (*opp) == TREE_TYPE (TREE_TYPE (TREE_OPERAND (*opp, 1)))) && (TREE_TYPE (*opp) == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*opp, 0), 0)))) *opp = TREE_OPERAND (TREE_OPERAND (*opp, 0), 0); } if (is_gimple_call (stmt)) { if (gimple_call_internal_p (stmt)) gimple_call_set_internal_fn (stmt, streamer_read_enum (ib, internal_fn, IFN_LAST)); else gimple_call_set_fntype (stmt, stream_read_tree (ib, data_in)); } break; case GIMPLE_NOP: case GIMPLE_PREDICT: break; case GIMPLE_TRANSACTION: gimple_transaction_set_label (stmt, stream_read_tree (ib, data_in)); break; default: internal_error ("bytecode stream: unknown GIMPLE statement tag %s", lto_tag_name (tag)); } /* Update the properties of symbols, SSA names and labels associated with STMT. */ if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL) { tree lhs = gimple_get_lhs (stmt); if (lhs && TREE_CODE (lhs) == SSA_NAME) SSA_NAME_DEF_STMT (lhs) = stmt; } else if (code == GIMPLE_LABEL) gcc_assert (emit_label_in_global_context_p (gimple_label_label (stmt)) || DECL_CONTEXT (gimple_label_label (stmt)) == fn->decl); else if (code == GIMPLE_ASM) { unsigned i; for (i = 0; i < gimple_asm_noutputs (stmt); i++) { tree op = TREE_VALUE (gimple_asm_output_op (stmt, i)); if (TREE_CODE (op) == SSA_NAME) SSA_NAME_DEF_STMT (op) = stmt; } } /* Reset alias information. */ if (code == GIMPLE_CALL) gimple_call_reset_alias_info (stmt); /* Mark the statement modified so its operand vectors can be filled in. */ gimple_set_modified (stmt, true); if (has_hist) stream_in_histogram_value (ib, stmt); return stmt; }
tree ubsan_type_descriptor (tree type, bool want_pointer_type_p) { /* See through any typedefs. */ type = TYPE_MAIN_VARIANT (type); tree decl = decl_for_type_lookup (type); /* It is possible that some of the earlier created DECLs were found unused, in that case they weren't emitted and varpool_get_node returns NULL node on them. But now we really need them. Thus, renew them here. */ if (decl != NULL_TREE && varpool_get_node (decl)) return build_fold_addr_expr (decl); tree dtype = ubsan_type_descriptor_type (); tree type2 = type; const char *tname = NULL; char *pretty_name; unsigned char deref_depth = 0; unsigned short tkind, tinfo; /* Get the name of the type, or the name of the pointer type. */ if (want_pointer_type_p) { gcc_assert (POINTER_TYPE_P (type)); type2 = TREE_TYPE (type); /* Remove any '*' operators from TYPE. */ while (POINTER_TYPE_P (type2)) deref_depth++, type2 = TREE_TYPE (type2); if (TREE_CODE (type2) == METHOD_TYPE) type2 = TYPE_METHOD_BASETYPE (type2); } if (TYPE_NAME (type2) != NULL) { if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE) tname = IDENTIFIER_POINTER (TYPE_NAME (type2)); else tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2))); } if (tname == NULL) /* We weren't able to determine the type name. */ tname = "<unknown>"; /* Decorate the type name with '', '*', "struct", or "union". */ pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth); if (want_pointer_type_p) { int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s", TYPE_VOLATILE (type2) ? "volatile " : "", TYPE_READONLY (type2) ? "const " : "", TYPE_RESTRICT (type2) ? "restrict " : "", TYPE_ATOMIC (type2) ? "_Atomic " : "", TREE_CODE (type2) == RECORD_TYPE ? "struct " : TREE_CODE (type2) == UNION_TYPE ? "union " : "", tname, deref_depth == 0 ? "" : " "); while (deref_depth-- > 0) pretty_name[pos++] = '*'; pretty_name[pos++] = '\''; pretty_name[pos] = '\0'; } else sprintf (pretty_name, "'%s'", tname); switch (TREE_CODE (type)) { case INTEGER_TYPE: tkind = 0x0000; break; case REAL_TYPE: tkind = 0x0001; break; default: tkind = 0xffff; break; } tinfo = get_ubsan_type_info_for_type (type); /* Create a new VAR_DECL of type descriptor. */ char tmp_name[32]; static unsigned int type_var_id_num; ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++); decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name), dtype); TREE_STATIC (decl) = 1; TREE_PUBLIC (decl) = 0; DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; DECL_EXTERNAL (decl) = 0; size_t len = strlen (pretty_name); tree str = build_string (len + 1, pretty_name); TREE_TYPE (str) = build_array_type (char_type_node, build_index_type (size_int (len))); TREE_READONLY (str) = 1; TREE_STATIC (str) = 1; tree ctor = build_constructor_va (dtype, 3, NULL_TREE, build_int_cst (short_unsigned_type_node, tkind), NULL_TREE, build_int_cst (short_unsigned_type_node, tinfo), NULL_TREE, str); TREE_CONSTANT (ctor) = 1; TREE_STATIC (ctor) = 1; DECL_INITIAL (decl) = ctor; rest_of_decl_compilation (decl, 1, 0); /* Save the VAR_DECL into the hash table. */ decl_for_type_insert (type, decl); return build_fold_addr_expr (decl); }
tree ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle) { /* See through any typedefs. */ type = TYPE_MAIN_VARIANT (type); tree decl = decl_for_type_lookup (type); /* It is possible that some of the earlier created DECLs were found unused, in that case they weren't emitted and varpool_get_node returns NULL node on them. But now we really need them. Thus, renew them here. */ if (decl != NULL_TREE && varpool_get_node (decl)) return build_fold_addr_expr (decl); tree dtype = ubsan_type_descriptor_type (); tree type2 = type; const char *tname = NULL; char *pretty_name; unsigned char deref_depth = 0; unsigned short tkind, tinfo; /* Get the name of the type, or the name of the pointer type. */ if (pstyle == UBSAN_PRINT_POINTER) { gcc_assert (POINTER_TYPE_P (type)); type2 = TREE_TYPE (type); /* Remove any '*' operators from TYPE. */ while (POINTER_TYPE_P (type2)) deref_depth++, type2 = TREE_TYPE (type2); if (TREE_CODE (type2) == METHOD_TYPE) type2 = TYPE_METHOD_BASETYPE (type2); } /* If an array, get its type. */ type2 = strip_array_types (type2); if (pstyle == UBSAN_PRINT_ARRAY) { while (POINTER_TYPE_P (type2)) deref_depth++, type2 = TREE_TYPE (type2); } if (TYPE_NAME (type2) != NULL) { if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE) tname = IDENTIFIER_POINTER (TYPE_NAME (type2)); else if (DECL_NAME (TYPE_NAME (type2)) != NULL) tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2))); } if (tname == NULL) /* We weren't able to determine the type name. */ tname = "<unknown>"; /* Decorate the type name with '', '*', "struct", or "union". */ pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth); if (pstyle == UBSAN_PRINT_POINTER) { int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s", TYPE_VOLATILE (type2) ? "volatile " : "", TYPE_READONLY (type2) ? "const " : "", TYPE_RESTRICT (type2) ? "restrict " : "", TYPE_ATOMIC (type2) ? "_Atomic " : "", TREE_CODE (type2) == RECORD_TYPE ? "struct " : TREE_CODE (type2) == UNION_TYPE ? "union " : "", tname, deref_depth == 0 ? "" : " "); while (deref_depth-- > 0) pretty_name[pos++] = '*'; pretty_name[pos++] = '\''; pretty_name[pos] = '\0'; } else if (pstyle == UBSAN_PRINT_ARRAY) { /* Pretty print the array dimensions. */ gcc_assert (TREE_CODE (type) == ARRAY_TYPE); tree t = type; int pos = sprintf (pretty_name, "'%s ", tname); while (deref_depth-- > 0) pretty_name[pos++] = '*'; while (TREE_CODE (t) == ARRAY_TYPE) { pretty_name[pos++] = '['; tree dom = TYPE_DOMAIN (t); if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST) pos += sprintf (&pretty_name[pos], HOST_WIDE_INT_PRINT_DEC, tree_to_shwi (TYPE_MAX_VALUE (dom)) + 1); else /* ??? We can't determine the variable name; print VLA unspec. */ pretty_name[pos++] = '*'; pretty_name[pos++] = ']'; t = TREE_TYPE (t); } pretty_name[pos++] = '\''; pretty_name[pos] = '\0'; /* Save the tree with stripped types. */ type = t; } else sprintf (pretty_name, "'%s'", tname); switch (TREE_CODE (type)) { case BOOLEAN_TYPE: case ENUMERAL_TYPE: case INTEGER_TYPE: tkind = 0x0000; break; case REAL_TYPE: /* FIXME: libubsan right now only supports float, double and long double type formats. */ if (TYPE_MODE (type) == TYPE_MODE (float_type_node) || TYPE_MODE (type) == TYPE_MODE (double_type_node) || TYPE_MODE (type) == TYPE_MODE (long_double_type_node)) tkind = 0x0001; else tkind = 0xffff; break; default: tkind = 0xffff; break; } tinfo = get_ubsan_type_info_for_type (type); /* Create a new VAR_DECL of type descriptor. */ char tmp_name[32]; static unsigned int type_var_id_num; ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++); decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name), dtype); TREE_STATIC (decl) = 1; TREE_PUBLIC (decl) = 0; DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; DECL_EXTERNAL (decl) = 0; size_t len = strlen (pretty_name); tree str = build_string (len + 1, pretty_name); TREE_TYPE (str) = build_array_type (char_type_node, build_index_type (size_int (len))); TREE_READONLY (str) = 1; TREE_STATIC (str) = 1; tree ctor = build_constructor_va (dtype, 3, NULL_TREE, build_int_cst (short_unsigned_type_node, tkind), NULL_TREE, build_int_cst (short_unsigned_type_node, tinfo), NULL_TREE, str); TREE_CONSTANT (ctor) = 1; TREE_STATIC (ctor) = 1; DECL_INITIAL (decl) = ctor; varpool_finalize_decl (decl); /* Save the VAR_DECL into the hash table. */ decl_for_type_insert (type, decl); return build_fold_addr_expr (decl); }
static void my_dump_gimple(gimple gnode, gimple_stmt_iterator *ptrgsi) { int gcode; tree tnode; tree funcdecl; tree desc_node; tree ptr_desc_node; tree t; tree tmp_var; tree const_char_restrict_ptr_type_node; gimple tmp_gstmt; gimple new_gnode; const char *hellocstr = "Hello, GCC!\n"; int i; struct c_binding *b; expanded_location xloc; /* * Extract the Gimple Code from a gimple node */ gcode = gimple_code(gnode); /* * Get the line number of cooresponding * source code from a gimple node */ if(gimple_has_location(gnode)) { xloc = expand_location(gimple_location(gnode)); printf("line %d:", xloc.line); } printf("\t\t\t\t%s\n", gimple_code_name[gcode]); switch(gcode) { case GIMPLE_ASSIGN: /* * Add a printf("Hello, GCC!\n"); statement * after the first appearing assignment * if yes equals to 1, then we have already * added the statement, and no need to add * again */ if(!yes) { /* * Since printf is a builtin function, we need * to get the function declaration using * built_in_decls[]. The index number can be * found in gcc source gcc/builtins.def */ funcdecl = built_in_decls[BUILT_IN_PRINTF]; if(funcdecl == NULL_TREE) { printf("cannot find printf\n"); } else { /* * In gimple, every statement is simplified into * three oprands mode. And our printf() statement * is change into following two gimple statements: * * <D.XXX> = (const char * restrict) &"Hello, GCC!\n"[0] * printf(<D.XXX>); * * Note that <D.XXX> is a temporary variable, we can * actually use any name we like as long as no * confliction. */ /* * Generate a STRING_CST, the value is "Hello, GCC!\n" */ desc_node = build_string(strlen(hellocstr), hellocstr); /* * Two points need to notice here: * 1. STRING_CST build by build_string() do * not have TREE_TYPE set, so we need to * set it manually. * 2. build_string() will add a trailing '\0' * when building the STRING_CST, so we do * not need to care with it. */ TREE_TYPE(desc_node) = build_array_type( char_type_node, build_index_type( build_int_cst(NULL_TREE, strlen(hellocstr)))); /* * Define a const char * restrict type node * here for convertion. * I'm not sure why we need to add a restrict * attribute, but GCC really does it when it * converting a STRING_CST from AST to Gimple. */ const_char_restrict_ptr_type_node = build_qualified_type( build_pointer_type( build_qualified_type( char_type_node, TYPE_QUAL_CONST)), TYPE_QUAL_RESTRICT); /* * When we in AST, if we want to use STRING_CST * the form is like this <ADDR_EXPR<STRING_CST>>, * but when we turn to gimple, it is like this * <ADDR_EXPR<ADDAR_REF<STRING_CST>>>. * So we need to do a convertion there. */ /* * First wrap STRING_CST with ARRAY_REF */ t = build4(ARRAY_REF, char_type_node, desc_node, build_int_cst(NULL_TREE, 0), NULL, NULL); /* * Second wrap ARRAY_REF with ADDR_EXPR */ ptr_desc_node = build1(ADDR_EXPR, const_char_restrict_ptr_type_node, t); /* * I'm not sure why we need to use fold_convert() * here, but if we do not, we cannot make the * compiling successful. */ ptr_desc_node = fold_convert( const_char_restrict_ptr_type_node, ptr_desc_node); /* * If is_gimple_min_invariant(ptr_desc_node) * is true, we build a corrent argument, otherwise * the argument is not suitable for gimple call */ if(!is_gimple_min_invariant(ptr_desc_node)) { printf("Something wrong with is_gimple_min_invariant\n"); return ; } /* * This applies for a temporary variable */ tmp_var = make_rename_temp( const_char_restrict_ptr_type_node, "plugin_var"); /* * Build a gimple statement. Still remember that? * <D.XXX> = (const char * restrict) "Hello, GCC!\n" */ tmp_gstmt = gimple_build_assign(tmp_var, ptr_desc_node); /* * Check if the gimple statment is corrent */ if(!is_gimple_assign(tmp_gstmt)) { printf("tmp_gstmt is invalid\n"); } printf("Insert gimple statment:"); print_gimple_stmt(stdout, tmp_gstmt, 0, TDF_DETAILS | TDF_VERBOSE | TDF_TREE); /* * Insert the gimple statment into the basic block */ gsi_insert_after(ptrgsi, tmp_gstmt, GSI_NEW_STMT); if(is_gimple_operand(tmp_var)) { printf("begin to insert printf\n"); yes = 1; printf("Insert gimple statment:"); /* * Insert the gimple statment printf * into the basic block */ new_gnode = gimple_build_call( funcdecl, 1, tmp_var); print_gimple_stmt(stdout, new_gnode, 0, 0); gsi_insert_after(ptrgsi, new_gnode, GSI_NEW_STMT); } else { print_generic_stmt(stdout, ptr_desc_node, TDF_DETAILS | TDF_VERBOSE | TDF_TREE); printf("Not Gimple Operands\n"); } /* * Since we have more than one consecutive statements * to insert, we can actually use build a gimple * sequence, insert all statement into the sequence, * and then insert the sequence into the basic block. * This seems to be a better method. */ } } else { } break; default: break; } }
void declare_function_name () { tree decl, type, init; char *name, *printable_name; int len; if (current_function_decl == NULL) { name = ""; printable_name = "top level"; } else { char *kind = "function"; if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE) kind = "method"; /* Allow functions to be nameless (such as artificial ones). */ if (DECL_NAME (current_function_decl)) name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl)); else name = ""; printable_name = (*decl_printable_name) (current_function_decl, &kind); } /* If the default size of char arrays isn't big enough for the name, make a bigger one. */ len = strlen (name) + 1; type = char_array_type_node; if (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TREE_TYPE (char_array_type_node))) < len) type = build_array_type (char_type_node, build_index_type (build_int_2 (len, 0))); push_obstacks_nochange (); decl = build_decl (VAR_DECL, get_identifier ("__FUNCTION__"), type); TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; DECL_SOURCE_LINE (decl) = 0; DECL_IN_SYSTEM_HEADER (decl) = 1; DECL_IGNORED_P (decl) = 1; init = build_string (len, name); TREE_TYPE (init) = type; DECL_INITIAL (decl) = init; finish_decl (pushdecl (decl), init, NULL_TREE); len = strlen (printable_name) + 1; type = char_array_type_node; if (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TREE_TYPE (char_array_type_node))) < len) type = build_array_type (char_type_node, build_index_type (build_int_2 (len, 0))); push_obstacks_nochange (); decl = build_decl (VAR_DECL, get_identifier ("__PRETTY_FUNCTION__"), type); TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; DECL_SOURCE_LINE (decl) = 0; DECL_IN_SYSTEM_HEADER (decl) = 1; DECL_IGNORED_P (decl) = 1; init = build_string (len, printable_name); TREE_TYPE (init) = type; DECL_INITIAL (decl) = init; finish_decl (pushdecl (decl), init, NULL_TREE); }
tree build_sized_array_type (tree base_type, int size) { tree index_type = build_index_type (build_int_cst (NULL_TREE, size - 1)); return build_array_type (base_type, index_type); }
static tree get_pseudo_ti_desc (tree type) { switch (TREE_CODE (type)) { case OFFSET_TYPE: return ptm_desc_type_node; case POINTER_TYPE: return ptr_desc_type_node; case ENUMERAL_TYPE: return enum_desc_type_node; case FUNCTION_TYPE: return func_desc_type_node; case ARRAY_TYPE: return ary_desc_type_node; case UNION_TYPE: case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (type)) return ptm_desc_type_node; else if (!COMPLETE_TYPE_P (type)) { if (!at_eof) cxx_incomplete_type_error (NULL_TREE, type); return class_desc_type_node; } else if (!BINFO_N_BASE_BINFOS (TYPE_BINFO (type))) return class_desc_type_node; else { tree binfo = TYPE_BINFO (type); VEC (tree) *base_accesses = BINFO_BASE_ACCESSES (binfo); tree base_binfo = BINFO_BASE_BINFO (binfo, 0); int num_bases = BINFO_N_BASE_BINFOS (binfo); if (num_bases == 1 && VEC_index (tree, base_accesses, 0) == access_public_node && !BINFO_VIRTUAL_P (base_binfo) && integer_zerop (BINFO_OFFSET (base_binfo))) /* single non-virtual public. */ return si_class_desc_type_node; else { tree var_desc; tree array_domain, base_array; if (TREE_VEC_LENGTH (vmi_class_desc_type_node) <= num_bases) { int ix; tree extend = make_tree_vec (num_bases + 5); for (ix = TREE_VEC_LENGTH (vmi_class_desc_type_node); ix--;) TREE_VEC_ELT (extend, ix) = TREE_VEC_ELT (vmi_class_desc_type_node, ix); vmi_class_desc_type_node = extend; } var_desc = TREE_VEC_ELT (vmi_class_desc_type_node, num_bases); if (var_desc) return var_desc; /* Create the array of __base_class_type_info entries. G++ 3.2 allocated an array that had one too many entries, and then filled that extra entries with zeros. */ if (abi_version_at_least (2)) array_domain = build_index_type (size_int (num_bases - 1)); else array_domain = build_index_type (size_int (num_bases)); base_array = build_array_type (base_desc_type_node, array_domain); push_nested_namespace (abi_node); var_desc = create_pseudo_type_info ("__vmi_class_type_info", num_bases, build_decl (FIELD_DECL, NULL_TREE, integer_type_node), build_decl (FIELD_DECL, NULL_TREE, integer_type_node), build_decl (FIELD_DECL, NULL_TREE, base_array), NULL); pop_nested_namespace (abi_node); TREE_VEC_ELT (vmi_class_desc_type_node, num_bases) = var_desc; return var_desc; } } default: return bltn_desc_type_node; } }
static tree get_init_field (segment_info *head, tree union_type, tree *field_init, record_layout_info rli) { segment_info *s; HOST_WIDE_INT length = 0; HOST_WIDE_INT offset = 0; unsigned HOST_WIDE_INT known_align, desired_align; bool overlap = false; tree tmp, field; tree init; unsigned char *data, *chk; VEC(constructor_elt,gc) *v = NULL; tree type = unsigned_char_type_node; int i; /* Obtain the size of the union and check if there are any overlapping initializers. */ for (s = head; s; s = s->next) { HOST_WIDE_INT slen = s->offset + s->length; if (s->sym->value) { if (s->offset < offset) overlap = true; offset = slen; } length = length < slen ? slen : length; } if (!overlap) return NULL_TREE; /* Now absorb all the initializer data into a single vector, whilst checking for overlapping, unequal values. */ data = XCNEWVEC (unsigned char, (size_t)length); chk = XCNEWVEC (unsigned char, (size_t)length); /* TODO - change this when default initialization is implemented. */ memset (data, '\0', (size_t)length); memset (chk, '\0', (size_t)length); for (s = head; s; s = s->next) if (s->sym->value) gfc_merge_initializers (s->sym->ts, s->sym->value, &data[s->offset], &chk[s->offset], (size_t)s->length); for (i = 0; i < length; i++) CONSTRUCTOR_APPEND_ELT (v, NULL, build_int_cst (type, data[i])); free (data); free (chk); /* Build a char[length] array to hold the initializers. Much of what follows is borrowed from build_field, above. */ tmp = build_int_cst (gfc_array_index_type, length - 1); tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp); tmp = build_array_type (type, tmp); field = build_decl (gfc_current_locus.lb->location, FIELD_DECL, NULL_TREE, tmp); known_align = BIGGEST_ALIGNMENT; desired_align = update_alignment_for_field (rli, field, known_align); if (desired_align > known_align) DECL_PACKED (field) = 1; DECL_FIELD_CONTEXT (field) = union_type; DECL_FIELD_OFFSET (field) = size_int (0); DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node; SET_DECL_OFFSET_ALIGN (field, known_align); rli->offset = size_binop (MAX_EXPR, rli->offset, size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (field), DECL_SIZE_UNIT (field))); init = build_constructor (TREE_TYPE (field), v); TREE_CONSTANT (init) = 1; *field_init = init; for (s = head; s; s = s->next) { if (s->sym->value == NULL) continue; gfc_free_expr (s->sym->value); s->sym->value = NULL; } return field; }
void cilk_init_builtins (void) { /* Now build the following __cilkrts_pedigree struct: struct __cilkrts_pedigree { uint64_t rank; struct __cilkrts_pedigree *parent; } */ tree pedigree_type = lang_hooks.types.make_type (RECORD_TYPE); tree pedigree_ptr = build_pointer_type (pedigree_type); tree field = add_field ("rank", uint64_type_node, NULL_TREE); cilk_trees[CILK_TI_PEDIGREE_RANK] = field; field = add_field ("parent", pedigree_ptr, field); cilk_trees[CILK_TI_PEDIGREE_PARENT] = field; finish_builtin_struct (pedigree_type, "__cilkrts_pedigree_GCC", field, NULL_TREE); lang_hooks.types.register_builtin_type (pedigree_type, "__cilkrts_pedigree_t"); cilk_pedigree_type_decl = pedigree_type; /* Build the Cilk Stack Frame: struct __cilkrts_stack_frame { uint32_t flags; uint32_t size; struct __cilkrts_stack_frame *call_parent; __cilkrts_worker *worker; void *except_data; void *ctx[4]; uint32_t mxcsr; uint16_t fpcsr; uint16_t reserved; __cilkrts_pedigree pedigree; }; */ tree frame = lang_hooks.types.make_type (RECORD_TYPE); tree frame_ptr = build_pointer_type (frame); tree worker_type = lang_hooks.types.make_type (RECORD_TYPE); tree worker_ptr = build_pointer_type (worker_type); tree s_type_node = build_int_cst (size_type_node, 4); tree flags = add_field ("flags", uint32_type_node, NULL_TREE); tree size = add_field ("size", uint32_type_node, flags); tree parent = add_field ("call_parent", frame_ptr, size); tree worker = add_field ("worker", worker_ptr, parent); tree except = add_field ("except_data", frame_ptr, worker); tree context = add_field ("ctx", build_array_type (ptr_type_node, build_index_type (s_type_node)), except); tree mxcsr = add_field ("mxcsr", uint32_type_node, context); tree fpcsr = add_field ("fpcsr", uint16_type_node, mxcsr); tree reserved = add_field ("reserved", uint16_type_node, fpcsr); tree pedigree = add_field ("pedigree", pedigree_type, reserved); /* Now add them to a common structure whose fields are #defined to something that is used at a later stage. */ cilk_trees[CILK_TI_FRAME_FLAGS] = flags; cilk_trees[CILK_TI_FRAME_PARENT] = parent; cilk_trees[CILK_TI_FRAME_WORKER] = worker; cilk_trees[CILK_TI_FRAME_EXCEPTION] = except; cilk_trees[CILK_TI_FRAME_CONTEXT] = context; /* We don't care about reserved, so no need to store it in cilk_trees. */ cilk_trees[CILK_TI_FRAME_PEDIGREE] = pedigree; TREE_ADDRESSABLE (frame) = 1; finish_builtin_struct (frame, "__cilkrts_st_frame_GCC", pedigree, NULL_TREE); cilk_frame_type_decl = frame; lang_hooks.types.register_builtin_type (frame, "__cilkrts_frame_t"); cilk_frame_ptr_type_decl = build_qualified_type (frame_ptr, TYPE_QUAL_VOLATILE); /* Now let's do the following worker struct: struct __cilkrts_worker { __cilkrts_stack_frame *volatile *volatile tail; __cilkrts_stack_frame *volatile *volatile head; __cilkrts_stack_frame *volatile *volatile exc; __cilkrts_stack_frame *volatile *volatile protected_tail; __cilkrts_stack_frame *volatile *ltq_limit; int32_t self; global_state_t *g; local_state *l; cilkred_map *reducer_map; __cilkrts_stack_frame *current_stack_frame; void *reserved; __cilkrts_worker_sysdep_state *sysdep; __cilkrts_pedigree pedigree; } */ tree fptr_volatil_type = build_qualified_type (frame_ptr, TYPE_QUAL_VOLATILE); tree fptr_volatile_ptr = build_pointer_type (fptr_volatil_type); tree fptr_vol_ptr_vol = build_qualified_type (fptr_volatile_ptr, TYPE_QUAL_VOLATILE); tree g = lang_hooks.types.make_type (RECORD_TYPE); finish_builtin_struct (g, "__cilkrts_global_state", NULL_TREE, NULL_TREE); tree l = lang_hooks.types.make_type (RECORD_TYPE); finish_builtin_struct (l, "__cilkrts_local_state", NULL_TREE, NULL_TREE); tree sysdep_t = lang_hooks.types.make_type (RECORD_TYPE); finish_builtin_struct (sysdep_t, "__cilkrts_worker_sysdep_state", NULL_TREE, NULL_TREE); field = add_field ("tail", fptr_vol_ptr_vol, NULL_TREE); cilk_trees[CILK_TI_WORKER_TAIL] = field; field = add_field ("head", fptr_vol_ptr_vol, field); field = add_field ("exc", fptr_vol_ptr_vol, field); field = add_field ("protected_tail", fptr_vol_ptr_vol, field); field = add_field ("ltq_limit", fptr_volatile_ptr, field); field = add_field ("self", integer_type_node, field); field = add_field ("g", build_pointer_type (g), field); field = add_field ("l", build_pointer_type (g), field); field = add_field ("reducer_map", ptr_type_node, field); field = add_field ("current_stack_frame", frame_ptr, field); cilk_trees[CILK_TI_WORKER_CUR] = field; field = add_field ("saved_protected_tail", fptr_volatile_ptr, field); field = add_field ("sysdep", build_pointer_type (sysdep_t), field); field = add_field ("pedigree", pedigree_type, field); cilk_trees[CILK_TI_WORKER_PEDIGREE] = field; finish_builtin_struct (worker_type, "__cilkrts_worker_GCC", field, NULL_TREE); tree fptr_arglist = tree_cons (NULL_TREE, frame_ptr, void_list_node); tree fptr_fun = build_function_type (void_type_node, fptr_arglist); /* void __cilkrts_enter_frame_1 (__cilkrts_stack_frame *); */ cilk_enter_fndecl = install_builtin ("__cilkrts_enter_frame_1", fptr_fun, BUILT_IN_CILK_ENTER_FRAME, false); /* void __cilkrts_enter_frame_fast_1 (__cilkrts_stack_frame *); */ cilk_enter_fast_fndecl = install_builtin ("__cilkrts_enter_frame_fast_1", fptr_fun, BUILT_IN_CILK_ENTER_FRAME_FAST, false); /* void __cilkrts_pop_frame (__cilkrts_stack_frame *); */ cilk_pop_fndecl = install_builtin ("__cilkrts_pop_frame", fptr_fun, BUILT_IN_CILK_POP_FRAME, false); /* void __cilkrts_leave_frame (__cilkrts_stack_frame *); */ cilk_leave_fndecl = install_builtin ("__cilkrts_leave_frame", fptr_fun, BUILT_IN_CILK_LEAVE_FRAME, false); /* void __cilkrts_sync (__cilkrts_stack_frame *); */ cilk_sync_fndecl = install_builtin ("__cilkrts_sync", fptr_fun, BUILT_IN_CILK_SYNC, false); /* void __cilkrts_detach (__cilkrts_stack_frame *); */ cilk_detach_fndecl = install_builtin ("__cilkrts_detach", fptr_fun, BUILT_IN_CILK_DETACH, false); /* __cilkrts_rethrow (struct stack_frame *); */ cilk_rethrow_fndecl = install_builtin ("__cilkrts_rethrow", fptr_fun, BUILT_IN_CILK_RETHROW, false); TREE_NOTHROW (cilk_rethrow_fndecl) = 0; /* __cilkrts_save_fp_ctrl_state (__cilkrts_stack_frame *); */ cilk_save_fp_fndecl = install_builtin ("__cilkrts_save_fp_ctrl_state", fptr_fun, BUILT_IN_CILK_SAVE_FP, false); /* __cilkrts_cilk_for_32 (...); */ cilk_for_32_fndecl = declare_cilk_for_builtin ("__cilkrts_cilk_for_32", unsigned_intSI_type_node, BUILT_IN_CILK_FOR_32); /* __cilkrts_cilk_for_64 (...); */ cilk_for_64_fndecl = declare_cilk_for_builtin ("__cilkrts_cilk_for_64", unsigned_intDI_type_node, BUILT_IN_CILK_FOR_64); }