diff mbox

[4/4] compile: remove the unmaintained compile program

Message ID 54398C51.3080301@ramsay1.demon.co.uk (mailing list archive)
State Rejected, archived
Headers show

Commit Message

Ramsay Jones Oct. 11, 2014, 8 p.m. UTC
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
---
 .gitignore     |    1 -
 Makefile       |    4 +-
 compile-i386.c | 2407 --------------------------------------------------------
 compile.c      |   84 --
 compile.h      |   10 -
 5 files changed, 1 insertion(+), 2505 deletions(-)
 delete mode 100644 compile-i386.c
 delete mode 100644 compile.c
 delete mode 100644 compile.h
diff mbox

Patch

diff --git a/.gitignore b/.gitignore
index d32d063..7d4cdf2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,7 +16,6 @@  test-lexing
 test-parsing
 obfuscate
 sparse
-compile
 graph
 test-dissect
 test-linearize
diff --git a/Makefile b/Makefile
index 3f3c71a..8effeb4 100644
--- a/Makefile
+++ b/Makefile
@@ -52,7 +52,7 @@  MAN1DIR=$(MANDIR)/man1
 INCLUDEDIR=$(PREFIX)/include
 PKGCONFIGDIR=$(LIBDIR)/pkgconfig
 
-PROGRAMS=test-lexing test-parsing obfuscate compile graph sparse \
+PROGRAMS=test-lexing test-parsing obfuscate graph sparse \
 	 test-linearize example test-unssa test-dissect ctags
 INST_PROGRAMS=sparse cgcc
 INST_MAN1=sparse.1 cgcc.1
@@ -171,8 +171,6 @@  sparse.pc: sparse.pc.in
 	$(QUIET_GEN)sed $(SED_PC_CMD) sparse.pc.in > sparse.pc
 
 
-compile_EXTRA_DEPS = compile-i386.o
-
 $(foreach p,$(PROGRAMS),$(eval $(p): $($(p)_EXTRA_DEPS) $(LIBS)))
 $(PROGRAMS): % : %.o 
 	$(QUIET_LINK)$(LD) $(LDFLAGS) -o $@ $^ $($@_EXTRA_OBJS)
