1/*
2 * Example of how to write a compiler with sparse
3 */
4#include <stdio.h>
5#include <stdlib.h>
6#include <stdarg.h>
7#include <string.h>
8#include <assert.h>
9
10#include "symbol.h"
11#include "expression.h"
12#include "linearize.h"
13#include "flow.h"
14#include "storage.h"
15#include "target.h"
16
17static const char *opcodes[] = {
18	[OP_BADOP] = "bad_op",
19
20	/* Fn entrypoint */
21	[OP_ENTRY] = "<entry-point>",
22
23	/* Terminator */
24	[OP_RET] = "ret",
25	[OP_BR] = "br",
26	[OP_CBR] = "cbr",
27	[OP_SWITCH] = "switch",
28	[OP_COMPUTEDGOTO] = "jmp *",
29
30	/* Binary */
31	[OP_ADD] = "add",
32	[OP_SUB] = "sub",
33	[OP_MUL] = "mul",
34	[OP_DIVU] = "divu",
35	[OP_DIVS] = "divs",
36	[OP_MODU] = "modu",
37	[OP_MODS] = "mods",
38	[OP_SHL] = "shl",
39	[OP_LSR] = "lsr",
40	[OP_ASR] = "asr",
41
42	/* Logical */
43	[OP_AND] = "and",
44	[OP_OR] = "or",
45	[OP_XOR] = "xor",
46
47	/* Binary comparison */
48	[OP_SET_EQ] = "seteq",
49	[OP_SET_NE] = "setne",
50	[OP_SET_LE] = "setle",
51	[OP_SET_GE] = "setge",
52	[OP_SET_LT] = "setlt",
53	[OP_SET_GT] = "setgt",
54	[OP_SET_B] = "setb",
55	[OP_SET_A] = "seta",
56	[OP_SET_BE] = "setbe",
57	[OP_SET_AE] = "setae",
58
59	/* Uni */
60	[OP_NOT] = "not",
61	[OP_NEG] = "neg",
62
63	/* Special three-input */
64	[OP_SEL] = "select",
65
66	/* Memory */
67	[OP_LOAD] = "load",
68	[OP_STORE] = "store",
69	[OP_LABEL] = "label",
70	[OP_SETVAL] = "set",
71
72	/* Other */
73	[OP_PHI] = "phi",
74	[OP_PHISOURCE] = "phisrc",
75	[OP_COPY] = "copy",
76	[OP_SEXT] = "sext",
77	[OP_ZEXT] = "zext",
78	[OP_TRUNC] = "trunc",
79	[OP_FCVTU] = "fcvtu",
80	[OP_FCVTS] = "fcvts",
81	[OP_UCVTF] = "ucvtf",
82	[OP_SCVTF] = "scvtf",
83	[OP_FCVTF] = "fcvtf",
84	[OP_UTPTR] = "utptr",
85	[OP_PTRTU] = "utptr",
86	[OP_PTRCAST] = "ptrcast",
87	[OP_CALL] = "call",
88	[OP_SLICE] = "slice",
89	[OP_NOP] = "nop",
90	[OP_DEATHNOTE] = "dead",
91	[OP_ASM] = "asm",
92
93	/* Sparse tagging (line numbers, context, whatever) */
94	[OP_CONTEXT] = "context",
95};
96
97static int last_reg, stack_offset;
98
99struct hardreg {
100	const char *name;
101	struct pseudo_list *contains;
102	unsigned busy:16,
103		 dead:8,
104		 used:1;
105};
106
107#define TAG_DEAD 1
108#define TAG_DIRTY 2
109
110/* Our "switch" generation is very very stupid. */
111#define SWITCH_REG (1)
112
113static void output_bb(struct basic_block *bb, unsigned long generation);
114
115/*
116 * We only know about the caller-clobbered registers
117 * right now.
118 */
119static struct hardreg hardregs[] = {
120	{ .name = "%eax" },
121	{ .name = "%edx" },
122	{ .name = "%ecx" },
123	{ .name = "%ebx" },
124	{ .name = "%esi" },
125	{ .name = "%edi" },
126
127	{ .name = "%ebp" },
128	{ .name = "%esp" },
129};
130#define REGNO 6
131#define REG_EBP 6
132#define REG_ESP 7
133
134struct bb_state {
135	struct position pos;
136	struct storage_hash_list *inputs;
137	struct storage_hash_list *outputs;
138	struct storage_hash_list *internal;
139
140	/* CC cache.. */
141	int cc_opcode, cc_dead;
142	pseudo_t cc_target;
143};
144
145enum optype {
146	OP_UNDEF,
147	OP_REG,
148	OP_VAL,
149	OP_MEM,
150	OP_ADDR,
151};
152
153struct operand {
154	enum optype type;
155	int size;
156	union {
157		struct hardreg *reg;
158		long long value;
159		struct /* OP_MEM and OP_ADDR */ {
160			unsigned int offset;
161			unsigned int scale;
162			struct symbol *sym;
163			struct hardreg *base;
164			struct hardreg *index;
165		};
166	};
167};
168
169static const char *show_op(struct bb_state *state, struct operand *op)
170{
171	static char buf[256][4];
172	static int bufnr;
173	char *p, *ret;
174	int nr;
175
176	nr = (bufnr + 1) & 3;
177	bufnr = nr;
178	ret = p = buf[nr];
179
180	switch (op->type) {
181	case OP_UNDEF:
182		return "undef";
183	case OP_REG:
184		return op->reg->name;
185	case OP_VAL:
186		sprintf(p, "$%lld", op->value);
187		break;
188	case OP_MEM:
189	case OP_ADDR:
190		if (op->offset)
191			p += sprintf(p, "%d", op->offset);
192		if (op->sym)
193			p += sprintf(p, "%s%s",
194				op->offset ? "+" : "",
195				show_ident(op->sym->ident));
196		if (op->base || op->index) {
197			p += sprintf(p, "(%s%s%s",
198				op->base ? op->base->name : "",
199				(op->base && op->index) ? "," : "",
200				op->index ? op->index->name : "");
201			if (op->scale > 1)
202				p += sprintf(p, ",%d", op->scale);
203			*p++ = ')';
204			*p = '\0';
205		}
206		break;
207	}
208	return ret;
209}
210
211static struct storage_hash *find_storage_hash(pseudo_t pseudo, struct storage_hash_list *list)
212{
213	struct storage_hash *entry;
214	FOR_EACH_PTR(list, entry) {
215		if (entry->pseudo == pseudo)
216			return entry;
217	} END_FOR_EACH_PTR(entry);
218	return NULL;
219}
220
221static struct storage_hash *find_or_create_hash(pseudo_t pseudo, struct storage_hash_list **listp)
222{
223	struct storage_hash *entry;
224
225	entry = find_storage_hash(pseudo, *listp);
226	if (!entry) {
227		entry = alloc_storage_hash(alloc_storage());
228		entry->pseudo = pseudo;
229		add_ptr_list(listp, entry);
230	}
231	return entry;
232}
233
234/* Eventually we should just build it up in memory */
235static void FORMAT_ATTR(2) output_line(struct bb_state *state, const char *fmt, ...)
236{
237	va_list args;
238
239	va_start(args, fmt);
240	vprintf(fmt, args);
241	va_end(args);
242}
243
244static void FORMAT_ATTR(2) output_label(struct bb_state *state, const char *fmt, ...)
245{
246	static char buffer[512];
247	va_list args;
248
249	va_start(args, fmt);
250	vsnprintf(buffer, sizeof(buffer), fmt, args);
251	va_end(args);
252
253	output_line(state, "%s:\n", buffer);
254}
255
256static void FORMAT_ATTR(2) output_insn(struct bb_state *state, const char *fmt, ...)
257{
258	static char buffer[512];
259	va_list args;
260
261	va_start(args, fmt);
262	vsnprintf(buffer, sizeof(buffer), fmt, args);
263	va_end(args);
264
265	output_line(state, "\t%s\n", buffer);
266}
267
268#define output_insn(state, fmt, arg...) \
269	output_insn(state, fmt "\t\t# %s" , ## arg , __FUNCTION__)
270
271static void FORMAT_ATTR(2) output_comment(struct bb_state *state, const char *fmt, ...)
272{
273	static char buffer[512];
274	va_list args;
275
276	if (!verbose)
277		return;
278	va_start(args, fmt);
279	vsnprintf(buffer, sizeof(buffer), fmt, args);
280	va_end(args);
281
282	output_line(state, "\t# %s\n", buffer);
283}
284
285static const char *show_memop(struct storage *storage)
286{
287	static char buffer[1000];
288
289	if (!storage)
290		return "undef";
291	switch (storage->type) {
292	case REG_FRAME:
293		sprintf(buffer, "%d(FP)", storage->offset);
294		break;
295	case REG_STACK:
296		sprintf(buffer, "%d(SP)", storage->offset);
297		break;
298	case REG_REG:
299		return hardregs[storage->regno].name;
300	default:
301		return show_storage(storage);
302	}
303	return buffer;
304}
305
306static int alloc_stack_offset(int size)
307{
308	int ret = stack_offset;
309	stack_offset = ret + size;
310	return ret;
311}
312
313static void alloc_stack(struct bb_state *state, struct storage *storage)
314{
315	storage->type = REG_STACK;
316	storage->offset = alloc_stack_offset(4);
317}
318
319/*
320 * Can we re-generate the pseudo, so that we don't need to
321 * flush it to memory? We can regenerate:
322 *  - immediates and symbol addresses
323 *  - pseudos we got as input in non-registers
324 *  - pseudos we've already saved off earlier..
325 */
326static int can_regenerate(struct bb_state *state, pseudo_t pseudo)
327{
328	struct storage_hash *in;
329
330	switch (pseudo->type) {
331	case PSEUDO_VAL:
332	case PSEUDO_SYM:
333		return 1;
334
335	default:
336		in = find_storage_hash(pseudo, state->inputs);
337		if (in && in->storage->type != REG_REG)
338			return 1;
339		in = find_storage_hash(pseudo, state->internal);
340		if (in)
341			return 1;
342	}
343	return 0;
344}
345
346static void flush_one_pseudo(struct bb_state *state, struct hardreg *hardreg, pseudo_t pseudo)
347{
348	struct storage_hash *out;
349	struct storage *storage;
350
351	if (can_regenerate(state, pseudo))
352		return;
353
354	output_comment(state, "flushing %s from %s", show_pseudo(pseudo), hardreg->name);
355	out = find_storage_hash(pseudo, state->internal);
356	if (!out) {
357		out = find_storage_hash(pseudo, state->outputs);
358		if (!out)
359			out = find_or_create_hash(pseudo, &state->internal);
360	}
361	storage = out->storage;
362	switch (storage->type) {
363	default:
364		/*
365		 * Aieee - the next user wants it in a register, but we
366		 * need to flush it to memory in between. Which means that
367		 * we need to allocate an internal one, dammit..
368		 */
369		out = find_or_create_hash(pseudo, &state->internal);
370		storage = out->storage;
371		/* Fall through */
372	case REG_UDEF:
373		alloc_stack(state, storage);
374		/* Fall through */
375	case REG_STACK:
376		output_insn(state, "movl %s,%s", hardreg->name, show_memop(storage));
377		break;
378	}
379}
380
381/* Flush a hardreg out to the storage it has.. */
382static void flush_reg(struct bb_state *state, struct hardreg *reg)
383{
384	pseudo_t pseudo;
385
386	if (reg->busy)
387		output_comment(state, "reg %s flushed while busy is %d!", reg->name, reg->busy);
388	if (!reg->contains)
389		return;
390	reg->dead = 0;
391	reg->used = 1;
392	FOR_EACH_PTR_TAG(reg->contains, pseudo) {
393		if (CURRENT_TAG(pseudo) & TAG_DEAD)
394			continue;
395		if (!(CURRENT_TAG(pseudo) & TAG_DIRTY))
396			continue;
397		flush_one_pseudo(state, reg, pseudo);
398	} END_FOR_EACH_PTR(pseudo);
399	free_ptr_list(&reg->contains);
400}
401
402static struct storage_hash *find_pseudo_storage(struct bb_state *state, pseudo_t pseudo, struct hardreg *reg)
403{
404	struct storage_hash *src;
405
406	src = find_storage_hash(pseudo, state->internal);
407	if (!src) {
408		src = find_storage_hash(pseudo, state->inputs);
409		if (!src) {
410			src = find_storage_hash(pseudo, state->outputs);
411			/* Undefined? Screw it! */
412			if (!src)
413				return NULL;
414
415			/*
416			 * If we found output storage, it had better be local stack
417			 * that we flushed to earlier..
418			 */
419			if (src->storage->type != REG_STACK)
420				return NULL;
421		}
422	}
423
424	/*
425	 * Incoming pseudo with out any pre-set storage allocation?
426	 * We can make up our own, and obviously prefer to get it
427	 * in the register we already selected (if it hasn't been
428	 * used yet).
429	 */
430	if (src->storage->type == REG_UDEF) {
431		if (reg && !reg->used) {
432			src->storage->type = REG_REG;
433			src->storage->regno = reg - hardregs;
434			return NULL;
435		}
436		alloc_stack(state, src->storage);
437	}
438	return src;
439}
440
441static void mark_reg_dead(struct bb_state *state, pseudo_t pseudo, struct hardreg *reg)
442{
443	pseudo_t p;
444
445	FOR_EACH_PTR_TAG(reg->contains, p) {
446		if (p != pseudo)
447			continue;
448		if (CURRENT_TAG(p) & TAG_DEAD)
449			continue;
450		output_comment(state, "marking pseudo %s in reg %s dead", show_pseudo(pseudo), reg->name);
451		TAG_CURRENT(p, TAG_DEAD);
452		reg->dead++;
453	} END_FOR_EACH_PTR(p);
454}
455
456static void add_pseudo_reg(struct bb_state *state, pseudo_t pseudo, struct hardreg *reg)
457{
458	output_comment(state, "added pseudo %s to reg %s", show_pseudo(pseudo), reg->name);
459	add_ptr_list_tag(&reg->contains, pseudo, TAG_DIRTY);
460}
461
462static struct hardreg *preferred_reg(struct bb_state *state, pseudo_t target)
463{
464	struct storage_hash *dst;
465
466	dst = find_storage_hash(target, state->outputs);
467	if (dst) {
468		struct storage *storage = dst->storage;
469		if (storage->type == REG_REG)
470			return hardregs + storage->regno;
471	}
472	return NULL;
473}
474
475static struct hardreg *empty_reg(struct bb_state *state)
476{
477	int i;
478	struct hardreg *reg = hardregs;
479
480	for (i = 0; i < REGNO; i++, reg++) {
481		if (!reg->contains)
482			return reg;
483	}
484	return NULL;
485}
486
487static struct hardreg *target_reg(struct bb_state *state, pseudo_t pseudo, pseudo_t target)
488{
489	int i;
490	int unable_to_find_reg = 0;
491	struct hardreg *reg;
492
493	/* First, see if we have a preferred target register.. */
494	reg = preferred_reg(state, target);
495	if (reg && !reg->contains)
496		goto found;
497
498	reg = empty_reg(state);
499	if (reg)
500		goto found;
501
502	i = last_reg;
503	do {
504		i++;
505		if (i >= REGNO)
506			i = 0;
507		reg = hardregs + i;
508		if (!reg->busy) {
509			flush_reg(state, reg);
510			last_reg = i;
511			goto found;
512		}
513	} while (i != last_reg);
514	assert(unable_to_find_reg);
515
516found:
517	add_pseudo_reg(state, pseudo, reg);
518	return reg;
519}
520
521static struct hardreg *find_in_reg(struct bb_state *state, pseudo_t pseudo)
522{
523	int i;
524	struct hardreg *reg;
525
526	for (i = 0; i < REGNO; i++) {
527		pseudo_t p;
528
529		reg = hardregs + i;
530		FOR_EACH_PTR_TAG(reg->contains, p) {
531			if (p == pseudo) {
532				last_reg = i;
533				output_comment(state, "found pseudo %s in reg %s (busy=%d)", show_pseudo(pseudo), reg->name, reg->busy);
534				return reg;
535			}
536		} END_FOR_EACH_PTR(p);
537	}
538	return NULL;
539}
540
541static void flush_pseudo(struct bb_state *state, pseudo_t pseudo, struct storage *storage)
542{
543	struct hardreg *reg = find_in_reg(state, pseudo);
544
545	if (reg)
546		flush_reg(state, reg);
547}
548
549static void flush_cc_cache_to_reg(struct bb_state *state, pseudo_t pseudo, struct hardreg *reg)
550{
551	int opcode = state->cc_opcode;
552
553	state->cc_opcode = 0;
554	state->cc_target = NULL;
555	output_insn(state, "%s %s", opcodes[opcode], reg->name);
556}
557
558static void flush_cc_cache(struct bb_state *state)
559{
560	pseudo_t pseudo = state->cc_target;
561
562	if (pseudo) {
563		struct hardreg *dst;
564
565		state->cc_target = NULL;
566
567		if (!state->cc_dead) {
568			dst = target_reg(state, pseudo, pseudo);
569			flush_cc_cache_to_reg(state, pseudo, dst);
570		}
571	}
572}
573
574static void add_cc_cache(struct bb_state *state, int opcode, pseudo_t pseudo)
575{
576	assert(!state->cc_target);
577	state->cc_target = pseudo;
578	state->cc_opcode = opcode;
579	state->cc_dead = 0;
580	output_comment(state, "caching %s", opcodes[opcode]);
581}
582
583/* Fill a hardreg with the pseudo it has */
584static struct hardreg *fill_reg(struct bb_state *state, struct hardreg *hardreg, pseudo_t pseudo)
585{
586	struct storage_hash *src;
587	struct instruction *def;
588
589	if (state->cc_target == pseudo) {
590		flush_cc_cache_to_reg(state, pseudo, hardreg);
591		return hardreg;
592	}
593
594	switch (pseudo->type) {
595	case PSEUDO_VAL:
596		output_insn(state, "movl $%lld,%s", pseudo->value, hardreg->name);
597		break;
598	case PSEUDO_SYM:
599		src = find_pseudo_storage(state, pseudo, NULL);
600		/* Static thing? */
601		if (!src) {
602			output_insn(state, "movl $<%s>,%s", show_pseudo(pseudo), hardreg->name);
603			break;
604		}
605		switch (src->storage->type) {
606		case REG_REG:
607			/* Aiaiaiaiaii! Need to flush it to temporary memory */
608			src = find_or_create_hash(pseudo, &state->internal);
609			/* Fall through */
610		default:
611			alloc_stack(state, src->storage);
612			/* Fall through */
613		case REG_STACK:
614		case REG_FRAME:
615			flush_pseudo(state, pseudo, src->storage);
616			output_insn(state, "leal %s,%s", show_memop(src->storage), hardreg->name);
617			break;
618		}
619		break;
620	case PSEUDO_ARG:
621	case PSEUDO_REG:
622		def = pseudo->def;
623		if (def && (def->opcode == OP_SETVAL || def->opcode == OP_LABEL)) {
624			output_insn(state, "movl $<%s>,%s", show_pseudo(def->target), hardreg->name);
625			break;
626		}
627		src = find_pseudo_storage(state, pseudo, hardreg);
628		if (!src)
629			break;
630		if (src->flags & TAG_DEAD)
631			mark_reg_dead(state, pseudo, hardreg);
632		output_insn(state, "mov.%d %s,%s", 32, show_memop(src->storage), hardreg->name);
633		break;
634	default:
635		output_insn(state, "reload %s from %s", hardreg->name, show_pseudo(pseudo));
636		break;
637	}
638	return hardreg;
639}
640
641static struct hardreg *getreg(struct bb_state *state, pseudo_t pseudo, pseudo_t target)
642{
643	struct hardreg *reg;
644
645	reg = find_in_reg(state, pseudo);
646	if (reg)
647		return reg;
648	reg = target_reg(state, pseudo, target);
649	return fill_reg(state, reg, pseudo);
650}
651
652static void move_reg(struct bb_state *state, struct hardreg *src, struct hardreg *dst)
653{
654	output_insn(state, "movl %s,%s", src->name, dst->name);
655}
656
657static struct hardreg *copy_reg(struct bb_state *state, struct hardreg *src, pseudo_t target)
658{
659	int i;
660	struct hardreg *reg;
661
662	/* If the container has been killed off, just re-use it */
663	if (!src->contains)
664		return src;
665
666	/* If "src" only has one user, and the contents are dead, we can re-use it */
667	if (src->busy == 1 && src->dead == 1)
668		return src;
669
670	reg = preferred_reg(state, target);
671	if (reg && !reg->contains) {
672		output_comment(state, "copying %s to preferred target %s", show_pseudo(target), reg->name);
673		move_reg(state, src, reg);
674		return reg;
675	}
676
677	for (i = 0; i < REGNO; i++) {
678		reg = hardregs + i;
679		if (!reg->contains) {
680			output_comment(state, "copying %s to %s", show_pseudo(target), reg->name);
681			output_insn(state, "movl %s,%s", src->name, reg->name);
682			return reg;
683		}
684	}
685
686	flush_reg(state, src);
687	return src;
688}
689
690static void put_operand(struct bb_state *state, struct operand *op)
691{
692	switch (op->type) {
693	case OP_REG:
694		op->reg->busy--;
695		break;
696	case OP_ADDR:
697	case OP_MEM:
698		if (op->base)
699			op->base->busy--;
700		if (op->index)
701			op->index->busy--;
702		break;
703	default:
704		break;
705	}
706}
707
708static struct operand *alloc_op(void)
709{
710	struct operand *op = malloc(sizeof(*op));
711	memset(op, 0, sizeof(*op));
712	return op;
713}
714
715static struct operand *get_register_operand(struct bb_state *state, pseudo_t pseudo, pseudo_t target)
716{
717	struct operand *op = alloc_op();
718	op->type = OP_REG;
719	op->reg = getreg(state, pseudo, target);
720	op->reg->busy++;
721	return op;
722}
723
724static int get_sym_frame_offset(struct bb_state *state, pseudo_t pseudo)
725{
726	int offset = pseudo->nr;
727	if (offset < 0) {
728		offset = alloc_stack_offset(4);
729		pseudo->nr = offset;
730	}
731	return offset;
732}
733
734static struct operand *get_generic_operand(struct bb_state *state, pseudo_t pseudo)
735{
736	struct hardreg *reg;
737	struct storage *src;
738	struct storage_hash *hash;
739	struct operand *op = malloc(sizeof(*op));
740
741	memset(op, 0, sizeof(*op));
742	switch (pseudo->type) {
743	case PSEUDO_VAL:
744		op->type = OP_VAL;
745		op->value = pseudo->value;
746		break;
747
748	case PSEUDO_SYM: {
749		struct symbol *sym = pseudo->sym;
750		op->type = OP_ADDR;
751		if (sym->ctype.modifiers & MOD_NONLOCAL) {
752			op->sym = sym;
753			break;
754		}
755		op->base = hardregs + REG_EBP;
756		op->offset = get_sym_frame_offset(state, pseudo);
757		break;
758	}
759
760	default:
761		reg = find_in_reg(state, pseudo);
762		if (reg) {
763			op->type = OP_REG;
764			op->reg = reg;
765			reg->busy++;
766			break;
767		}
768		hash = find_pseudo_storage(state, pseudo, NULL);
769		if (!hash)
770			break;
771		src = hash->storage;
772		switch (src->type) {
773		case REG_REG:
774			op->type = OP_REG;
775			op->reg = hardregs + src->regno;
776			op->reg->busy++;
777			break;
778		case REG_FRAME:
779			op->type = OP_MEM;
780			op->offset = src->offset;
781			op->base = hardregs + REG_EBP;
782			break;
783		case REG_STACK:
784			op->type = OP_MEM;
785			op->offset = src->offset;
786			op->base = hardregs + REG_ESP;
787			break;
788		default:
789			break;
790		}
791	}
792	return op;
793}
794
795/* Callers should be made to use the proper "operand" formats */
796static const char *generic(struct bb_state *state, pseudo_t pseudo)
797{
798	struct hardreg *reg;
799	struct operand *op = get_generic_operand(state, pseudo);
800	static char buf[100];
801	const char *str;
802
803	switch (op->type) {
804	case OP_ADDR:
805		if (!op->offset && op->base && !op->sym)
806			return op->base->name;
807		if (op->sym && !op->base) {
808			int len = sprintf(buf, "$ %s", show_op(state, op));
809			if (op->offset)
810				sprintf(buf + len, " + %d", op->offset);
811			return buf;
812		}
813		str = show_op(state, op);
814		put_operand(state, op);
815		reg = target_reg(state, pseudo, NULL);
816		output_insn(state, "lea %s,%s", show_op(state, op), reg->name);
817		return reg->name;
818
819	default:
820		str = show_op(state, op);
821	}
822	put_operand(state, op);
823	return str;
824}
825
826static struct operand *get_address_operand(struct bb_state *state, struct instruction *memop)
827{
828	struct hardreg *base;
829	struct operand *op = get_generic_operand(state, memop->src);
830
831	switch (op->type) {
832	case OP_ADDR:
833		op->offset += memop->offset;
834		break;
835	default:
836		put_operand(state, op);
837		base = getreg(state, memop->src, NULL);
838		op->type = OP_ADDR;
839		op->base = base;
840		base->busy++;
841		op->offset = memop->offset;
842		op->sym = NULL;
843	}
844	return op;
845}
846
847static const char *address(struct bb_state *state, struct instruction *memop)
848{
849	struct operand *op = get_address_operand(state, memop);
850	const char *str = show_op(state, op);
851	put_operand(state, op);
852	return str;
853}
854
855static const char *reg_or_imm(struct bb_state *state, pseudo_t pseudo)
856{
857	switch(pseudo->type) {
858	case PSEUDO_VAL:
859		return show_pseudo(pseudo);
860	default:
861		return getreg(state, pseudo, NULL)->name;
862	}
863}
864
865static void kill_dead_reg(struct hardreg *reg)
866{
867	if (reg->dead) {
868		pseudo_t p;
869
870		FOR_EACH_PTR_TAG(reg->contains, p) {
871			if (CURRENT_TAG(p) & TAG_DEAD) {
872				DELETE_CURRENT_PTR(p);
873				reg->dead--;
874			}
875		} END_FOR_EACH_PTR(p);
876		PACK_PTR_LIST(&reg->contains);
877		assert(!reg->dead);
878	}
879}
880
881static struct hardreg *target_copy_reg(struct bb_state *state, struct hardreg *src, pseudo_t target)
882{
883	kill_dead_reg(src);
884	return copy_reg(state, src, target);
885}
886
887static void do_binop(struct bb_state *state, struct instruction *insn, pseudo_t val1, pseudo_t val2)
888{
889	const char *op = opcodes[insn->opcode];
890	struct operand *src = get_register_operand(state, val1, insn->target);
891	struct operand *src2 = get_generic_operand(state, val2);
892	struct hardreg *dst;
893
894	dst = target_copy_reg(state, src->reg, insn->target);
895	output_insn(state, "%s.%d %s,%s", op, insn->size, show_op(state, src2), dst->name);
896	put_operand(state, src);
897	put_operand(state, src2);
898	add_pseudo_reg(state, insn->target, dst);
899}
900
901static void generate_binop(struct bb_state *state, struct instruction *insn)
902{
903	flush_cc_cache(state);
904	do_binop(state, insn, insn->src1, insn->src2);
905}
906
907static int is_dead_reg(struct bb_state *state, pseudo_t pseudo, struct hardreg *reg)
908{
909	pseudo_t p;
910	FOR_EACH_PTR_TAG(reg->contains, p) {
911		if (p == pseudo)
912			return CURRENT_TAG(p) & TAG_DEAD;
913	} END_FOR_EACH_PTR(p);
914	return 0;
915}
916
917/*
918 * Commutative binops are much more flexible, since we can switch the
919 * sources around to satisfy the target register, or to avoid having
920 * to load one of them into a register..
921 */
922static void generate_commutative_binop(struct bb_state *state, struct instruction *insn)
923{
924	pseudo_t src1, src2;
925	struct hardreg *reg1, *reg2;
926
927	flush_cc_cache(state);
928	src1 = insn->src1;
929	src2 = insn->src2;
930	reg2 = find_in_reg(state, src2);
931	if (!reg2)
932		goto dont_switch;
933	reg1 = find_in_reg(state, src1);
934	if (!reg1)
935		goto do_switch;
936	if (!is_dead_reg(state, src2, reg2))
937		goto dont_switch;
938	if (!is_dead_reg(state, src1, reg1))
939		goto do_switch;
940
941	/* Both are dead. Is one preferable? */
942	if (reg2 != preferred_reg(state, insn->target))
943		goto dont_switch;
944
945do_switch:
946	src1 = src2;
947	src2 = insn->src1;
948dont_switch:
949	do_binop(state, insn, src1, src2);
950}
951
952/*
953 * This marks a pseudo dead. It still stays on the hardreg list (the hardreg
954 * still has its value), but it's scheduled to be killed after the next
955 * "sequence point" when we call "kill_read_pseudos()"
956 */
957static void mark_pseudo_dead(struct bb_state *state, pseudo_t pseudo)
958{
959	int i;
960	struct storage_hash *src;
961
962	if (state->cc_target == pseudo)
963		state->cc_dead = 1;
964	src = find_pseudo_storage(state, pseudo, NULL);
965	if (src)
966		src->flags |= TAG_DEAD;
967	for (i = 0; i < REGNO; i++)
968		mark_reg_dead(state, pseudo, hardregs + i);
969}
970
971static void kill_dead_pseudos(struct bb_state *state)
972{
973	int i;
974
975	for (i = 0; i < REGNO; i++) {
976		kill_dead_reg(hardregs + i);
977	}
978}
979
980static void generate_store(struct instruction *insn, struct bb_state *state)
981{
982	output_insn(state, "mov.%d %s,%s", insn->size, reg_or_imm(state, insn->target), address(state, insn));
983}
984
985static void generate_load(struct instruction *insn, struct bb_state *state)
986{
987	const char *input = address(state, insn);
988	struct hardreg *dst;
989
990	kill_dead_pseudos(state);
991	dst = target_reg(state, insn->target, NULL);
992	output_insn(state, "mov.%d %s,%s", insn->size, input, dst->name);
993}
994
995static void kill_pseudo(struct bb_state *state, pseudo_t pseudo)
996{
997	int i;
998	struct hardreg *reg;
999
1000	output_comment(state, "killing pseudo %s", show_pseudo(pseudo));
1001	for (i = 0; i < REGNO; i++) {
1002		pseudo_t p;
1003
1004		reg = hardregs + i;
1005		FOR_EACH_PTR_TAG(reg->contains, p) {
1006			if (p != pseudo)
1007				continue;
1008			if (CURRENT_TAG(p) & TAG_DEAD)
1009				reg->dead--;
1010			output_comment(state, "removing pseudo %s from reg %s",
1011				show_pseudo(pseudo), reg->name);
1012			DELETE_CURRENT_PTR(p);
1013		} END_FOR_EACH_PTR(p);
1014		PACK_PTR_LIST(&reg->contains);
1015	}
1016}
1017
1018static void generate_copy(struct bb_state *state, struct instruction *insn)
1019{
1020	struct hardreg *src = getreg(state, insn->src, insn->target);
1021	kill_pseudo(state, insn->target);
1022	add_pseudo_reg(state, insn->target, src);
1023}
1024
1025static void generate_cast(struct bb_state *state, struct instruction *insn)
1026{
1027	struct hardreg *src = getreg(state, insn->src, insn->target);
1028	struct hardreg *dst;
1029	unsigned int old = insn->orig_type ? insn->orig_type->bit_size : 0;
1030	unsigned int new = insn->size;
1031
1032	/*
1033	 * Cast to smaller type? Ignore the high bits, we
1034	 * just keep both pseudos in the same register.
1035	 */
1036	if (old >= new) {
1037		add_pseudo_reg(state, insn->target, src);
1038		return;
1039	}
1040
1041	dst = target_copy_reg(state, src, insn->target);
1042
1043	if (insn->orig_type && (insn->orig_type->ctype.modifiers & MOD_SIGNED)) {
1044		output_insn(state, "sext.%d.%d %s", old, new, dst->name);
1045	} else {
1046		unsigned long long mask;
1047		mask = ~(~0ULL << old);
1048		mask &= ~(~0ULL << new);
1049		output_insn(state, "andl.%d $%#llx,%s", insn->size, mask, dst->name);
1050	}
1051	add_pseudo_reg(state, insn->target, dst);
1052}
1053
1054static void generate_output_storage(struct bb_state *state);
1055
1056static const char *conditional[] = {
1057	[OP_SET_EQ] = "e",
1058	[OP_SET_NE] = "ne",
1059	[OP_SET_LE] = "le",
1060	[OP_SET_GE] = "ge",
1061	[OP_SET_LT] = "lt",
1062	[OP_SET_GT] = "gt",
1063	[OP_SET_B] = "b",
1064	[OP_SET_A] = "a",
1065	[OP_SET_BE] = "be",
1066	[OP_SET_AE] = "ae"
1067};
1068
1069
1070static void generate_branch(struct bb_state *state, struct instruction *br)
1071{
1072	const char *cond = "XXX";
1073	struct basic_block *target;
1074
1075	if (br->cond) {
1076		if (state->cc_target == br->cond) {
1077			cond = conditional[state->cc_opcode];
1078		} else {
1079			struct hardreg *reg = getreg(state, br->cond, NULL);
1080			output_insn(state, "testl %s,%s", reg->name, reg->name);
1081			cond = "ne";
1082		}
1083	}
1084	generate_output_storage(state);
1085	target = br->bb_true;
1086	if (br->cond) {
1087		output_insn(state, "j%s .L%p", cond, target);
1088		target = br->bb_false;
1089	}
1090	output_insn(state, "jmp .L%p", target);
1091}
1092
1093/* We've made sure that there is a dummy reg live for the output */
1094static void generate_switch(struct bb_state *state, struct instruction *insn)
1095{
1096	struct hardreg *reg = hardregs + SWITCH_REG;
1097
1098	generate_output_storage(state);
1099	output_insn(state, "switch on %s", reg->name);
1100	output_insn(state, "unimplemented: %s", show_instruction(insn));
1101}
1102
1103static void generate_ret(struct bb_state *state, struct instruction *ret)
1104{
1105	if (ret->src && ret->src != VOID) {
1106		struct hardreg *wants = hardregs+0;
1107		struct hardreg *reg = getreg(state, ret->src, NULL);
1108		if (reg != wants)
1109			output_insn(state, "movl %s,%s", reg->name, wants->name);
1110	}
1111	output_insn(state, "ret");
1112}
1113
1114/*
1115 * Fake "call" linearization just as a taster..
1116 */
1117static void generate_call(struct bb_state *state, struct instruction *insn)
1118{
1119	int offset = 0;
1120	pseudo_t arg;
1121
1122	FOR_EACH_PTR(insn->arguments, arg) {
1123		output_insn(state, "pushl %s", generic(state, arg));
1124		offset += 4;
1125	} END_FOR_EACH_PTR(arg);
1126	flush_reg(state, hardregs+0);
1127	flush_reg(state, hardregs+1);
1128	flush_reg(state, hardregs+2);
1129	output_insn(state, "call %s", show_pseudo(insn->func));
1130	if (offset)
1131		output_insn(state, "addl $%d,%%esp", offset);
1132	if (insn->target && insn->target != VOID)
1133		add_pseudo_reg(state, insn->target, hardregs+0);
1134}
1135
1136static void generate_select(struct bb_state *state, struct instruction *insn)
1137{
1138	const char *cond;
1139	struct hardreg *src1, *src2, *dst;
1140
1141	src1 = getreg(state, insn->src2, NULL);
1142	dst = copy_reg(state, src1, insn->target);
1143	add_pseudo_reg(state, insn->target, dst);
1144	src2 = getreg(state, insn->src3, insn->target);
1145
1146	if (state->cc_target == insn->src1) {
1147		cond = conditional[state->cc_opcode];
1148	} else {
1149		struct hardreg *reg = getreg(state, insn->src1, NULL);
1150		output_insn(state, "testl %s,%s", reg->name, reg->name);
1151		cond = "ne";
1152	}
1153
1154	output_insn(state, "sel%s %s,%s", cond, src2->name, dst->name);
1155}
1156
1157struct asm_arg {
1158	const struct ident *name;
1159	const char *value;
1160	pseudo_t pseudo;
1161	struct hardreg *reg;
1162};
1163
1164static void replace_asm_arg(char **dst_p, struct asm_arg *arg)
1165{
1166	char *dst = *dst_p;
1167	int len = strlen(arg->value);
1168
1169	memcpy(dst, arg->value, len);
1170	*dst_p = dst + len;
1171}
1172
1173static void replace_asm_percent(const char **src_p, char **dst_p, struct asm_arg *args, int nr)
1174{
1175	const char *src = *src_p;
1176	char c;
1177	int index;
1178
1179	c = *src++;
1180	switch (c) {
1181	case '0' ... '9':
1182		index = c - '0';
1183		if (index < nr)
1184			replace_asm_arg(dst_p, args+index);
1185		break;
1186	}
1187	*src_p = src;
1188	return;
1189}
1190
1191static void replace_asm_named(const char **src_p, char **dst_p, struct asm_arg *args, int nr)
1192{
1193	const char *src = *src_p;
1194	const char *end = src;
1195
1196	for(;;) {
1197		char c = *end++;
1198		if (!c)
1199			return;
1200		if (c == ']') {
1201			int i;
1202
1203			*src_p = end;
1204			for (i = 0; i < nr; i++) {
1205				const struct ident *ident = args[i].name;
1206				int len;
1207				if (!ident)
1208					continue;
1209				len = ident->len;
1210				if (memcmp(src, ident->name, len))
1211					continue;
1212				replace_asm_arg(dst_p, args+i);
1213				return;
1214			}
1215		}
1216	}
1217}
1218
1219static const char *replace_asm_args(const char *str, struct asm_arg *args, int nr)
1220{
1221	static char buffer[1000];
1222	char *p = buffer;
1223
1224	for (;;) {
1225		char c = *str;
1226		*p = c;
1227		if (!c)
1228			return buffer;
1229		str++;
1230		switch (c) {
1231		case '%':
1232			if (*str == '%') {
1233				str++;
1234				p++;
1235				continue;
1236			}
1237			replace_asm_percent(&str, &p, args, nr);
1238			continue;
1239		case '[':
1240			replace_asm_named(&str, &p, args, nr);
1241			continue;
1242		default:
1243			break;
1244		}
1245		p++;
1246	}
1247}
1248
1249#define MAX_ASM_ARG (50)
1250static struct asm_arg asm_arguments[MAX_ASM_ARG];
1251
1252static struct asm_arg *generate_asm_inputs(struct bb_state *state, struct asm_constraint_list *list, struct asm_arg *arg)
1253{
1254	struct asm_constraint *entry;
1255
1256	FOR_EACH_PTR(list, entry) {
1257		const char *constraint = entry->constraint;
1258		pseudo_t pseudo = entry->pseudo;
1259		struct hardreg *reg, *orig;
1260		const char *string;
1261		int index;
1262
1263		string = "undef";
1264		switch (*constraint) {
1265		case 'r':
1266			string = getreg(state, pseudo, NULL)->name;
1267			break;
1268		case '0' ... '9':
1269			index = *constraint - '0';
1270			reg = asm_arguments[index].reg;
1271			orig = find_in_reg(state, pseudo);
1272			if (orig)
1273				move_reg(state, orig, reg);
1274			else
1275				fill_reg(state, reg, pseudo);
1276			string = reg->name;
1277			break;
1278		default:
1279			string = generic(state, pseudo);
1280			break;
1281		}
1282
1283		output_insn(state, "# asm input \"%s\": %s : %s", constraint, show_pseudo(pseudo), string);
1284
1285		arg->name = entry->ident;
1286		arg->value = string;
1287		arg->pseudo = NULL;
1288		arg->reg = NULL;
1289		arg++;
1290	} END_FOR_EACH_PTR(entry);
1291	return arg;
1292}
1293
1294static struct asm_arg *generate_asm_outputs(struct bb_state *state, struct asm_constraint_list *list, struct asm_arg *arg)
1295{
1296	struct asm_constraint *entry;
1297
1298	FOR_EACH_PTR(list, entry) {
1299		const char *constraint = entry->constraint;
1300		pseudo_t pseudo = entry->pseudo;
1301		struct hardreg *reg;
1302		const char *string;
1303
1304		while (*constraint == '=' || *constraint == '+')
1305			constraint++;
1306
1307		string = "undef";
1308		switch (*constraint) {
1309		case 'r':
1310		default:
1311			reg = target_reg(state, pseudo, NULL);
1312			arg->pseudo = pseudo;
1313			arg->reg = reg;
1314			string = reg->name;
1315			break;
1316		}
1317
1318		output_insn(state, "# asm output \"%s\": %s : %s", constraint, show_pseudo(pseudo), string);
1319
1320		arg->name = entry->ident;
1321		arg->value = string;
1322		arg++;
1323	} END_FOR_EACH_PTR(entry);
1324	return arg;
1325}
1326
1327static void generate_asm(struct bb_state *state, struct instruction *insn)
1328{
1329	const char *str = insn->string;
1330
1331	if (insn->asm_rules->outputs || insn->asm_rules->inputs) {
1332		struct asm_arg *arg;
1333
1334		arg = generate_asm_outputs(state, insn->asm_rules->outputs, asm_arguments);
1335		arg = generate_asm_inputs(state, insn->asm_rules->inputs, arg);
1336		str = replace_asm_args(str, asm_arguments, arg - asm_arguments);
1337	}
1338	output_insn(state, "%s", str);
1339}
1340
1341static void generate_compare(struct bb_state *state, struct instruction *insn)
1342{
1343	struct hardreg *src;
1344	const char *src2;
1345	int opcode;
1346
1347	flush_cc_cache(state);
1348	opcode = insn->opcode;
1349
1350	/*
1351	 * We should try to switch these around if necessary,
1352	 * and update the opcode to match..
1353	 */
1354	src = getreg(state, insn->src1, insn->target);
1355	src2 = generic(state, insn->src2);
1356
1357	output_insn(state, "cmp.%d %s,%s", insn->size, src2, src->name);
1358
1359	add_cc_cache(state, opcode, insn->target);
1360}
1361
1362static void generate_one_insn(struct instruction *insn, struct bb_state *state)
1363{
1364	if (verbose)
1365		output_comment(state, "%s", show_instruction(insn));
1366
1367	switch (insn->opcode) {
1368	case OP_ENTRY: {
1369		struct symbol *sym = insn->bb->ep->name;
1370		const char *name = show_ident(sym->ident);
1371		if (sym->ctype.modifiers & MOD_STATIC)
1372			printf("\n\n%s:\n", name);
1373		else
1374			printf("\n\n.globl %s\n%s:\n", name, name);
1375		break;
1376	}
1377
1378	/*
1379	 * OP_LABEL & OP_SETVAL likewise doesn't actually generate any
1380	 * code. On use, the "def" of the pseudo will be
1381	 * looked up.
1382	 */
1383	case OP_LABEL:
1384	case OP_SETVAL:
1385		break;
1386
1387	case OP_STORE:
1388		generate_store(insn, state);
1389		break;
1390
1391	case OP_LOAD:
1392		generate_load(insn, state);
1393		break;
1394
1395	case OP_DEATHNOTE:
1396		mark_pseudo_dead(state, insn->target);
1397		return;
1398
1399	case OP_COPY:
1400		generate_copy(state, insn);
1401		break;
1402
1403	case OP_ADD: case OP_MUL:
1404	case OP_AND: case OP_OR: case OP_XOR:
1405		generate_commutative_binop(state, insn);
1406		break;
1407
1408	case OP_SUB: case OP_DIVU: case OP_DIVS:
1409	case OP_MODU: case OP_MODS:
1410	case OP_SHL: case OP_LSR: case OP_ASR:
1411 		generate_binop(state, insn);
1412		break;
1413
1414	case OP_BINCMP ... OP_BINCMP_END:
1415		generate_compare(state, insn);
1416		break;
1417
1418	case OP_SEXT: case OP_ZEXT:
1419	case OP_TRUNC:
1420	case OP_PTRCAST:
1421	case OP_UTPTR:
1422	case OP_PTRTU:
1423	case OP_FCVTU: case OP_FCVTS:
1424	case OP_UCVTF: case OP_SCVTF:
1425	case OP_FCVTF:
1426		generate_cast(state, insn);
1427		break;
1428
1429	case OP_SEL:
1430		generate_select(state, insn);
1431		break;
1432
1433	case OP_BR:
1434	case OP_CBR:
1435		generate_branch(state, insn);
1436		break;
1437
1438	case OP_SWITCH:
1439		generate_switch(state, insn);
1440		break;
1441
1442	case OP_CALL:
1443		generate_call(state, insn);
1444		break;
1445
1446	case OP_RET:
1447		generate_ret(state, insn);
1448		break;
1449
1450	case OP_ASM:
1451		generate_asm(state, insn);
1452		break;
1453
1454	case OP_PHI:
1455	case OP_PHISOURCE:
1456	default:
1457		output_insn(state, "unimplemented: %s", show_instruction(insn));
1458		break;
1459	}
1460	kill_dead_pseudos(state);
1461}
1462
1463#define VERY_BUSY 1000
1464#define REG_FIXED 2000
1465
1466static void write_reg_to_storage(struct bb_state *state, struct hardreg *reg, pseudo_t pseudo, struct storage *storage)
1467{
1468	int i;
1469	struct hardreg *out;
1470
1471	switch (storage->type) {
1472	case REG_REG:
1473		out = hardregs + storage->regno;
1474		if (reg == out)
1475			return;
1476		output_insn(state, "movl %s,%s", reg->name, out->name);
1477		return;
1478	case REG_UDEF:
1479		if (reg->busy < VERY_BUSY) {
1480			storage->type = REG_REG;
1481			storage->regno = reg - hardregs;
1482			reg->busy = REG_FIXED;
1483			return;
1484		}
1485
1486		/* Try to find a non-busy register.. */
1487		for (i = 0; i < REGNO; i++) {
1488			out = hardregs + i;
1489			if (out->contains)
1490				continue;
1491			output_insn(state, "movl %s,%s", reg->name, out->name);
1492			storage->type = REG_REG;
1493			storage->regno = i;
1494			out->busy = REG_FIXED;
1495			return;
1496		}
1497
1498		/* Fall back on stack allocation ... */
1499		alloc_stack(state, storage);
1500		/* Fall through */
1501	default:
1502		output_insn(state, "movl %s,%s", reg->name, show_memop(storage));
1503		return;
1504	}
1505}
1506
1507static void write_val_to_storage(struct bb_state *state, pseudo_t src, struct storage *storage)
1508{
1509	struct hardreg *out;
1510
1511	switch (storage->type) {
1512	case REG_UDEF:
1513		alloc_stack(state, storage);
1514	default:
1515		output_insn(state, "movl %s,%s", show_pseudo(src), show_memop(storage));
1516		break;
1517	case REG_REG:
1518		out = hardregs + storage->regno;
1519		output_insn(state, "movl %s,%s", show_pseudo(src), out->name);
1520	}
1521}
1522
1523static void fill_output(struct bb_state *state, pseudo_t pseudo, struct storage *out)
1524{
1525	int i;
1526	struct storage_hash *in;
1527	struct instruction *def;
1528
1529	/* Is that pseudo a constant value? */
1530	switch (pseudo->type) {
1531	case PSEUDO_VAL:
1532		write_val_to_storage(state, pseudo, out);
1533		return;
1534	case PSEUDO_REG:
1535		def = pseudo->def;
1536		if (def && (def->opcode == OP_SETVAL || def->opcode == OP_LABEL)) {
1537			write_val_to_storage(state, pseudo, out);
1538			return;
1539		}
1540	default:
1541		break;
1542	}
1543
1544	/* See if we have that pseudo in a register.. */
1545	for (i = 0; i < REGNO; i++) {
1546		struct hardreg *reg = hardregs + i;
1547		pseudo_t p;
1548
1549		FOR_EACH_PTR_TAG(reg->contains, p) {
1550			if (p == pseudo) {
1551				write_reg_to_storage(state, reg, pseudo, out);
1552				return;
1553			}
1554		} END_FOR_EACH_PTR(p);
1555	}
1556
1557	/* Do we have it in another storage? */
1558	in = find_storage_hash(pseudo, state->internal);
1559	if (!in) {
1560		in = find_storage_hash(pseudo, state->inputs);
1561		/* Undefined? */
1562		if (!in)
1563			return;
1564	}
1565	switch (out->type) {
1566	case REG_UDEF:
1567		*out = *in->storage;
1568		break;
1569	case REG_REG:
1570		output_insn(state, "movl %s,%s", show_memop(in->storage), hardregs[out->regno].name);
1571		break;
1572	default:
1573		if (out == in->storage)
1574			break;
1575		if ((out->type == in->storage->type) && (out->regno == in->storage->regno))
1576			break;
1577		output_insn(state, "movl %s,%s", show_memop(in->storage), show_memop(out));
1578		break;
1579	}
1580	return;
1581}
1582
1583static int final_pseudo_flush(struct bb_state *state, pseudo_t pseudo, struct hardreg *reg)
1584{
1585	struct storage_hash *hash;
1586	struct storage *out;
1587	struct hardreg *dst;
1588
1589	/*
1590	 * Since this pseudo is live at exit, we'd better have output
1591	 * storage for it..
1592	 */
1593	hash = find_storage_hash(pseudo, state->outputs);
1594	if (!hash)
1595		return 1;
1596	out = hash->storage;
1597
1598	/* If the output is in a register, try to get it there.. */
1599	if (out->type == REG_REG) {
1600		dst = hardregs + out->regno;
1601		/*
1602		 * Two good cases: nobody is using the right register,
1603		 * or we've already set it aside for output..
1604		 */
1605		if (!dst->contains || dst->busy > VERY_BUSY)
1606			goto copy_to_dst;
1607
1608		/* Aiee. Try to keep it in a register.. */
1609		dst = empty_reg(state);
1610		if (dst)
1611			goto copy_to_dst;
1612
1613		return 0;
1614	}
1615
1616	/* If the output is undefined, let's see if we can put it in a register.. */
1617	if (out->type == REG_UDEF) {
1618		dst = empty_reg(state);
1619		if (dst) {
1620			out->type = REG_REG;
1621			out->regno = dst - hardregs;
1622			goto copy_to_dst;
1623		}
1624		/* Uhhuh. Not so good. No empty registers right now */
1625		return 0;
1626	}
1627
1628	/* If we know we need to flush it, just do so already .. */
1629	output_insn(state, "movl %s,%s", reg->name, show_memop(out));
1630	return 1;
1631
1632copy_to_dst:
1633	if (reg == dst)
1634		return 1;
1635	output_insn(state, "movl %s,%s", reg->name, dst->name);
1636	add_pseudo_reg(state, pseudo, dst);
1637	return 1;
1638}
1639
1640/*
1641 * This tries to make sure that we put all the pseudos that are
1642 * live on exit into the proper storage
1643 */
1644static void generate_output_storage(struct bb_state *state)
1645{
1646	struct storage_hash *entry;
1647
1648	/* Go through the fixed outputs, making sure we have those regs free */
1649	FOR_EACH_PTR(state->outputs, entry) {
1650		struct storage *out = entry->storage;
1651		if (out->type == REG_REG) {
1652			struct hardreg *reg = hardregs + out->regno;
1653			pseudo_t p;
1654			int flushme = 0;
1655
1656			reg->busy = REG_FIXED;
1657			FOR_EACH_PTR_TAG(reg->contains, p) {
1658				if (p == entry->pseudo) {
1659					flushme = -100;
1660					continue;
1661				}
1662				if (CURRENT_TAG(p) & TAG_DEAD)
1663					continue;
1664
1665				/* Try to write back the pseudo to where it should go ... */
1666				if (final_pseudo_flush(state, p, reg)) {
1667					DELETE_CURRENT_PTR(p);
1668					continue;
1669				}
1670				flushme++;
1671			} END_FOR_EACH_PTR(p);
1672			PACK_PTR_LIST(&reg->contains);
1673			if (flushme > 0)
1674				flush_reg(state, reg);
1675		}
1676	} END_FOR_EACH_PTR(entry);
1677
1678	FOR_EACH_PTR(state->outputs, entry) {
1679		fill_output(state, entry->pseudo, entry->storage);
1680	} END_FOR_EACH_PTR(entry);
1681}
1682
1683static void generate(struct basic_block *bb, struct bb_state *state)
1684{
1685	int i;
1686	struct storage_hash *entry;
1687	struct instruction *insn;
1688
1689	for (i = 0; i < REGNO; i++) {
1690		free_ptr_list(&hardregs[i].contains);
1691		hardregs[i].busy = 0;
1692		hardregs[i].dead = 0;
1693		hardregs[i].used = 0;
1694	}
1695
1696	FOR_EACH_PTR(state->inputs, entry) {
1697		struct storage *storage = entry->storage;
1698		const char *name = show_storage(storage);
1699		output_comment(state, "incoming %s in %s", show_pseudo(entry->pseudo), name);
1700		if (storage->type == REG_REG) {
1701			int regno = storage->regno;
1702			add_pseudo_reg(state, entry->pseudo, hardregs + regno);
1703			name = hardregs[regno].name;
1704		}
1705	} END_FOR_EACH_PTR(entry);
1706
1707	output_label(state, ".L%p", bb);
1708	FOR_EACH_PTR(bb->insns, insn) {
1709		if (!insn->bb)
1710			continue;
1711		generate_one_insn(insn, state);
1712	} END_FOR_EACH_PTR(insn);
1713
1714	if (verbose) {
1715		output_comment(state, "--- in ---");
1716		FOR_EACH_PTR(state->inputs, entry) {
1717			output_comment(state, "%s <- %s", show_pseudo(entry->pseudo), show_storage(entry->storage));
1718		} END_FOR_EACH_PTR(entry);
1719		output_comment(state, "--- spill ---");
1720		FOR_EACH_PTR(state->internal, entry) {
1721			output_comment(state, "%s <-> %s", show_pseudo(entry->pseudo), show_storage(entry->storage));
1722		} END_FOR_EACH_PTR(entry);
1723		output_comment(state, "--- out ---");
1724		FOR_EACH_PTR(state->outputs, entry) {
1725			output_comment(state, "%s -> %s", show_pseudo(entry->pseudo), show_storage(entry->storage));
1726		} END_FOR_EACH_PTR(entry);
1727	}
1728	printf("\n");
1729}
1730
1731static void generate_list(struct basic_block_list *list, unsigned long generation)
1732{
1733	struct basic_block *bb;
1734	FOR_EACH_PTR(list, bb) {
1735		if (bb->generation == generation)
1736			continue;
1737		output_bb(bb, generation);
1738	} END_FOR_EACH_PTR(bb);
1739}
1740
1741/*
1742 * Mark all the output registers of all the parents
1743 * as being "used" - this does not mean that we cannot
1744 * re-use them, but it means that we cannot ask the
1745 * parents to pass in another pseudo in one of those
1746 * registers that it already uses for another child.
1747 */
1748static void mark_used_registers(struct basic_block *bb, struct bb_state *state)
1749{
1750	struct basic_block *parent;
1751
1752	FOR_EACH_PTR(bb->parents, parent) {
1753		struct storage_hash_list *outputs = gather_storage(parent, STOR_OUT);
1754		struct storage_hash *entry;
1755
1756		FOR_EACH_PTR(outputs, entry) {
1757			struct storage *s = entry->storage;
1758			if (s->type == REG_REG) {
1759				struct hardreg *reg = hardregs + s->regno;
1760				reg->used = 1;
1761			}
1762		} END_FOR_EACH_PTR(entry);
1763	} END_FOR_EACH_PTR(parent);
1764}
1765
1766static void output_bb(struct basic_block *bb, unsigned long generation)
1767{
1768	struct bb_state state;
1769
1770	bb->generation = generation;
1771
1772	/* Make sure all parents have been generated first */
1773	generate_list(bb->parents, generation);
1774
1775	state.pos = bb->pos;
1776	state.inputs = gather_storage(bb, STOR_IN);
1777	state.outputs = gather_storage(bb, STOR_OUT);
1778	state.internal = NULL;
1779	state.cc_opcode = 0;
1780	state.cc_target = NULL;
1781
1782	/* Mark incoming registers used */
1783	mark_used_registers(bb, &state);
1784
1785	generate(bb, &state);
1786
1787	free_ptr_list(&state.inputs);
1788	free_ptr_list(&state.outputs);
1789
1790	/* Generate all children... */
1791	generate_list(bb->children, generation);
1792}
1793
1794/*
1795 * We should set up argument sources here..
1796 *
1797 * Things like "first three arguments in registers" etc
1798 * are all for this place.
1799 *
1800 * On x86, we default to stack, unless it's a static
1801 * function that doesn't have its address taken.
1802 *
1803 * I should implement the -mregparm=X cmd line option.
1804 */
1805static void set_up_arch_entry(struct entrypoint *ep, struct instruction *entry)
1806{
1807	pseudo_t arg;
1808	struct symbol *sym, *argtype;
1809	int i, offset, regparm;
1810
1811	sym = ep->name;
1812	regparm = 0;
1813	if (!(sym->ctype.modifiers & MOD_ADDRESSABLE))
1814		regparm = 3;
1815	sym = sym->ctype.base_type;
1816	i = 0;
1817	offset = 0;
1818	PREPARE_PTR_LIST(sym->arguments, argtype);
1819	FOR_EACH_PTR(entry->arg_list, arg) {
1820		struct storage *in = lookup_storage(entry->bb, arg, STOR_IN);
1821		if (!in) {
1822			in = alloc_storage();
1823			add_storage(in, entry->bb, arg, STOR_IN);
1824		}
1825		if (i < regparm) {
1826			in->type = REG_REG;
1827			in->regno = i;
1828		} else {
1829			int bits = argtype ? argtype->bit_size : 0;
1830
1831			if (bits < bits_in_int)
1832				bits = bits_in_int;
1833
1834			in->type = REG_FRAME;
1835			in->offset = offset;
1836
1837			offset += bits_to_bytes(bits);
1838		}
1839		i++;
1840		NEXT_PTR_LIST(argtype);
1841	} END_FOR_EACH_PTR(arg);
1842	FINISH_PTR_LIST(argtype);
1843}
1844
1845/*
1846 * Set up storage information for "return"
1847 *
1848 * Not strictly necessary, since the code generator will
1849 * certainly move the return value to the right register,
1850 * but it can help register allocation if the allocator
1851 * sees that the target register is going to return in %eax.
1852 */
1853static void set_up_arch_exit(struct basic_block *bb, struct instruction *ret)
1854{
1855	pseudo_t pseudo = ret->src;
1856
1857	if (pseudo && pseudo != VOID) {
1858		struct storage *out = lookup_storage(bb, pseudo, STOR_OUT);
1859		if (!out) {
1860			out = alloc_storage();
1861			add_storage(out, bb, pseudo, STOR_OUT);
1862		}
1863		out->type = REG_REG;
1864		out->regno = 0;
1865	}
1866}
1867
1868/*
1869 * Set up dummy/silly output storage information for a switch
1870 * instruction. We need to make sure that a register is available
1871 * when we generate code for switch, so force that by creating
1872 * a dummy output rule.
1873 */
1874static void set_up_arch_switch(struct basic_block *bb, struct instruction *insn)
1875{
1876	pseudo_t pseudo = insn->cond;
1877	struct storage *out = lookup_storage(bb, pseudo, STOR_OUT);
1878	if (!out) {
1879		out = alloc_storage();
1880		add_storage(out, bb, pseudo, STOR_OUT);
1881	}
1882	out->type = REG_REG;
1883	out->regno = SWITCH_REG;
1884}
1885
1886static void arch_set_up_storage(struct entrypoint *ep)
1887{
1888	struct basic_block *bb;
1889
1890	/* Argument storage etc.. */
1891	set_up_arch_entry(ep, ep->entry);
1892
1893	FOR_EACH_PTR(ep->bbs, bb) {
1894		struct instruction *insn = last_instruction(bb->insns);
1895		if (!insn)
1896			continue;
1897		switch (insn->opcode) {
1898		case OP_RET:
1899			set_up_arch_exit(bb, insn);
1900			break;
1901		case OP_SWITCH:
1902			set_up_arch_switch(bb, insn);
1903			break;
1904		default:
1905			/* nothing */;
1906		}
1907	} END_FOR_EACH_PTR(bb);
1908}
1909
1910static void output(struct entrypoint *ep)
1911{
1912	unsigned long generation = ++bb_generation;
1913
1914	last_reg = -1;
1915	stack_offset = 0;
1916
1917	/* Get rid of SSA form (phinodes etc) */
1918	unssa(ep);
1919
1920	/* Set up initial inter-bb storage links */
1921	set_up_storage(ep);
1922
1923	/* Architecture-specific storage rules.. */
1924	arch_set_up_storage(ep);
1925
1926	/* Show the results ... */
1927	output_bb(ep->entry->bb, generation);
1928
1929	/* Clear the storage hashes for the next function.. */
1930	free_storage();
1931}
1932
1933static int compile(struct symbol_list *list)
1934{
1935	struct symbol *sym;
1936	FOR_EACH_PTR(list, sym) {
1937		struct entrypoint *ep;
1938		expand_symbol(sym);
1939		ep = linearize_symbol(sym);
1940		if (ep)
1941			output(ep);
1942	} END_FOR_EACH_PTR(sym);
1943
1944	return 0;
1945}
1946
1947int main(int argc, char **argv)
1948{
1949	struct string_list *filelist = NULL;
1950	char *file;
1951
1952	compile(sparse_initialize(argc, argv, &filelist));
1953	dbg_dead = 1;
1954	FOR_EACH_PTR(filelist, file) {
1955		compile(sparse(file));
1956	} END_FOR_EACH_PTR(file);
1957	return 0;
1958}
1959
1960