summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/.gitignore1
-rw-r--r--src/Makefile9
-rw-r--r--src/all.h7
-rw-r--r--src/emit.c42
-rw-r--r--src/isel.c3
-rw-r--r--src/main.c27
-rwxr-xr-xsrc/test/go.sh2
7 files changed, 67 insertions, 24 deletions
diff --git a/src/.gitignore b/src/.gitignore
index 0416fa9..cfd89d7 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,5 +1,6 @@
 qbe
 doc
+config.h
 .comfile
 *.o
 *.out
diff --git a/src/Makefile b/src/Makefile
index b9c87df..9f13008 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -6,7 +6,14 @@ CFLAGS = -Wall -Wextra -std=c99 -g -pedantic
 $(BIN): $(OBJ)
 	$(CC) $(LDFLAGS) $(OBJ) -o $@
 
-$(OBJ): all.h
+$(OBJ): all.h config.h
+
+config.h:
+	@case `uname` in                                \
+	*Darwin*) echo "#define Defaultasm Gasmacho" ;; \
+	*Linux*)  echo "#define Defaultasm Gaself" ;;   \
+	esac > $@
+
 
 .PHONY: clean check syndoc
 clean:
diff --git a/src/all.h b/src/all.h
index e0542da..03661ad 100644
--- a/src/all.h
+++ b/src/all.h
@@ -400,6 +400,7 @@ struct Con {
 		float s;
 	} bits;
 	char flt; /* for printing, see parse.c */
+	char local;
 };
 
 typedef struct Addr Addr;
@@ -469,6 +470,10 @@ struct Dat {
 
 
 /* main.c */
+enum Asm {
+	Gasmacho,
+	Gaself,
+};
 extern char debug['Z'+1];
 
 /* util.c */
@@ -548,6 +553,8 @@ void spill(Fn *);
 void rega(Fn *);
 
 /* emit.c */
+extern char *locprefix;
+extern char *symprefix;
 void emitfn(Fn *, FILE *);
 void emitdat(Dat *, FILE *);
 int stashfp(int64_t, int);
diff --git a/src/emit.c b/src/emit.c
index b9dc782..df96afd 100644
--- a/src/emit.c
+++ b/src/emit.c
@@ -1,5 +1,7 @@
 #include "all.h"
 
+char *locprefix, *symprefix;
+
 enum {
 	SLong = 0,
 	SWord = 1,
@@ -147,7 +149,7 @@ emitcon(Con *con, FILE *f)
 	default:
 		diag("emit: invalid constant");
 	case CAddr:
-		fputs(con->label, f);
+		fprintf(f, "%s%s", con->local ? locprefix : symprefix, con->label);
 		if (con->bits.i)
 			fprintf(f, "%+"PRId64, con->bits.i);
 		break;
@@ -273,10 +275,10 @@ Next:
 			}
 			if (m->offset.type != CUndef)
 				emitcon(&m->offset, f);
-			if (req(m->base, R) && req(m->index, R))
-				break;
 			fputc('(', f);
-			if (!req(m->base, R))
+			if (req(m->base, R))
+				fprintf(f, "%%rip");
+			else
 				fprintf(f, "%%%s", regtoa(m->base.val, SLong));
 			if (!req(m->index, R))
 				fprintf(f, ", %%%s, %d",
@@ -396,6 +398,10 @@ emitins(Ins i, Fn *fn, FILE *f)
 		&& (val = fn->con[i.arg[0].val].bits.i) >= 0
 		&& val <= UINT32_MAX) {
 			emitf("movl %W0, %W=", &i, fn, f);
+		} else if (isreg(i.to)
+		&& rtype(i.arg[0]) == RCon
+		&& fn->con[i.arg[0].val].type == CAddr) {
+			emitf("lea%k %M0, %=", &i, fn, f);
 		} else if (!req(i.arg[0], i.to))
 			emitf("mov%k %0, %=", &i, fn, f);
 		break;
@@ -493,12 +499,11 @@ emitfn(Fn *fn, FILE *f)
 
 	fprintf(f,
 		".text\n"
-		".globl %s\n"
-		".type %s, @function\n"
-		"%s:\n"
+		".globl %s%s\n"
+		"%s%s:\n"
 		"\tpush %%rbp\n"
 		"\tmov %%rsp, %%rbp\n",
-		fn->name, fn->name, fn->name
+		symprefix, fn->name, symprefix, fn->name
 	);
 	fs = framesz(fn);
 	if (fs)
@@ -510,7 +515,7 @@ emitfn(Fn *fn, FILE *f)
 		}
 
 	for (b=fn->start; b; b=b->link) {
-		fprintf(f, ".L%s:\n", b->name);
+		fprintf(f, "%s%s:\n", locprefix, b->name);
 		for (i=b->ins; i!=&b->ins[b->nins]; i++)
 			emitins(*i, fn, f);
 		switch (b->jmp.type) {
@@ -527,7 +532,7 @@ emitfn(Fn *fn, FILE *f)
 			break;
 		case JJmp:
 			if (b->s1 != b->link)
-				fprintf(f, "\tjmp .L%s\n", b->s1->name);
+				fprintf(f, "\tjmp %s%s\n", locprefix, b->s1->name);
 			break;
 		default:
 			c = b->jmp.type - JXJc;
@@ -539,7 +544,7 @@ emitfn(Fn *fn, FILE *f)
 					s = b->s2;
 				} else
 					diag("emit: unhandled jump (1)");
-				fprintf(f, "\tj%s .L%s\n", ctoa[c], s->name);
+				fprintf(f, "\tj%s %s%s\n", ctoa[c], locprefix, s->name);
 				break;
 			}
 			diag("emit: unhandled jump (2)");
