summaryrefslogtreecommitdiffhomepage
path: root/src/ast/entity.c
blob: 380c60235bc8cf30337a1d94d06e50412d574352 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
 * This file is part of cparser.
 * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
 */
#include "entity_t.h"

#include <assert.h>

#include "adt/panic.h"
#include "adt/strutil.h"
#include "adt/util.h"
#include "ast_t.h"

const char *get_entity_kind_name(entity_kind_t kind)
{
	switch (kind) {
	case ENTITY_FUNCTION:        return "function";
	case ENTITY_VARIABLE:        return "variable";
	case ENTITY_PARAMETER:       return "parameter";
	case ENTITY_COMPOUND_MEMBER: return "compound member";
	case ENTITY_CLASS:           return "class";
	case ENTITY_STRUCT:          return "struct";
	case ENTITY_UNION:           return "union";
	case ENTITY_ENUM:            return "enum";
	case ENTITY_ENUM_VALUE:      return "enum value";
	case ENTITY_LABEL:           return "label";
	case ENTITY_LOCAL_LABEL:     return "local label";
	case ENTITY_TYPEDEF:         return "typedef";
	case ENTITY_NAMESPACE:       return "namespace";
	case ENTITY_ASM_ARGUMENT:    return "asm argument";
	}

	panic("invalid entity kind");
}

/**
 * Returns the size of an entity node.
 *
 * @param kind  the entity kind
 */
static size_t get_entity_struct_size(entity_kind_t kind)
{
	static const size_t sizes[] = {
		[ENTITY_VARIABLE]        = sizeof(variable_t),
		[ENTITY_PARAMETER]       = sizeof(variable_t),
		[ENTITY_COMPOUND_MEMBER] = sizeof(compound_member_t),
		[ENTITY_FUNCTION]        = sizeof(function_t),
		[ENTITY_TYPEDEF]         = sizeof(declaration_t),
		[ENTITY_STRUCT]          = sizeof(compound_t),
		[ENTITY_UNION]           = sizeof(compound_t),
		[ENTITY_ENUM]            = sizeof(enum_t),
		[ENTITY_ENUM_VALUE]      = sizeof(enum_value_t),
		[ENTITY_LABEL]           = sizeof(label_t),
		[ENTITY_LOCAL_LABEL]     = sizeof(label_t),
		[ENTITY_NAMESPACE]       = sizeof(namespace_t),
		[ENTITY_ASM_ARGUMENT]    = sizeof(asm_argument_t),
	};
	assert(kind < ARRAY_SIZE(sizes));
	assert(sizes[kind] != 0);
	return sizes[kind];
}

/**
 * Allocate an entity of given kind and initialize all
 * fields with zero.
 *
 * @param kind   the kind of the entity to allocate
 */
entity_t *allocate_entity_zero(entity_kind_t const kind, entity_namespace_t const namespc, symbol_t *const symbol, position_t const *const pos)
{
	size_t    const size   = get_entity_struct_size(kind);
	entity_t *const entity = allocate_ast_zero(size);
	entity->kind           = kind;
	entity->base.namespc   = namespc;
	entity->base.symbol    = symbol;
	entity->base.pos       = *pos;
	return entity;
}

elf_visibility_t get_elf_visibility_from_string(const char *string)
{
	if (streq(string, "default")) {
		return ELF_VISIBILITY_DEFAULT;
	} else if (streq(string, "hidden")) {
		return ELF_VISIBILITY_HIDDEN;
	} else if (streq(string, "internal")) {
		return ELF_VISIBILITY_INTERNAL;
	} else if (streq(string, "protected")) {
		return ELF_VISIBILITY_PROTECTED;
	} else {
		return ELF_VISIBILITY_ERROR;
	}
}

entity_t *skip_unnamed_bitfields(entity_t *entry)
{
	for (; entry != NULL; entry = entry->base.next) {
		assert(entry->kind == ENTITY_COMPOUND_MEMBER);
		if (!entry->compound_member.bitfield || entry->base.symbol != NULL)
			break;
	}
	return entry;
}

unsigned get_declaration_alignment(const declaration_t *declaration)
{
	unsigned result = declaration->alignment;
	if (result != 0)
		return result;
	if (declaration->modifiers & DM_PACKED)
		return 1;
	const type_t *type = declaration->type;
	if (declaration->base.kind == ENTITY_COMPOUND_MEMBER)
		return get_type_alignment_compound(type);
	return get_ctype_alignment(type);
}