Ejemplo n.º 1
0
static void walk_entity(entity_t *entity, const walk_env_t *const env)
{
	env->declaration_func(entity, env->env);

	switch (entity->kind) {
	case ENTITY_VARIABLE: {
		const variable_t    *variable    = &entity->variable;
		const initializer_t *initializer = variable->initializer;
		walk_type(entity->declaration.type, env);
		if (initializer != NULL) {
			walk_initializer(initializer, env);
		}
		return;
	}
	case ENTITY_ENUM_VALUE:
		if (entity->enum_value.value != NULL)
			walk_expression(entity->enum_value.value, env);
		return;
	case ENTITY_TYPEDEF:
		walk_type(entity->declaration.type, env);
		return;
	case ENTITY_FUNCTION:
		walk_type(entity->declaration.type, env);
		if (entity->function.body != NULL)
			walk_statement(entity->function.body, env);
		return;
	case ENTITY_COMPOUND_MEMBER:
	case ENTITY_PARAMETER:
		walk_type(entity->declaration.type, env);
		return;
	case ENTITY_CLASS:
	case ENTITY_STRUCT:
	case ENTITY_UNION:
		walk_scope(&entity->compound.members, env);
		return;
	case ENTITY_NAMESPACE:
		walk_scope(&entity->namespacee.members, env);
		return;
	case ENTITY_ENUM:
		for (entity_t *entry = entity->enume.first_value;
		     entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
		     entry = entry->base.next) {
			walk_entity(entry, env);
		}
		return;
	case ENTITY_LABEL:
	case ENTITY_LOCAL_LABEL:
		return;
	case ENTITY_ASM_ARGUMENT:
		walk_expression(entity->asm_argument.expression, env);
		return;
	}
	panic("invalid entity");
}
Ejemplo n.º 2
0
static void walk_type(type_t *const type, const walk_env_t *const env)
{
	if (pset_find_ptr(env->visited_types, type) != NULL)
		return;
	pset_insert_ptr(env->visited_types, type);

	switch (type->kind) {
	case TYPE_ATOMIC:
	case TYPE_COMPLEX:
	case TYPE_IMAGINARY:
	case TYPE_REFERENCE:
	case TYPE_ERROR:
	case TYPE_VOID:
	case TYPE_BUILTIN_TEMPLATE:
		return;
	case TYPE_POINTER:
		walk_type(type->pointer.points_to, env);
		return;
	case TYPE_ARRAY:
		walk_type(type->array.element_type, env);
		if (type->array.size_expression != NULL)
			walk_expression(type->array.size_expression, env);
		return;
	case TYPE_FUNCTION:
		for (function_parameter_t *parameter = type->function.parameters;
		     parameter != NULL; parameter = parameter->next) {
			walk_type(parameter->type, env);
		}
		walk_type(type->function.return_type, env);
		return;
	case TYPE_TYPEOF: {
		expression_t *const expr = type->typeoft.expression;
		if (expr)
			walk_expression(expr, env);
		return;
	}
	case TYPE_TYPEDEF:
		walk_entity((entity_t*)type->typedeft.typedefe, env);
		return;
	case TYPE_COMPOUND_STRUCT:
	case TYPE_COMPOUND_UNION:
		walk_entity((entity_t*)type->compound.compound, env);
		return;
	case TYPE_ENUM:
		walk_entity((entity_t*)type->enumt.enume, env);
		return;
	}
	panic("invalid type");
}
Ejemplo n.º 3
0
static void walk_expression(expression_t *const expr,
                            const walk_env_t *const env)
{
	env->expression_func(expr, env->env);

	switch (expr->base.kind) {
	case EXPR_STATEMENT:
		walk_statement(expr->statement.statement, env);
		return;

	case EXPR_BINARY_CASES:
		walk_expression(expr->binary.left, env);
		walk_expression(expr->binary.right, env);
		return;

	case EXPR_UNARY_CASES_OPTIONAL:
		if (expr->unary.value == NULL)
			return;
		/* FALLTHROUGH */
	case EXPR_UNARY_CASES_MANDATORY:
		walk_expression(expr->unary.value, env);
		return;

	case EXPR_CALL:
		walk_expression(expr->call.function, env);
		for (call_argument_t *arg = expr->call.arguments; arg != NULL;
		     arg = arg->next) {
			walk_expression(arg->expression, env);
		}
		return;

	case EXPR_COMPOUND_LITERAL:
		walk_initializer(expr->compound_literal.initializer, env);
		return;

	case EXPR_CONDITIONAL:
		walk_expression(expr->conditional.condition, env);
		/* may be NULL because of gnu extension */
		if (expr->conditional.true_expression != NULL)
			walk_expression(expr->conditional.true_expression, env);
		walk_expression(expr->conditional.false_expression, env);
		return;

	case EXPR_BUILTIN_CONSTANT_P:
		walk_expression(expr->builtin_constant.value, env);
		return;

	case EXPR_BUILTIN_TYPES_COMPATIBLE_P:
		walk_type(expr->builtin_types_compatible.left, env);
		walk_type(expr->builtin_types_compatible.right, env);
		return;

	case EXPR_SELECT:
		walk_expression(expr->select.compound, env);
		return;

	case EXPR_ARRAY_ACCESS:
		walk_expression(expr->array_access.array_ref, env);
		walk_expression(expr->array_access.index, env);
		return;

	case EXPR_CLASSIFY_TYPE:
		walk_expression(expr->classify_type.type_expression, env);
		return;

	case EXPR_SIZEOF:
	case EXPR_ALIGNOF: {
		expression_t *tp_expression = expr->typeprop.tp_expression;
		if (tp_expression != NULL) {
			walk_expression(tp_expression, env);
		}
		return;
	}

	case EXPR_VA_START:
		walk_expression(expr->va_starte.ap, env);
		return;

	case EXPR_VA_ARG:
		walk_expression(expr->va_arge.ap, env);
		return;

	case EXPR_VA_COPY:
		walk_expression(expr->va_copye.src, env);
		walk_expression(expr->va_copye.dst, env);
		return;

	case EXPR_OFFSETOF:
		walk_designator(expr->offsetofe.designator, env);
		return;

	case EXPR_LITERAL_CASES:
	case EXPR_LITERAL_CHARACTER:
	case EXPR_REFERENCE:
	case EXPR_ENUM_CONSTANT:
	case EXPR_STRING_LITERAL:
	case EXPR_FUNCNAME:
	case EXPR_LABEL_ADDRESS:
	case EXPR_ERROR:
		return;
	}
	panic("invalid expr kind");
}
Ejemplo n.º 4
0
void 
gather_interface_dies(root_die& root, 
	set<iterator_base>& out, type_set& dedup_types_out, 
	std::function<bool(const iterator_base&)> pred)
{
	/* We want to deduplicate the types that we output, as we go. 
	 * CARE: what about anonymous types? We might want to generate names for them 
	 * based on their offset, in which case deduplication isn't transparent. 
	 * For this reason we output dedup_types_out separately from the DIEs.
	 * However, everything in dedup_types_out is also in out (FIXME: is this a good idea?) */
	auto toplevel_seq = root.grandchildren();
	type_set& types = dedup_types_out;
	/* FIXME: it needn't be just grandchildren. */
	for (auto i_d = std::move(toplevel_seq.first); i_d != toplevel_seq.second; ++i_d)
	{
		if (pred(i_d.base().base()))
		{
			// looks like a goer -- add it to the objs
			out.insert(i_d.base().base());
			
			/* utility that will come in handy */
			auto add_all_types = [&types, &root](iterator_df<type_die> outer_t) {
				walk_type(outer_t, iterator_base::END, 
					[&types, &root](iterator_df<type_die> t, iterator_df<program_element_die> reason) -> bool {
						if (!t) return false; // void case
						auto memb = reason.as_a<member_die>();
						if (memb && memb->get_declaration() && *memb->get_declaration()
							&& memb->get_external() && *memb->get_external())
						{
							// static member vars don't get added nor recursed on
							return false;
						}
						// apart from that, insert all nonvoids....
						auto inserted = types.insert(t);
						if (!inserted.second)
						{
							// cerr << "Type was already present: " << *t 
							// 	<< " (or something equal to it: " << *inserted.first
							// 	<< ")" << endl;
							// cerr << "Attributes: " << t->copy_attrs(root) << endl;
							return false; // was already present
						}
						else
						{
							cerr << "Inserted new type: " << *t << endl;
							// cerr << "Attributes: " << t->copy_attrs(root) << endl;
							return true;
						}
					}
				);
			};
			
			/* Also output everything that this depends on. We have to case-split
			 * for now. */
			if (i_d.base().base().is_a<subprogram_die>())
			{
				// make sure we have all the relevant types in our set
				auto i_subp = i_d.base().base().as_a<subprogram_die>();
				if (i_subp->find_type()) add_all_types(i_subp->find_type());
				auto fps = i_subp->children().subseq_of<formal_parameter_die>();
				for (auto i_fp = std::move(fps.first); i_fp != fps.second; ++i_fp)
				{
					auto outer_t = i_fp->find_type();
					add_all_types(outer_t);
				}
			}
			else if (i_d.base().base().is_a<variable_die>())
			{
				add_all_types(i_d.base().base().as_a<variable_die>()->get_type());
			}
			else if (i_d.base().base().is_a<type_die>())
			{
				/* Just walk it. */
				add_all_types(i_d.base().base().as_a<type_die>());
			}
		} // end if pred
	} // end for
	
	/* Now we've gathered everything. Make sure everything in "types" is in 
	 * "out". */
	for (auto i_d = types.begin(); i_d != types.end(); ++i_d)
	{
		out.insert(*i_d);
	}
	
	/* Check that everything that's in "out", if it is a type, is also in 
	 * types. */
	for (auto i_d = out.begin(); i_d != out.end(); ++i_d)
	{
		if (i_d->is_a<type_die>() && !i_d->is_a<subprogram_die>())
		{
			if (types.find(i_d->as_a<type_die>()) == types.end())
			{
				cerr << "BUG: didn't find " << i_d->summary() << " in types list." << endl;
			}
		}
	}
}