Ejemplo n.º 1
0
void analyze_irg_args_weight(ir_graph *irg)
{
	ir_entity *entity = get_irg_entity(irg);
	if (entity == NULL)
		return;

	assert(is_method_entity(entity));
	if (entity->attr.mtd_attr.param_weight != NULL)
		return;

	ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
	inc_irg_visited(irg);
	analyze_method_params_weight(entity);
	ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
}
Ejemplo n.º 2
0
void init_rta_callbacks() {
	// collect rtti entities
	cpmap_init(&rtti2class, hash_ptr, ptr_equals);
	class_walk_super2sub(NULL, walk_classes_and_collect_rtti, NULL);

	// collect clinit entities
	cpmap_init(&class2init, hash_ptr, ptr_equals);
	ir_type *glob = get_glob_type();
	for (size_t i=0; i<get_class_n_members(glob); i++) {
		ir_entity *entity = get_class_member(glob, i);
		if (is_method_entity(entity) && strcmp(get_entity_name(entity), "<clinit>.()V") == 0) {
			char *classname = read_classname_from_clinit_ldname(get_entity_ld_name(entity));
			ir_type *klass = class_registry_get(classname);
			assert(klass);
			//printf(" %s -> %s (%s)\n", get_compound_name(klass), get_entity_name(entity), get_entity_ld_name(entity));
			cpmap_set(&class2init, klass, entity);
			free(classname);
		}
	}
}
Ejemplo n.º 3
0
int tr_verify(void)
{
	bool     fine = true;

	type_walk(check_tore, NULL, &fine);

	for (ir_segment_t s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
		ir_type const *const segment = get_segment_type(s);
		for (size_t e = 0; e < get_compound_n_members(segment); ++e) {
			ir_entity const *const entity = get_compound_member(segment, e);
			ident           *const ld_ident = get_entity_ld_ident(entity);
			if (ld_ident == NULL &&
				get_entity_visibility(entity) != ir_visibility_private) {
				report_error("public segment member %+F has no name",
				             entity);
				fine = false;
				continue;
			}
			if (segment->flags & tf_info)
				fine &= verify_info_member(segment, entity);
		}
	}

	ir_type const *const thread_locals
		= get_segment_type(IR_SEGMENT_THREAD_LOCAL);
	for (size_t i = 0, n = get_compound_n_members(thread_locals); i < n; ++i) {
		const ir_entity *entity = get_compound_member(thread_locals, i);
		/* this is odd and should not be allowed I think */
		if (is_method_entity(entity)) {
			report_error("method %+F in thread local segment", entity);
			fine = false;
		}
		if (get_entity_linkage(entity) & IR_LINKAGE_CONSTANT) {
			report_error("entity %+F in thread local segment is constant",
			             entity);
			fine = false;
		}
	}

	return fine;
}
Ejemplo n.º 4
0
/**
 * Creates a deep copy of an entity.
 */