@@ -571,10 +576,9 @@ emitdat(Dat *d, FILE *f)
 		if (!align)
 			fprintf(f, ".align 8\n");
 		fprintf(f,
-			".globl %s\n"
-			".type %s, @object\n"
-			"%s:\n",
-			d->u.str, d->u.str, d->u.str
+			".globl %s%s\n"
+			"%s%s:\n",
+			symprefix, d->u.str, symprefix, d->u.str
 		);
 		break;
 	case DZ:
@@ -644,19 +648,19 @@ emitfin(FILE *f)
 	for (b=stash, i=0; b; b=b->link, i++)
 		if (b->wide)
 			fprintf(f,
-				".Lfp%d:\n"
+				"%sfp%d:\n"
 				"\t.quad %"PRId64
 				" /* %f */\n",
-				i, b->bits,
+				locprefix, i, b->bits,
 				*(double *)&b->bits
 			);
 	for (b=stash, i=0; b; b=b->link, i++)
 		if (!b->wide)
 			fprintf(f,
-				".Lfp%d:\n"
+				"%sfp%d:\n"
 				"\t.long %"PRId64
 				" /* %lf */\n",
-				i, b->bits & 0xffffffff,
+				locprefix, i, b->bits & 0xffffffff,
 				*(float *)&b->bits
 			);
 	while ((b=stash)) {
diff --git a/src/isel.c b/src/isel.c
index 48e29ef..2a55733 100644
--- a/src/isel.c
+++ b/src/isel.c
@@ -132,8 +132,9 @@ fixarg(Ref *r, int k, int phi, Fn *fn)
 		vgrow(&fn->mem, ++fn->nmem);
 		memset(&a, 0, sizeof a);
 		a.offset.type = CAddr;
+		a.offset.local = 1;
 		n = stashfp(fn->con[r0.val].bits.i, KWIDE(k));
-		sprintf(a.offset.label, ".Lfp%d", n);
+		sprintf(a.offset.label, "fp%d", n);
 		fn->mem[fn->nmem-1] = a;
 	}
 	else if (!phi && k == Kl && noimm(r0, fn)) {
diff --git a/src/main.c b/src/main.c
index b8cd7d6..c1664be 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,4 +1,5 @@
 #include "all.h"
+#include "config.h"
 #include <ctype.h>
 #include <getopt.h>
 
@@ -74,10 +75,11 @@ main(int ac, char *av[])
 {
 	FILE *inf;
 	char *f;
-	int c;
+	int c, asm;
 
+	asm = Defaultasm;
 	outf = stdout;
-	while ((c = getopt(ac, av, "d:o:")) != -1)
+	while ((c = getopt(ac, av, "d:o:G:")) != -1)
 		switch (c) {
 		case 'd':
 			for (; *optarg; optarg++)
@@ -90,11 +92,32 @@ main(int ac, char *av[])
 			if (strcmp(optarg, "-") != 0)
 				outf = fopen(optarg, "w");
 			break;
+		case 'G':
+			if (strcmp(optarg, "e") == 0)
+				asm = Gaself;
+			else if (strcmp(optarg, "m") == 0)
+				asm = Gasmacho;
+			else {
+				fprintf(stderr, "unknown gas flavor '%s'\n", optarg);
+				exit(1);
+			}
+			break;
 		default:
 			fprintf(stderr, "usage: %s [-d <flags>] [-o out] {file.ssa, -}\n", av[0]);
 			exit(1);
 		}
 
+	switch (asm) {
+	case Gaself:
+		locprefix = ".L";
+		symprefix = "";
+		break;
+	case Gasmacho:
+		locprefix = "L";
+		symprefix = "_";
+		break;
+	}
+
 	do {
 		f = av[optind];
 		if (!f || strcmp(f, "-") == 0) {
diff --git a/src/test/go.sh b/src/test/go.sh
index 35bf525..696f690 100755
--- a/src/test/go.sh
+++ b/src/test/go.sh
@@ -41,7 +41,7 @@ once() {
 
 	echo "$T... "
 
-	if ! ./qbe $T -o $ASM
+	if ! ./qbe -o $ASM $T
 	then
 		echo "[qbe fail]"
 		return 1