3 * Common code generator facilities.
11 char *gen_label_break = NULL;
12 char *gen_label_continue = NULL;
13 char *gen_label_switch = NULL;
14 char *gen_label_break_backup = NULL;
15 char *gen_label_continue_backup = NULL;
16 char *gen_label_switch_backup = NULL;
18 static void gen_emit_emitter(bool indent, const char *fmt, va_list list) {
30 void gen_emit(const char *fmt, ...) {
33 gen_emit_emitter(true, fmt, va);
37 void gen_emit_inline(const char *fmt, ...) {
40 gen_emit_emitter(false, fmt, va);
44 void gen_jump_backup(void) {
45 gen_label_break_backup = gen_label_break;
46 gen_label_continue_backup = gen_label_continue;
49 void gen_jump_save(char *lbreak, char *lcontinue) {
52 gen_label_break = lbreak;
53 gen_label_continue = lcontinue;
56 void gen_jump_restore(void) {
57 gen_label_break = gen_label_break_backup;
58 gen_label_continue = gen_label_continue_backup;
61 void gen_jump(const char *label) {
63 compile_ice("gen_jump");
65 gen_emit("jmp %s", label);
68 void gen_label(const char *label) {
69 gen_emit("%s:", label);
73 * Some expressions are architecture-independent thanks to generic generation
76 static void gen_statement_switch(ast_t *ast) {
77 gen_label_switch_backup = gen_label_switch;
78 gen_label_break_backup = gen_label_break;
79 gen_expression(ast->switchstmt.expr);
80 gen_label_switch = ast_label();
81 gen_label_break = ast_label();
82 gen_jump(gen_label_switch);
83 if (ast->switchstmt.body)
84 gen_expression(ast->switchstmt.body);
85 gen_label(gen_label_switch);
86 gen_label(gen_label_break);
87 gen_label_switch = gen_label_switch_backup;
88 gen_label_break = gen_label_break_backup;
91 static void gen_statement_do(ast_t *ast) {
92 char *begin = ast_label();
93 char *end = ast_label();
94 gen_jump_save(end, begin);
96 gen_expression(ast->forstmt.body);
97 gen_expression(ast->forstmt.cond);
104 static void gen_statement_compound(ast_t *ast) {
105 for (list_iterator_t *it = list_iterator(ast->compound); !list_iterator_end(it); )
106 gen_expression(list_iterator_next(it));
109 static void gen_statement_goto(ast_t *ast) {
110 gen_jump(ast->gotostmt.where);
113 static void gen_statement_label(ast_t *ast) {
114 if (ast->gotostmt.where)
115 gen_label(ast->gotostmt.where);
118 static void gen_statement_cond(ast_t *ast) {
119 gen_expression(ast->ifstmt.cond);
120 char *ne = ast_label();
122 if (ast->ifstmt.then)
123 gen_expression(ast->ifstmt.then);
124 if (ast->ifstmt.last) {
125 char *end = ast_label();
128 gen_expression(ast->ifstmt.last);
135 static void gen_statement_for(ast_t *ast) {
136 if (ast->forstmt.init)
137 gen_expression(ast->forstmt.init);
138 char *begin = ast_label();
139 char *step = ast_label();
140 char *end = ast_label();
141 gen_jump_save(end, step);
143 if (ast->forstmt.cond) {
144 gen_expression(ast->forstmt.cond);
147 gen_expression(ast->forstmt.body);
149 if (ast->forstmt.step)
150 gen_expression(ast->forstmt.step);
156 static void gen_statement_while(ast_t *ast) {
157 char *begin = ast_label();
158 char *end = ast_label();
159 gen_jump_save(end, begin);
161 gen_expression(ast->forstmt.cond);
163 gen_expression(ast->forstmt.body);
169 static void gen_statement_return(ast_t *ast) {
170 if (ast->returnstmt) {
171 gen_expression(ast->returnstmt);
172 gen_boolean_maybe(ast->returnstmt->ctype);
177 static void gen_statement_break(void) {
178 gen_jump(gen_label_break);
181 static void gen_statement_continue(void) {
182 gen_jump(gen_label_continue);
185 static void gen_statement_default(void) {
186 gen_label(gen_label_switch);
187 gen_label_switch = ast_label();
190 static void gen_comma(ast_t *ast) {
191 gen_expression(ast->left);
192 gen_expression(ast->right);
195 static void gen_data_bss(ast_t *ast) {
197 if (!ast->decl.var->ctype->isstatic)
198 gen_emit(".global %s", ast->decl.var->variable.name);
199 gen_emit(".lcomm %s, %d", ast->decl.var->variable.name, ast->decl.var->ctype->size);
202 static void gen_data_global(ast_t *variable) {
203 if (variable->decl.init)
204 gen_data(variable, 0, 0);
206 gen_data_bss(variable);
209 static void gen_declaration_initialization(list_t *init, int offset) {
210 for (list_iterator_t *it = list_iterator(init); !list_iterator_end(it); ) {
211 ast_t *node = list_iterator_next(it);
212 if (node->init.value->type == AST_TYPE_LITERAL && node->init.type->bitfield.size <= 0)
213 gen_literal_save(node->init.value, node->init.type, node->init.offset + offset);
215 gen_expression(node->init.value);
216 gen_save_local(node->init.type, node->init.offset + offset);
221 static void gen_declaration(ast_t *ast) {
225 gen_zero(ast->decl.var->variable.off, ast->decl.var->variable.off + ast->decl.var->ctype->size);
226 gen_declaration_initialization(ast->decl.init, ast->decl.var->variable.off);
229 void gen_ensure_lva(ast_t *ast) {
230 if (ast->variable.init) {
231 gen_zero(ast->variable.off, ast->variable.off + ast->ctype->size);
232 gen_declaration_initialization(ast->variable.init, ast->variable.off);
234 ast->variable.init = NULL;
237 void gen_expression(ast_t *ast) {
241 case AST_TYPE_STATEMENT_IF: gen_statement_cond(ast); break;
242 case AST_TYPE_EXPRESSION_TERNARY: gen_statement_cond(ast); break;
243 case AST_TYPE_STATEMENT_FOR: gen_statement_for(ast); break;
244 case AST_TYPE_STATEMENT_WHILE: gen_statement_while(ast); break;
245 case AST_TYPE_STATEMENT_DO: gen_statement_do(ast); break;
246 case AST_TYPE_STATEMENT_COMPOUND: gen_statement_compound(ast); break;
247 case AST_TYPE_STATEMENT_SWITCH: gen_statement_switch(ast); break;
248 case AST_TYPE_STATEMENT_GOTO: gen_statement_goto(ast); break;
249 case AST_TYPE_STATEMENT_LABEL: gen_statement_label(ast); break;
250 case AST_TYPE_STATEMENT_RETURN: gen_statement_return(ast); break;
251 case AST_TYPE_STATEMENT_BREAK: gen_statement_break(); break;
252 case AST_TYPE_STATEMENT_CONTINUE: gen_statement_continue(); break;
253 case AST_TYPE_STATEMENT_DEFAULT: gen_statement_default(); break;
254 case AST_TYPE_CALL: gen_function_call(ast); break;
255 case AST_TYPE_POINTERCALL: gen_function_call(ast); break;
256 case AST_TYPE_LITERAL: gen_literal(ast); break;
257 case AST_TYPE_STRING: gen_literal_string(ast); break;
258 case AST_TYPE_VAR_LOCAL: gen_variable_local(ast); break;
259 case AST_TYPE_VAR_GLOBAL: gen_variable_global(ast); break;
260 case AST_TYPE_DECLARATION: gen_declaration(ast); break;
261 case AST_TYPE_DEREFERENCE: gen_dereference(ast); break;
262 case AST_TYPE_ADDRESS: gen_address(ast->unary.operand); break;
263 case AST_TYPE_STATEMENT_CASE: gen_case(ast); break;
264 case AST_TYPE_VA_START: gen_va_start(ast); break;
265 case AST_TYPE_VA_ARG: gen_va_arg(ast); break;
266 case '!': gen_not(ast); break;
267 case AST_TYPE_NEGATE: gen_negate(ast); break;
268 case AST_TYPE_AND: gen_and(ast); break;
269 case AST_TYPE_OR: gen_or(ast); break;
270 case AST_TYPE_POST_INCREMENT: gen_postfix(ast, "add"); break;
271 case AST_TYPE_POST_DECREMENT: gen_postfix(ast, "sub"); break;
272 case AST_TYPE_PRE_INCREMENT: gen_prefix (ast, "add"); break;
273 case AST_TYPE_PRE_DECREMENT: gen_prefix (ast, "sub"); break;
274 case AST_TYPE_EXPRESSION_CAST: gen_cast(ast); break;
275 case AST_TYPE_STRUCT: gen_struct(ast); break;
276 case '&': gen_bitandor(ast); break;
277 case '|': gen_bitandor(ast); break;
278 case '~': gen_bitnot(ast); break;
279 case ',': gen_comma(ast); break;
280 case '=': gen_assign(ast); break;
281 case AST_TYPE_CONVERT: gen_conversion(ast); break;
282 case AST_TYPE_STATEMENT_GOTO_COMPUTED: gen_goto_computed(ast); break;
283 case AST_TYPE_STATEMENT_LABEL_COMPUTED: gen_address_label(ast); break;
289 void gen_toplevel(ast_t *ast) {
291 if (ast->type == AST_TYPE_FUNCTION) {
292 gen_function_prologue(ast);
293 gen_expression(ast->function.body);
294 gen_function_epilogue();
295 } else if (ast->type == AST_TYPE_DECLARATION) {
296 gen_data_global(ast);