beemitter.h 2.55 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

Christian Würdig's avatar
Christian Würdig committed
6
7
/**
 * @file
8
 * @brief       Interface for text output.
Christian Würdig's avatar
Christian Würdig committed
9
10
 * @author      Matthias Braun
 * @date        12.03.2007
11
 *
12
13
 * This is a framework for emitting line base text used by most backends to
 * emit assembly code.
Matthias Braun's avatar
Matthias Braun committed
14
 */
Michael Beck's avatar
Michael Beck committed
15
16
#ifndef FIRM_BE_BEEMITTER_H
#define FIRM_BE_BEEMITTER_H
Matthias Braun's avatar
Matthias Braun committed
17
18
19
20

#include <stdio.h>
#include "obst.h"

21
22
/* don't use the following vars directly, they're only here for the inlines */
extern struct obstack  emit_obst;
Matthias Braun's avatar
Matthias Braun committed
23

Michael Beck's avatar
Michael Beck committed
24
25
26
/**
 * Emit a character to the (assembler) output.
 */
27
static inline void be_emit_char(char c)
28
29
{
	obstack_1grow(&emit_obst, c);
Matthias Braun's avatar
Matthias Braun committed
30
31
}

Michael Beck's avatar
Michael Beck committed
32
33
34
35
36
37
/**
 * Emit a string to the (assembler) output.
 *
 * @param str  the string
 * @param l    the length of the given string
 */
38
static inline void be_emit_string_len(const char *str, size_t l)
Matthias Braun's avatar
Matthias Braun committed
39
{
40
	obstack_grow(&emit_obst, str, l);
Matthias Braun's avatar
Matthias Braun committed
41
42
}

Michael Beck's avatar
Michael Beck committed
43
44
45
46
47
/**
 * Emit a null-terminated string to the (assembler) output.
 *
 * @param str  the null-terminated string
 */
48
static inline void be_emit_string(const char *str)
Matthias Braun's avatar
Matthias Braun committed
49
50
{
	size_t len = strlen(str);
51
	be_emit_string_len(str, len);
Matthias Braun's avatar
Matthias Braun committed
52
53
}

Michael Beck's avatar
Michael Beck committed
54
55
56
57
58
/**
 * Emit a C string-constant to the (assembler) output.
 *
 * @param str  the null-terminated string constant
 */
59
#define be_emit_cstring(str) \
Michael Beck's avatar
Michael Beck committed
60
	be_emit_string_len(str, sizeof(str) - 1)
Matthias Braun's avatar
Matthias Braun committed
61

Michael Beck's avatar
Michael Beck committed
62
63
64
65
66
/**
 * Initializes an emitter environment.
 *
 * @param F    a file handle where the emitted file is written to.
 */
67
void be_emit_init(FILE *F);
Michael Beck's avatar
Michael Beck committed
68
69
70
71

/**
 * Destroys the given emitter environment.
 */
72
void be_emit_exit(void);
Matthias Braun's avatar
Matthias Braun committed
73

Michael Beck's avatar
Michael Beck committed
74
75
76
77
78
/**
 * Emit the output of an ir_printf.
 *
 * @param fmt  the ir_printf format
 */
79
void be_emit_irprintf(const char *fmt, ...);
Michael Beck's avatar
Michael Beck committed
80
81
82
83
84
85

/**
 * Emit the output of an ir_vprintf.
 *
 * @param fmt  the ir_printf format
 */
86
void be_emit_irvprintf(const char *fmt, va_list args);
Michael Beck's avatar
Michael Beck committed
87
88
89
90

/**
 * Flush the line in the current line buffer to the emitter file.
 */
91
void be_emit_write_line(void);
Matthias Braun's avatar
Matthias Braun committed
92

93
94
/** Return column in current line. Counting starts at 0. */
static inline size_t be_emit_get_column(void)
95
{
96
	return obstack_object_size(&emit_obst);
97
98
}

99
100
101
102
103
104
#define BE_EMITF(node, fmt, ap, in_delay_slot) \
	va_list ap; \
	va_start(ap, fmt); \
	be_emit_char('\t'); \
	if (in_delay_slot) \
		be_emit_char(' '); \
105
106
	for (size_t node##__n;;) \
		if (node##__n = strcspn(fmt, "\n%"), be_emit_string_len(fmt, node##__n), fmt += node##__n, *fmt == '\0') { \
107
108
109
110
111
112
113
114
115
116
117
118
119
			be_emit_finish_line_gas(node); \
			va_end(ap); \
			break; \
		} else if (*fmt == '\n') { \
			++fmt; \
			be_emit_char('\n'); \
			be_emit_write_line(); \
			be_emit_char('\t'); \
		} else if (*++fmt == '%') { \
			++fmt; \
			be_emit_char('%'); \
		} else

120
#endif