static void mf_decl_cache_locals (void) { gimple g; gimple_seq seq = NULL; /* Build the cache vars. */ mf_cache_shift_decl_l = mf_mark (create_tmp_reg (TREE_TYPE (mf_cache_shift_decl), "__mf_lookup_shift_l")); mf_cache_mask_decl_l = mf_mark (create_tmp_reg (TREE_TYPE (mf_cache_mask_decl), "__mf_lookup_mask_l")); /* Build initialization nodes for the cache vars. We just load the globals into the cache variables. */ g = gimple_build_assign (mf_cache_shift_decl_l, mf_cache_shift_decl); gimple_set_location (g, DECL_SOURCE_LOCATION (current_function_decl)); gimple_seq_add_stmt (&seq, g); g = gimple_build_assign (mf_cache_mask_decl_l, mf_cache_mask_decl); gimple_set_location (g, DECL_SOURCE_LOCATION (current_function_decl)); gimple_seq_add_stmt (&seq, g); insert_edge_copies_seq (seq, ENTRY_BLOCK_PTR); gsi_commit_edge_inserts (); }
/* 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); }
/* 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); }
/* Helper for mudflap_init: construct a decl with the given category, name, and type, mark it an external reference, and pushdecl it. */ static inline tree mf_make_builtin (enum tree_code category, const char *name, tree type) { tree decl = mf_mark (build_decl (category, get_identifier (name), type)); TREE_PUBLIC (decl) = 1; DECL_EXTERNAL (decl) = 1; lang_hooks.decls.pushdecl (decl); return decl; }
static void mf_decl_cache_locals (void) { tree t, shift_init_stmts, mask_init_stmts; tree_stmt_iterator tsi; /* Build the cache vars. */ mf_cache_shift_decl_l = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_shift_decl), "__mf_lookup_shift_l")); mf_cache_mask_decl_l = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_mask_decl), "__mf_lookup_mask_l")); /* Build initialization nodes for the cache vars. We just load the globals into the cache variables. */ t = build2 (MODIFY_EXPR, TREE_TYPE (mf_cache_shift_decl_l), mf_cache_shift_decl_l, mf_cache_shift_decl); SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl)); gimplify_to_stmt_list (&t); shift_init_stmts = t; t = build2 (MODIFY_EXPR, TREE_TYPE (mf_cache_mask_decl_l), mf_cache_mask_decl_l, mf_cache_mask_decl); SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl)); gimplify_to_stmt_list (&t); mask_init_stmts = t; /* Anticipating multiple entry points, we insert the cache vars initializers in each successor of the ENTRY_BLOCK_PTR. */ for (tsi = tsi_start (shift_init_stmts); ! tsi_end_p (tsi); tsi_next (&tsi)) insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR); for (tsi = tsi_start (mask_init_stmts); ! tsi_end_p (tsi); tsi_next (&tsi)) insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR); bsi_commit_edge_inserts (); }
/* Helper for mudflap_init: construct a decl with the given category, name, and type, mark it an external reference, and pushdecl it. */ static inline tree mf_make_builtin (enum tree_code category, const char *name, tree type) { tree decl = mf_mark (build_decl (UNKNOWN_LOCATION, category, get_identifier (name), type)); TREE_PUBLIC (decl) = 1; DECL_EXTERNAL (decl) = 1; lang_hooks.decls.pushdecl (decl); /* The decl was declared by the compiler. */ DECL_ARTIFICIAL (decl) = 1; /* And we don't want debug info for it. */ DECL_IGNORED_P (decl) = 1; return decl; }
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; }
static tree mx_xform_instrument_pass2(tree temp) { DEBUGLOG("========== Entered mx_xform_instrument_pass2 =============\n"); // TODO figure out what to do with COMPONENT_REFs. ideally this should never come here. if (TREE_CODE(temp) == COMPONENT_REF) return NULL_TREE; tree instr_node = find_instr_node(temp); // Zahed: New mods if (instr_node == NULL_TREE) return NULL_TREE; tree struct_type = TREE_TYPE(instr_node); tree rz_orig_val = DECL_CHAIN(TYPE_FIELDS(struct_type)); DEBUGLOG("============ Exiting mx_xform_instrument_pass2 =============\n"); return mf_mark(build3 (COMPONENT_REF, TREE_TYPE(rz_orig_val), instr_node, rz_orig_val, NULL_TREE)); }
/* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of _DECLs if appropriate. Arrange to call the __mf_register function now, and the __mf_unregister function later for each. Return the gimple sequence after synthesis. */ gimple_seq mx_register_decls (tree decl, gimple_seq seq, location_t location) { gimple_seq finally_stmts = NULL; gimple_stmt_iterator initially_stmts = gsi_start (seq); while (decl != NULL_TREE) { if (mf_decl_eligible_p (decl) /* Not already processed. */ && ! mf_marked_p (decl) /* Automatic variable. */ && ! DECL_EXTERNAL (decl) && ! TREE_STATIC (decl)) { tree size = NULL_TREE, variable_name; gimple unregister_fncall, register_fncall; tree unregister_fncall_param, register_fncall_param; /* Variable-sized objects should have sizes already been gimplified when we got here. */ size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl))); gcc_assert (is_gimple_val (size)); unregister_fncall_param = mf_mark (build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (decl)), decl)); /* __mf_unregister (&VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */ unregister_fncall = gimple_build_call (mf_unregister_fndecl, 3, unregister_fncall_param, size, integer_three_node); variable_name = mf_varname_tree (decl); register_fncall_param = mf_mark (build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (decl)), decl)); /* __mf_register (&VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */ register_fncall = gimple_build_call (mf_register_fndecl, 4, register_fncall_param, size, integer_three_node, variable_name); /* Accumulate the two calls. */ gimple_set_location (register_fncall, location); gimple_set_location (unregister_fncall, location); /* Add the __mf_register call at the current appending point. */ if (gsi_end_p (initially_stmts)) { if (!mf_artificial (decl)) warning (OPT_Wmudflap, "mudflap cannot track %qE in stub function", DECL_NAME (decl)); } else { gsi_insert_before (&initially_stmts, register_fncall, GSI_SAME_STMT); /* Accumulate the FINALLY piece. */ gimple_seq_add_stmt (&finally_stmts, unregister_fncall); } mf_mark (decl); } decl = DECL_CHAIN (decl); } /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */ if (finally_stmts != NULL) { gimple stmt = gimple_build_try (seq, finally_stmts, GIMPLE_TRY_FINALLY); gimple_seq new_seq = NULL; gimple_seq_add_stmt (&new_seq, stmt); return new_seq; } else return seq; }
/* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of _DECLs if appropriate. Arrange to call the __mf_register function now, and the __mf_unregister function later for each. Return the gimple sequence after synthesis. */ gimple_seq mx_register_decls (tree decl, gimple_seq seq, gimple stmt, location_t location, bool func_args) { gimple_seq finally_stmts = NULL; gimple_stmt_iterator initially_stmts = gsi_start (seq); bool sframe_inserted = false; size_t front_rz_size, rear_rz_size; tree fsize, rsize, size; gimple uninit_fncall_front, uninit_fncall_rear, init_fncall_front, \ init_fncall_rear, init_assign_stmt; tree fncall_param_front, fncall_param_rear; int map_ret; while (decl != NULL_TREE) { if ((mf_decl_eligible_p (decl) || TREE_CODE(TREE_TYPE(decl)) == ARRAY_TYPE) /* Not already processed. */ && ! mf_marked_p (decl) /* Automatic variable. */ && ! DECL_EXTERNAL (decl) && ! TREE_STATIC (decl) && get_name(decl)) { DEBUGLOG("DEBUG Instrumenting %s is_complete_type %d\n", IDENTIFIER_POINTER(DECL_NAME(decl)), COMPLETE_TYPE_P(decl)); /* construct a tree corresponding to the type struct{ unsigned int rz_front[6U]; original variable unsigned int rz_rear[6U]; }; */ if (!sframe_inserted){ gimple ensure_fn_call = gimple_build_call (lbc_ensure_sframe_bitmap_fndecl, 0); gimple_set_location (ensure_fn_call, location); gsi_insert_before (&initially_stmts, ensure_fn_call, GSI_SAME_STMT); sframe_inserted = true; } // Calculate the zone sizes size_t element_size = 0, request_size = 0; if (COMPLETE_TYPE_P(decl)){ request_size = TREE_INT_CST_LOW(TYPE_SIZE_UNIT(TREE_TYPE(decl))); if (TREE_CODE(TREE_TYPE(decl)) == ARRAY_TYPE) element_size = TREE_INT_CST_LOW(TYPE_SIZE_UNIT(TREE_TYPE(TREE_TYPE(decl)))); else element_size = request_size; } calculate_zone_sizes(element_size, request_size, /*global*/ false, COMPLETE_TYPE_P(decl), &front_rz_size, &rear_rz_size); DEBUGLOG("DEBUG *SIZES* req_size %u, ele_size %u, fsize %u, rsize %u\n", request_size, element_size, front_rz_size, rear_rz_size); tree struct_type = create_struct_type(decl, front_rz_size, rear_rz_size); tree struct_var = create_struct_var(struct_type, decl, location); declare_vars(struct_var, stmt, 0); /* Inserting into hashtable */ PWord_t PV; JSLI(PV, decl_map, mf_varname_tree(decl)); gcc_assert(PV); *PV = (PWord_t) struct_var; fsize = convert (unsigned_type_node, size_int(front_rz_size)); gcc_assert (is_gimple_val (fsize)); tree rz_front = TYPE_FIELDS(struct_type); fncall_param_front = mf_mark (build1 (ADDR_EXPR, ptr_type_node, build3 (COMPONENT_REF, TREE_TYPE(rz_front), struct_var, rz_front, NULL_TREE))); uninit_fncall_front = gimple_build_call (lbc_uninit_front_rz_fndecl, 2, fncall_param_front, fsize); init_fncall_front = gimple_build_call (lbc_init_front_rz_fndecl, 2, fncall_param_front, fsize); gimple_set_location (init_fncall_front, location); gimple_set_location (uninit_fncall_front, location); // In complete types have only a front red zone if (COMPLETE_TYPE_P(decl)){ rsize = convert (unsigned_type_node, size_int(rear_rz_size)); gcc_assert (is_gimple_val (rsize)); tree rz_rear = DECL_CHAIN(DECL_CHAIN(TYPE_FIELDS (struct_type))); fncall_param_rear = mf_mark (build1 (ADDR_EXPR, ptr_type_node, build3 (COMPONENT_REF, TREE_TYPE(rz_rear), struct_var, rz_rear, NULL_TREE))); init_fncall_rear = gimple_build_call (lbc_init_rear_rz_fndecl, 2, fncall_param_rear, rsize); uninit_fncall_rear = gimple_build_call (lbc_uninit_rear_rz_fndecl, 2, fncall_param_rear, rsize); gimple_set_location (init_fncall_rear, location); gimple_set_location (uninit_fncall_rear, location); } // TODO Do I need this? #if 0 if (DECL_INITIAL(decl) != NULL_TREE){ // This code never seems to be getting executed for somehting like int i = 10; // I have no idea why? But looking at the tree dump, seems like its because // by the time it gets here, these kind of statements are split into two statements // as int i; and i = 10; respectively. I am leaving it in just in case. tree orig_var_type = DECL_CHAIN(TYPE_FIELDS (struct_type)); tree orig_var_lval = mf_mark (build3 (COMPONENT_REF, TREE_TYPE(orig_var_type), struct_var, orig_var_type, NULL_TREE)); init_assign_stmt = gimple_build_assign(orig_var_lval, DECL_INITIAL(decl)); gimple_set_location (init_assign_stmt, location); } #endif if (gsi_end_p (initially_stmts)) { // TODO handle this if (!DECL_ARTIFICIAL (decl)) warning (OPT_Wmudflap, "mudflap cannot track %qE in stub function", DECL_NAME (decl)); } else { #if 0 // Insert the declaration initializer if (DECL_INITIAL(decl) != NULL_TREE) gsi_insert_before (&initially_stmts, init_assign_stmt, GSI_SAME_STMT); #endif //gsi_insert_before (&initially_stmts, register_fncall, GSI_SAME_STMT); gsi_insert_before (&initially_stmts, init_fncall_front, GSI_SAME_STMT); if (COMPLETE_TYPE_P(decl)) gsi_insert_before (&initially_stmts, init_fncall_rear, GSI_SAME_STMT); /* Accumulate the FINALLY piece. */ //gimple_seq_add_stmt (&finally_stmts, unregister_fncall); gimple_seq_add_stmt (&finally_stmts, uninit_fncall_front); if (COMPLETE_TYPE_P(decl)) gimple_seq_add_stmt (&finally_stmts, uninit_fncall_rear); } mf_mark (decl); } decl = DECL_CHAIN (decl); } /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */ if (finally_stmts != NULL) { gimple stmt = gimple_build_try (seq, finally_stmts, GIMPLE_TRY_FINALLY); gimple_seq new_seq = gimple_seq_alloc (); gimple_seq_add_stmt (&new_seq, stmt); return new_seq; } else return seq; }
/* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of _DECLs if appropriate. Arrange to call the __mf_register function now, and the __mf_unregister function later for each. */ static void mx_register_decls (tree decl, tree *stmt_list) { tree finally_stmts = NULL_TREE; tree_stmt_iterator initially_stmts = tsi_start (*stmt_list); while (decl != NULL_TREE) { if (mf_decl_eligible_p (decl) /* Not already processed. */ && ! mf_marked_p (decl) /* Automatic variable. */ && ! DECL_EXTERNAL (decl) && ! TREE_STATIC (decl)) { tree size = NULL_TREE, variable_name; tree unregister_fncall, unregister_fncall_params; tree register_fncall, register_fncall_params; size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl))); /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */ unregister_fncall_params = tree_cons (NULL_TREE, convert (ptr_type_node, mf_mark (build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (decl)), decl))), tree_cons (NULL_TREE, size, tree_cons (NULL_TREE, /* __MF_TYPE_STACK */ build_int_cst (NULL_TREE, 3), NULL_TREE))); /* __mf_unregister (...) */ unregister_fncall = build_function_call_expr (mf_unregister_fndecl, unregister_fncall_params); /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */ variable_name = mf_varname_tree (decl); register_fncall_params = tree_cons (NULL_TREE, convert (ptr_type_node, mf_mark (build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (decl)), decl))), tree_cons (NULL_TREE, size, tree_cons (NULL_TREE, /* __MF_TYPE_STACK */ build_int_cst (NULL_TREE, 3), tree_cons (NULL_TREE, variable_name, NULL_TREE)))); /* __mf_register (...) */ register_fncall = build_function_call_expr (mf_register_fndecl, register_fncall_params); /* Accumulate the two calls. */ /* ??? Set EXPR_LOCATION. */ gimplify_stmt (®ister_fncall); gimplify_stmt (&unregister_fncall); /* Add the __mf_register call at the current appending point. */ if (tsi_end_p (initially_stmts)) warning (0, "mudflap cannot track %qs in stub function", IDENTIFIER_POINTER (DECL_NAME (decl))); else { tsi_link_before (&initially_stmts, register_fncall, TSI_SAME_STMT); /* Accumulate the FINALLY piece. */ append_to_statement_list (unregister_fncall, &finally_stmts); } mf_mark (decl); } decl = TREE_CHAIN (decl); } /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */ if (finally_stmts != NULL_TREE) { tree t = build2 (TRY_FINALLY_EXPR, void_type_node, *stmt_list, finally_stmts); *stmt_list = NULL; append_to_statement_list (t, stmt_list); } }