1 /*
2  * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19 
20 /**
21  * @file
22  * @brief   emit assembler for a backend graph
23  */
24 #include "config.h"
25 
26 #include <limits.h>
27 
28 #include "xmalloc.h"
29 #include "tv.h"
30 #include "iredges.h"
31 #include "debug.h"
32 #include "irgwalk.h"
33 #include "irprintf.h"
34 #include "irop_t.h"
35 #include "irargs_t.h"
36 #include "irprog.h"
37 
38 #include "besched.h"
39 #include "begnuas.h"
40 #include "beblocksched.h"
41 
42 #include "amd64_emitter.h"
43 #include "gen_amd64_emitter.h"
44 #include "gen_amd64_regalloc_if.h"
45 #include "amd64_nodes_attr.h"
46 #include "amd64_new_nodes.h"
47 
48 #include "benode.h"
49 
50 /*************************************************************
51  *             _       _    __   _          _
52  *            (_)     | |  / _| | |        | |
53  *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
54  * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
55  * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
56  * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
57  * | |                                       | |
58  * |_|                                       |_|
59  *************************************************************/
60 
61 /**
62  * Returns the target block for a control flow node.
63  */
get_cfop_target_block(const ir_node * irn)64 static ir_node *get_cfop_target_block(const ir_node *irn)
65 {
66 	return (ir_node*)get_irn_link(irn);
67 }
68 
amd64_emitf(ir_node const * const node,char const * fmt,...)69 void amd64_emitf(ir_node const *const node, char const *fmt, ...)
70 {
71 	va_list ap;
72 	va_start(ap, fmt);
73 
74 	be_emit_char('\t');
75 	for (;;) {
76 		char const *start = fmt;
77 
78 		while (*fmt != '%' && *fmt != '\n' && *fmt != '\0')
79 			++fmt;
80 		if (fmt != start) {
81 			be_emit_string_len(start, fmt - start);
82 		}
83 
84 		if (*fmt == '\n') {
85 			be_emit_char('\n');
86 			be_emit_write_line();
87 			be_emit_char('\t');
88 			++fmt;
89 			continue;
90 		}
91 
92 		if (*fmt == '\0')
93 			break;
94 
95 		++fmt;
96 
97 		switch (*fmt++) {
98 			arch_register_t const *reg;
99 
100 			case '%':
101 				be_emit_char('%');
102 				break;
103 
104 			case 'C': {
105 				amd64_attr_t const *const attr = get_amd64_attr_const(node);
106 				be_emit_irprintf("$0x%X", attr->ext.imm_value);
107 				break;
108 			}
109 
110 			case 'D':
111 				if (*fmt < '0' || '9' <= *fmt)
112 					goto unknown;
113 				reg = arch_get_irn_register_out(node, *fmt++ - '0');
114 				goto emit_R;
115 
116 			case 'E': {
117 				ir_entity const *const ent = va_arg(ap, ir_entity const*);
118 				be_gas_emit_entity(ent);
119 				break;
120 			}
121 
122 			case 'L': {
123 				ir_node *const block = get_cfop_target_block(node);
124 				be_gas_emit_block_name(block);
125 				break;
126 			}
127 
128 			case 'O': {
129 				amd64_SymConst_attr_t const *const attr = get_amd64_SymConst_attr_const(node);
130 				if (attr->fp_offset)
131 					be_emit_irprintf("%d", attr->fp_offset);
132 				break;
133 			}
134 
135 			case 'R':
136 				reg = va_arg(ap, arch_register_t const*);
137 emit_R:
138 				be_emit_char('%');
139 				be_emit_string(reg->name);
140 				break;
141 
142 			case 'S': {
143 				int pos;
144 				if ('0' <= *fmt && *fmt <= '9') {
145 					pos = *fmt++ - '0';
146 				} else if (*fmt == '*') {
147 					++fmt;
148 					pos = va_arg(ap, int);
149 				} else {
150 					goto unknown;
151 				}
152 				reg = arch_get_irn_register_in(node, pos);
153 				goto emit_R;
154 			}
155 
156 			case 'd': {
157 				int const num = va_arg(ap, int);
158 				be_emit_irprintf("%d", num);
159 				break;
160 			}
161 
162 			case 's': {
163 				char const *const str = va_arg(ap, char const*);
164 				be_emit_string(str);
165 				break;
166 			}
167 
168 			case 'u': {
169 				unsigned const num = va_arg(ap, unsigned);
170 				be_emit_irprintf("%u", num);
171 				break;
172 			}
173 
174 			default:
175 unknown:
176 				panic("unknown format conversion");
177 		}
178 	}
179 
180 	be_emit_finish_line_gas(node);
181 	va_end(ap);
182 }
183 
184 /***********************************************************************************
185  *                  _          __                                             _
186  *                 (_)        / _|                                           | |
187  *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
188  * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
189  * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
190  * |_| |_| |_|\__,_|_|_| |_| |_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
191  *
192  ***********************************************************************************/
193 
194 /**
195  * Default emitter for anything that we don't want to generate code for.
196  */
emit_nothing(const ir_node * node)197 static void emit_nothing(const ir_node *node)
198 {
199 	(void) node;
200 }
201 
202 /**
203  * Emit a SymConst.
204  */
emit_amd64_SymConst(const ir_node * irn)205 static void emit_amd64_SymConst(const ir_node *irn)
206 {
207 	const amd64_SymConst_attr_t *attr = get_amd64_SymConst_attr_const(irn);
208 #if 0
209 	sym_or_tv_t key, *entry;
210 	unsigned label;
211 
212 	key.u.id     = get_entity_ld_ident(attr->entity);
213 	key.is_ident = 1;
214 	key.label    = 0;
215 	entry = set_insert(sym_or_tv_t, sym_or_tv, &key, sizeof(key), hash_ptr(key.u.generic));
216 	if (entry->label == 0) {
217 		/* allocate a label */
218 		entry->label = get_unique_label();
219 	}
220 	label = entry->label;
221 #endif
222 
223 	amd64_emitf(irn, "mov $%E, %D0", attr->entity);
224 }
225 
226 /**
227  * Emit a Conv.
228  */
emit_amd64_Conv(const ir_node * irn)229 static void emit_amd64_Conv(const ir_node *irn)
230 {
231 	amd64_emitf(irn, "mov %S0, %D0");
232 }
233 
234 
235 /**
236  * Returns the next block in a block schedule.
237  */
sched_next_block(const ir_node * block)238 static ir_node *sched_next_block(const ir_node *block)
239 {
240     return (ir_node*)get_irn_link(block);
241 }
242 
243 /**
244  * Emit a Jmp.
245  */
emit_amd64_Jmp(const ir_node * node)246 static void emit_amd64_Jmp(const ir_node *node)
247 {
248 	ir_node *block, *next_block;
249 
250 	/* for now, the code works for scheduled and non-schedules blocks */
251 	block = get_nodes_block(node);
252 
253 	/* we have a block schedule */
254 	next_block = sched_next_block(block);
255 	if (get_cfop_target_block(node) != next_block) {
256 		amd64_emitf(node, "jmp %L");
257 	} else if (be_options.verbose_asm) {
258 		amd64_emitf(node, "/* fallthrough to %L */");
259 	}
260 }
261 
262 /**
263  * Emit a Compare with conditional branch.
264  */
emit_amd64_Jcc(const ir_node * irn)265 static void emit_amd64_Jcc(const ir_node *irn)
266 {
267 	const ir_node      *proj_true  = NULL;
268 	const ir_node      *proj_false = NULL;
269 	const ir_node      *block;
270 	const ir_node      *next_block;
271 	const char         *suffix;
272 	const amd64_attr_t *attr      = get_amd64_attr_const(irn);
273 	ir_relation         relation  = attr->ext.relation;
274 	ir_node            *op1       = get_irn_n(irn, 0);
275 	const amd64_attr_t *cmp_attr  = get_amd64_attr_const(op1);
276 	bool                is_signed = !cmp_attr->data.cmp_unsigned;
277 
278 	assert(is_amd64_Cmp(op1));
279 
280 	foreach_out_edge(irn, edge) {
281 		ir_node *proj = get_edge_src_irn(edge);
282 		long nr = get_Proj_proj(proj);
283 		if (nr == pn_Cond_true) {
284 			proj_true = proj;
285 		} else {
286 			proj_false = proj;
287 		}
288 	}
289 
290 	if (cmp_attr->data.ins_permuted) {
291 		relation = get_inversed_relation(relation);
292 	}
293 
294 	/* for now, the code works for scheduled and non-schedules blocks */
295 	block = get_nodes_block(irn);
296 
297 	/* we have a block schedule */
298 	next_block = sched_next_block(block);
299 
300 	assert(relation != ir_relation_false);
301 	assert(relation != ir_relation_true);
302 
303 	if (get_cfop_target_block(proj_true) == next_block) {
304 		/* exchange both proj's so the second one can be omitted */
305 		const ir_node *t = proj_true;
306 
307 		proj_true  = proj_false;
308 		proj_false = t;
309 		relation   = get_negated_relation(relation);
310 	}
311 
312 	switch (relation & ir_relation_less_equal_greater) {
313 		case ir_relation_equal:              suffix = "e"; break;
314 		case ir_relation_less:               suffix = is_signed ? "l"  : "b"; break;
315 		case ir_relation_less_equal:         suffix = is_signed ? "le" : "be"; break;
316 		case ir_relation_greater:            suffix = is_signed ? "g"  : "a"; break;
317 		case ir_relation_greater_equal:      suffix = is_signed ? "ge" : "ae"; break;
318 		case ir_relation_less_greater:       suffix = "ne"; break;
319 		case ir_relation_less_equal_greater: suffix = "mp"; break;
320 		default: panic("Cmp has unsupported pnc");
321 	}
322 
323 	/* emit the true proj */
324 	amd64_emitf(proj_true, "j%s %L", suffix);
325 
326 	if (get_cfop_target_block(proj_false) != next_block) {
327 		amd64_emitf(proj_false, "jmp %L");
328 	} else if (be_options.verbose_asm) {
329 		amd64_emitf(proj_false, "/* fallthrough to %L */");
330 	}
331 }
332 
333 /**
334  * Emits code for a call.
335  */
emit_be_Call(const ir_node * node)336 static void emit_be_Call(const ir_node *node)
337 {
338 	ir_entity *entity = be_Call_get_entity(node);
339 
340 	/* %eax/%rax is used in AMD64 to pass the number of vector parameters for
341 	 * variable argument counts */
342 	if (get_method_variadicity (be_Call_get_type((ir_node *) node))) {
343 		/* But this still is a hack... */
344 		amd64_emitf(node, "xor %%rax, %%rax");
345 	}
346 
347 	if (entity) {
348 		amd64_emitf(node, "call %E", entity);
349 	} else {
350 		be_emit_pad_comment();
351 		be_emit_cstring("/* FIXME: call NULL entity?! */\n");
352 	}
353 }
354 
355 /**
356  * emit copy node
357  */
emit_be_Copy(const ir_node * irn)358 static void emit_be_Copy(const ir_node *irn)
359 {
360 	ir_mode *mode = get_irn_mode(irn);
361 
362 	if (arch_get_irn_register_in(irn, 0) == arch_get_irn_register_out(irn, 0)) {
363 		/* omitted Copy */
364 		return;
365 	}
366 
367 	if (mode_is_float(mode)) {
368 		panic("move not supported for FP");
369 	} else if (mode_is_data(mode)) {
370 		amd64_emitf(irn, "mov %S0, %D0");
371 	} else {
372 		panic("move not supported for this mode");
373 	}
374 }
375 
emit_be_Perm(const ir_node * node)376 static void emit_be_Perm(const ir_node *node)
377 {
378 	const arch_register_t *in0, *in1;
379 
380 	in0 = arch_get_irn_register(get_irn_n(node, 0));
381 	in1 = arch_get_irn_register(get_irn_n(node, 1));
382 
383 	arch_register_class_t const* const cls0 = in0->reg_class;
384 	assert(cls0 == in1->reg_class && "Register class mismatch at Perm");
385 
386 	amd64_emitf(node, "xchg %R, %R", in0, in1);
387 
388 	if (cls0 != &amd64_reg_classes[CLASS_amd64_gp]) {
389 		panic("unexpected register class in be_Perm (%+F)", node);
390 	}
391 }
392 
emit_amd64_FrameAddr(const ir_node * irn)393 static void emit_amd64_FrameAddr(const ir_node *irn)
394 {
395 	const amd64_SymConst_attr_t *attr =
396 		(const amd64_SymConst_attr_t*) get_amd64_attr_const(irn);
397 
398 	amd64_emitf(irn, "mov %S0, %D0");
399 	amd64_emitf(irn, "add $%u, %D0", attr->fp_offset);
400 }
401 
402 /**
403  * Emits code to increase stack pointer.
404  */
emit_be_IncSP(const ir_node * node)405 static void emit_be_IncSP(const ir_node *node)
406 {
407 	int offs = be_get_IncSP_offset(node);
408 
409 	if (offs == 0)
410 		return;
411 
412 	if (offs > 0) {
413 		amd64_emitf(node, "sub, $%d, %D0", offs);
414 	} else {
415 		amd64_emitf(node, "add, $%d, %D0", -offs);
416 	}
417 }
418 
419 /**
420  * Emits code for a return.
421  */
emit_be_Return(const ir_node * node)422 static void emit_be_Return(const ir_node *node)
423 {
424 	be_emit_cstring("\tret");
425 	be_emit_finish_line_gas(node);
426 }
427 
428 
emit_amd64_binop_op(const ir_node * irn,int second_op)429 static void emit_amd64_binop_op(const ir_node *irn, int second_op)
430 {
431 	if (irn->op == op_amd64_Add) {
432 		amd64_emitf(irn, "add %S*, %D0", second_op);
433 	} else if (irn->op == op_amd64_Sub) {
434 		amd64_emitf(irn, "neg %S*",      second_op);
435 		amd64_emitf(irn, "add %S*, %D0", second_op);
436 		amd64_emitf(irn, "neg %S*",      second_op);
437 	}
438 
439 }
440 
441 /**
442  * Emits an arithmetic operation that handles arbitraty input registers.
443  */
emit_amd64_binop(const ir_node * irn)444 static void emit_amd64_binop(const ir_node *irn)
445 {
446 	const arch_register_t *reg_s1 = arch_get_irn_register_in(irn, 0);
447 	const arch_register_t *reg_s2 = arch_get_irn_register_in(irn, 1);
448 	const arch_register_t *reg_d1 = arch_get_irn_register_out(irn, 0);
449 
450 	int second_op = 0;
451 
452 	if (reg_d1 != reg_s1 && reg_d1 != reg_s2) {
453 		amd64_emitf(irn, "mov %R, %R", reg_s1, reg_d1);
454 		second_op = 1;
455 	} else if (reg_d1 == reg_s2 && reg_d1 != reg_s1) {
456 		second_op = 0;
457 	}
458 
459 	emit_amd64_binop_op(irn, second_op);
460 }
461 
462 /**
463  * The type of a emitter function.
464  */
465 typedef void (emit_func)(const ir_node *irn);
466 
467 /**
468  * Set a node emitter. Make it a bit more type safe.
469  */
set_emitter(ir_op * op,emit_func arm_emit_node)470 static inline void set_emitter(ir_op *op, emit_func arm_emit_node)
471 {
472 	op->ops.generic = (op_func)arm_emit_node;
473 }
474 
475 /**
476  * Enters the emitter functions for handled nodes into the generic
477  * pointer of an opcode.
478  */
amd64_register_emitters(void)479 static void amd64_register_emitters(void)
480 {
481 	/* first clear the generic function pointer for all ops */
482 	ir_clear_opcodes_generic_func();
483 
484 	/* register all emitter functions defined in spec */
485 	amd64_register_spec_emitters();
486 
487 	set_emitter(op_amd64_SymConst,   emit_amd64_SymConst);
488 	set_emitter(op_amd64_Jmp,        emit_amd64_Jmp);
489 	set_emitter(op_amd64_Jcc,        emit_amd64_Jcc);
490 	set_emitter(op_amd64_Conv,       emit_amd64_Conv);
491 	set_emitter(op_amd64_FrameAddr,  emit_amd64_FrameAddr);
492 	set_emitter(op_be_Return,        emit_be_Return);
493 	set_emitter(op_be_Call,          emit_be_Call);
494 	set_emitter(op_be_Copy,          emit_be_Copy);
495 	set_emitter(op_be_IncSP,         emit_be_IncSP);
496 	set_emitter(op_be_Perm,          emit_be_Perm);
497 
498 	set_emitter(op_amd64_Add,        emit_amd64_binop);
499 	set_emitter(op_amd64_Sub,        emit_amd64_binop);
500 
501 	set_emitter(op_be_Start,         emit_nothing);
502 	set_emitter(op_be_Keep,          emit_nothing);
503 	set_emitter(op_Phi,              emit_nothing);
504 }
505 
506 typedef void (*emit_func_ptr) (const ir_node *);
507 
508 /**
509  * Emits code for a node.
510  */
amd64_emit_node(const ir_node * node)511 static void amd64_emit_node(const ir_node *node)
512 {
513 	ir_op               *op       = get_irn_op(node);
514 
515 	if (op->ops.generic) {
516 		emit_func_ptr func = (emit_func_ptr) op->ops.generic;
517 		(*func) (node);
518 	} else {
519 		ir_fprintf(stderr, "No emitter for node %+F\n", node);
520 	}
521 }
522 
523 /**
524  * Walks over the nodes in a block connected by scheduling edges
525  * and emits code for each node.
526  */
amd64_gen_block(ir_node * block,void * data)527 static void amd64_gen_block(ir_node *block, void *data)
528 {
529 	(void) data;
530 
531 	if (! is_Block(block))
532 		return;
533 
534 	be_gas_begin_block(block, true);
535 
536 	sched_foreach(block, node) {
537 		amd64_emit_node(node);
538 	}
539 }
540 
541 
542 /**
543  * Sets labels for control flow nodes (jump target)
544  * TODO: Jump optimization
545  */
amd64_gen_labels(ir_node * block,void * env)546 static void amd64_gen_labels(ir_node *block, void *env)
547 {
548 	ir_node *pred;
549 	int n = get_Block_n_cfgpreds(block);
550 	(void) env;
551 
552 	for (n--; n >= 0; n--) {
553 		pred = get_Block_cfgpred(block, n);
554 		set_irn_link(pred, block);
555 	}
556 }
557 
558 /**
559  * Main driver
560  */
amd64_gen_routine(ir_graph * irg)561 void amd64_gen_routine(ir_graph *irg)
562 {
563 	ir_entity *entity = get_irg_entity(irg);
564 	ir_node  **blk_sched;
565 	size_t i, n;
566 
567 	/* register all emitter functions */
568 	amd64_register_emitters();
569 
570 	blk_sched = be_create_block_schedule(irg);
571 
572 	be_gas_emit_function_prolog(entity, 4, NULL);
573 
574 	irg_block_walk_graph(irg, amd64_gen_labels, NULL, NULL);
575 
576 	n = ARR_LEN(blk_sched);
577 	for (i = 0; i < n; i++) {
578 		ir_node *block = blk_sched[i];
579 		ir_node *next  = (i + 1) < n ? blk_sched[i+1] : NULL;
580 
581 		set_irn_link(block, next);
582 	}
583 
584 	for (i = 0; i < n; ++i) {
585 		ir_node *block = blk_sched[i];
586 
587 		amd64_gen_block(block, 0);
588 	}
589 
590 	be_gas_emit_function_epilog(entity);
591 }
592