static ir_entity *deep_entity_copy(ir_entity *old)
{
	ir_entity *newe = XMALLOC(ir_entity);

	*newe = *old;
	if (old->initializer != NULL) {
		/* FIXME: the initializers are NOT copied */
	} else if (is_method_entity(old)) {
		/* do NOT copy them, reanalyze. This might be the best solution */
		newe->attr.mtd_attr.param_access = NULL;
		newe->attr.mtd_attr.param_weight = NULL;
	}
	newe->overwrites    = NULL;
	newe->overwrittenby = NULL;

#ifdef DEBUG_libfirm
	newe->nr = get_irp_new_node_nr();
#endif
	hook_new_entity(newe);
	return newe;
}
Ejemplo n.º 5
0
void jit_compile_execute_main(void)
{
	unsigned const alignment  = 16;
	unsigned const align_mask = ~(alignment-1);

	optimize_lower_ir_prog();

	/* This is somewhat ad-hoc testing code for the jit, it is limited and
	 * will not handle all firm programs. */

	const struct {
		char const *name;
		void const *func;
	} external_functions[] = {
		{ "atoi",    (void const*)(intptr_t)atoi    },
		{ "free",    (void const*)(intptr_t)free    },
		{ "getchar", (void const*)(intptr_t)getchar },
		{ "malloc",  (void const*)(intptr_t)malloc  },
		{ "printf",  (void const*)(intptr_t)printf  },
		{ "puts",    (void const*)(intptr_t)puts    },
		{ "rand",    (void const*)(intptr_t)rand    },
		{ "realloc", (void const*)(intptr_t)realloc },
	};

	ir_jit_segment_t   *const segment   = be_new_jit_segment();
	ir_entity         **      funcents  = NEW_ARR_F(ir_entity*, 0);
	ir_jit_function_t **      functions = NEW_ARR_F(ir_jit_function_t*, 0);
	ir_entity          *main_entity     = NULL;

	size_t         code_size   = 0;
	ir_type *const global_type = get_glob_type();
	for (size_t i = 0, n = get_compound_n_members(global_type); i < n; ++i) {
		ir_entity  *const entity  = get_compound_member(global_type, i);
		char const *const ld_name = get_entity_ld_name(entity);

		if (is_method_entity(entity)
		 && !(get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN)) {
			ir_graph *const irg = get_entity_irg(entity);
			if (irg != NULL) {
				ir_jit_function_t *const func = be_jit_compile(segment, irg);
				if (func == NULL)
					panic("Could not jit compile '%s'", ld_name);
				unsigned const misalign = alignment - (code_size%alignment);
				code_size += (misalign != alignment ? misalign : 0);

				ARR_APP1(ir_jit_function_t*, functions, func);
				ARR_APP1(ir_entity*, funcents, entity);
				code_size += be_get_function_size(func);
				if (streq(ld_name, "main") || streq(ld_name, "_main"))
					main_entity = entity;
				continue;
			}
		}

		/* See if its one of our well-known functions */
		for (unsigned f = 0; f < ARRAY_SIZE(external_functions); ++f) {
			char const *const name = external_functions[f].name;
			void const *const func = external_functions[f].func;
			if (streq(ld_name, name)
			 || (ld_name[0] == '_' && streq(&ld_name[1], name))) {
				be_jit_set_entity_addr(entity, func);
				break;
			}
		}
	}

	if (main_entity == NULL)
		panic("Could not find main() function");

	/* Allocate executable memory */
	char *const memory = mmap(0, code_size, PROT_READ | PROT_WRITE,
	                          MAP_PRIVATE | MAP_ANON, -1, 0);
	if (memory == NULL)
		panic("Could not mmap memory");

	/* Determine final function addresses */
	size_t const n_functions = ARR_LEN(functions);
	assert(ARR_LEN(funcents) == n_functions);
	unsigned offset = 0;
	for (size_t i = 0; i < n_functions; ++i) {
		offset = (offset + alignment - 1) & align_mask;
		char      *const dest   = memory + offset;
		ir_entity *const entity = funcents[i];
		be_jit_set_entity_addr(entity, dest);
		offset += be_get_function_size(functions[i]);
	}
	assert(offset == code_size);

	/* Emit and resolve */
	for (size_t i = 0; i < n_functions; ++i) {
		ir_entity  *const entity = funcents[i];
		char       *const dest
			= memory + ((char const*)be_jit_get_entity_addr(entity) - memory);
		be_emit_function(dest, functions[i]);
	}
	be_destroy_jit_segment(segment);

	if (mprotect(memory, code_size, PROT_EXEC) != 0)
		panic("Couldn't make memory executable");

	typedef int (*mainfunc)(int argc, char **argv);
	mainfunc main_ptr = (mainfunc)(intptr_t)be_jit_get_entity_addr(main_entity);
	int res = main_ptr(0, NULL);
	fprintf(stderr, "Exit code: %d\n", res);

	munmap(memory, code_size);
}
Ejemplo n.º 6
0
/*
 * Optimize the frame type of an irg by removing
 * never touched entities.
 */
