summaryrefslogtreecommitdiffhomepage
path: root/ir/be/bemodule.c
blob: d4140e044f8ce68829b0d6b17b3706d72771c658 (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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
 * This file is part of libFirm.
 * Copyright (C) 2012 University of Karlsruhe.
 */

/**
 * @file
 * @brief       Backend module interface.
 * @author      Matthias Braun
 * @date        29.09.2005
 */
#include "bemodule.h"

#include "isas.h"
#include "util.h"
#include "xmalloc.h"
#include <stdbool.h>
#include <stdlib.h>

/**
 * A module list entry.
 */
struct be_module_list_entry_t {
	const char *name;                    /**< The name of the entry. */
	void *data;                          /**< Some data associated with this entry. */
	struct be_module_list_entry_t *next; /**< Points to the next entry. */
};

void be_init_2addr(void);
void be_init_arch(void);
void be_init_blocksched(void);
void be_init_chordal(void);
void be_init_chordal_common(void);
void be_init_chordal_main(void);
void be_init_copyheur4(void);
void be_init_copyilp(void);
void be_init_copyilp2(void);
void be_init_copynone(void);
void be_init_copyopt(void);
void be_init_daemelspill(void);
void be_init_dwarf(void);
void be_init_listsched(void);
void be_init_live(void);
void be_init_loopana(void);
void be_init_pbqp(void);
void be_init_pbqp_coloring(void);
void be_init_peephole(void);
void be_init_pref_alloc(void);
void be_init_ra(void);
void be_init_sched(void);
void be_init_sched_normal(void);
void be_init_sched_rand(void);
void be_init_sched_trivial(void);
void be_init_spill(void);
void be_init_spillbelady(void);
void be_init_spilloptions(void);
void be_init_spillslots(void);
void be_init_ssaconstr(void);
void be_init_state(void);

void be_quit_pbqp(void);

/**
 * Driver for module initialization.
 * Call your module initialization function here.
 */
void be_init_modules(void)
{
	static bool run_once = false;
	if (run_once)
		return;
	run_once = true;

	be_init_2addr();
	be_init_arch();
	be_init_blocksched();
	be_init_chordal_common();
	be_init_copyopt();
	be_init_dwarf();
	be_init_live();
	be_init_loopana();
	be_init_peephole();
	be_init_ra();
	be_init_sched();
	be_init_spill();
	be_init_spilloptions();
	be_init_spillslots();
	be_init_ssaconstr();
	be_init_state();

	/* in the following groups the first one is the default */
	be_init_arch_ia32();
	be_init_arch_arm();
	be_init_arch_mips();
	be_init_arch_sparc();
	be_init_arch_amd64();
	be_init_arch_riscv32();
	be_init_arch_TEMPLATE();

	be_init_listsched();
	be_init_sched_normal();
	be_init_sched_rand();
	be_init_sched_trivial();

	be_init_chordal_main();
	be_init_pref_alloc();

	be_init_chordal();
	be_init_pbqp_coloring();

	be_init_spillbelady();
	be_init_daemelspill();

	be_init_copyheur4();
	be_init_copyilp2();
	be_init_copynone();
	be_init_copyilp();

#ifdef FIRM_GRGEN_BE
	be_init_pbqp();
#endif
}

void be_quit_modules(void)
{
#ifdef FIRM_GRGEN_BE
	be_quit_pbqp();
#endif
}

//---------------------------------------------------------------------------

typedef struct module_opt_data_t {
	void **var;
	be_module_list_entry_t * const *list_head;
} module_opt_data_t;

/**
 * Searches in list for module option. If found, set option to given value and
 * return true.
 * Beware: return value of 0 means error.
 */
static bool set_opt_module(void *const data, size_t const length, char const *const opt)
{
	(void)length;

	const module_opt_data_t *moddata = (module_opt_data_t*)data;
	bool                     res     = false;
	for (const be_module_list_entry_t *module = *(moddata->list_head);
	     module != NULL; module = module->next) {
		if (streq(module->name, opt)) {
			*(moddata->var) = module->data;
			res = true;
			break;
		}
	}

	return res;
}

/**
 * Dump the names of all registered module options.
 */
static int dump_opt_module(char *buf, size_t buflen, void *data)
{
	const module_opt_data_t *moddata = (module_opt_data_t*)data;
	for (const be_module_list_entry_t *module = *(moddata->list_head);
	     module != NULL; module = module->next) {
		if (module->data == *(moddata->var)) {
			snprintf(buf, buflen, "%s", module->name);
			return strlen(buf);
		}
	}

	snprintf(buf, buflen, "none");
	return strlen(buf);
}

/**
 * Dump the values of all register module options.
 */
static int dump_opt_module_vals(char *buf, size_t buflen, void *data)
{
	const module_opt_data_t *moddata = (module_opt_data_t*)data;
	char                    *p       = buf;
	for (const be_module_list_entry_t *module = *(moddata->list_head);
	     module != NULL; module = module->next) {
		size_t name_len = strlen(module->name);

		if (module != *(moddata->list_head)) {
			p       = strncat(p, ", ", buflen - 1);
			buflen -= 2;
		}

		p = strncat(p, module->name, buflen - 1);
		if (name_len >= buflen)
			break;

		buflen -= name_len;
	}

	return strlen(buf);
}

/**
 * Add a new module to list.
 */
void be_add_module_to_list(be_module_list_entry_t **list_head, const char *name,
                           void *module)
{
	be_module_list_entry_t *entry = XMALLOC(be_module_list_entry_t);
	entry->name = name;
	entry->data = module;
	entry->next = *list_head;
	*list_head  = entry;
}

/**
 * Add an option for a module.
 */
void be_add_module_list_opt(lc_opt_entry_t *grp, const char *name,
                            const char *description,
                            be_module_list_entry_t * const * list_head,
                            void **var)
{
	module_opt_data_t *moddata = XMALLOC(module_opt_data_t);
	moddata->var       = var;
	moddata->list_head = list_head;

	lc_opt_add_opt(grp, name, description, lc_opt_type_enum,
	               moddata, sizeof(moddata[0]), set_opt_module,
	               dump_opt_module, dump_opt_module_vals);
}