<commit_before>/*
 * This file is part of libFirm.
 * Copyright (C) 2012 University of Karlsruhe.
 */

/**
 * @file
 * @brief    Removal of unreachable methods.
 * @author   <NAME>
 */
#include "iroptimize.h"
#include "typerep.h"
#include "type_t.h"
#include "entity_t.h"
#include "irprog_t.h"
#include "irgwalk.h"
#include "error.h"
#include "debug.h"

DEBUG_ONLY(static firm_dbg_module_t *dbg;)

static void visit_entity(ir_entity *entity);

static void visit_node(ir_node *node, void *env)
{
	(void) env;

	ir_entity *entity;
	if (is_Address(node)) {
		entity = get_Address_entity(node);
	} else if (is_Offset(node)) {
		entity = get_Offset_entity(node);
	} else if (is_Sel(node)) {
		entity = get_Sel_entity(node);
	} else {
		return;
	}
	visit_entity(entity);
}

static void start_visit_node(ir_node *node)
{
	ir_graph *irg = get_irn_irg(node);
	if (get_irg_visited(irg) < get_max_irg_visited()) {
		set_irg_visited(irg, get_max_irg_visited());
	}
	irg_walk_2(node, visit_node, NULL, NULL);
}

static void visit_initializer(ir_initializer_t *initializer)
{
	switch (initializer->kind) {
	case IR_INITIALIZER_CONST:
		start_visit_node(initializer->consti.value);
		return;
	case IR_INITIALIZER_TARVAL:
	case IR_INITIALIZER_NULL:
		return;

	case IR_INITIALIZER_COMPOUND: {
		for (size_t i = 0; i < initializer->compound.n_initializers; ++i) {
			ir_initializer_t *subinitializer
				= initializer->compound.initializers[i];
			visit_initializer(subinitializer);
		}
		return;
	}
	}
	panic("invalid initializer found");
}

static void visit_entity(ir_entity *entity)
{
	if (entity_visited(entity))
		return;
	mark_entity_visited(entity);

	if (entity->initializer != NULL) {
		visit_initializer(entity->initializer);
	}

	if (is_method_entity(entity)) {
		ir_graph *irg = get_entity_irg(entity);
		if (irg != NULL)
			start_visit_node(get_irg_end(irg));
	}

	if (is_alias_entity(entity)) {
		ir_entity *aliased = get_entity_alias(entity);
		visit_entity(aliased);
	}
}

static void visit_segment(ir_type *segment)
{
	for (int i = 0, n = get_compound_n_members(segment); i < n; ++i) {
		ir_entity *entity = get_compound_member(segment, i);
		if (get_entity_visibility(entity) != ir_visibility_external
				&& !(get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER)
				&& !(get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN))
			continue;

		visit_entity(entity);
	}
}

static void garbage_collect_in_segment(ir_type *segment)
{
	for (int i = get_compound_n_members(segment); i-- > 0; ) {
		ir_entity *entity = get_compound_member(segment, i);
		if (entity_visited(entity))
			continue;

		DB((dbg, LEVEL_1, "  removing entity %+F\n", entity));

		free_entity(entity);
	}
}

void garbage_collect_entities(void)
{
	FIRM_DBG_REGISTER(dbg, "firm.opt.garbagecollect");

	/* start a type walk for all externally visible entities */
	irp_reserve_resources(irp, IRP_RESOURCE_TYPE_VISITED);
	inc_master_type_visited();
	inc_max_irg_visited();

	for (ir_segment_t s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
		ir_type *type = get_segment_type(s);
		mark_type_visited(type);

		visit_segment(type);
	}

	/* remove graphs of non-visited functions
	 * (we have to count backwards, because freeing the graph moves the last
	 *  graph in the list to the free position) */
	foreach_irp_irg_r(i, irg) {
		ir_entity *entity = get_irg_entity(irg);

		if (entity_visited(entity))
			continue;

		DB((dbg, LEVEL_1, "  freeing method %+F\n", entity));
		free_ir_graph(irg);
	}

	/* we can now remove all non-visited (global) entities */
	for (ir_segment_t s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
		ir_type *type = get_segment_type(s);
		garbage_collect_in_segment(type);
	}
	irp_free_resources(irp, IRP_RESOURCE_TYPE_VISITED);
}
<commit_msg>garbage_collect: simplify by using get_irn_entity_attr()<commit_after>/*
 * This file is part of libFirm.
 * Copyright (C) 2012 University of Karlsruhe.
 */