void opt_frame_irg(ir_graph *irg)
{
	ir_type   *frame_tp = get_irg_frame_type(irg);
	ir_entity *ent, *list;
	ir_node   *frame, *sel;
	size_t    i, n = get_class_n_members(frame_tp);
	int       o;

	if (n <= 0)
		return;

	assure_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS);

	irp_reserve_resources(irp, IRP_RESOURCE_ENTITY_LINK);

	/* clear all entity links */
	for (i = n; i > 0;) {
		ent = get_class_member(frame_tp, --i);
		set_entity_link(ent, NULL);
	}

	/* look for uses */
	frame = get_irg_frame(irg);

	/* mark all used entities */
	for (o = get_irn_n_outs(frame) - 1; o >= 0; --o) {
		sel = get_irn_out(frame, o);
		if (is_Sel(sel)) {
			ent = get_Sel_entity(sel);
			/* only entities on the frame */
			if (get_entity_owner(ent) == frame_tp)
				set_entity_link(ent, ent);
		}
	}

	/* link unused ones */
	list = NULL;
	for (i = n; i > 0;) {
		ent = get_class_member(frame_tp, --i);
		/* beware of inner functions: those are NOT unused */
		if (get_entity_link(ent) == NULL && !is_method_entity(ent)) {
			set_entity_link(ent, list);
			list = ent;
		}
	}

	if (list != NULL) {
		/* delete list members */
		for (ent = list; ent; ent = list) {
			list = (ir_entity*)get_entity_link(ent);
			free_entity(ent);
		}
		/* we changed the frame type, its layout should be redefined */
		set_type_state(frame_tp, layout_undefined);
	}
	irp_free_resources(irp, IRP_RESOURCE_ENTITY_LINK);

	/* we changed the type, this affects none of the currently known graph
	 * properties, but I don't use ALL because I don't know if someone adds
	 * type-based properties at some point */
	confirm_irg_properties(irg,
		IR_GRAPH_PROPERTIES_CONTROL_FLOW
		| IR_GRAPH_PROPERTY_NO_BADS
		| IR_GRAPH_PROPERTY_NO_TUPLES
		| IR_GRAPH_PROPERTY_CONSISTENT_OUT_EDGES
		| IR_GRAPH_PROPERTY_CONSISTENT_OUTS
		| IR_GRAPH_PROPERTY_CONSISTENT_ENTITY_USAGE
		| IR_GRAPH_PROPERTY_MANY_RETURNS);
}
Ejemplo n.º 7
0
int check_entity(const ir_entity *entity)
{
	bool fine = true;

	ir_linkage linkage = get_entity_linkage(entity);
	if (linkage & IR_LINKAGE_NO_CODEGEN) {
		if (!is_method_entity(entity)) {
			report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not a function", entity);
			fine = false;
		} else if (get_entity_irg(entity) == NULL) {
			report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but has no ir-graph anyway", entity);
			fine = false;
		}
		if (!is_externally_visible(entity)) {
			report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not externally visible", entity);
			fine = false;
		}
	}
	check_external_linkage(entity, IR_LINKAGE_WEAK, "WEAK");
	check_external_linkage(entity, IR_LINKAGE_GARBAGE_COLLECT,
	                       "GARBAGE_COLLECT");
	check_external_linkage(entity, IR_LINKAGE_MERGE, "MERGE");

	ir_type const *const type  = get_entity_type(entity);
	ir_type const *const owner = get_entity_owner(entity);
	switch (get_entity_kind(entity)) {
	case IR_ENTITY_ALIAS:
		if (!is_segment_type(owner)) {
			report_error("alias entity %+F has non-segment owner %+F", entity,
			             owner);
			fine = false;
		}
		break;

	case IR_ENTITY_NORMAL: {
		ir_initializer_t const *const init = get_entity_initializer(entity);
		if (init)
			fine &= check_initializer(init, type, entity);

		if (!is_data_type(type)) {
			report_error("normal entity %+F has non-data type %+F", entity,
			             type);
			fine = false;
		}
		break;
	}

	case IR_ENTITY_COMPOUND_MEMBER:
		if (!is_compound_type(owner)) {
			report_error("compound member entity %+F has non-compound owner %+F",
			             entity, owner);
			fine = false;
		}
		break;

	case IR_ENTITY_LABEL:
		if (type != get_code_type()) {
			report_error("label entity %+F has non-code type %+F", entity,
			             type);
			fine = false;
		}
		break;

	case IR_ENTITY_METHOD:
		if (!is_Method_type(type)) {
			report_error("method entity %+F has non-method type %+F", entity,
			             type);
			fine = false;
		}
		ir_graph *irg = get_entity_irg(entity);
		if (irg != NULL) {
			ir_entity *irg_entity = get_irg_entity(irg);
			if (irg_entity != entity) {
				report_error("entity(%+F)->irg->entity(%+F) relation invalid",
				             entity, irg_entity);
				fine = false;
			}
		}
		break;
	case IR_ENTITY_PARAMETER:
		if (!is_frame_type(owner)) {
			report_error("parameter entity %+F has non-frame owner %+F",
			             entity, owner);
			fine = false;
		}
		if (!is_data_type(type)) {
			report_error("parameter entity %+F has non-data type %+F", entity,
			             type);
			fine = false;
		}
		break;

	case IR_ENTITY_UNKNOWN:
		break;

	case IR_ENTITY_SPILLSLOT:
		if (is_frame_type(owner)) {
			report_error("spillslot %+F must be on frame type", entity);
			fine = false;
		}
		break;
	}
	if (is_frame_type(owner) && entity_has_definition(entity)) {
		report_error("entity %+F on frame %+F has initialized", entity, owner);
		fine = false;
	}

	return fine;
}
Ejemplo n.º 8
0
int tr_verify(void)
{
	bool          fine = true;
	ir_type      *constructors;
	ir_type      *destructors;
	ir_type      *thread_locals;

	type_walk(check_tore, NULL, &fine);

	for (ir_segment_t s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
		const ir_type *type = get_segment_type(s);
		for (size_t e = 0; e < get_compound_n_members(type); ++e) {
			ir_entity *entity = get_compound_member(type, e);
			if (get_entity_ld_ident(entity) == NULL &&
				get_entity_visibility(entity) != ir_visibility_private) {
				report_error("public segment member %+F has no name",
				             entity);
				fine = false;
			}
		}
	}

	constructors = get_segment_type(IR_SEGMENT_CONSTRUCTORS);
	for (size_t i = 0, n = get_compound_n_members(constructors); i < n; ++i) {
		const ir_entity *entity = get_compound_member(constructors, i);
		if ((get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER) == 0) {
			report_error("entity %+F in constructors without LINKAGE_HIDDEN_USER",
			             entity);
			fine = false;
		}
		/* Mach-O doesn't like labels in this section */
		if (get_entity_ld_name(entity)[0] != '\0') {
			report_error("entity %+F in constructors must not have an ld_name",
			             entity);
			fine = false;
		}
	}
	destructors = get_segment_type(IR_SEGMENT_DESTRUCTORS);
	for (size_t i = 0, n = get_compound_n_members(destructors); i < n; ++i) {
		const ir_entity *entity = get_compound_member(destructors, i);
		if ((get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER) == 0) {
			report_error("entity %+F in destructors without LINKAGE_HIDDEN_USER",
			             entity);
			fine = false;
		}
		/* Mach-O doesn't like labels in this section */
		if (get_entity_ld_name(entity)[0] != '\0') {
			report_error("entity %+F in destructors must not have an ld_name",
			             entity);
			fine = false;
		}
	}
	thread_locals = get_segment_type(IR_SEGMENT_THREAD_LOCAL);
	for (size_t i = 0, n = get_compound_n_members(thread_locals); i < n; ++i) {
		const ir_entity *entity = get_compound_member(thread_locals, i);
		/* this is odd and should not be allowed I think */
		if (is_method_entity(entity)) {
			report_error("method %+F in thread local segment");
			fine = false;
		}
		if (get_entity_linkage(entity) & IR_LINKAGE_CONSTANT) {
			report_error("entity %+F in thread local segment is constant");
			fine = false;
		}
	}

	return fine;
}
Ejemplo n.º 9
0
int check_entity(const ir_entity *entity)
{
	bool        fine    = true;
	ir_type    *tp      = get_entity_type(entity);
	ir_linkage  linkage = get_entity_linkage(entity);

	fine &= constants_on_wrong_irg(entity);

	if (is_method_entity(entity)) {
		ir_graph *irg = get_entity_irg(entity);
		if (irg != NULL) {
			ir_entity *irg_entity = get_irg_entity(irg);
			if (irg_entity != entity) {
				report_error("entity(%+F)->irg->entity(%+F) relation invalid",
				             entity, irg_entity);
				fine = false;
			}
		}
		if (get_entity_peculiarity(entity) == peculiarity_existent) {
			ir_entity *impl = get_SymConst_entity(get_atomic_ent_value(entity));
			if (impl == NULL) {
				report_error("inherited method entity %+F must have constant pointing to existent entity.", entity);
				fine = false;
			}
		}
	}

	if (linkage & IR_LINKAGE_NO_CODEGEN) {
		if (!is_method_entity(entity)) {
			report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not a function", entity);
			fine = false;
		} else if (get_entity_irg(entity) == NULL) {
			report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but has no ir-graph anyway", entity);
			fine = false;
		}
		if (get_entity_visibility(entity) != ir_visibility_external) {
			report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not externally visible", entity);
			fine = false;
		}
	}
	check_external_linkage(entity, IR_LINKAGE_WEAK, "WEAK");
	check_external_linkage(entity, IR_LINKAGE_GARBAGE_COLLECT,
	                       "GARBAGE_COLLECT");
	check_external_linkage(entity, IR_LINKAGE_MERGE, "MERGE");

	if (is_atomic_entity(entity) && entity->initializer != NULL) {
		ir_mode *mode = NULL;
		ir_initializer_t *initializer = entity->initializer;
		switch (initializer->kind) {
		case IR_INITIALIZER_CONST:
			mode = get_irn_mode(get_initializer_const_value(initializer));
			break;
		case IR_INITIALIZER_TARVAL:
			mode = get_tarval_mode(get_initializer_tarval_value(initializer));
			break;
		case IR_INITIALIZER_NULL:
		case IR_INITIALIZER_COMPOUND:
			break;
		}
		if (mode != NULL && mode != get_type_mode(tp)) {
			report_error("initializer of entity %+F has wrong mode.", entity);
			fine = false;
		}
	}
	return fine;
}