diff --git a/compile-i386.c b/compile-i386.c
deleted file mode 100644
index 88169ec..0000000
--- a/compile-i386.c
+++ /dev/null
@@ -1,2407 +0,0 @@ 
-/*
- * sparse/compile-i386.c
- *
- * Copyright (C) 2003 Transmeta Corp.
- *               2003 Linus Torvalds
- * Copyright 2003 Jeff Garzik
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * x86 backend
- *
- * TODO list:
- * in general, any non-32bit SYM_BASETYPE is unlikely to work.
- * complex initializers
- * bitfields
- * global struct/union variables
- * addressing structures, and members of structures (as opposed to
- *     scalars) on the stack.  Requires smarter stack frame allocation.
- * labels / goto
- * any function argument that isn't 32 bits (or promoted to such)
- * inline asm
- * floating point
- *
- */
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#include "lib.h"
-#include "allocate.h"
-#include "token.h"
-#include "parse.h"
-#include "symbol.h"
-#include "scope.h"
-#include "expression.h"
-#include "target.h"
-#include "compile.h"
-#include "bitmap.h"
-
-struct textbuf {
-	unsigned int	len;	/* does NOT include terminating null */
-	char		*text;
-	struct textbuf	*next;
-	struct textbuf	*prev;
-};
-
-struct loop_stack {
-	int		continue_lbl;
-	int		loop_bottom_lbl;
-	struct loop_stack *next;
-};
-
-struct atom;
-struct storage;
-DECLARE_PTR_LIST(str_list, struct atom);
-DECLARE_PTR_LIST(atom_list, struct atom);
-DECLARE_PTR_LIST(storage_list, struct storage);
-
-struct function {
-	int stack_size;
-	int pseudo_nr;
-	struct storage_list *pseudo_list;
-	struct atom_list *atom_list;
-	struct str_list *str_list;
-	struct loop_stack *loop_stack;
-	struct symbol **argv;
-	unsigned int argc;
-	int ret_target;
-};
-
-enum storage_type {
-	STOR_PSEUDO,	/* variable stored on the stack */
-	STOR_ARG,	/* function argument */
-	STOR_SYM,	/* a symbol we can directly ref in the asm */
-	STOR_REG,	/* scratch register */
-	STOR_VALUE,	/* integer constant */
-	STOR_LABEL,	/* label / jump target */
-	STOR_LABELSYM,	/* label generated from symbol's pointer value */
-};
-
-struct reg_info {
-	const char	*name;
-	struct storage	*contains;
-	const unsigned char aliases[12];
-#define own_regno aliases[0]
-};
-
-struct storage {
-	enum storage_type type;
-	unsigned long flags;
-
-	/* STOR_REG */
-	struct reg_info *reg;
-	struct symbol *ctype;
-
-	union {
-		/* STOR_PSEUDO */
-		struct {
-			int pseudo;
-			int offset;
-			int size;
-		};
-		/* STOR_ARG */
-		struct {
-			int idx;
-		};
-		/* STOR_SYM */
-		struct {
-			struct symbol *sym;
-		};
-		/* STOR_VALUE */
-		struct {
-			long long value;
-		};
-		/* STOR_LABEL */
-		struct {
-			int label;
-		};
-		/* STOR_LABELSYM */
-		struct {
-			struct symbol *labelsym;
-		};
-	};
-};
-
-enum {
-	STOR_LABEL_VAL	= (1 << 0),
-	STOR_WANTS_FREE	= (1 << 1),
-};
-
-struct symbol_private {
-	struct storage *addr;
-};
-
-enum atom_type {
-	ATOM_TEXT,
-	ATOM_INSN,
-	ATOM_CSTR,
-};
-
-struct atom {
-	enum atom_type type;
-	union {
-		/* stuff for text */
-		struct {
-			char *text;
-			unsigned int text_len;  /* w/o terminating null */
-		};
-
-		/* stuff for insns */
-		struct {
-			char insn[32];
-			char comment[40];
-			struct storage *op1;
-			struct storage *op2;
-		};
-
-		/* stuff for C strings */
-		struct {
-			struct string *string;
-			int label;
-		};
-	};
-};
-
-
-static struct function *current_func = NULL;
-static struct textbuf *unit_post_text = NULL;
-static const char *current_section;
-
-static void emit_comment(const char * fmt, ...) FORMAT_ATTR(1);
-static void emit_move(struct storage *src, struct storage *dest,
-		      struct symbol *ctype, const char *comment);
-static int type_is_signed(struct symbol *sym);
-static struct storage *x86_address_gen(struct expression *expr);
-static struct storage *x86_symbol_expr(struct symbol *sym);
-static void x86_symbol(struct symbol *sym);
-static struct storage *x86_statement(struct statement *stmt);
-static struct storage *x86_expression(struct expression *expr);
-
-enum registers {
-	NOREG,
-	 AL,  DL,  CL,  BL,  AH,  DH,  CH,  BH,	// 8-bit
-	 AX,  DX,  CX,  BX,  SI,  DI,  BP,  SP,	// 16-bit
-	EAX, EDX, ECX, EBX, ESI, EDI, EBP, ESP,	// 32-bit
-	EAX_EDX, ECX_EBX, ESI_EDI,		// 64-bit
-};
-
-/* This works on regno's, reg_info's and hardreg_storage's */
-#define byte_reg(reg) ((reg) - 16)
-#define highbyte_reg(reg) ((reg)-12)
-#define word_reg(reg) ((reg)-8)
-
-#define REGINFO(nr, str, conflicts...)	[nr] = { .name = str, .aliases = { nr , conflicts } }
-
-static struct reg_info reg_info_table[] = {
-	REGINFO( AL,  "%al", AX, EAX, EAX_EDX),
-	REGINFO( DL,  "%dl", DX, EDX, EAX_EDX),
-	REGINFO( CL,  "%cl", CX, ECX, ECX_EBX),
-	REGINFO( BL,  "%bl", BX, EBX, ECX_EBX),
-	REGINFO( AH,  "%ah", AX, EAX, EAX_EDX),
-	REGINFO( DH,  "%dh", DX, EDX, EAX_EDX),
-	REGINFO( CH,  "%ch", CX, ECX, ECX_EBX),
-	REGINFO( BH,  "%bh", BX, EBX, ECX_EBX),
-	REGINFO( AX,  "%ax", AL, AH, EAX, EAX_EDX),
-	REGINFO( DX,  "%dx", DL, DH, EDX, EAX_EDX),
-	REGINFO( CX,  "%cx", CL, CH, ECX, ECX_EBX),
-	REGINFO( BX,  "%bx", BL, BH, EBX, ECX_EBX),
-	REGINFO( SI,  "%si", ESI, ESI_EDI),
-	REGINFO( DI,  "%di", EDI, ESI_EDI),
-	REGINFO( BP,  "%bp", EBP),
-	REGINFO( SP,  "%sp", ESP),
-	REGINFO(EAX, "%eax", AL, AH, AX, EAX_EDX),
-	REGINFO(EDX, "%edx", DL, DH, DX, EAX_EDX),
-	REGINFO(ECX, "%ecx", CL, CH, CX, ECX_EBX),
-	REGINFO(EBX, "%ebx", BL, BH, BX, ECX_EBX),
-	REGINFO(ESI, "%esi", SI, ESI_EDI),
-	REGINFO(EDI, "%edi", DI, ESI_EDI),
-	REGINFO(EBP, "%ebp", BP),
-	REGINFO(ESP, "%esp", SP),
-	REGINFO(EAX_EDX, "%eax:%edx", AL, AH, AX, EAX, DL, DH, DX, EDX),
-	REGINFO(ECX_EBX, "%ecx:%ebx", CL, CH, CX, ECX, BL, BH, BX, EBX),
-	REGINFO(ESI_EDI, "%esi:%edi", SI, ESI, DI, EDI),
-};
-
-#define REGSTORAGE(nr) [nr] = { .type = STOR_REG, .reg = reg_info_table + (nr) }
-
-static struct storage hardreg_storage_table[] = {
-	REGSTORAGE(AL), REGSTORAGE(DL), REGSTORAGE(CL), REGSTORAGE(BL),
-	REGSTORAGE(AH), REGSTORAGE(DH), REGSTORAGE(CH), REGSTORAGE(BH),
-	REGSTORAGE(AX), REGSTORAGE(DX), REGSTORAGE(CX), REGSTORAGE(BX),
-	REGSTORAGE(SI), REGSTORAGE(DI), REGSTORAGE(BP), REGSTORAGE(SP),
-	REGSTORAGE(EAX), REGSTORAGE(EDX), REGSTORAGE(ECX), REGSTORAGE(EBX),
-	REGSTORAGE(ESI), REGSTORAGE(EDI), REGSTORAGE(EBP), REGSTORAGE(ESP),
-	REGSTORAGE(EAX_EDX), REGSTORAGE(ECX_EBX), REGSTORAGE(ESI_EDI),
-};
-
-#define REG_EAX (&hardreg_storage_table[EAX])
-#define REG_ECX (&hardreg_storage_table[ECX])
-#define REG_EDX (&hardreg_storage_table[EDX])
-#define REG_ESP (&hardreg_storage_table[ESP])
-#define REG_DL	(&hardreg_storage_table[DL])
-#define REG_DX	(&hardreg_storage_table[DX])
-#define REG_AL	(&hardreg_storage_table[AL])
-#define REG_AX	(&hardreg_storage_table[AX])
-
-static DECLARE_BITMAP(regs_in_use, 256);
-
-static inline struct storage * reginfo_reg(struct reg_info *info)
-{
-	return hardreg_storage_table + info->own_regno;
-}
-
-static struct storage * get_hardreg(struct storage *reg, int clear)
-{
-	struct reg_info *info = reg->reg;
-	const unsigned char *aliases;
-	int regno;
-
-	aliases = info->aliases;
-	while ((regno = *aliases++) != NOREG) {
-		if (test_bit(regno, regs_in_use))
-			goto busy;
-		if (clear)
-			reg_info_table[regno].contains = NULL;
-	}
-	set_bit(info->own_regno, regs_in_use);
-	return reg;
-busy:
-	fprintf(stderr, "register %s is busy\n", info->name);
-	if (regno + reg_info_table != info)
-		fprintf(stderr, "  conflicts with %s\n", reg_info_table[regno].name);
-	exit(1);
-}
-
-static void put_reg(struct storage *reg)
-{
-	struct reg_info *info = reg->reg;
-	int regno = info->own_regno;
-
-	if (test_and_clear_bit(regno, regs_in_use))
-		return;
-	fprintf(stderr, "freeing already free'd register %s\n", reg_info_table[regno].name);
-}
-
-struct regclass {
-	const char *name;
-	const unsigned char regs[30];
-};
-
-static struct regclass regclass_8 = { "8-bit", { AL, DL, CL, BL, AH, DH, CH, BH }};
-static struct regclass regclass_16 = { "16-bit", { AX, DX, CX, BX, SI, DI, BP }};
-static struct regclass regclass_32 = { "32-bit", { EAX, EDX, ECX, EBX, ESI, EDI, EBP }};
-static struct regclass regclass_64 = { "64-bit", { EAX_EDX, ECX_EBX, ESI_EDI }};
-
-static struct regclass regclass_32_8 = { "32-bit bytes", { EAX, EDX, ECX, EBX }};
-
-static struct regclass *get_regclass_bits(int bits)
-{
-	switch (bits) {
-	case 8: return &regclass_8;
-	case 16: return &regclass_16;
-	case 64: return &regclass_64;
-	default: return &regclass_32;
-	}
-}
-
-static struct regclass *get_regclass(struct expression *expr)
-{
-	return get_regclass_bits(expr->ctype->bit_size);
-}
-
-static int register_busy(int regno)
-{
-	if (!test_bit(regno, regs_in_use)) {
-		struct reg_info *info = reg_info_table + regno;
-		const unsigned char *regs = info->aliases+1;
-
-		while ((regno = *regs) != NOREG) {
-			regs++;
-			if (test_bit(regno, regs_in_use))
-				goto busy;
-		}
-		return 0;
-	}
-busy:
-	return 1;
-}
-
-static struct storage *get_reg(struct regclass *class)
-{
-	const unsigned char *regs = class->regs;
-	int regno;
-
-	while ((regno = *regs) != NOREG) {
-		regs++;
-		if (register_busy(regno))
-			continue;
-		return get_hardreg(hardreg_storage_table + regno, 1);
-	}
-	fprintf(stderr, "Ran out of %s registers\n", class->name);
-	exit(1);
-}
-
-static struct storage *get_reg_value(struct storage *value, struct regclass *class)
-{
-	struct reg_info *info;
-	struct storage *reg;
-
-	/* Do we already have it somewhere */
-	info = value->reg;
-	if (info && info->contains == value) {
-		emit_comment("already have register %s", info->name);
-		return get_hardreg(hardreg_storage_table + info->own_regno, 0);
-	}
-
-	reg = get_reg(class);
-	emit_move(value, reg, value->ctype, "reload register");
-	info = reg->reg;
-	info->contains = value;
-	value->reg = info;
-	return reg;
-}
-
-static struct storage *temp_from_bits(unsigned int bit_size)
-{
-	return get_reg(get_regclass_bits(bit_size));
-}
-
-static inline unsigned int pseudo_offset(struct storage *s)
-{
-	if (s->type != STOR_PSEUDO)
-		return 123456;	/* intentionally bogus value */
-
-	return s->offset;
-}
-
-static inline unsigned int arg_offset(struct storage *s)
-{
-	if (s->type != STOR_ARG)
-		return 123456;	/* intentionally bogus value */
-
-	/* FIXME: this is wrong wrong wrong */
-	return current_func->stack_size + ((1 + s->idx) * 4);
-}
-
-static const char *pretty_offset(int ofs)
-{
-	static char esp_buf[64];
-
-	if (ofs)
-		sprintf(esp_buf, "%d(%%esp)", ofs);
-	else
-		strcpy(esp_buf, "(%esp)");
-
-	return esp_buf;
-}
-
-static void stor_sym_init(struct symbol *sym)
-{
-	struct storage *stor;
-	struct symbol_private *priv;
-
-	priv = calloc(1, sizeof(*priv) + sizeof(*stor));
-	if (!priv)
-		die("OOM in stor_sym_init");
-
-	stor = (struct storage *) (priv + 1);
-
-	priv->addr = stor;
-	stor->type = STOR_SYM;
-	stor->sym = sym;
-}
-
-static const char *stor_op_name(struct storage *s)
-{
-	static char name[32];
-
-	switch (s->type) {
-	case STOR_PSEUDO:
-		strcpy(name, pretty_offset((int) pseudo_offset(s)));
-		break;
-	case STOR_ARG:
-		strcpy(name, pretty_offset((int) arg_offset(s)));
-		break;
-	case STOR_SYM:
-		strcpy(name, show_ident(s->sym->ident));
-		break;
-	case STOR_REG:
-		strcpy(name, s->reg->name);
-		break;
-	case STOR_VALUE:
-		sprintf(name, "$%Ld", s->value);
-		break;
-	case STOR_LABEL:
-		sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
-			s->label);
-		break;
-	case STOR_LABELSYM:
-		sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
-			s->labelsym);
-		break;
-	}
-
-	return name;
-}
-
-static struct atom *new_atom(enum atom_type type)
-{
-	struct atom *atom;
-
-	atom = calloc(1, sizeof(*atom));	/* TODO: chunked alloc */
-	if (!atom)
-		die("nuclear OOM");
-
-	atom->type = type;
-
-	return atom;
-}
-
-static inline void push_cstring(struct function *f, struct string *str,
-				int label)
-{
-	struct atom *atom;
-
-	atom = new_atom(ATOM_CSTR);
-	atom->string = str;
-	atom->label = label;
-
-	add_ptr_list(&f->str_list, atom);	/* note: _not_ atom_list */
-}
-
-static inline void push_atom(struct function *f, struct atom *atom)
-{
-	add_ptr_list(&f->atom_list, atom);
-}
-
-static void push_text_atom(struct function *f, const char *text)
-{
-	struct atom *atom = new_atom(ATOM_TEXT);
-
-	atom->text = strdup(text);
-	atom->text_len = strlen(text);
-
-	push_atom(f, atom);
-}
-
-static struct storage *new_storage(enum storage_type type)
-{
-	struct storage *stor;
-
-	stor = calloc(1, sizeof(*stor));
-	if (!stor)
-		die("OOM in new_storage");
-
-	stor->type = type;
-
-	return stor;
-}
-
-static struct storage *stack_alloc(int n_bytes)
-{
-	struct function *f = current_func;
-	struct storage *stor;
-
-	assert(f != NULL);
-
-	stor = new_storage(STOR_PSEUDO);
-	stor->type = STOR_PSEUDO;
-	stor->pseudo = f->pseudo_nr;
-	stor->offset = f->stack_size; /* FIXME: stack req. natural align */
-	stor->size = n_bytes;
-	f->stack_size += n_bytes;
-	f->pseudo_nr++;
-
-	add_ptr_list(&f->pseudo_list, stor);
-
-	return stor;
-}
-
-static struct storage *new_labelsym(struct symbol *sym)
-{
-	struct storage *stor;
-
-	stor = new_storage(STOR_LABELSYM);
-
-	if (stor) {
-		stor->flags |= STOR_WANTS_FREE;
-		stor->labelsym = sym;
-	}
-
-	return stor;
-}
-
-static struct storage *new_val(long long value)
-{
-	struct storage *stor;
-
-	stor = new_storage(STOR_VALUE);
-
-	if (stor) {
-		stor->flags |= STOR_WANTS_FREE;
-		stor->value = value;
-	}
-
-	return stor;
-}
-
-static int new_label(void)
-{
-	static int label = 0;
-	return ++label;
-}
-
-static void textbuf_push(struct textbuf **buf_p, const char *text)
-{
-	struct textbuf *tmp, *list = *buf_p;
-	unsigned int text_len = strlen(text);
-	unsigned int alloc_len = text_len + 1 + sizeof(*list);
-
-	tmp = calloc(1, alloc_len);
-	if (!tmp)
-		die("OOM on textbuf alloc");
-
-	tmp->text = ((void *) tmp) + sizeof(*tmp);
-	memcpy(tmp->text, text, text_len + 1);
-	tmp->len = text_len;
-
-	/* add to end of list */
-	if (!list) {
-		list = tmp;
-		tmp->prev = tmp;
-	} else {
-		tmp->prev = list->prev;
-		tmp->prev->next = tmp;
-		list->prev = tmp;
-	}
-	tmp->next = list;
-
-	*buf_p = list;
-}
-
-static void textbuf_emit(struct textbuf **buf_p)
-{
-	struct textbuf *tmp, *list = *buf_p;
-
-	while (list) {
-		tmp = list;
-		if (tmp->next == tmp)
-			list = NULL;
-		else {
-			tmp->prev->next = tmp->next;
-			tmp->next->prev = tmp->prev;
-			list = tmp->next;
-		}
-
-		fputs(tmp->text, stdout);
-
-		free(tmp);
-	}
-
-	*buf_p = list;
-}
-
-static void insn(const char *insn, struct storage *op1, struct storage *op2,
-		 const char *comment_in)
-{
-	struct function *f = current_func;
-	struct atom *atom = new_atom(ATOM_INSN);
-
-	assert(insn != NULL);
-
-	strcpy(atom->insn, insn);
-	if (comment_in && (*comment_in))
-		strncpy(atom->comment, comment_in,
-			sizeof(atom->comment) - 1);
-
-	atom->op1 = op1;
-	atom->op2 = op2;
-
-	push_atom(f, atom);
-}
-
-static void emit_comment(const char *fmt, ...)
-{
-	struct function *f = current_func;
-	static char tmpbuf[100] = "\t# ";
-	va_list args;
-	int i;
-
-	va_start(args, fmt);
-	i = vsnprintf(tmpbuf+3, sizeof(tmpbuf)-4, fmt, args);
-	va_end(args);
-	tmpbuf[i+3] = '\n';
-	tmpbuf[i+4] = '\0';
-	push_text_atom(f, tmpbuf);
-}
-
-static void emit_label (int label, const char *comment)
-{
-	struct function *f = current_func;
-	char s[64];
-
-	if (!comment)
-		sprintf(s, ".L%d:\n", label);
-	else
-		sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
-
-	push_text_atom(f, s);
-}
-
-static void emit_labelsym (struct symbol *sym, const char *comment)
-{
-	struct function *f = current_func;
-	char s[64];
-
-	if (!comment)
-		sprintf(s, ".LS%p:\n", sym);
-	else
-		sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
-
-	push_text_atom(f, s);
-}
-
-void emit_unit_begin(const char *basename)
-{
-	printf("\t.file\t\"%s\"\n", basename);
-}
-
-void emit_unit_end(void)
-{
-	textbuf_emit(&unit_post_text);
-	printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
-}
-
-/* conditionally switch sections */
-static void emit_section(const char *s)
-{
-	if (s == current_section)
-		return;
-	if (current_section && (!strcmp(s, current_section)))
-		return;
-
-	printf("\t%s\n", s);
-	current_section = s;
-}
-
-static void emit_insn_atom(struct function *f, struct atom *atom)
-{
-	char s[128];
-	char comment[64];
-	struct storage *op1 = atom->op1;
-	struct storage *op2 = atom->op2;
-
-	if (atom->comment[0])
-		sprintf(comment, "\t\t# %s", atom->comment);
-	else
-		comment[0] = 0;
-
-	if (atom->op2) {
-		char tmp[16];
-		strcpy(tmp, stor_op_name(op1));
-		sprintf(s, "\t%s\t%s, %s%s\n",
-			atom->insn, tmp, stor_op_name(op2), comment);
-	} else if (atom->op1)
-		sprintf(s, "\t%s\t%s%s%s\n",
-			atom->insn, stor_op_name(op1),
-			comment[0] ? "\t" : "", comment);
-	else
-		sprintf(s, "\t%s\t%s%s\n",
-			atom->insn,
-			comment[0] ? "\t\t" : "", comment);
-
-	write(STDOUT_FILENO, s, strlen(s));
-}
-
-static void emit_atom_list(struct function *f)
-{
-	struct atom *atom;
-
-	FOR_EACH_PTR(f->atom_list, atom) {
-		switch (atom->type) {
-		case ATOM_TEXT: {
-			ssize_t rc = write(STDOUT_FILENO, atom->text,
-					   atom->text_len);
-			(void) rc;	/* FIXME */
-			break;
-		}
-		case ATOM_INSN:
-			emit_insn_atom(f, atom);
-			break;
-		case ATOM_CSTR:
-			assert(0);
-			break;
-		}
-	} END_FOR_EACH_PTR(atom);
-}
-
-static void emit_string_list(struct function *f)
-{
-	struct atom *atom;
-
-	emit_section(".section\t.rodata");
-
-	FOR_EACH_PTR(f->str_list, atom) {
-		/* FIXME: escape " in string */
-		printf(".L%d:\n", atom->label);
-		printf("\t.string\t%s\n", show_string(atom->string));
-
-		free(atom);
-	} END_FOR_EACH_PTR(atom);
-}
-
-static void func_cleanup(struct function *f)
-{
-	struct storage *stor;
-	struct atom *atom;
-
-	FOR_EACH_PTR(f->atom_list, atom) {
-		if ((atom->type == ATOM_TEXT) && (atom->text))
-			free(atom->text);
-		if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
-			free(atom->op1);
-		if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
-			free(atom->op2);
-		free(atom);
-	} END_FOR_EACH_PTR(atom);
-
-	FOR_EACH_PTR(f->pseudo_list, stor) {
-		free(stor);
-	} END_FOR_EACH_PTR(stor);
-
-	free_ptr_list(&f->pseudo_list);
-	free(f);
-}
-
-/* function prologue */
-static void emit_func_pre(struct symbol *sym)
-{
-	struct function *f;
-	struct symbol *arg;
-	unsigned int i, argc = 0, alloc_len;
-	unsigned char *mem;
-	struct symbol_private *privbase;
-	struct storage *storage_base;
-	struct symbol *base_type = sym->ctype.base_type;
-
-	FOR_EACH_PTR(base_type->arguments, arg) {
-		argc++;
-	} END_FOR_EACH_PTR(arg);
-
-	alloc_len =
-		sizeof(*f) +
-		(argc * sizeof(struct symbol *)) +
-		(argc * sizeof(struct symbol_private)) +
-		(argc * sizeof(struct storage));
-	mem = calloc(1, alloc_len);
-	if (!mem)
-		die("OOM on func info");
-
-	f		=  (struct function *) mem;
-	mem		+= sizeof(*f);
-	f->argv		=  (struct symbol **) mem;
-	mem		+= (argc * sizeof(struct symbol *));
-	privbase	=  (struct symbol_private *) mem;
-	mem		+= (argc * sizeof(struct symbol_private));
-	storage_base	=  (struct storage *) mem;
-
-	f->argc = argc;
-	f->ret_target = new_label();
-
-	i = 0;
-	FOR_EACH_PTR(base_type->arguments, arg) {
-		f->argv[i] = arg;
-		arg->aux = &privbase[i];
-		storage_base[i].type = STOR_ARG;
-		storage_base[i].idx = i;
-		privbase[i].addr = &storage_base[i];
-		i++;
-	} END_FOR_EACH_PTR(arg);
-
-	assert(current_func == NULL);
-	current_func = f;
-}
-
-/* function epilogue */
-static void emit_func_post(struct symbol *sym)
-{
-	const char *name = show_ident(sym->ident);
-	struct function *f = current_func;
-	int stack_size = f->stack_size;
-
-	if (f->str_list)
-		emit_string_list(f);
-
-	/* function prologue */
-	emit_section(".text");
-	if ((sym->ctype.modifiers & MOD_STATIC) == 0)
-		printf(".globl %s\n", name);
-	printf("\t.type\t%s, @function\n", name);
-	printf("%s:\n", name);
-
-	if (stack_size) {
-		char pseudo_const[16];
-
-		sprintf(pseudo_const, "$%d", stack_size);
-		printf("\tsubl\t%s, %%esp\n", pseudo_const);
-	}
-
-	/* function epilogue */
-
-	/* jump target for 'return' statements */
-	emit_label(f->ret_target, NULL);
-
-	if (stack_size) {
-		struct storage *val;
-
-		val = new_storage(STOR_VALUE);
-		val->value = (long long) (stack_size);
-		val->flags = STOR_WANTS_FREE;
-
-		insn("addl", val, REG_ESP, NULL);
-	}
-
-	insn("ret", NULL, NULL, NULL);
-
-	/* output everything to stdout */
-	fflush(stdout);		/* paranoia; needed? */
-	emit_atom_list(f);
-
-	/* function footer */
-	name = show_ident(sym->ident);
-	printf("\t.size\t%s, .-%s\n", name, name);
-
-	func_cleanup(f);
-	current_func = NULL;
-}
-
-/* emit object (a.k.a. variable, a.k.a. data) prologue */
-static void emit_object_pre(const char *name, unsigned long modifiers,
-			    unsigned long alignment, unsigned int byte_size)
-{
-	if ((modifiers & MOD_STATIC) == 0)
-		printf(".globl %s\n", name);
-	emit_section(".data");
-	if (alignment)
-		printf("\t.align %lu\n", alignment);
-	printf("\t.type\t%s, @object\n", name);
-	printf("\t.size\t%s, %d\n", name, byte_size);
-	printf("%s:\n", name);
-}
-
-/* emit value (only) for an initializer scalar */
-static void emit_scalar(struct expression *expr, unsigned int bit_size)
-{
-	const char *type;
-	long long ll;
-
-	assert(expr->type == EXPR_VALUE);
-
-	if (expr->value == 0ULL) {
-		printf("\t.zero\t%d\n", bit_size / 8);
-		return;
-	}
-
-	ll = (long long) expr->value;
-
-	switch (bit_size) {
-	case 8:		type = "byte";	ll = (char) ll; break;
-	case 16:	type = "value";	ll = (short) ll; break;
-	case 32:	type = "long";	ll = (int) ll; break;
-	case 64:	type = "quad";	break;
-	default:	type = NULL;	break;
-	}
-
-	assert(type != NULL);
-
-	printf("\t.%s\t%Ld\n", type, ll);
-}
-
-static void emit_global_noinit(const char *name, unsigned long modifiers,
-			       unsigned long alignment, unsigned int byte_size)
-{
-	char s[64];
-
-	if (modifiers & MOD_STATIC) {
-		sprintf(s, "\t.local\t%s\n", name);
-		textbuf_push(&unit_post_text, s);
-	}
-	if (alignment)
-		sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
-	else
-		sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
-	textbuf_push(&unit_post_text, s);
-}
-
-static int ea_current, ea_last;
-
-static void emit_initializer(struct symbol *sym,
-			     struct expression *expr)
-{
-	int distance = ea_current - ea_last - 1;
-
-	if (distance > 0)
-		printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
-
-	if (expr->type == EXPR_VALUE) {
-		struct symbol *base_type = sym->ctype.base_type;
-		assert(base_type != NULL);
-
-		emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
-		return;
-	}
-	if (expr->type != EXPR_INITIALIZER)
-		return;
-
-	assert(0); /* FIXME */
-}
-
-static int sort_array_cmp(const struct expression *a,
-			  const struct expression *b)
-{
-	int a_ofs = 0, b_ofs = 0;
-
-	if (a->type == EXPR_POS)
-		a_ofs = (int) a->init_offset;
-	if (b->type == EXPR_POS)
-		b_ofs = (int) b->init_offset;
-
-	return a_ofs - b_ofs;
-}
-
-/* move to front-end? */
-static void sort_array(struct expression *expr)
-{
-	struct expression *entry, **list;
-	unsigned int elem, sorted, i;
-
-	elem = 0;
-	FOR_EACH_PTR(expr->expr_list, entry) {
-		elem++;
-	} END_FOR_EACH_PTR(entry);
-
-	if (!elem)
-		return;
-
-	list = malloc(sizeof(entry) * elem);
-	if (!list)
-		die("OOM in sort_array");
-
-	/* this code is no doubt evil and ignores EXPR_INDEX possibly
-	 * to its detriment and other nasty things.  improvements
-	 * welcome.
-	 */
-	i = 0;
-	sorted = 0;
-	FOR_EACH_PTR(expr->expr_list, entry) {
-		if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
-			/* add entry to list[], in sorted order */
-			if (sorted == 0) {
-				list[0] = entry;
-				sorted = 1;
-			} else {
-				for (i = 0; i < sorted; i++)
-					if (sort_array_cmp(entry, list[i]) <= 0)
-						break;
-
-				/* If inserting into the middle of list[]
-				 * instead of appending, we memmove.
-				 * This is ugly, but thankfully
-				 * uncommon.  Input data with tons of
-				 * entries very rarely have explicit
-				 * offsets.  convert to qsort eventually...
-				 */
-				if (i != sorted)
-					memmove(&list[i + 1], &list[i],
-						(sorted - i) * sizeof(entry));
-				list[i] = entry;
-				sorted++;
-			}
-		}
-	} END_FOR_EACH_PTR(entry);
-
-	i = 0;
-	FOR_EACH_PTR(expr->expr_list, entry) {
-		if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
-			*THIS_ADDRESS(entry) = list[i++];
-	} END_FOR_EACH_PTR(entry);
-
-}
-
-static void emit_array(struct symbol *sym)
-{
-	struct symbol *base_type = sym->ctype.base_type;
-	struct expression *expr = sym->initializer;
-	struct expression *entry;
-
-	assert(base_type != NULL);
-
-	stor_sym_init(sym);
-
-	ea_last = -1;
-
-	emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
-		        sym->ctype.alignment,
-			sym->bit_size / 8);
-
-	sort_array(expr);
-
-	FOR_EACH_PTR(expr->expr_list, entry) {
-		if (entry->type == EXPR_VALUE) {
-			ea_current = 0;
-			emit_initializer(sym, entry);
-			ea_last = ea_current;
-		} else if (entry->type == EXPR_POS) {
-			ea_current =
-			    entry->init_offset / (base_type->bit_size / 8);
-			emit_initializer(sym, entry->init_expr);
-			ea_last = ea_current;
-		}
-	} END_FOR_EACH_PTR(entry);
-}
-
-void emit_one_symbol(struct symbol *sym)
-{
-	x86_symbol(sym);
-}
-
-static void emit_copy(struct storage *dest, struct storage *src,
-		      struct symbol *ctype)
-{
-	struct storage *reg = NULL;
-	unsigned int bit_size;
-
-	/* FIXME: Bitfield copy! */
-
-	bit_size = src->size * 8;
-	if (!bit_size)
-		bit_size = 32;
-	if ((src->type == STOR_ARG) && (bit_size < 32))
-		bit_size = 32;
-
-	reg = temp_from_bits(bit_size);
-	emit_move(src, reg, ctype, "begin copy ..");
-
-	bit_size = dest->size * 8;
-	if (!bit_size)
-		bit_size = 32;
-	if ((dest->type == STOR_ARG) && (bit_size < 32))
-		bit_size = 32;
-
-	emit_move(reg, dest, ctype, ".... end copy");
-	put_reg(reg);
-}
-
-static void emit_store(struct expression *dest_expr, struct storage *dest,
-		       struct storage *src, int bits)
-{
-	/* FIXME: Bitfield store! */
-	printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
-}
-
-static void emit_scalar_noinit(struct symbol *sym)
-{
-	emit_global_noinit(show_ident(sym->ident),
-			   sym->ctype.modifiers, sym->ctype.alignment,
-			   sym->bit_size / 8);
-	stor_sym_init(sym);
-}
-
-static void emit_array_noinit(struct symbol *sym)
-{
-	emit_global_noinit(show_ident(sym->ident),
-			   sym->ctype.modifiers, sym->ctype.alignment,
-			   get_expression_value(sym->array_size) * (sym->bit_size / 8));
-	stor_sym_init(sym);
-}
-
-static const char *opbits(const char *insn, unsigned int bits)
-{
-	static char opbits_str[32];
-	char c;
-
-	switch (bits) {
-	case 8:	 c = 'b'; break;
-	case 16: c = 'w'; break;
-	case 32: c = 'l'; break;
-	case 64: c = 'q'; break;
-	default: abort(); break;
-	}
-
-	sprintf(opbits_str, "%s%c", insn, c);
-
-	return opbits_str;
-}
-
-static void emit_move(struct storage *src, struct storage *dest,
-		      struct symbol *ctype, const char *comment)
-{
-	unsigned int bits;
-	unsigned int is_signed;
-	unsigned int is_dest = (src->type == STOR_REG);
-	const char *opname;
-
-	if (ctype) {
-		bits = ctype->bit_size;
-		is_signed = type_is_signed(ctype);
-	} else {
-		bits = 32;
-		is_signed = 0;
-	}
-
-	/*
-	 * Are we moving from a register to a register?
-	 * Make the new reg to be the "cache".
-	 */
-	if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
-		struct storage *backing;
-
-reg_reg_move:
-		if (dest == src)
-			return;
-
-		backing = src->reg->contains;
-		if (backing) {
-			/* Is it still valid? */
-			if (backing->reg != src->reg)
-				backing = NULL;
-			else
-				backing->reg = dest->reg;
-		}
-		dest->reg->contains = backing;
-		insn("mov", src, dest, NULL);
-		return;
-	}
-
-	/*
-	 * Are we moving to a register from a non-reg?
-	 *
-	 * See if we have the non-reg source already cached
-	 * in a register..
-	 */
-	if (dest->type == STOR_REG) {
-		if (src->reg) {
-			struct reg_info *info = src->reg;
-			if (info->contains == src) {
-				src = reginfo_reg(info);
-				goto reg_reg_move;
-			}
-		}
-		dest->reg->contains = src;
-		src->reg = dest->reg;
-	}
-
-	if (src->type == STOR_REG) {
-		/* We could just mark the register dirty here and do lazy store.. */
-		src->reg->contains = dest;
-		dest->reg = src->reg;
-	}
-
-	if ((bits == 8) || (bits == 16)) {
-		if (is_dest)
-			opname = "mov";
-		else
-			opname = is_signed ? "movsx" : "movzx";
-	} else
-		opname = "mov";
-
-	insn(opbits(opname, bits), src, dest, comment);
-}
-
-static struct storage *emit_compare(struct expression *expr)
-{
-	struct storage *left = x86_expression(expr->left);
-	struct storage *right = x86_expression(expr->right);
-	struct storage *reg1, *reg2;
-	struct storage *new, *val;
-	const char *opname = NULL;
-	unsigned int right_bits = expr->right->ctype->bit_size;
-
-	switch(expr->op) {
-	case '<': 		opname = "setl";	break;
-	case '>':		opname = "setg";	break;
-	case SPECIAL_LTE:
-				opname = "setle";	break;
-	case SPECIAL_GTE:
-				opname = "setge";	break;
-	case SPECIAL_EQUAL:	opname = "sete";	break;
-	case SPECIAL_NOTEQUAL:	opname = "setne";	break;
-	case SPECIAL_UNSIGNED_LT:
-				opname = "setb";	break;
-	case SPECIAL_UNSIGNED_GT:
-				opname = "seta";	break;
-	case SPECIAL_UNSIGNED_LTE:
-				opname = "setb";	break;
-	case SPECIAL_UNSIGNED_GTE:
-				opname = "setae";	break;
-	default:
-		assert(0);
-		break;
-	}
-
-	/* init EDX to 0 */
-	val = new_storage(STOR_VALUE);
-	val->flags = STOR_WANTS_FREE;
-
-	reg1 = get_reg(&regclass_32_8);
-	emit_move(val, reg1, NULL, NULL);
-
-	/* move op1 into EAX */
-	reg2 = get_reg_value(left, get_regclass(expr->left));
-
-	/* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
-	insn(opbits("cmp", right_bits), right, reg2, NULL);
-	put_reg(reg2);
-
-	/* store result of operation, 0 or 1, in DL using SETcc */
-	insn(opname, byte_reg(reg1), NULL, NULL);
-
-	/* finally, store the result (DL) in a new pseudo / stack slot */
-	new = stack_alloc(4);
-	emit_move(reg1, new, NULL, "end EXPR_COMPARE");
-	put_reg(reg1);
-
-	return new;
-}
-
-static struct storage *emit_value(struct expression *expr)
-{
-#if 0 /* old and slow way */
-	struct storage *new = stack_alloc(4);
-	struct storage *val;
-
-	val = new_storage(STOR_VALUE);
-	val->value = (long long) expr->value;
-	val->flags = STOR_WANTS_FREE;
-	insn("movl", val, new, NULL);
-
-	return new;
-#else
-	struct storage *val;
-
-	val = new_storage(STOR_VALUE);
-	val->value = (long long) expr->value;
-
-	return val;	/* FIXME: memory leak */
-#endif
-}
-
-static struct storage *emit_divide(struct expression *expr, struct storage *left, struct storage *right)
-{
-	struct storage *eax_edx;
-	struct storage *reg, *new;
-	struct storage *val = new_storage(STOR_VALUE);
-
-	emit_comment("begin DIVIDE");
-	eax_edx = get_hardreg(hardreg_storage_table + EAX_EDX, 1);
-
-	/* init EDX to 0 */
-	val->flags = STOR_WANTS_FREE;
-	emit_move(val, REG_EDX, NULL, NULL);
-
-	new = stack_alloc(expr->ctype->bit_size / 8);
-
-	/* EAX is dividend */
-	emit_move(left, REG_EAX, NULL, NULL);
-
-	reg = get_reg_value(right, &regclass_32);
-
-	/* perform binop */
-	insn("div", reg, REG_EAX, NULL);
-	put_reg(reg);
-
-	reg = REG_EAX;
-	if (expr->op == '%')
-		reg = REG_EDX;
-	emit_move(reg, new, NULL, NULL);
-
-	put_reg(eax_edx);
-	emit_comment("end DIVIDE");
-	return new;
-}
-
-static struct storage *emit_binop(struct expression *expr)
-{
-	struct storage *left = x86_expression(expr->left);
-	struct storage *right = x86_expression(expr->right);
-	struct storage *new;
-	struct storage *dest, *src;
-	const char *opname = NULL;
-	const char *suffix = NULL;
-	char opstr[16];
-	int is_signed;
-
-	/* Divides have special register constraints */
-	if ((expr->op == '/') || (expr->op == '%'))
-		return emit_divide(expr, left, right);
-
-	is_signed = type_is_signed(expr->ctype);
-
-	switch (expr->op) {
-	case '+':
-		opname = "add";
-		break;
-	case '-':
-		opname = "sub";
-		break;
-	case '&':
-		opname = "and";
-		break;
-	case '|':
-		opname = "or";
-		break;
-	case '^':
-		opname = "xor";
-		break;
-	case SPECIAL_LEFTSHIFT:
-		opname = "shl";
-		break;
-	case SPECIAL_RIGHTSHIFT:
-		if (is_signed)
-			opname = "sar";
-		else
-			opname = "shr";
-		break;
-	case '*':
-		if (is_signed)
-			opname = "imul";
-		else
-			opname = "mul";
-		break;
-	case SPECIAL_LOGICAL_AND:
-		warning(expr->pos, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
-		opname = "and";
-		break;
-	case SPECIAL_LOGICAL_OR:
-		warning(expr->pos, "bogus bitwise or for logical op (should use 'or + setne' or something)");
-		opname = "or";
-		break;
-	default:
-		error_die(expr->pos, "unhandled binop '%s'\n", show_special(expr->op));
-		break;
-	}
-
-	dest = get_reg_value(right, &regclass_32);
-	src = get_reg_value(left, &regclass_32);
-	switch (expr->ctype->bit_size) {
-	case 8:
-		suffix = "b";
-		break;
-	case 16:
-		suffix = "w";
-		break;
-	case 32:
-		suffix = "l";
-		break;
-	case 64:
-		suffix = "q";		/* FIXME */
-		break;
-	default:
-		assert(0);
-		break;
-	}
-
-	snprintf(opstr, sizeof(opstr), "%s%s", opname, suffix);
-
-	/* perform binop */
-	insn(opstr, src, dest, NULL);
-	put_reg(src);
-
-	/* store result in new pseudo / stack slot */
-	new = stack_alloc(expr->ctype->bit_size / 8);
-	emit_move(dest, new, NULL, "end EXPR_BINOP");
-
-	put_reg(dest);
-
-	return new;
-}
-
-static int emit_conditional_test(struct storage *val)
-{
-	struct storage *reg;
-	struct storage *target_val;
-	int target_false;
-
-	/* load result into EAX */
-	emit_comment("begin if/conditional");
-	reg = get_reg_value(val, &regclass_32);
-
-	/* compare result with zero */
-	insn("test", reg, reg, NULL);
-	put_reg(reg);
-
-	/* create conditional-failed label to jump to */
-	target_false = new_label();
-	target_val = new_storage(STOR_LABEL);
-	target_val->label = target_false;
-	target_val->flags = STOR_WANTS_FREE;
-	insn("jz", target_val, NULL, NULL);
-
-	return target_false;
-}
-
-static int emit_conditional_end(int target_false)
-{
-	struct storage *cond_end_st;
-	int cond_end;
-
-	/* finished generating code for if-true statement.
-	 * add a jump-to-end jump to avoid falling through
-	 * to the if-false statement code.
-	 */
-	cond_end = new_label();
-	cond_end_st = new_storage(STOR_LABEL);
-	cond_end_st->label = cond_end;
-	cond_end_st->flags = STOR_WANTS_FREE;
-	insn("jmp", cond_end_st, NULL, NULL);
-
-	/* if we have both if-true and if-false statements,
-	 * the failed-conditional case will fall through to here
-	 */
-	emit_label(target_false, NULL);
-
-	return cond_end;
-}
-
-static void emit_if_conditional(struct statement *stmt)
-{
-	struct storage *val;
-	int cond_end;
-
-	/* emit test portion of conditional */
-	val = x86_expression(stmt->if_conditional);
-	cond_end = emit_conditional_test(val);
-
-	/* emit if-true statement */
-	x86_statement(stmt->if_true);
-
-	/* emit if-false statement, if present */
-	if (stmt->if_false) {
-		cond_end = emit_conditional_end(cond_end);
-		x86_statement(stmt->if_false);
-	}
-
-	/* end of conditional; jump target for if-true branch */
-	emit_label(cond_end, "end if");
-}
-
-static struct storage *emit_inc_dec(struct expression *expr, int postop)
-{
-	struct storage *addr = x86_address_gen(expr->unop);
-	struct storage *retval;
-	char opname[16];
-
-	strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
-			      expr->ctype->bit_size));
-
-	if (postop) {
-		struct storage *new = stack_alloc(4);
-
-		emit_copy(new, addr, expr->unop->ctype);
-
-		retval = new;
-	} else
-		retval = addr;
-
-	insn(opname, addr, NULL, NULL);
-
-	return retval;
-}
-
-static struct storage *emit_postop(struct expression *expr)
-{
-	return emit_inc_dec(expr, 1);
-}
-
-static struct storage *emit_return_stmt(struct statement *stmt)
-{
-	struct function *f = current_func;
-	struct expression *expr = stmt->ret_value;
-	struct storage *val = NULL, *jmplbl;
-
-	if (expr && expr->ctype) {
-		val = x86_expression(expr);
-		assert(val != NULL);
-		emit_move(val, REG_EAX, expr->ctype, "return");
-	}
-
-	jmplbl = new_storage(STOR_LABEL);
-	jmplbl->flags |= STOR_WANTS_FREE;
-	jmplbl->label = f->ret_target;
-	insn("jmp", jmplbl, NULL, NULL);
-
-	return val;
-}
-
-static struct storage *emit_conditional_expr(struct expression *expr)
-{
-	struct storage *cond, *true = NULL, *false = NULL;
-	struct storage *new = stack_alloc(expr->ctype->bit_size / 8);
-	int target_false, cond_end;
-
-	/* evaluate conditional */
-	cond = x86_expression(expr->conditional);
-	target_false = emit_conditional_test(cond);
-
-	/* handle if-true part of the expression */
-	true = x86_expression(expr->cond_true);
-
-	emit_copy(new, true, expr->ctype);
-
-	cond_end = emit_conditional_end(target_false);
-
-	/* handle if-false part of the expression */
-	false = x86_expression(expr->cond_false);
-
-	emit_copy(new, false, expr->ctype);
-
-	/* end of conditional; jump target for if-true branch */
-	emit_label(cond_end, "end conditional");
-
-	return new;
-}
-
-static struct storage *emit_select_expr(struct expression *expr)
-{
-	struct storage *cond = x86_expression(expr->conditional);
-	struct storage *true = x86_expression(expr->cond_true);
-	struct storage *false = x86_expression(expr->cond_false);
-	struct storage *reg_cond, *reg_true, *reg_false;
-	struct storage *new = stack_alloc(4);
-
-	emit_comment("begin SELECT");
-	reg_cond = get_reg_value(cond, get_regclass(expr->conditional));
-	reg_true = get_reg_value(true, get_regclass(expr));
-	reg_false = get_reg_value(false, get_regclass(expr));
-
-	/*
-	 * Do the actual select: check the conditional for zero,
-	 * move false over true if zero
-	 */ 
-	insn("test", reg_cond, reg_cond, NULL);
-	insn("cmovz", reg_false, reg_true, NULL);
-
-	/* Store it back */
-	emit_move(reg_true, new, expr->ctype, NULL);
-	put_reg(reg_cond);
-	put_reg(reg_true);
-	put_reg(reg_false);
-	emit_comment("end SELECT");
-	return new;
-}
-
-static struct storage *emit_symbol_expr_init(struct symbol *sym)
-{
-	struct expression *expr = sym->initializer;
-	struct symbol_private *priv = sym->aux;
-
-	if (priv == NULL) {
-		priv = calloc(1, sizeof(*priv));
-		sym->aux = priv;
-
-		if (expr == NULL) {
-			struct storage *new = stack_alloc(4);
-			fprintf(stderr, "FIXME! no value for symbol %s.  creating pseudo %d (stack offset %d)\n",
-				show_ident(sym->ident),
-				new->pseudo, new->pseudo * 4);
-			priv->addr = new;
-		} else {
-			priv->addr = x86_expression(expr);
-		}
-	}
-
-	return priv->addr;
-}
-
-static struct storage *emit_string_expr(struct expression *expr)
-{
-	struct function *f = current_func;
-	int label = new_label();
-	struct storage *new;
-
-	push_cstring(f, expr->string, label);
-
-	new = new_storage(STOR_LABEL);
-	new->label = label;
-	new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
-	return new;
-}
-
-static struct storage *emit_cast_expr(struct expression *expr)
-{
-	struct symbol *old_type, *new_type;
-	struct storage *op = x86_expression(expr->cast_expression);
-	int oldbits, newbits;
-	struct storage *new;
-
-	old_type = expr->cast_expression->ctype;
-	new_type = expr->cast_type;
-
-	oldbits = old_type->bit_size;
-	newbits = new_type->bit_size;
-	if (oldbits >= newbits)
-		return op;
-
-	emit_move(op, REG_EAX, old_type, "begin cast ..");
-
-	new = stack_alloc(newbits / 8);
-	emit_move(REG_EAX, new, new_type, ".... end cast");
-
-	return new;
-}
-
-static struct storage *emit_regular_preop(struct expression *expr)
-{
-	struct storage *target = x86_expression(expr->unop);
-	struct storage *val, *new = stack_alloc(4);
-	const char *opname = NULL;
-
-	switch (expr->op) {
-	case '!':
-		val = new_storage(STOR_VALUE);
-		val->flags = STOR_WANTS_FREE;
-		emit_move(val, REG_EDX, NULL, NULL);
-		emit_move(target, REG_EAX, expr->unop->ctype, NULL);
-		insn("test", REG_EAX, REG_EAX, NULL);
-		insn("setz", REG_DL, NULL, NULL);
-		emit_move(REG_EDX, new, expr->unop->ctype, NULL);
-
-		break;
-	case '~':
-		opname = "not";
-	case '-':
-		if (!opname)
-			opname = "neg";
-		emit_move(target, REG_EAX, expr->unop->ctype, NULL);
-		insn(opname, REG_EAX, NULL, NULL);
-		emit_move(REG_EAX, new, expr->unop->ctype, NULL);
-		break;
-	default:
-		assert(0);
-		break;
-	}
-
-	return new;
-}
-
-static void emit_case_statement(struct statement *stmt)
-{
-	emit_labelsym(stmt->case_label, NULL);
-	x86_statement(stmt->case_statement);
-}
-
-static void emit_switch_statement(struct statement *stmt)
-{
-	struct storage *val = x86_expression(stmt->switch_expression);
-	struct symbol *sym, *default_sym = NULL;
-	struct storage *labelsym, *label;
-	int switch_end = 0;
-
-	emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
-
-	/*
-	 * This is where a _real_ back-end would go through the
-	 * cases to decide whether to use a lookup table or a
-	 * series of comparisons etc
-	 */
-	FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
-		struct statement *case_stmt = sym->stmt;
-		struct expression *expr = case_stmt->case_expression;
-		struct expression *to = case_stmt->case_to;
-
-		/* default: */
-		if (!expr)
-			default_sym = sym;
-
-		/* case NNN: */
-		else {
-			struct storage *case_val = new_val(expr->value);
-
-			assert (expr->type == EXPR_VALUE);
-
-			insn("cmpl", case_val, REG_EAX, NULL);
-
-			if (!to) {
-				labelsym = new_labelsym(sym);
-				insn("je", labelsym, NULL, NULL);
-			} else {
-				int next_test;
-
-				label = new_storage(STOR_LABEL);
-				label->flags |= STOR_WANTS_FREE;
-				label->label = next_test = new_label();
-
-				/* FIXME: signed/unsigned */
-				insn("jl", label, NULL, NULL);
-
-				case_val = new_val(to->value);
-				insn("cmpl", case_val, REG_EAX, NULL);
-
-				/* TODO: implement and use refcounting... */
-				label = new_storage(STOR_LABEL);
-				label->flags |= STOR_WANTS_FREE;
-				label->label = next_test;
-
-				/* FIXME: signed/unsigned */
-				insn("jg", label, NULL, NULL);
-
-				labelsym = new_labelsym(sym);
-				insn("jmp", labelsym, NULL, NULL);
-
-				emit_label(next_test, NULL);
-			}
-		}
-	} END_FOR_EACH_PTR(sym);
-
-	if (default_sym) {
-		labelsym = new_labelsym(default_sym);
-		insn("jmp", labelsym, NULL, "default");
-	} else {
-		label = new_storage(STOR_LABEL);
-		label->flags |= STOR_WANTS_FREE;
-		label->label = switch_end = new_label();
-		insn("jmp", label, NULL, "goto end of switch");
-	}
-
-	x86_statement(stmt->switch_statement);
-
-	if (stmt->switch_break->used)
-		emit_labelsym(stmt->switch_break, NULL);
-
-	if (switch_end)
-		emit_label(switch_end, NULL);
-}
-
-static void x86_struct_member(struct symbol *sym)
-{
-	printf("\t%s:%d:%ld at offset %ld.%d", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset, sym->bit_offset);
-	printf("\n");
-}
-
-static void x86_symbol(struct symbol *sym)
-{
-	struct symbol *type;
-
-	if (!sym)
-		return;
-
-	type = sym->ctype.base_type;
-	if (!type)
-		return;
-
-	/*
-	 * Show actual implementation information
-	 */
-	switch (type->type) {
-
-	case SYM_ARRAY:
-		if (sym->initializer)
-			emit_array(sym);
-		else
-			emit_array_noinit(sym);
-		break;
-
-	case SYM_BASETYPE:
-		if (sym->initializer) {
-			emit_object_pre(show_ident(sym->ident),
-					sym->ctype.modifiers,
-				        sym->ctype.alignment,
-					sym->bit_size / 8);
-			emit_scalar(sym->initializer, sym->bit_size);
-			stor_sym_init(sym);
-		} else
-			emit_scalar_noinit(sym);
-		break;
-
-	case SYM_STRUCT:
-	case SYM_UNION: {
-		struct symbol *member;
-
-		printf(" {\n");
-		FOR_EACH_PTR(type->symbol_list, member) {
-			x86_struct_member(member);
-		} END_FOR_EACH_PTR(member);
-		printf("}\n");
-		break;
-	}
-
-	case SYM_FN: {
-		struct statement *stmt = type->stmt;
-		if (stmt) {
-			emit_func_pre(sym);
-			x86_statement(stmt);
-			emit_func_post(sym);
-		}
-		break;
-	}
-
-	default:
-		break;
-	}
-
-	if (sym->initializer && (type->type != SYM_BASETYPE) &&
-	    (type->type != SYM_ARRAY)) {
-		printf(" = \n");
-		x86_expression(sym->initializer);
-	}
-}
-
-static void x86_symbol_init(struct symbol *sym);
-
-static void x86_symbol_decl(struct symbol_list *syms)
-{
-	struct symbol *sym;
-	FOR_EACH_PTR(syms, sym) {
-		x86_symbol_init(sym);
-	} END_FOR_EACH_PTR(sym);
-}
-
-static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
-{
-	struct function *f = current_func;
-	struct loop_stack *ls;
-
-	ls = malloc(sizeof(*ls));
-	ls->continue_lbl = cont_lbl;
-	ls->loop_bottom_lbl = loop_bottom_lbl;
-	ls->next = f->loop_stack;
-	f->loop_stack = ls;
-}
-
-static void loopstk_pop(void)
-{
-	struct function *f = current_func;
-	struct loop_stack *ls;
-
-	assert(f->loop_stack != NULL);
-	ls = f->loop_stack;
-	f->loop_stack = f->loop_stack->next;
-	free(ls);
-}
-
-static int loopstk_break(void)
-{
-	return current_func->loop_stack->loop_bottom_lbl;
-}
-
-static int loopstk_continue(void)
-{
-	return current_func->loop_stack->continue_lbl;
-}
-
-static void emit_loop(struct statement *stmt)
-{
-	struct statement  *pre_statement = stmt->iterator_pre_statement;
-	struct expression *pre_condition = stmt->iterator_pre_condition;
-	struct statement  *statement = stmt->iterator_statement;
-	struct statement  *post_statement = stmt->iterator_post_statement;
-	struct expression *post_condition = stmt->iterator_post_condition;
-	int loop_top = 0, loop_bottom, loop_continue;
-	int have_bottom = 0;
-	struct storage *val;
-
-	loop_bottom = new_label();
-	loop_continue = new_label();
-	loopstk_push(loop_continue, loop_bottom);
-
-	x86_symbol_decl(stmt->iterator_syms);
-	x86_statement(pre_statement);
-	if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
-		loop_top = new_label();
-		emit_label(loop_top, "loop top");
-	}
-	if (pre_condition) {
-		if (pre_condition->type == EXPR_VALUE) {
-			if (!pre_condition->value) {
-				struct storage *lbv;
-				lbv = new_storage(STOR_LABEL);
-				lbv->label = loop_bottom;
-				lbv->flags = STOR_WANTS_FREE;
-				insn("jmp", lbv, NULL, "go to loop bottom");
-				have_bottom = 1;
-			}
-		} else {
-			struct storage *lbv = new_storage(STOR_LABEL);
-			lbv->label = loop_bottom;
-			lbv->flags = STOR_WANTS_FREE;
-			have_bottom = 1;
-
-			val = x86_expression(pre_condition);
-
-			emit_move(val, REG_EAX, NULL, "loop pre condition");
-			insn("test", REG_EAX, REG_EAX, NULL);
-			insn("jz", lbv, NULL, NULL);
-		}
-	}
-	x86_statement(statement);
-	if (stmt->iterator_continue->used)
-		emit_label(loop_continue, "'continue' iterator");
-	x86_statement(post_statement);
-	if (!post_condition) {
-		struct storage *lbv = new_storage(STOR_LABEL);
-		lbv->label = loop_top;
-		lbv->flags = STOR_WANTS_FREE;
-		insn("jmp", lbv, NULL, "go to loop top");
-	} else if (post_condition->type == EXPR_VALUE) {
-		if (post_condition->value) {
-			struct storage *lbv = new_storage(STOR_LABEL);
-			lbv->label = loop_top;
-			lbv->flags = STOR_WANTS_FREE;
-			insn("jmp", lbv, NULL, "go to loop top");
-		}
-	} else {
-		struct storage *lbv = new_storage(STOR_LABEL);
-		lbv->label = loop_top;
-		lbv->flags = STOR_WANTS_FREE;
-
-		val = x86_expression(post_condition);
-
-		emit_move(val, REG_EAX, NULL, "loop post condition");
-		insn("test", REG_EAX, REG_EAX, NULL);
-		insn("jnz", lbv, NULL, NULL);
-	}
-	if (have_bottom || stmt->iterator_break->used)
-		emit_label(loop_bottom, "loop bottom");
-
-	loopstk_pop();
-}
-
-/*
- * Print out a statement
- */
-static struct storage *x86_statement(struct statement *stmt)
-{
-	if (!stmt)
-		return NULL;
-	switch (stmt->type) {
-	default:
-		return NULL;
-	case STMT_RETURN:
-		return emit_return_stmt(stmt);
-	case STMT_DECLARATION:
-		x86_symbol_decl(stmt->declaration);
-		break;
-	case STMT_COMPOUND: {
-		struct statement *s;
-		struct storage *last = NULL;
-
-		FOR_EACH_PTR(stmt->stmts, s) {
-			last = x86_statement(s);
-		} END_FOR_EACH_PTR(s);
-
-		return last;
-	}
-
-	case STMT_EXPRESSION:
-		return x86_expression(stmt->expression);
-	case STMT_IF:
-		emit_if_conditional(stmt);
-		return NULL;
-
-	case STMT_CASE:
-		emit_case_statement(stmt);
-		break;
-	case STMT_SWITCH:
-		emit_switch_statement(stmt);
-		break;
-
-	case STMT_ITERATOR:
-		emit_loop(stmt);
-		break;
-
-	case STMT_NONE:
-		break;
-
-	case STMT_LABEL:
-		printf(".L%p:\n", stmt->label_identifier);
-		x86_statement(stmt->label_statement);
-		break;
-
-	case STMT_GOTO:
-		if (stmt->goto_expression) {
-			struct storage *val = x86_expression(stmt->goto_expression);
-			printf("\tgoto *v%d\n", val->pseudo);
-		} else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
-			struct storage *lbv = new_storage(STOR_LABEL);
-			lbv->label = loopstk_break();
-			lbv->flags = STOR_WANTS_FREE;
-			insn("jmp", lbv, NULL, "'break'; go to loop bottom");
-		} else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
-			struct storage *lbv = new_storage(STOR_LABEL);
-			lbv->label = loopstk_continue();
-			lbv->flags = STOR_WANTS_FREE;
-			insn("jmp", lbv, NULL, "'continue'; go to loop top");
-		} else {
-			struct storage *labelsym = new_labelsym(stmt->goto_label);
-			insn("jmp", labelsym, NULL, NULL);
-		}
-		break;
-	case STMT_ASM:
-		printf("\tasm( .... )\n");
-		break;
-	}
-	return NULL;
-}
-
-static struct storage *x86_call_expression(struct expression *expr)
-{
-	struct function *f = current_func;
-	struct symbol *direct;
-	struct expression *arg, *fn;
-	struct storage *retval, *fncall;
-	int framesize;
-	char s[64];
-
-	if (!expr->ctype) {
-		warning(expr->pos, "\tcall with no type!");
-		return NULL;
-	}
-
-	framesize = 0;
-	FOR_EACH_PTR_REVERSE(expr->args, arg) {
-		struct storage *new = x86_expression(arg);
-		int size = arg->ctype->bit_size;
-
-		/*
-		 * FIXME: i386 SysV ABI dictates that values
-		 * smaller than 32 bits should be placed onto
-		 * the stack as 32-bit objects.  We should not
-		 * blindly do a 32-bit push on objects smaller
-		 * than 32 bits.
-		 */
-		if (size < 32)
-			size = 32;
-		insn("pushl", new, NULL,
-		     !framesize ? "begin function call" : NULL);
-
-		framesize += bits_to_bytes(size);
-	} END_FOR_EACH_PTR_REVERSE(arg);
-
-	fn = expr->fn;
-
-	/* Remove dereference, if any */
-	direct = NULL;
-	if (fn->type == EXPR_PREOP) {
-		if (fn->unop->type == EXPR_SYMBOL) {
-			struct symbol *sym = fn->unop->symbol;
-			if (sym->ctype.base_type->type == SYM_FN)
-				direct = sym;
-		}
-	}
-	if (direct) {
-		struct storage *direct_stor = new_storage(STOR_SYM);
-		direct_stor->flags |= STOR_WANTS_FREE;
-		direct_stor->sym = direct;
-		insn("call", direct_stor, NULL, NULL);
-	} else {
-		fncall = x86_expression(fn);
-		emit_move(fncall, REG_EAX, fn->ctype, NULL);
-
-		strcpy(s, "\tcall\t*%eax\n");
-		push_text_atom(f, s);
-	}
-
-	/* FIXME: pay attention to BITS_IN_POINTER */
-	if (framesize) {
-		struct storage *val = new_storage(STOR_VALUE);
-		val->value = (long long) framesize;
-		val->flags = STOR_WANTS_FREE;
-		insn("addl", val, REG_ESP, NULL);
-	}
-
-	retval = stack_alloc(4);
-	emit_move(REG_EAX, retval, NULL, "end function call");
-
-	return retval;
-}
-
-static struct storage *x86_address_gen(struct expression *expr)
-{
-	struct function *f = current_func;
-	struct storage *addr;
-	struct storage *new;
-	char s[32];
-
-	addr = x86_expression(expr->unop);
-	if (expr->unop->type == EXPR_SYMBOL)
-		return addr;
-
-	emit_move(addr, REG_EAX, NULL, "begin deref ..");
-
-	/* FIXME: operand size */
-	strcpy(s, "\tmovl\t(%eax), %ecx\n");
-	push_text_atom(f, s);
-
-	new = stack_alloc(4);
-	emit_move(REG_ECX, new, NULL, ".... end deref");
-
-	return new;
-}
-
-static struct storage *x86_assignment(struct expression *expr)
-{
-	struct expression *target = expr->left;
-	struct storage *val, *addr;
-
-	if (!expr->ctype)
-		return NULL;
-
-	val = x86_expression(expr->right);
-	addr = x86_address_gen(target);
-
-	switch (val->type) {
-	/* copy, where both operands are memory */
-	case STOR_PSEUDO:
-	case STOR_ARG:
-		emit_copy(addr, val, expr->ctype);
-		break;
-
-	/* copy, one or zero operands are memory */
-	case STOR_REG:
-	case STOR_SYM:
-	case STOR_VALUE:
-	case STOR_LABEL:
-		emit_move(val, addr, expr->left->ctype, NULL);
-		break;
-
-	case STOR_LABELSYM:
-		assert(0);
-		break;
-	}
-	return val;
-}
-
-static int x86_initialization(struct symbol *sym, struct expression *expr)
-{
-	struct storage *val, *addr;
-	int bits;
-
-	if (!expr->ctype)
-		return 0;
-
-	bits = expr->ctype->bit_size;
-	val = x86_expression(expr);
-	addr = x86_symbol_expr(sym);
-	// FIXME! The "target" expression is for bitfield store information.
-	// Leave it NULL, which works fine.
-	emit_store(NULL, addr, val, bits);
-	return 0;
-}
-
-static struct storage *x86_access(struct expression *expr)
-{
-	return x86_address_gen(expr);
-}
-
-static struct storage *x86_preop(struct expression *expr)
-{
-	/*
-	 * '*' is an lvalue access, and is fundamentally different
-	 * from an arithmetic operation. Maybe it should have an
-	 * expression type of its own..
-	 */
-	if (expr->op == '*')
-		return x86_access(expr);
-	if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
-		return emit_inc_dec(expr, 0);
-	return emit_regular_preop(expr);
-}
-
-static struct storage *x86_symbol_expr(struct symbol *sym)
-{
-	struct storage *new = stack_alloc(4);
-
-	if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
-		printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
-		return new;
-	}
-	if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
-		printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
-		return new;
-	}
-	printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
-	return new;
-}
-
-static void x86_symbol_init(struct symbol *sym)
-{
-	struct symbol_private *priv = sym->aux;
-	struct expression *expr = sym->initializer;
-	struct storage *new;
-
-	if (expr)
-		new = x86_expression(expr);
-	else
-		new = stack_alloc(sym->bit_size / 8);
-
-	if (!priv) {
-		priv = calloc(1, sizeof(*priv));
-		sym->aux = priv;
-		/* FIXME: leak! we don't free... */
-		/* (well, we don't free symbols either) */
-	}
-
-	priv->addr = new;
-}
-
-static int type_is_signed(struct symbol *sym)
-{
-	if (sym->type == SYM_NODE)
-		sym = sym->ctype.base_type;
-	if (sym->type == SYM_PTR)
-		return 0;
-	return !(sym->ctype.modifiers & MOD_UNSIGNED);
-}
-
-static struct storage *x86_label_expr(struct expression *expr)
-{
-	struct storage *new = stack_alloc(4);
-	printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
-	return new;
-}
-
-static struct storage *x86_statement_expr(struct expression *expr)
-{
-	return x86_statement(expr->statement);
-}
-
-static int x86_position_expr(struct expression *expr, struct symbol *base)
-{
-	struct storage *new = x86_expression(expr->init_expr);
-	struct symbol *ctype = expr->init_expr->ctype;
-
-	printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
-		expr->init_offset, ctype->bit_offset,
-		show_ident(base->ident));
-	return 0;
-}
-
-static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
-{
-	struct expression *entry;
-
-	FOR_EACH_PTR(expr->expr_list, entry) {
-		// Nested initializers have their positions already
-		// recursively calculated - just output them too
-		if (entry->type == EXPR_INITIALIZER) {
-			x86_initializer_expr(entry, ctype);
-			continue;
-		}
-
-		// Ignore initializer indexes and identifiers - the
-		// evaluator has taken them into account
-		if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
-			continue;
-		if (entry->type == EXPR_POS) {
-			x86_position_expr(entry, ctype);
-			continue;
-		}
-		x86_initialization(ctype, entry);
-	} END_FOR_EACH_PTR(entry);
-}
-
-/*
- * Print out an expression. Return the pseudo that contains the
- * variable.
- */
-static struct storage *x86_expression(struct expression *expr)
-{
-	if (!expr)
-		return NULL;
-
-	if (!expr->ctype) {
-		struct position *pos = &expr->pos;
-		printf("\tno type at %s:%d:%d\n",
-			stream_name(pos->stream),
-			pos->line, pos->pos);
-		return NULL;
-	}
-
-	switch (expr->type) {
-	default:
-		return NULL;
-	case EXPR_CALL:
-		return x86_call_expression(expr);
-
-	case EXPR_ASSIGNMENT:
-		return x86_assignment(expr);
-
-	case EXPR_COMPARE:
-		return emit_compare(expr);
-	case EXPR_BINOP:
-	case EXPR_COMMA:
-	case EXPR_LOGICAL:
-		return emit_binop(expr);
-	case EXPR_PREOP:
-		return x86_preop(expr);
-	case EXPR_POSTOP:
-		return emit_postop(expr);
-	case EXPR_SYMBOL:
-		return emit_symbol_expr_init(expr->symbol);
-	case EXPR_DEREF:
-	case EXPR_SIZEOF:
-	case EXPR_ALIGNOF:
-		warning(expr->pos, "invalid expression after evaluation");
-		return NULL;
-	case EXPR_CAST:
-	case EXPR_FORCE_CAST:
-	case EXPR_IMPLIED_CAST:
-		return emit_cast_expr(expr);
-	case EXPR_VALUE:
-		return emit_value(expr);
-	case EXPR_STRING:
-		return emit_string_expr(expr);
-	case EXPR_INITIALIZER:
-		x86_initializer_expr(expr, expr->ctype);
-		return NULL;
-	case EXPR_SELECT:
-		return emit_select_expr(expr);
-	case EXPR_CONDITIONAL:
-		return emit_conditional_expr(expr);
-	case EXPR_STATEMENT:
-		return x86_statement_expr(expr);
-	case EXPR_LABEL:
-		return x86_label_expr(expr);
-
-	// None of these should exist as direct expressions: they are only
-	// valid as sub-expressions of initializers.
-	case EXPR_POS:
-		warning(expr->pos, "unable to show plain initializer position expression");
-		return NULL;
-	case EXPR_IDENTIFIER:
-		warning(expr->pos, "unable to show identifier expression");
-		return NULL;
-	case EXPR_INDEX:
-		warning(expr->pos, "unable to show index expression");
-		return NULL;
-	case EXPR_TYPE:
-		warning(expr->pos, "unable to show type expression");
-		return NULL;
-	case EXPR_FVALUE:
-		warning(expr->pos, "floating point support is not implemented");
-		return NULL;
-	}
-	return NULL;
-}
diff --git a/compile.c b/compile.c
deleted file mode 100644
index 48f9c70..0000000
--- a/compile.c
+++ /dev/null
@@ -1,84 +0,0 @@ 
-/*
- * Example trivial client program that uses the sparse library
- * and x86 backend.
- *
- * Copyright (C) 2003 Transmeta Corp.
- *               2003 Linus Torvalds
- * Copyright 2003 Jeff Garzik
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "lib.h"
-#include "allocate.h"
-#include "token.h"
-#include "parse.h"
-#include "symbol.h"
-#include "expression.h"
-#include "compile.h"
-
-static void clean_up_symbols(struct symbol_list *list)
-{
-	struct symbol *sym;
-
-	FOR_EACH_PTR(list, sym) {
-		expand_symbol(sym);
-		emit_one_symbol(sym);
-	} END_FOR_EACH_PTR(sym);
-}
-
-int main(int argc, char **argv)
-{
-	char *file;
-	struct string_list *filelist = NULL;
-
-	clean_up_symbols(sparse_initialize(argc, argv, &filelist));
-	FOR_EACH_PTR_NOTAG(filelist, file) {
-		struct symbol_list *list;
-		const char *basename = strrchr(file, '/');
-		basename = basename ?  basename+1 : file;
-
-		list = sparse(file);
-
-		// Do type evaluation and simplification
-		emit_unit_begin(basename);
-		clean_up_symbols(list);
-		emit_unit_end();
-	} END_FOR_EACH_PTR_NOTAG(file);
-
-#if 0
-	// And show the allocation statistics
-	show_ident_alloc();
-	show_token_alloc();
-	show_symbol_alloc();
-	show_expression_alloc();
-	show_statement_alloc();
-	show_string_alloc();
-	show_bytes_alloc();
-#endif
-	return 0;
-}
diff --git a/compile.h b/compile.h
deleted file mode 100644
index 177363a..0000000
--- a/compile.h
+++ /dev/null
@@ -1,10 +0,0 @@ 
-#ifndef COMPILE_H
-#define COMPILE_H
-
-struct symbol;
-
-extern void emit_one_symbol(struct symbol *);
-extern void emit_unit_begin(const char *);
-extern void emit_unit_end(void);
-
-#endif /* COMPILE_H */