aboutsummaryrefslogtreecommitdiff
path: root/lib.h
blob: c27dfb6445bdfd4dfd2e2d0a5b235e8c48fed292 (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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
#ifndef LIB_H
#define LIB_H

#include <stdlib.h>
#include <stddef.h>

/*
 * Basic helper routine descriptions for 'sparse'.
 *
 * Copyright (C) 2003 Transmeta Corp.
 *               2003 Linus Torvalds
 *               2004 Christopher Li
 *
 *  Licensed under the Open Software License version 1.1
 */

#include "compat.h"

extern int verbose, optimize, preprocessing;
extern int repeat_phase, merge_phi_sources;

#define container(ptr, type, member) \
	(type *)((void *)(ptr) - offsetof(type, member))

extern unsigned int hexval(unsigned int c);

struct position {
	unsigned int type:6,
		     stream:10,
		     newline:1,
		     whitespace:1,
		     pos:14;
	unsigned int line:31,
		     noexpand:1;
};

struct ident;
struct token;
struct symbol;
struct statement;
struct expression;
struct basic_block;
struct entrypoint;
struct instruction;
struct multijmp;
struct pseudo;

/* Silly type-safety check ;) */
#define DECLARE_PTR_LIST(listname,type)	struct listname { type *list[1]; }
#define CHECK_TYPE(head,ptr)		(void)(&(ptr) == &(head)->list[0])
#define TYPEOF(head)			__typeof__(&(head)->list[0])
#define VRFY_PTR_LIST(head)		(void)(sizeof((head)->list[0]))

DECLARE_PTR_LIST(symbol_list, struct symbol);
DECLARE_PTR_LIST(statement_list, struct statement);
DECLARE_PTR_LIST(expression_list, struct expression);
DECLARE_PTR_LIST(basic_block_list, struct basic_block);
DECLARE_PTR_LIST(instruction_list, struct instruction);
DECLARE_PTR_LIST(multijmp_list, struct multijmp);
DECLARE_PTR_LIST(pseudo_list, struct pseudo);

typedef struct pseudo *pseudo_t;

struct token *skip_to(struct token *, int);
struct token *expect(struct token *, int, const char *);
#ifdef __GNUC__
#define FORMAT_ATTR(pos) __attribute__ ((__format__ (__printf__, pos, pos+1)))
#else
#define FORMAT_ATTR(pos)
#endif
extern void die(const char *, ...) FORMAT_ATTR(1);
extern void info(struct position, const char *, ...) FORMAT_ATTR(2);
extern void warning(struct position, const char *, ...) FORMAT_ATTR(2);
extern void error(struct position, const char *, ...) FORMAT_ATTR(2);
extern void error_die(struct position, const char *, ...) FORMAT_ATTR(2);
#undef FORMAT_ATTR

#define LIST_NODE_NR (29)

struct ptr_list {
	int nr;
	struct ptr_list *prev;
	struct ptr_list *next;
	void *list[LIST_NODE_NR];
};

#define ptr_list_empty(x) ((x) == NULL)

void * delete_ptr_list_last(struct ptr_list **head);
void delete_ptr_list_entry(struct ptr_list **, void *, int);
void replace_ptr_list_entry(struct ptr_list **, void *old, void *new, int);
extern void sort_list(struct ptr_list **, int (*)(const void *, const void *));

extern void **__add_ptr_list(struct ptr_list **, void *, unsigned long tag);
extern void concat_ptr_list(struct ptr_list *a, struct ptr_list **b);
extern void __free_ptr_list(struct ptr_list **);
extern int ptr_list_size(struct ptr_list *);
extern char **handle_switch(char *arg, char **next);
extern void add_pre_buffer(const char *fmt, ...);
int linearize_ptr_list(struct ptr_list *, void **, int);

/*
 * Hey, who said that you can't do overloading in C?
 *
 * You just have to be creative, and use some gcc
 * extensions..
 */
#define add_ptr_list_tag(list,entry,tag) \
	(TYPEOF(*(list))) (CHECK_TYPE(*(list),(entry)),__add_ptr_list((struct ptr_list **)(list), (entry), (tag)))
#define add_ptr_list(list,entry) \
	add_ptr_list_tag(list,entry,0)
#define free_ptr_list(list) \
	do { VRFY_PTR_LIST(*(list)); __free_ptr_list((struct ptr_list **)(list)); } while (0)

extern unsigned int pre_buffer_size;
extern unsigned char pre_buffer[8192];
extern int include_fd;
extern char *include;
extern int preprocess_only;
extern int Wdefault_bitfield_sign;
extern int Wundefined_preprocessor;
extern int Wbitwise, Wtypesign, Wcontext;

extern void declare_builtin_functions(void);
extern void create_builtin_stream(void);
extern struct symbol_list *sparse(int argc, char **argv);

static inline int symbol_list_size(struct symbol_list* list)
{
	return ptr_list_size((struct ptr_list *)(list));
}

static inline int statement_list_size(struct statement_list* list)
{
	return ptr_list_size((struct ptr_list *)(list));
}

static inline int expression_list_size(struct expression_list* list)
{
	return ptr_list_size((struct ptr_list *)(list));
}

static inline int instruction_list_size(struct instruction_list* list)
{
	return ptr_list_size((struct ptr_list *)(list));
}

static inline int pseudo_list_size(struct pseudo_list* list)
{
	return ptr_list_size((struct ptr_list *)(list));
}

static inline int bb_list_size(struct basic_block_list* list)
{
	return ptr_list_size((struct ptr_list *)(list));
}

static inline void free_instruction_list(struct instruction_list **head)
{
	free_ptr_list((struct ptr_list **)head);
}

static inline struct instruction * delete_last_instruction(struct instruction_list **head)
{
	return delete_ptr_list_last((struct ptr_list **)head);
}

static inline struct basic_block * delete_last_basic_block(struct basic_block_list **head)
{
	return delete_ptr_list_last((struct ptr_list **)head);
}

#define PTR_ENTRY(h,i)	(void *)(~3UL & (unsigned long)(h)->list[i])

static inline void *first_ptr_list(struct ptr_list *list)
{
	if (!list)
		return NULL;
	return PTR_ENTRY(list, 0);
}

static inline void *last_ptr_list(struct ptr_list *list)
{

	if (!list)
		return NULL;
	list = list->prev;
	return PTR_ENTRY(list, list->nr-1);
}

static inline struct basic_block *first_basic_block(struct basic_block_list *head)
{
	return first_ptr_list((struct ptr_list *)head);
}
static inline struct instruction *last_instruction(struct instruction_list *head)
{
	return last_ptr_list((struct ptr_list *)head);
}

static inline struct instruction *first_instruction(struct instruction_list *head)
{
	return first_ptr_list((struct ptr_list *)head);
}

static inline pseudo_t first_pseudo(struct pseudo_list *head)
{
	return first_ptr_list((struct ptr_list *)head);
}

static inline void concat_symbol_list(struct symbol_list *from, struct symbol_list **to)
{
	concat_ptr_list((struct ptr_list *)from, (struct ptr_list **)to);
}

static inline void concat_basic_block_list(struct basic_block_list *from, struct basic_block_list **to)
{
	concat_ptr_list((struct ptr_list *)from, (struct ptr_list **)to);
}

static inline void concat_instruction_list(struct instruction_list *from, struct instruction_list **to)
{
	concat_ptr_list((struct ptr_list *)from, (struct ptr_list **)to);
}

static inline void add_symbol(struct symbol_list **list, struct symbol *sym)
{
	add_ptr_list(list, sym);
}

static inline void add_statement(struct statement_list **list, struct statement *stmt)
{
	add_ptr_list(list, stmt);
}

static inline void add_expression(struct expression_list **list, struct expression *expr)
{
	add_ptr_list(list, expr);
}

#define DO_PREPARE(head, ptr, __head, __list, __nr)					\
	do {										\
		struct ptr_list *__head = (struct ptr_list *) (head);			\
		struct ptr_list *__list = __head;					\
		int __nr = 0;								\
		CHECK_TYPE(head,ptr);							\
		if (__head) ptr = PTR_ENTRY(__head, 0);					\
		else ptr = NULL

#define DO_NEXT(ptr, __head, __list, __nr)						\
		if (ptr) {								\
			if (++__nr < __list->nr) {					\
				ptr = PTR_ENTRY(__list,__nr);				\
			} else {							\
				__list = __list->next;					\
				ptr = NULL;						\
				if (__list != __head) {					\
					__nr = 0;					\
					ptr = PTR_ENTRY(__list,0);			\
				}							\
			}								\
		}

#define DO_RESET(ptr, __head, __list, __nr)						\
	do {										\
		__nr = 0;								\
		__list = __head;							\
		if (__head) ptr = PTR_ENTRY(__head, 0);					\
	} while (0)

#define DO_FINISH(ptr, __head, __list, __nr)						\
		(void)(__nr); /* Sanity-check nesting */				\
	} while (0)

#define PREPARE_PTR_LIST(head, ptr) \
	DO_PREPARE(head, ptr, __head##ptr, __list##ptr, __nr##ptr)

#define NEXT_PTR_LIST(ptr) \
	DO_NEXT(ptr, __head##ptr, __list##ptr, __nr##ptr)

#define RESET_PTR_LIST(ptr) \
	DO_RESET(ptr, __head##ptr, __list##ptr, __nr##ptr)

#define FINISH_PTR_LIST(ptr) \
	DO_FINISH(ptr, __head##ptr, __list##ptr, __nr##ptr)

#define DO_FOR_EACH(head, ptr, __head, __list, __nr) do {				\
	struct ptr_list *__head = (struct ptr_list *) (head);				\
	struct ptr_list *__list = __head;						\
	CHECK_TYPE(head,ptr);								\
	if (__head) {									\
		do { int __nr;								\
			for (__nr = 0; __nr < __list->nr; __nr++) {			\
				do {							\
					ptr = PTR_ENTRY(__list,__nr);			\
					do {

#define DO_END_FOR_EACH(ptr, __head, __list, __nr)					\
					} while (0);					\
				} while (0);						\
			}								\
		} while ((__list = __list->next) != __head);				\
	}										\
} while (0)

#define DO_FOR_EACH_REVERSE(head, ptr, __head, __list, __nr) do {			\
	struct ptr_list *__head = (struct ptr_list *) (head);				\
	struct ptr_list *__list = __head;						\
	CHECK_TYPE(head,ptr);								\
	if (__head) {									\
		do { int __nr;								\
			__list = __list->prev;						\
			__nr = __list->nr;						\
			while (--__nr >= 0) {						\
				do {							\
					ptr = PTR_ENTRY(__list,__nr);			\
					do {


#define DO_END_FOR_EACH_REVERSE(ptr, __head, __list, __nr)				\
					} while (0);					\
				} while (0);						\
			}								\
		} while (__list != __head);						\
	}										\
} while (0)

#define DO_REVERSE(ptr, __head, __list, __nr, new, __newhead, __newlist, __newnr) do {	\
	struct ptr_list *__newhead = __head;						\
	struct ptr_list *__newlist = __list;						\
	int __newnr = __nr;								\
	new = ptr;									\
	goto __inside##new;								\
	if (1) {									\
		do {									\
			__newlist = __newlist->prev;					\
			__newnr = __newlist->nr;					\
	__inside##new:									\
			while (--__newnr >= 0) {					\
				do {							\
					new = PTR_ENTRY(__newlist,__newnr);		\
					do {

#define RECURSE_PTR_REVERSE(ptr, new)							\
	DO_REVERSE(ptr, __head##ptr, __list##ptr, __nr##ptr,				\
		   new, __head##new, __list##new, __nr##new)

#define DO_THIS_ADDRESS(ptr, __head, __list, __nr)					\
	((__typeof__(&(ptr))) (__list->list + __nr))

#define FOR_EACH_PTR(head, ptr) \
	DO_FOR_EACH(head, ptr, __head##ptr, __list##ptr, __nr##ptr)

#define END_FOR_EACH_PTR(ptr) \
	DO_END_FOR_EACH(ptr, __head##ptr, __list##ptr, __nr##ptr)

#define FOR_EACH_PTR_REVERSE(head, ptr) \
	DO_FOR_EACH_REVERSE(head, ptr, __head##ptr, __list##ptr, __nr##ptr)

#define END_FOR_EACH_PTR_REVERSE(ptr) \
	DO_END_FOR_EACH_REVERSE(ptr, __head##ptr, __list##ptr, __nr##ptr)

#define THIS_ADDRESS(ptr) \
	DO_THIS_ADDRESS(ptr, __head##ptr, __list##ptr, __nr##ptr)

extern void split_ptr_list_head(struct ptr_list *);

#define DO_SPLIT(ptr, __head, __list, __nr) do {					\
	split_ptr_list_head(__list);							\
	if (__nr >= __list->nr) {							\
		__nr -= __list->nr;							\
		__list = __list->next;							\
	};										\
} while (0)

#define DO_INSERT_CURRENT(new, ptr, __head, __list, __nr) do {				\
	void **__this, **__last;							\
	if (__list->nr == LIST_NODE_NR)							\
		DO_SPLIT(ptr, __head, __list, __nr);					\
	__this = __list->list + __nr;							\
	__last = __list->list + __list->nr - 1;						\
	while (__last >= __this) {							\
		__last[1] = __last[0];							\
		__last--;								\
	}										\
	*__this = (new);								\
	__list->nr++;									\
} while (0)

#define INSERT_CURRENT(new, ptr) \
	DO_INSERT_CURRENT(new, ptr, __head##ptr, __list##ptr, __nr##ptr)

#define DO_DELETE_CURRENT(ptr, __head, __list, __nr) do {				\
	void **__this = __list->list + __nr;						\
	void **__last = __list->list + __list->nr - 1;					\
	while (__this < __last) {							\
		__this[0] = __this[1];							\
		__this++;								\
	}										\
	*__this = (void *)0xf0f0f0f0;							\
	__list->nr--; __nr--;								\
} while (0)

#define DELETE_CURRENT_PTR(ptr) \
	DO_DELETE_CURRENT(ptr, __head##ptr, __list##ptr, __nr##ptr)

#define REPLACE_CURRENT_PTR(ptr, new_ptr)						\
	do { *THIS_ADDRESS(ptr) = (new_ptr); } while (0)

extern void pack_ptr_list(struct ptr_list **);

#define PACK_PTR_LIST(x) pack_ptr_list((struct ptr_list **)(x))

#define hashval(x) ((unsigned long)(x))

static inline void update_tag(void *p, unsigned long tag)
{
	unsigned long *ptr = p;
	*ptr = tag | (~3UL & *ptr);
}

static inline void *tag_ptr(void *ptr, unsigned long tag)
{
	return (void *)(tag | (unsigned long)ptr);
}

#define CURRENT_TAG(ptr) (3 & (unsigned long)*THIS_ADDRESS(ptr))
#define TAG_CURRENT(ptr,val)	update_tag(THIS_ADDRESS(ptr),val)

#endif