/**
 * @file
 * @brief    Removal of unreachable methods.
 * @author   <NAME>
 */
#include "iroptimize.h"
#include "typerep.h"
#include "type_t.h"
#include "entity_t.h"
#include "irprog_t.h"
#include "irgwalk.h"
#include "error.h"
#include "debug.h"

DEBUG_ONLY(static firm_dbg_module_t *dbg;)

static void visit_entity(ir_entity *entity);

static void visit_node(ir_node *node, void *env)
{
	(void) env;
	ir_entity *entity = get_irn_entity_attr(node);
	if (entity != NULL)
		visit_entity(entity);
}

static void start_visit_node(ir_node *node)
{
	ir_graph *irg = get_irn_irg(node);
	if (get_irg_visited(irg) < get_max_irg_visited()) {
		set_irg_visited(irg, get_max_irg_visited());
	}
	irg_walk_2(node, visit_node, NULL, NULL);
}

static void visit_initializer(ir_initializer_t *initializer)
{
	switch (initializer->kind) {
	case IR_INITIALIZER_CONST:
		start_visit_node(initializer->consti.value);
		return;
	case IR_INITIALIZER_TARVAL:
	case IR_INITIALIZER_NULL:
		return;

	case IR_INITIALIZER_COMPOUND: {
		for (size_t i = 0; i < initializer->compound.n_initializers; ++i) {
			ir_initializer_t *subinitializer
				= initializer->compound.initializers[i];
			visit_initializer(subinitializer);
		}
		return;
	}
	}
	panic("invalid initializer found");
}

static void visit_entity(ir_entity *entity)
{
	if (entity_visited(entity))
		return;
	mark_entity_visited(entity);

	if (entity->initializer != NULL) {
		visit_initializer(entity->initializer);
	}

	if (is_method_entity(entity)) {
		ir_graph *irg = get_entity_irg(entity);
		if (irg != NULL)
			start_visit_node(get_irg_end(irg));
	}

	if (is_alias_entity(entity)) {
		ir_entity *aliased = get_entity_alias(entity);
		visit_entity(aliased);
	}
}

static void visit_segment(ir_type *segment)
{
	for (int i = 0, n = get_compound_n_members(segment); i < n; ++i) {
		ir_entity *entity = get_compound_member(segment, i);
		if (get_entity_visibility(entity) != ir_visibility_external
				&& !(get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER)
				&& !(get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN))
			continue;

		visit_entity(entity);
	}
}

static void garbage_collect_in_segment(ir_type *segment)
{
	for (int i = get_compound_n_members(segment); i-- > 0; ) {
		ir_entity *entity = get_compound_member(segment, i);
		if (entity_visited(entity))
			continue;

		DB((dbg, LEVEL_1, "  removing entity %+F\n", entity));

		free_entity(entity);
	}
}

void garbage_collect_entities(void)
{
	FIRM_DBG_REGISTER(dbg, "firm.opt.garbagecollect");

	/* start a type walk for all externally visible entities */
	irp_reserve_resources(irp, IRP_RESOURCE_TYPE_VISITED);
	inc_master_type_visited();
	inc_max_irg_visited();

	for (ir_segment_t s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
		ir_type *type = get_segment_type(s);
		mark_type_visited(type);

		visit_segment(type);
	}

	/* remove graphs of non-visited functions
	 * (we have to count backwards, because freeing the graph moves the last
	 *  graph in the list to the free position) */
	foreach_irp_irg_r(i, irg) {
		ir_entity *entity = get_irg_entity(irg);

		if (entity_visited(entity))
			continue;

		DB((dbg, LEVEL_1, "  freeing method %+F\n", entity));
		free_ir_graph(irg);
	}

	/* we can now remove all non-visited (global) entities */
	for (ir_segment_t s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
		ir_type *type = get_segment_type(s);
		garbage_collect_in_segment(type);
	}
	irp_free_resources(irp, IRP_RESOURCE_TYPE_VISITED);
}

{'fraction_non_alphanumeric': 0.12596820220138605, 'fraction_numerical': 0.002717760565294198, 'mean_word_length': 5.216216216216216, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6684689', 'n_tokens_mistral': 3040, 'n_tokens_neox': 2868, 'n_words': 564}