scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 5403b6a8b32780b34bf2abade344b91f995f5b5d
parent 41d8bab34e6ac22f9659b623328c6d4dd4e7b9a4
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 23 Oct 2024 16:16:02 +0200

build/cc2: Flat dir tree

This is a previous step to move forward a recursive Makefile.

Diffstat:
Msrc/cmd/scc-cc/cc2/Makefile | 12+++++-------
Rsrc/cmd/scc-cc/cc2/target/amd64-sysv/arch.h -> src/cmd/scc-cc/cc2/amd64-sysv/arch.h | 0
Asrc/cmd/scc-cc/cc2/amd64-sysv/cgen.c | 13+++++++++++++
Asrc/cmd/scc-cc/cc2/amd64-sysv/code.c | 214+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cmd/scc-cc/cc2/amd64-sysv/optm.c | 9+++++++++
Asrc/cmd/scc-cc/cc2/amd64-sysv/target.mk | 9+++++++++
Asrc/cmd/scc-cc/cc2/amd64-sysv/types.c | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cmd/scc-cc/cc2/arm64-sysv/types.c | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/cmd/scc-cc/cc2/deps.mk | 90++++++++++++++++++++++++++++++++++++++++----------------------------------------
Rsrc/cmd/scc-cc/cc2/target/i386-sysv/arch.h -> src/cmd/scc-cc/cc2/i386-sysv/arch.h | 0
Asrc/cmd/scc-cc/cc2/i386-sysv/cgen.c | 14++++++++++++++
Asrc/cmd/scc-cc/cc2/i386-sysv/code.c | 213+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cmd/scc-cc/cc2/i386-sysv/optm.c | 9+++++++++
Asrc/cmd/scc-cc/cc2/i386-sysv/target.mk | 9+++++++++
Asrc/cmd/scc-cc/cc2/i386-sysv/types.c | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rsrc/cmd/scc-cc/cc2/target/qbe/arch.h -> src/cmd/scc-cc/cc2/qbe/arch.h | 0
Asrc/cmd/scc-cc/cc2/qbe/cgen.c | 782+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cmd/scc-cc/cc2/qbe/code.c | 605+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cmd/scc-cc/cc2/qbe/optm.c | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cmd/scc-cc/cc2/qbe_amd64-sysv/target.mk | 9+++++++++
Asrc/cmd/scc-cc/cc2/qbe_arm64-sysv/target.mk | 9+++++++++
Dsrc/cmd/scc-cc/cc2/target/amd64-sysv/cgen.c | 13-------------
Dsrc/cmd/scc-cc/cc2/target/amd64-sysv/code.c | 214-------------------------------------------------------------------------------
Dsrc/cmd/scc-cc/cc2/target/amd64-sysv/optm.c | 9---------
Dsrc/cmd/scc-cc/cc2/target/amd64-sysv/target.mk | 9---------
Dsrc/cmd/scc-cc/cc2/target/amd64-sysv/types.c | 93-------------------------------------------------------------------------------
Dsrc/cmd/scc-cc/cc2/target/arm64-sysv/types.c | 93-------------------------------------------------------------------------------
Dsrc/cmd/scc-cc/cc2/target/i386-sysv/cgen.c | 14--------------
Dsrc/cmd/scc-cc/cc2/target/i386-sysv/code.c | 213-------------------------------------------------------------------------------
Dsrc/cmd/scc-cc/cc2/target/i386-sysv/optm.c | 9---------
Dsrc/cmd/scc-cc/cc2/target/i386-sysv/target.mk | 9---------
Dsrc/cmd/scc-cc/cc2/target/i386-sysv/types.c | 92-------------------------------------------------------------------------------
Dsrc/cmd/scc-cc/cc2/target/qbe/cgen.c | 782-------------------------------------------------------------------------------
Dsrc/cmd/scc-cc/cc2/target/qbe/code.c | 605-------------------------------------------------------------------------------
Dsrc/cmd/scc-cc/cc2/target/qbe/optm.c | 56--------------------------------------------------------
Dsrc/cmd/scc-cc/cc2/target/qbe_amd64-sysv/target.mk | 9---------
Dsrc/cmd/scc-cc/cc2/target/qbe_arm64-sysv/target.mk | 9---------
Dsrc/cmd/scc-cc/cc2/target/z80-scc/cgen.c | 159-------------------------------------------------------------------------------
Dsrc/cmd/scc-cc/cc2/target/z80-scc/code.c | 232-------------------------------------------------------------------------------
Dsrc/cmd/scc-cc/cc2/target/z80-scc/optm.c | 9---------
Dsrc/cmd/scc-cc/cc2/target/z80-scc/target.mk | 9---------
Dsrc/cmd/scc-cc/cc2/target/z80-scc/types.c | 92-------------------------------------------------------------------------------
Rsrc/cmd/scc-cc/cc2/target/z80-scc/arch.h -> src/cmd/scc-cc/cc2/z80-scc/arch.h | 0
Asrc/cmd/scc-cc/cc2/z80-scc/cgen.c | 159+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cmd/scc-cc/cc2/z80-scc/code.c | 232+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cmd/scc-cc/cc2/z80-scc/optm.c | 9+++++++++
Asrc/cmd/scc-cc/cc2/z80-scc/target.mk | 9+++++++++
Asrc/cmd/scc-cc/cc2/z80-scc/types.c | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
48 files changed, 2780 insertions(+), 2782 deletions(-)

diff --git a/src/cmd/scc-cc/cc2/Makefile b/src/cmd/scc-cc/cc2/Makefile @@ -3,8 +3,6 @@ PROJECTDIR = ../../../.. include $(PROJECTDIR)/scripts/rules.mk -MORE_CPPFLAGS = -I$(INCDIR)/$(STD) -I$(CMDDIR) -I. - OBJS =\ main.o\ parser.o\ @@ -33,9 +31,9 @@ error.h: cc2.h clean: rm -f target/*/*.o error.h -include target/amd64-sysv/target.mk -include target/i386-sysv/target.mk -include target/qbe_amd64-sysv/target.mk -include target/qbe_arm64-sysv/target.mk -include target/z80-scc/target.mk +include amd64-sysv/target.mk +include i386-sysv/target.mk +include qbe_amd64-sysv/target.mk +include qbe_arm64-sysv/target.mk +include z80-scc/target.mk include deps.mk diff --git a/src/cmd/scc-cc/cc2/target/amd64-sysv/arch.h b/src/cmd/scc-cc/cc2/amd64-sysv/arch.h diff --git a/src/cmd/scc-cc/cc2/amd64-sysv/cgen.c b/src/cmd/scc-cc/cc2/amd64-sysv/cgen.c @@ -0,0 +1,13 @@ +#include "arch.h" +#include <scc/scc.h> +#include "../cc2.h" + +Node * +cgen(Node *np) +{ +} + +Node * +sethi(Node *np) +{ +} diff --git a/src/cmd/scc-cc/cc2/amd64-sysv/code.c b/src/cmd/scc-cc/cc2/amd64-sysv/code.c @@ -0,0 +1,214 @@ +#include <stdio.h> +#include <stdlib.h> + +#include <scc/cstd.h> +#include <scc/scc.h> + +#include "arch.h" +#include "../cc2.h" + +enum segment { + CODESEG, + DATASEG, + BSSSEG, + NOSEG +}; + +static int curseg = NOSEG; + +static void +segment(int seg) +{ + static char *txt[] = { + [CODESEG] = "\t.text\n", + [DATASEG] = "\t.data\n", + [BSSSEG] = "\t.bss\n", + }; + + if (seg == curseg) + return; + fputs(txt[seg], stdout); + curseg = seg; +} + +static char * +symname(Symbol *sym) +{ + static char name[INTIDENTSIZ+1]; + + if (sym->name) { + switch (sym->kind) { + case SEXTRN: + case SGLOB: + case SPRIV: + return sym->name; + } + } + + sprintf(name, ".L%d", sym->numid); + + return name; +} + +static void +emitconst(Node *np) +{ + switch (np->type.size) { + case 1: + printf("%d", (int) np->u.i & 0xFF); + break; + case 2: + printf("%d", (int) np->u.i & 0xFFFF); + break; + case 4: + printf("%ld", (long) np->u.i & 0xFFFFFFFF); + break; + case 8: + printf("%lld", (long long) np->u.i & 0xFFFFFFFF); + break; + default: + abort(); + } +} + +static void +emittree(Node *np) +{ + if (!np) + return; + + switch (np->op) { + case OSTRING: + pprint(np->u.s); + free(np->u.s); + np->u.s = NULL; + break; + case OCONST: + emitconst(np); + break; + case OADDR: + emittree(np->left); + break; + case OMEM: + fputs(symname(np->u.sym), stdout); + break; + default: + emittree(np->left); + printf(" %c ", np->op); + emittree(np->right); + break; + } +} +static void +size2asm(Type *tp) +{ + char *s; + + if (tp->flags & STRF) { + s = "\t.ascii\t"; + } else { + switch (tp->size) { + case 1: + s = "\t.byte\t"; + break; + case 2: + s = "\t.short\t"; + break; + case 4: + s = "\t.long\t"; + break; + case 8: + s = "\t.quad\t"; + break; + default: + s = "\t.space\t%lu,"; + break; + } + } + printf(s, tp->size); +} + + +void +data(Node *np) +{ + size2asm(&np->type); + emittree(np); + putchar('\n'); +} + +static void +label(Symbol *sym) +{ + int seg; + char *name = symname(sym); + Type *tp = &sym->type; + + if (sym->type.flags & FUNF) + seg = CODESEG; + else if (sym->type.flags & INITF) + seg = DATASEG; + else + seg = BSSSEG; + segment(seg); + + switch (sym->kind) { + case SEXTRN: + printf("\t.extern\t%s\n", name); + case SLOCAL: + return; + case SGLOB: + printf("\t.global\t%s\n", name); + if (seg == BSSSEG) + printf("\t.comm\t%s,%lu\n", name, tp->size); + break; + } + if (sym->type.align != 1) + printf("\t.align\t%lu\n", sym->type.align ); + printf("%s:\n", name); +} + +void +defglobal(Symbol *sym) +{ + label(sym); + if (sym->kind == SEXTRN || (sym->type.flags & INITF)) + return; + size2asm(&sym->type); + puts("0"); +} + +void +deftype(Type *tp) +{ +} + +void +defvar(Symbol *sym) +{ +} + +void +defpar(Symbol *sym) +{ +} + +void +newfun(void) +{ +} + +void +writeout(void) +{ +} + +void +endinit(void) +{ +} + +void +getbblocks(void) +{ +} diff --git a/src/cmd/scc-cc/cc2/amd64-sysv/optm.c b/src/cmd/scc-cc/cc2/amd64-sysv/optm.c @@ -0,0 +1,9 @@ +#include <scc/scc.h> + +#include "../cc2.h" + +Node * +optm_dep(Node *np) +{ + return np; +} diff --git a/src/cmd/scc-cc/cc2/amd64-sysv/target.mk b/src/cmd/scc-cc/cc2/amd64-sysv/target.mk @@ -0,0 +1,9 @@ +OBJ-amd64-sysv = $(OBJS) \ + amd64-sysv/cgen.o \ + amd64-sysv/optm.o \ + amd64-sysv/code.o \ + amd64-sysv/types.o + +cc2-amd64-sysv: $(LIBSCC) $(OBJ-amd64-sysv) + $(CC) $(PROJ_LDFLAGS) $(OBJ-amd64-sysv) -lscc $(PROJ_LDLIBS) -o $@ + cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-cc/cc2/amd64-sysv/types.c b/src/cmd/scc-cc/cc2/amd64-sysv/types.c @@ -0,0 +1,93 @@ +#include <scc/scc.h> + +#include "../cc2.h" + + +Type int8type = { + .flags = SIGNF | INTF, + .size = 1, + .align = 1 +}; + +Type int16type = { + .flags = SIGNF | INTF, + .size = 2, + .align = 2 +}; + +Type int32type = { + .flags = SIGNF | INTF, + .size = 4, + .align = 4 +}; + +Type int64type = { + .flags = SIGNF | INTF, + .size = 8, + .align = 8 +}; + +Type uint8type = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type uint16type = { + .flags = INTF, + .size = 2, + .align = 2 +}; + +Type uint32type = { + .flags = INTF, + .size = 4, + .align = 4 +}; + +Type uint64type = { + .flags = INTF, + .size = 8, + .align = 8 +}; + +Type ptrtype = { + .flags = INTF, + .size = 8, + .align = 8 +}; + +Type booltype = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type float32type = { + .flags = FLOATF, + .size = 4, + .align = 4 +}; + +Type float64type = { + .flags = FLOATF, + .size = 8, + .align = 8 +}; + +Type float80type = { + .flags = FLOATF, + .size = 16, + .align = 16 +}; + +Type voidtype = { + .size = 0, + .align = 0 +}; + +Type arg_type = { + .flags = ARRF, + .size = 24, + .align = 8 +}; diff --git a/src/cmd/scc-cc/cc2/arm64-sysv/types.c b/src/cmd/scc-cc/cc2/arm64-sysv/types.c @@ -0,0 +1,93 @@ +#include <scc/scc.h> + +#include "../cc2.h" + + +Type int8type = { + .flags = SIGNF | INTF, + .size = 1, + .align = 1 +}; + +Type int16type = { + .flags = SIGNF | INTF, + .size = 2, + .align = 2 +}; + +Type int32type = { + .flags = SIGNF | INTF, + .size = 4, + .align = 4 +}; + +Type int64type = { + .flags = SIGNF | INTF, + .size = 8, + .align = 8 +}; + +Type uint8type = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type uint16type = { + .flags = INTF, + .size = 2, + .align = 2 +}; + +Type uint32type = { + .flags = INTF, + .size = 4, + .align = 4 +}; + +Type uint64type = { + .flags = INTF, + .size = 8, + .align = 8 +}; + +Type ptrtype = { + .flags = INTF, + .size = 8, + .align = 8 +}; + +Type booltype = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type float32type = { + .flags = FLOATF, + .size = 4, + .align = 4 +}; + +Type float64type = { + .flags = FLOATF, + .size = 8, + .align = 8 +}; + +Type float80type = { + .flags = FLOATF, + .size = 16, + .align = 16 +}; + +Type voidtype = { + .size = 0, + .align = 0 +}; + +Type arg_type = { + .flags = ARRF, + .size = 24, + .align = 8 +}; diff --git a/src/cmd/scc-cc/cc2/deps.mk b/src/cmd/scc-cc/cc2/deps.mk @@ -16,48 +16,48 @@ peep.o: $(INCDIR)/bits/scc/scc.h peep.o: cc2.h symbol.o: $(INCDIR)/bits/scc/scc.h symbol.o: cc2.h -target/amd64-sysv/cgen.o: $(INCDIR)/bits/scc/scc.h -target/amd64-sysv/cgen.o: target/amd64-sysv/../../cc2.h -target/amd64-sysv/cgen.o: target/amd64-sysv/arch.h -target/amd64-sysv/code.o: $(INCDIR)/bits/scc/cstd.h -target/amd64-sysv/code.o: $(INCDIR)/bits/scc/scc.h -target/amd64-sysv/code.o: target/amd64-sysv/../../cc2.h -target/amd64-sysv/code.o: target/amd64-sysv/arch.h -target/amd64-sysv/optm.o: $(INCDIR)/bits/scc/scc.h -target/amd64-sysv/optm.o: target/amd64-sysv/../../cc2.h -target/amd64-sysv/types.o: $(INCDIR)/bits/scc/scc.h -target/amd64-sysv/types.o: target/amd64-sysv/../../cc2.h -target/arm64-sysv/types.o: $(INCDIR)/bits/scc/scc.h -target/arm64-sysv/types.o: target/arm64-sysv/../../cc2.h -target/i386-sysv/cgen.o: $(INCDIR)/bits/scc/scc.h -target/i386-sysv/cgen.o: target/i386-sysv/../../cc2.h -target/i386-sysv/cgen.o: target/i386-sysv/arch.h -target/i386-sysv/code.o: $(INCDIR)/bits/scc/cstd.h -target/i386-sysv/code.o: $(INCDIR)/bits/scc/scc.h -target/i386-sysv/code.o: target/i386-sysv/../../cc2.h -target/i386-sysv/code.o: target/i386-sysv/arch.h -target/i386-sysv/optm.o: $(INCDIR)/bits/scc/scc.h -target/i386-sysv/optm.o: target/i386-sysv/../../cc2.h -target/i386-sysv/types.o: $(INCDIR)/bits/scc/scc.h -target/i386-sysv/types.o: target/i386-sysv/../../cc2.h -target/qbe/cgen.o: $(INCDIR)/bits/scc/cstd.h -target/qbe/cgen.o: $(INCDIR)/bits/scc/scc.h -target/qbe/cgen.o: target/qbe/../../cc2.h -target/qbe/cgen.o: target/qbe/arch.h -target/qbe/code.o: $(INCDIR)/bits/scc/cstd.h -target/qbe/code.o: $(INCDIR)/bits/scc/scc.h -target/qbe/code.o: target/qbe/../../cc2.h -target/qbe/code.o: target/qbe/arch.h -target/qbe/optm.o: $(INCDIR)/bits/scc/scc.h -target/qbe/optm.o: target/qbe/../../cc2.h -target/z80-scc/cgen.o: $(INCDIR)/bits/scc/scc.h -target/z80-scc/cgen.o: target/z80-scc/../../cc2.h -target/z80-scc/cgen.o: target/z80-scc/arch.h -target/z80-scc/code.o: $(INCDIR)/bits/scc/cstd.h -target/z80-scc/code.o: $(INCDIR)/bits/scc/scc.h -target/z80-scc/code.o: target/z80-scc/../../cc2.h -target/z80-scc/code.o: target/z80-scc/arch.h -target/z80-scc/optm.o: $(INCDIR)/bits/scc/scc.h -target/z80-scc/optm.o: target/z80-scc/../../cc2.h -target/z80-scc/types.o: $(INCDIR)/bits/scc/scc.h -target/z80-scc/types.o: target/z80-scc/../../cc2.h +amd64-sysv/cgen.o: $(INCDIR)/bits/scc/scc.h +amd64-sysv/cgen.o: amd64-sysv/../cc2.h +amd64-sysv/cgen.o: amd64-sysv/arch.h +amd64-sysv/code.o: $(INCDIR)/bits/scc/cstd.h +amd64-sysv/code.o: $(INCDIR)/bits/scc/scc.h +amd64-sysv/code.o: amd64-sysv/../cc2.h +amd64-sysv/code.o: amd64-sysv/arch.h +amd64-sysv/optm.o: $(INCDIR)/bits/scc/scc.h +amd64-sysv/optm.o: amd64-sysv/../cc2.h +amd64-sysv/types.o: $(INCDIR)/bits/scc/scc.h +amd64-sysv/types.o: amd64-sysv/../cc2.h +arm64-sysv/types.o: $(INCDIR)/bits/scc/scc.h +arm64-sysv/types.o: arm64-sysv/../cc2.h +i386-sysv/cgen.o: $(INCDIR)/bits/scc/scc.h +i386-sysv/cgen.o: i386-sysv/../cc2.h +i386-sysv/cgen.o: i386-sysv/arch.h +i386-sysv/code.o: $(INCDIR)/bits/scc/cstd.h +i386-sysv/code.o: $(INCDIR)/bits/scc/scc.h +i386-sysv/code.o: i386-sysv/../cc2.h +i386-sysv/code.o: i386-sysv/arch.h +i386-sysv/optm.o: $(INCDIR)/bits/scc/scc.h +i386-sysv/optm.o: i386-sysv/../cc2.h +i386-sysv/types.o: $(INCDIR)/bits/scc/scc.h +i386-sysv/types.o: i386-sysv/../cc2.h +qbe/cgen.o: $(INCDIR)/bits/scc/cstd.h +qbe/cgen.o: $(INCDIR)/bits/scc/scc.h +qbe/cgen.o: qbe/../cc2.h +qbe/cgen.o: qbe/arch.h +qbe/code.o: $(INCDIR)/bits/scc/cstd.h +qbe/code.o: $(INCDIR)/bits/scc/scc.h +qbe/code.o: qbe/../cc2.h +qbe/code.o: qbe/arch.h +qbe/optm.o: $(INCDIR)/bits/scc/scc.h +qbe/optm.o: qbe/../cc2.h +z80-scc/cgen.o: $(INCDIR)/bits/scc/scc.h +z80-scc/cgen.o: z80-scc/../cc2.h +z80-scc/cgen.o: z80-scc/arch.h +z80-scc/code.o: $(INCDIR)/bits/scc/cstd.h +z80-scc/code.o: $(INCDIR)/bits/scc/scc.h +z80-scc/code.o: z80-scc/../cc2.h +z80-scc/code.o: z80-scc/arch.h +z80-scc/optm.o: $(INCDIR)/bits/scc/scc.h +z80-scc/optm.o: z80-scc/../cc2.h +z80-scc/types.o: $(INCDIR)/bits/scc/scc.h +z80-scc/types.o: z80-scc/../cc2.h diff --git a/src/cmd/scc-cc/cc2/target/i386-sysv/arch.h b/src/cmd/scc-cc/cc2/i386-sysv/arch.h diff --git a/src/cmd/scc-cc/cc2/i386-sysv/cgen.c b/src/cmd/scc-cc/cc2/i386-sysv/cgen.c @@ -0,0 +1,14 @@ +#include <scc/scc.h> + +#include "arch.h" +#include "../cc2.h" + +Node * +cgen(Node *np) +{ +} + +Node * +sethi(Node *np) +{ +} diff --git a/src/cmd/scc-cc/cc2/i386-sysv/code.c b/src/cmd/scc-cc/cc2/i386-sysv/code.c @@ -0,0 +1,213 @@ +#include <stdio.h> +#include <stdlib.h> + +#include <scc/cstd.h> +#include <scc/scc.h> + +#include "arch.h" +#include "../cc2.h" + +enum segment { + CODESEG, + DATASEG, + BSSSEG, + NOSEG +}; + +static int curseg = NOSEG; + +static void +segment(int seg) +{ + static char *txt[] = { + [CODESEG] = "\t.text\n", + [DATASEG] = "\t.data\n", + [BSSSEG] = "\t.bss\n", + }; + + if (seg == curseg) + return; + fputs(txt[seg], stdout); + curseg = seg; +} + +static char * +symname(Symbol *sym) +{ + static char name[INTIDENTSIZ+1]; + + if (sym->name) { + switch (sym->kind) { + case SEXTRN: + case SGLOB: + case SPRIV: + return sym->name; + } + } + + sprintf(name, ".L%d", sym->numid); + + return name; +} + +static void +emitconst(Node *np) +{ + switch (np->type.size) { + case 1: + printf("%d", (int) np->u.i & 0xFF); + break; + case 2: + printf("%d", (int) np->u.i & 0xFFFF); + break; + case 4: + printf("%ld", (long) np->u.i & 0xFFFFFFFF); + break; + case 8: + printf("%lld", (long long) np->u.i & 0xFFFFFFFF); + break; + default: + abort(); + } +} + +static void +emittree(Node *np) +{ + if (!np) + return; + + switch (np->op) { + case OSTRING: + pprint(np->u.s); + free(np->u.s); + np->u.s = NULL; + break; + case OCONST: + emitconst(np); + break; + case OADDR: + emittree(np->left); + break; + case OMEM: + fputs(symname(np->u.sym), stdout); + break; + default: + emittree(np->left); + printf(" %c ", np->op); + emittree(np->right); + break; + } +} +static void +size2asm(Type *tp) +{ + char *s; + + if (tp->flags & STRF) { + s = "\t.ascii\t"; + } else { + switch (tp->size) { + case 1: + s = "\t.byte\t"; + break; + case 2: + s = "\t.short\t"; + break; + case 4: + s = "\t.long\t"; + break; + case 8: + s = "\t.quad\t"; + break; + default: + s = "\t.space\t%lu,"; + break; + } + } + printf(s, tp->size); +} + +void +data(Node *np) +{ + size2asm(&np->type); + emittree(np); + putchar('\n'); +} + +static void +label(Symbol *sym) +{ + int seg; + char *name = symname(sym); + Type *tp = &sym->type; + + if (sym->type.flags & FUNF) + seg = CODESEG; + else if (sym->type.flags & INITF) + seg = DATASEG; + else + seg = BSSSEG; + segment(seg); + + switch (sym->kind) { + case SEXTRN: + printf("\t.extern\t%s\n", name); + case SLOCAL: + return; + case SGLOB: + printf("\t.global\t%s\n", name); + if (seg == BSSSEG) + printf("\t.comm\t%s,%lu\n", name, tp->size); + break; + } + if (sym->type.align != 1) + printf("\t.align\t%lu\n", sym->type.align ); + printf("%s:\n", name); +} + +void +defglobal(Symbol *sym) +{ + label(sym); + if (sym->kind == SEXTRN || (sym->type.flags & INITF)) + return; + size2asm(&sym->type); + puts("0"); +} + +void +deftype(Type *tp) +{ +} + +void +defpar(Symbol *sym) +{ +} + +void +defvar(Symbol *sym) +{ +} + +void +newfun(void) +{ +} + +void +writeout(void) +{ +} + +void +endinit(void) +{ +} + +void +getbblocks(void) +{ +} diff --git a/src/cmd/scc-cc/cc2/i386-sysv/optm.c b/src/cmd/scc-cc/cc2/i386-sysv/optm.c @@ -0,0 +1,9 @@ +#include <scc/scc.h> + +#include "../cc2.h" + +Node * +optm_dep(Node *np) +{ + return np; +} diff --git a/src/cmd/scc-cc/cc2/i386-sysv/target.mk b/src/cmd/scc-cc/cc2/i386-sysv/target.mk @@ -0,0 +1,9 @@ +OBJ-i386-sysv = $(OBJS) \ + i386-sysv/cgen.o \ + i386-sysv/optm.o \ + i386-sysv/code.o \ + i386-sysv/types.o + +cc2-i386-sysv: $(LIBSCC) $(OBJ-i386-sysv) + $(CC) $(PROJ_LDFLAGS) $(OBJ-i386-sysv) -lscc $(PROJ_LDLIBS) -o $@ + cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-cc/cc2/i386-sysv/types.c b/src/cmd/scc-cc/cc2/i386-sysv/types.c @@ -0,0 +1,92 @@ +#include <scc/scc.h> + +#include "../cc2.h" + + +Type int8type = { + .flags = SIGNF | INTF, + .size = 1, + .align = 1 +}; + +Type int16type = { + .flags = SIGNF | INTF, + .size = 2, + .align = 2 +}; + +Type int32type = { + .flags = SIGNF | INTF, + .size = 4, + .align = 4 +}; + +Type int64type = { + .flags = SIGNF | INTF, + .size = 8, + .align = 4 +}; + +Type uint8type = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type uint16type = { + .flags = INTF, + .size = 2, + .align = 2 +}; + +Type uint32type = { + .flags = INTF, + .size = 4, + .align = 2 +}; + +Type uint64type = { + .flags = INTF, + .size = 8, + .align = 4 +}; + +Type ptrtype = { + .flags = INTF, + .size = 4, + .align = 4 +}; + +Type booltype = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type float32type = { + .flags = FLOATF, + .size = 4, + .align = 4 +}; + +Type float64type = { + .flags = FLOATF, + .size = 8, + .align = 4 +}; + +Type float80type = { + .flags = FLOATF, + .size = 12, + .align = 4 +}; + +Type voidtype = { + .size = 0, + .align = 0 +}; + +Type arg_type = { + .size = 4, + .align = 4 +}; diff --git a/src/cmd/scc-cc/cc2/target/qbe/arch.h b/src/cmd/scc-cc/cc2/qbe/arch.h diff --git a/src/cmd/scc-cc/cc2/qbe/cgen.c b/src/cmd/scc-cc/cc2/qbe/cgen.c @@ -0,0 +1,782 @@ +#include <assert.h> +#include <stdlib.h> + +#include <scc/cstd.h> +#include <scc/scc.h> + +#include "arch.h" +#include "../cc2.h" + +#define I1BYTES 0 +#define I2BYTES 1 +#define I4BYTES 2 +#define I8BYTES 3 + +static unsigned char opasmw[][2] = { + [OADD] = {ASADDW, ASADDW}, + [OSUB] = {ASSUBW, ASSUBW}, + [OMUL] = {ASMULW, ASMULW}, + [OMOD] = {ASMODW, ASUMODW}, + [ODIV] = {ASDIVW, ASUDIVW}, + [OSHL] = {ASSHLW, ASSHLW}, + [OSHR] = {ASSHRW, ASUSHRW}, + [OLT] = {ASLTW, ASULTW}, + [OGT] = {ASGTW, ASUGTW}, + [OLE] = {ASLEW, ASULEW}, + [OGE] = {ASGEW, ASUGEW}, + [OEQ] = {ASEQW, ASEQW}, + [ONE] = {ASNEW, ASNEW}, + [OBAND] = {ASBANDW, ASBANDW}, + [OBOR] = {ASBORW, ASBORW}, + [OBXOR] = {ASBXORW, ASBXORW}, +}; + +static unsigned char opasml[][2] = { + [OADD] = {ASADDL, ASADDL}, + [OSUB] = {ASSUBL, ASSUBL}, + [OMUL] = {ASMULL, ASMULL}, + [OMOD] = {ASMODL, ASUMODL}, + [ODIV] = {ASDIVL, ASUDIVL}, + [OSHL] = {ASSHLL, ASSHLL}, + [OSHR] = {ASSHRL, ASUSHRL}, + [OLT] = {ASLTL, ASULTL}, + [OGT] = {ASGTL, ASUGTL}, + [OLE] = {ASLEL, ASULEL}, + [OGE] = {ASGEL, ASUGEL}, + [OEQ] = {ASEQL, ASEQL}, + [ONE] = {ASNEL, ASNEL}, + [OBAND] = {ASBANDL, ASBANDL}, + [OBOR] = {ASBORL, ASBORL}, + [OBXOR] = {ASBXORL, ASBXORL}, +}; + +static unsigned char opasms[][2] = { + [OADD] = {ASADDS, ASADDS}, + [OSUB] = {ASSUBS, ASSUBS}, + [OMUL] = {ASMULS, ASMULS}, + [ODIV] = {ASDIVS, ASDIVS}, + [OLT] = {ASLTS, ASLTS}, + [OGT] = {ASGTS, ASGTS}, + [OLE] = {ASLES, ASLES}, + [OGE] = {ASGES, ASGES}, + [OEQ] = {ASEQS, ASEQS}, + [ONE] = {ASNES, ASNES}, +}; + +static unsigned char opasmd[][2] = { + [OADD] = {ASADDD, ASADDD}, + [OSUB] = {ASSUBD, ASSUBD}, + [OMUL] = {ASMULD, ASMULD}, + [ODIV] = {ASDIVD, ASDIVD}, + [OLT] = {ASLTD, ASLTD}, + [OGT] = {ASGTD, ASGTD}, + [OLE] = {ASLED, ASLED}, + [OGE] = {ASGED, ASGED}, + [OEQ] = {ASEQD, ASEQD}, + [ONE] = {ASNED, ASNED}, +}; + +static unsigned char (*opbin[][2])[2] = { + {opasmw, opasml}, + {opasms, opasmd}, +}; + +static unsigned char i2i_conv[4][4][2] = { + [I1BYTES] = { + [I4BYTES] = {ASEXTBW, ASUEXTBW}, + [I8BYTES] = {ASEXTBL, ASUEXTBL}, + }, + [I2BYTES] = { + [I4BYTES] = {ASEXTHW, ASUEXTHW}, + [I8BYTES] = {ASEXTHL, ASUEXTHL}, + }, + [I4BYTES] = { + [I8BYTES] = {ASEXTWL, ASUEXTWL}, + } +}; + +static unsigned char f2i_conv[4][4][2] = { + [I4BYTES] = { + [I4BYTES] = {ASSTOW, ASSTOUW}, + [I8BYTES] = {ASSTOL, ASDTOUL}, + }, + [I8BYTES] = { + [I4BYTES] = {ASDTOW, ASDTOUW}, + [I8BYTES] = {ASDTOL, ASDTOUL}, + } +}; + +static unsigned char i2f_conv[4][4][2] = { + [I4BYTES] = { + [I4BYTES] = {ASSWTOS, ASUWTOS}, + [I8BYTES] = {ASSWTOD, ASUWTOD}, + }, + [I8BYTES] = { + [I4BYTES] = {ASSLTOS, ASULTOS}, + [I8BYTES] = {ASSLTOD, ASULTOD}, + } +}; + +extern Type int32type, uint32type, ptrtype; + +/* + * This is strongly influenced by + * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps) + * calculate addresability as follows + * AUTO => 11 value+fp + * REG => 11 reg + * STATIC => 11 (value) + * CONST => 11 $value + * These values of addressability are not used in the code generation. + * They are only used to calculate the Sethi-Ullman numbers. Since + * QBE is AMD64 targered we could do a better job there, and try to + * detect some of the complex addressing modes of these processors. + */ +static Node * +complex(Node *np) +{ + Node *lp = np->left, *rp = np->right; + + if (np->address > 10) + return np; + if (lp) + np->complex = lp->complex; + if (rp) { + int d = np->complex - rp->complex; + + if (d == 0) + ++np->complex; + else if (d < 0) + np->complex = rp->complex; + } + if (np->complex == 0) + ++np->complex; + + return np; +} + +Node * +sethi(Node *np) +{ + Node *lp, *rp; + + if (!np) + return np; + + np->complex = 0; + np->address = 0; + lp = np->left; + rp = np->right; + + switch (np->op) { + case OAUTO: + case OREG: + case OMEM: + case OCONST: + np->address = 11; + break; + case OASSIG: + assert(lp->op != OCAST); + goto binary; + case OCPL: + assert(np->type.flags & INTF); + np->op = OBXOR; + rp = constnode(NULL, ~(TUINT) 0, &np->type); + goto binary; + case OSNEG: + np->op = OSUB; + rp = lp; + lp = constnode(NULL, 0, &np->type); + if ((np->type.flags & INTF) == 0) + lp->u.f = 0.0; + default: + binary: + lp = sethi(lp); + rp = sethi(rp); + break; + } + np->left = lp; + np->right = rp; + + return complex(np); +} + +static int +bytes2idx(int nbytes) +{ + if (nbytes== 1) + return I1BYTES; + else if (nbytes == 2) + return I2BYTES; + else if (nbytes == 4) + return I4BYTES; + else if (nbytes == 8) + return I8BYTES; + else + abort(); +} + +static Node * +load(Type *tp, Node *np) +{ + int op; + Node *new; + int flags = tp->flags; + + if (flags & (AGGRF|FUNF|ARRF|PTRF)) + return np; + + switch (tp->size) { + case 1: + op = ASLDSB; + break; + case 2: + op = ASLDSH; + break; + case 4: + op = (flags & FLOATF) ? ASLDS : ASLDSW; + break; + case 8: + op = (flags & FLOATF) ? ASLDD : ASLDL; + break; + default: + abort(); + } + /* + * unsigned version of operations are always +1 the + * signed version + */ + if ((flags & (INTF|SIGNF)) == INTF && tp->size < 8) + ++op; + + new = tmpnode(tp); + code(op, new, np, NULL); + + return new; +} + +static Node *rhs(Node *np); + +static Node * +cast(Type *td, Node *np) +{ + Type *ts; + Node *tmp; + int op, d_isint, s_isint, sidx, didx, sign; + + ts = &np->type; + d_isint = (td->flags & INTF) != 0; + s_isint = (ts->flags & INTF) != 0; + + sidx = bytes2idx(ts->size); + didx = bytes2idx(td->size); + + sign = (ts->flags & SIGNF) == 0; + + if (d_isint && s_isint) { + /* conversion from int to int */ + if (didx < I4BYTES) + didx = bytes2idx(4); + + if (didx <= sidx) { + np->type = *td; + return np; + } + + op = i2i_conv[sidx][didx][sign]; + } else if (d_isint) { + /* conversion from float to int */ + if (didx < I4BYTES) + didx = bytes2idx(4); + + op = f2i_conv[sidx][didx][sign]; + } else if (s_isint) { + /* conversion from int to float */ + if (sidx == I1BYTES || sidx == I2BYTES) { + ts = (ts->flags&SIGNF) ? &int32type : &uint32type; + np = cast(ts, np); + } + op = i2f_conv[sidx][didx][sign]; + } else { + /* conversion from float to float */ + op = (didx == I4BYTES) ? ASEXTS : ASTRUNCD; + } + + assert(op != 0); + tmp = tmpnode(td); + code(op, tmp, np, NULL); + + return tmp; +} + +static Node * +call(Node *np, Node *fun) +{ + int n, op; + Type *tp; + Node **q, *tmp, *p, *pars[NR_FUNPARAM]; + + for (n = 0, p = np->right; p; p = p->right) + pars[n++] = rhs(p->left); + + tp = &np->type; + tmp = tmpnode(tp); + code(ASCALL, tmp, fun, NULL); + + for (q = pars; q < &pars[n]; ++q) { + op = (q == &pars[n-1]) ? ASPARE : ASPAR; + code(op, NULL, *q, tmpnode(&(*q)->type)); + } + code((np->op == OCALL) ? ASCALLE : ASCALLEX, NULL, NULL, NULL); + + return tmp; +} + +static Node * +copy(Type *tp, Node *to, Node *from) +{ + int op; + + switch (tp->size) { + case 0: + return from; + case 1: + op = ASCOPYB; + break; + case 2: + op = ASCOPYH; + break; + case 4: + op = (tp->flags & FLOATF) ? ASCOPYS : ASCOPYW; + break; + case 8: + op = (tp->flags & FLOATF) ? ASCOPYD : ASCOPYL; + break; + default: + abort(); + } + code(op, to, from, NULL); + return from; +} + +static Node * +field(Node *np, int islhs) +{ + Node *tmp, *addr; + TUINT offset = np->right->u.sym->u.off; + + addr = rhs(np->left); + tmp = node(OADD); + tmp->type = ptrtype; + tmp->left = addr; + tmp->right = constnode(NULL, offset, &ptrtype); + addr = rhs(tmp); + + if (!islhs) + addr = load(&np->type, addr); + return addr; +} + +static Node * +lhs(Node *np) +{ + switch (np->op) { + case OREG: + case OMEM: + case OAUTO: + return np; + case OPTR: + return rhs(np->left); + case OFIELD: + return field(np, 1); + default: + abort(); + } +} + +static void +bool(Node *np, Symbol *true, Symbol *false) +{ + Node *l = np->left, *r = np->right; + Node ret, ifyes, ifno; + Symbol *label; + + switch (np->op) { + case ONEG: + bool(l, false, true); + break; + case OAND: + label = newlabel(); + bool(l, label, false); + setlabel(label); + bool(r, true, false); + break; + case OOR: + label = newlabel(); + bool(l, true, label); + setlabel(label); + bool(r, true, false); + break; + default: + label2node(&ifyes, true); + label2node(&ifno, false); + code(ASBRANCH, rhs(np), &ifyes, &ifno); + break; + } +} + +static Node * +ternary(Node *np) +{ + Node ifyes, ifno, phi, *colon, *tmp; + + tmp = tmpnode(&np->type); + label2node(&ifyes, NULL); + label2node(&ifno, NULL); + label2node(&phi, NULL); + + colon = np->right; + code(ASBRANCH, rhs(np->left), &ifyes, &ifno); + + setlabel(ifyes.u.sym); + copy(&tmp->type, tmp, rhs(colon->left)); + code(ASJMP, NULL, &phi, NULL); + + setlabel(ifno.u.sym); + copy(&tmp->type, tmp, rhs(colon->right)); + setlabel(phi.u.sym); + + return tmp; +} + +static Node * +function(void) +{ + Node aux; + Symbol *p; + + /* allocate stack space for parameters */ + for (p = locals; p; p = p->next) { + if ((p->type.flags & PARF) == 0) + continue; + if ((p->type.flags & AGGRF) != 0) + continue; + code(ASALLOC, label2node(&aux, p), NULL, NULL); + } + + /* allocate stack space for local variables) */ + for (p = locals; p; p = p->next) { + if ((p->type.flags & PARF) != 0) + continue; + if (p->kind != SAUTO || p->id == TMPSYM) + continue; + code(ASALLOC, label2node(&aux, p), NULL, NULL); + } + + /* store formal parameters in parameters */ + for (p = locals; p; p = p->next) { + if ((p->type.flags & PARF) == 0) + continue; + if ((p->type.flags & AGGRF) != 0) + continue; + if ((p->type.flags & (ARRF|AGGRF)) == 0) + code(ASFORM, label2node(&aux, p), NULL, NULL); + } + return NULL; +} + +static void +swtch_if(Node *idx) +{ + Node aux1, aux2, *np; + Symbol *deflabel = NULL; + + for (;;) { + np = delstmt(); + setlabel(np->label); + + switch (np->op) { + case OESWITCH: + if (!deflabel) + deflabel = np->u.sym; + aux1.op = OJMP; + aux1.label = NULL; + aux1.u.sym = deflabel; + cgen(&aux1); + return; + case OCASE: + aux1 = *np; + aux1.op = OBRANCH; + aux1.label = NULL; + aux1.left = &aux2; + + aux2.op = OEQ; + aux2.type = idx->type; + aux2.left = np->left; + aux2.right = idx; + + cgen(&aux1); + break; + case ODEFAULT: + deflabel = np->u.sym; + break; + default: + abort(); + } + } +} + +static int +assignop(Type *tp) +{ + int flags = tp->flags; + + if (flags & (AGGRF|FUNF|ARRF)) + return ASSTM; + + switch (tp->size) { + case 1: + return ASSTB; + case 2: + return ASSTH; + case 4: + return (tp->flags & FLOATF) ? ASSTS : ASSTW; + case 8: + return (tp->flags & FLOATF) ? ASSTD : ASSTL; + default: + abort(); + } +} + +static void +rhs_rhs(Node **lp, Node **rp) +{ + Node *l = *lp, *r = *rp; + + if (l->complex >= r->complex) { + l = rhs(l); + r = rhs(r); + } else { + r = rhs(r); + l = rhs(l); + } + + *lp = l, *rp = r; +} + +static void +lhs_rhs(Node **lp, Node **rp) +{ + Node *l = *lp, *r = *rp; + + if (l->complex >= r->complex) { + l = lhs(l); + r = rhs(r); + } else { + r = rhs(r); + l = lhs(l); + } + + *lp = l, *rp = r; +} + +static Node * +assign(Node *np) +{ + Node *ret, aux; + Node *l = np->left, *r = np->right; + int op; + + switch (np->u.subop) { + break; + case OINC: + op = OADD; + goto post_oper; + case ODEC: + op = OSUB; + post_oper: + lhs_rhs(&l, &r); + ret = load(&l->type, l); + aux.op = op; + aux.left = ret; + aux.right = r; + aux.type = np->type; + r = rhs(sethi(&aux)); + break; + default: + /* assign abbreviation */ + assert(l->type.size == r->type.size); + if (r->type.size < 4) { + lhs_rhs(&l, &r); + aux.op = np->u.subop; + aux.left = load(&r->type, l); + aux.right = r; + aux.type = int32type; + aux.address = np->address; + ret = r = sethi(rhs(&aux)); + break; + } + + aux.op = np->u.subop; + aux.left = l; + aux.right = r; + aux.type = np->type; + aux.address = np->address; + r = sethi(&aux); + case 0: + lhs_rhs(&l, &r); + ret = r; + break; + } + + code(assignop(&np->type), l, r, NULL); + return ret; +} + +static Node * +rhs(Node *np) +{ + Node *tmp, aux1, aux2; + Node *phi, *l = np->left, *r = np->right; + Type *tp; + int sign, size, isfloat, op; + Symbol *true, *false; + + tp = &np->type; + + switch (np->op) { + case OBFUN: + return function(); + case ONOP: + case OBLOOP: + case OELOOP: + case OEFUN: + return NULL; + case OTMP: + case OCONST: + return np; + case OMEM: + case OREG: + case OAUTO: + return load(tp, np); + case ONEG: + case OAND: + case OOR: + true = newlabel(); + false = newlabel(); + phi = label2node(&aux1, NULL); + tmp = tmpnode(&int32type); + + bool(np, true, false); + + setlabel(true); + code(ASCOPYW, tmp, constnode(&aux2, 1, &int32type), NULL); + code(ASJMP, NULL, phi, NULL); + + setlabel(false); + code(ASCOPYW, tmp, constnode(&aux2, 0, &int32type), NULL); + + setlabel(phi->u.sym); + return tmp; + case OMOD: + case OSHL: + case OBAND: + case OBOR: + case OBXOR: + case OSHR: + assert(tp->flags & INTF); + case ODIV: + case OLT: + case OGT: + case OLE: + case OGE: + case OADD: + case OSUB: + case OMUL: + case OEQ: + case ONE: + assert(tp->size == 4 || tp->size == 8); + + sign = (tp->flags & SIGNF) == 0; + size = tp->size == 8; + isfloat = (tp->flags & FLOATF) != 0; + op = opbin[isfloat][size][np->op][sign]; + rhs_rhs(&l, &r); + tmp = tmpnode(tp); + code(op, tmp, l, r); + return tmp; + case OCALL: + case OCALLE: + if (l->op == OPTR) + l = rhs(l); + return call(np, l); + case OCAST: + return cast(tp, rhs(l)); + case OASSIG: + return assign(np); + case OASK: + return ternary(np); + case OCOMMA: + rhs(l); + return rhs(r); + case OPTR: + return load(tp, rhs(l)); + case OADDR: + l = lhs(l); + l->type = *tp; + l->type.flags |= PTRF; + return l; + case OFIELD: + return field(np, 0); + case OBUILTIN: + switch (np->u.subop) { + case BVA_START: + l = rhs(l); + code(ASVSTAR, NULL, l, NULL); + case BVA_END: + return NULL; + case BVA_ARG: + l = rhs(l); + tmp = tmpnode(tp); + code(ASVARG, tmp, l, NULL); + return tmp; + default: + abort(); + } + default: + abort(); + } + abort(); +} + +Node * +cgen(Node *np) +{ + Node aux, *p, *next; + + setlabel(np->label); + switch (np->op) { + case OJMP: + label2node(&aux, np->u.sym); + code(ASJMP, NULL, &aux, NULL); + break; + case OBRANCH: + next = np->next; + if (!next->label) + next->label = newlabel(); + bool(np->left, np->u.sym, next->label); + break; + case ORET: + p = (np->left) ? rhs(np->left) : NULL; + code(ASRET, NULL, p, NULL); + break; + case OBSWITCH: + p = rhs(np->left); + swtch_if(p); + break; + default: + rhs(np); + break; + } + return NULL; +} diff --git a/src/cmd/scc-cc/cc2/qbe/code.c b/src/cmd/scc-cc/cc2/qbe/code.c @@ -0,0 +1,605 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <scc/cstd.h> +#include <scc/scc.h> + +#include "arch.h" +#include "../cc2.h" + +#define ADDR_LEN (INTIDENTSIZ+64) + +static void binary(void), unary(void), store(void), jmp(void), ret(void), + branch(void), call(void), ecall(void), param(void), + asalloc(void), form2local(void), blit(void), vastart(void), + vaarg(void); + +static struct opdata { + void (*fun)(void); + char *txt; + char letter; +} optbl [] = { + [ASLDSB] = {.fun = unary, .txt = "loadsb", .letter = 'w'}, + [ASLDUB] = {.fun = unary, .txt = "loadub", .letter = 'w'}, + [ASLDSH] = {.fun = unary, .txt = "loadsh", .letter = 'w'}, + [ASLDUH] = {.fun = unary, .txt = "loaduh", .letter = 'w'}, + [ASLDSW] = {.fun = unary, .txt = "loadsw", .letter = 'w'}, + [ASLDUW] = {.fun = unary, .txt = "loaduw", .letter = 'w'}, + [ASLDL] = {.fun = unary, .txt = "loadl", .letter = 'l'}, + [ASLDS] = {.fun = unary, .txt = "loads", .letter = 's'}, + [ASLDD] = {.fun = unary, .txt = "loadd", .letter = 'd'}, + + [ASCOPYB] = {.fun = unary, .txt = "copy", .letter = 'b'}, + [ASCOPYH] = {.fun = unary, .txt = "copy", .letter = 'h'}, + [ASCOPYW] = {.fun = unary, .txt = "copy", .letter = 'w'}, + [ASCOPYL] = {.fun = unary, .txt = "copy", .letter = 'l'}, + [ASCOPYS] = {.fun = unary, .txt = "copy", .letter = 's'}, + [ASCOPYD] = {.fun = unary, .txt = "copy", .letter = 'd'}, + + [ASSTB] = {.fun = store, .txt = "store", .letter = 'b'}, + [ASSTH] = {.fun = store, .txt = "store", .letter = 'h'}, + [ASSTW] = {.fun = store, .txt = "store", .letter = 'w'}, + [ASSTL] = {.fun = store, .txt = "store", .letter = 'l'}, + [ASSTM] = {.fun = blit}, + [ASSTS] = {.fun = store, .txt = "store", .letter = 's'}, + [ASSTD] = {.fun = store, .txt = "store", .letter = 'd'}, + + [ASADDW] = {.fun = binary, .txt = "add", .letter = 'w'}, + [ASSUBW] = {.fun = binary, .txt = "sub", .letter = 'w'}, + [ASMULW] = {.fun = binary, .txt = "mul", .letter = 'w'}, + [ASMODW] = {.fun = binary, .txt = "rem", .letter = 'w'}, + [ASUMODW] = {.fun = binary, .txt = "urem", .letter = 'w'}, + [ASDIVW] = {.fun = binary, .txt = "div", .letter = 'w'}, + [ASUDIVW] = {.fun = binary, .txt = "udiv", .letter = 'w'}, + [ASSHLW] = {.fun = binary, .txt = "shl", .letter = 'w'}, + [ASSHRW] = {.fun = binary, .txt = "sar", .letter = 'w'}, + [ASUSHRW] = {.fun = binary, .txt = "shr", .letter = 'w'}, + [ASLTW] = {.fun = binary, .txt = "csltw", .letter = 'w'}, + [ASULTW] = {.fun = binary, .txt = "cultw", .letter = 'w'}, + [ASGTW] = {.fun = binary, .txt = "csgtw", .letter = 'w'}, + [ASUGTW] = {.fun = binary, .txt = "cugtw", .letter = 'w'}, + [ASLEW] = {.fun = binary, .txt = "cslew", .letter = 'w'}, + [ASULEW] = {.fun = binary, .txt = "culew", .letter = 'w'}, + [ASGEW] = {.fun = binary, .txt = "csgew", .letter = 'w'}, + [ASUGEW] = {.fun = binary, .txt = "cugew", .letter = 'w'}, + [ASEQW] = {.fun = binary, .txt = "ceqw", .letter = 'w'}, + [ASNEW] = {.fun = binary, .txt = "cnew", .letter = 'w'}, + [ASBANDW] = {.fun = binary, .txt = "and", .letter = 'w'}, + [ASBORW] = {.fun = binary, .txt = "or", .letter = 'w'}, + [ASBXORW] = {.fun = binary, .txt = "xor", .letter = 'w'}, + + [ASADDL] = {.fun = binary, .txt = "add", .letter = 'l'}, + [ASSUBL] = {.fun = binary, .txt = "sub", .letter = 'l'}, + [ASMULL] = {.fun = binary, .txt = "mul", .letter = 'l'}, + [ASMODL] = {.fun = binary, .txt = "rem", .letter = 'l'}, + [ASUMODL] = {.fun = binary, .txt = "urem", .letter = 'l'}, + [ASDIVL] = {.fun = binary, .txt = "div", .letter = 'l'}, + [ASUDIVL] = {.fun = binary, .txt = "udiv", .letter = 'l'}, + [ASSHLL] = {.fun = binary, .txt = "shl", .letter = 'l'}, + [ASSHRL] = {.fun = binary, .txt = "sar", .letter = 'l'}, + [ASUSHRL] = {.fun = binary, .txt = "shr", .letter = 'l'}, + [ASLTL] = {.fun = binary, .txt = "csltl", .letter = 'w'}, + [ASULTL] = {.fun = binary, .txt = "cultl", .letter = 'w'}, + [ASGTL] = {.fun = binary, .txt = "csgtl", .letter = 'w'}, + [ASUGTL] = {.fun = binary, .txt = "cugtl", .letter = 'w'}, + [ASLEL] = {.fun = binary, .txt = "cslel", .letter = 'w'}, + [ASULEL] = {.fun = binary, .txt = "culel", .letter = 'w'}, + [ASGEL] = {.fun = binary, .txt = "csgel", .letter = 'w'}, + [ASUGEL] = {.fun = binary, .txt = "cugel", .letter = 'w'}, + [ASEQL] = {.fun = binary, .txt = "ceql", .letter = 'w'}, + [ASNEL] = {.fun = binary, .txt = "cnel", .letter = 'w'}, + [ASBANDL] = {.fun = binary, .txt = "and", .letter = 'l'}, + [ASBORL] = {.fun = binary, .txt = "or", .letter = 'l'}, + [ASBXORL] = {.fun = binary, .txt = "xor", .letter = 'l'}, + + [ASADDS] = {.fun = binary, .txt = "add", .letter = 's'}, + [ASSUBS] = {.fun = binary, .txt = "sub", .letter = 's'}, + [ASMULS] = {.fun = binary, .txt = "mul", .letter = 's'}, + [ASDIVS] = {.fun = binary, .txt = "div", .letter = 's'}, + [ASLTS] = {.fun = binary, .txt = "clts", .letter = 'w'}, + [ASGTS] = {.fun = binary, .txt = "cgts", .letter = 'w'}, + [ASLES] = {.fun = binary, .txt = "cles", .letter = 'w'}, + [ASGES] = {.fun = binary, .txt = "cges", .letter = 'w'}, + [ASEQS] = {.fun = binary, .txt = "ceqs", .letter = 'w'}, + [ASNES] = {.fun = binary, .txt = "cnes", .letter = 'w'}, + + [ASADDD] = {.fun = binary, .txt = "add", .letter = 'd'}, + [ASSUBD] = {.fun = binary, .txt = "sub", .letter = 'd'}, + [ASMULD] = {.fun = binary, .txt = "mul", .letter = 'd'}, + [ASDIVD] = {.fun = binary, .txt = "div", .letter = 'd'}, + [ASLTD] = {.fun = binary, .txt = "cltd", .letter = 'w'}, + [ASGTD] = {.fun = binary, .txt = "cgtd", .letter = 'w'}, + [ASLED] = {.fun = binary, .txt = "cled", .letter = 'w'}, + [ASGED] = {.fun = binary, .txt = "cged", .letter = 'w'}, + [ASEQD] = {.fun = binary, .txt = "ceqd", .letter = 'w'}, + [ASNED] = {.fun = binary, .txt = "cned", .letter = 'w'}, + + [ASEXTBW] = {.fun = unary, .txt = "extsb", .letter = 'w'}, + [ASUEXTBW]= {.fun = unary, .txt = "extub", .letter = 'w'}, + [ASEXTBL] = {.fun = unary, .txt = "extsb", .letter = 'l'}, + [ASUEXTBL]= {.fun = unary, .txt = "extub", .letter = 'l'}, + [ASEXTHW] = {.fun = unary, .txt = "extsh", .letter = 'w'}, + [ASUEXTHW]= {.fun = unary, .txt = "extuh", .letter = 'w'}, + [ASEXTHL] = {.fun = unary, .txt = "extsh", .letter = 'l'}, + [ASUEXTHL]= {.fun = unary, .txt = "extuh", .letter = 'l'}, + [ASEXTWL] = {.fun = unary, .txt = "extsw", .letter = 'l'}, + [ASUEXTWL]= {.fun = unary, .txt = "extuw", .letter = 'l'}, + + [ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'}, + [ASSTOUL] = {.fun = unary, .txt = "stoui", .letter = 'l'}, + [ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'}, + [ASSTOUW] = {.fun = unary, .txt = "stoui", .letter = 'w'}, + [ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'}, + [ASDTOUL] = {.fun = unary, .txt = "dtoui", .letter = 'l'}, + [ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'}, + [ASDTOUW] = {.fun = unary, .txt = "dtoui", .letter = 'w'}, + + [ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'}, + [ASUWTOD] = {.fun = unary, .txt = "uwtof", .letter = 'd'}, + [ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'}, + [ASUWTOS] = {.fun = unary, .txt = "uwtof", .letter = 's'}, + [ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'}, + [ASULTOD] = {.fun = unary, .txt = "ultof", .letter = 'd'}, + [ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'}, + [ASULTOS] = {.fun = unary, .txt = "ultof", .letter = 's'}, + + [ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'}, + [ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'}, + + [ASBRANCH] = {.fun = branch}, + [ASJMP] = {.fun = jmp}, + [ASRET] = {.fun = ret}, + [ASCALL] = {.fun = call}, + [ASCALLE] = {.fun = ecall, .txt = ")"}, + [ASCALLEX] = {.fun = ecall, .txt = ", ...)"}, + [ASPAR] = {.fun = param, .txt = "%s %s, "}, + [ASPARE] = {.fun = param, .txt = "%s %s"}, + [ASALLOC] = {.fun = asalloc}, + [ASFORM] = {.fun = form2local}, + + [ASVSTAR] = {.fun = vastart}, + [ASVARG] = {.fun = vaarg}, +}; + +static char buff[ADDR_LEN]; +/* + * : is for user-defined Aggregate Types + * $ is for globals (represented by a pointer) + * % is for function-scope temporaries + * @ is for block labels + */ +static char +sigil(Symbol *sym) +{ + switch (sym->kind) { + case SEXTRN: + case SGLOB: + case SPRIV: + case SLOCAL: + return '$'; + case SAUTO: + case STMP: + return '%'; + case SLABEL: + return '@'; + default: + abort(); + } +} + +static char * +symname(Symbol *sym) +{ + char c = sigil(sym); + + if (sym->name) { + switch (sym->kind) { + case SEXTRN: + case SGLOB: + sprintf(buff, "%c%s", c, sym->name); + return buff; + case SLOCAL: + case SPRIV: + case SAUTO: + sprintf(buff, "%c%s.L%u", c, sym->name, sym->id); + return buff; + default: + abort(); + } + } + sprintf(buff, "%c.L%u", c, sym->numid); + + return buff; +} + +static void +emitconst(Node *np) +{ + switch (np->type.size) { + case 1: + printf("%d", (int) np->u.i & 0xFF); + break; + case 2: + printf("%d", (int) np->u.i & 0xFFFF); + break; + case 4: + printf("%ld", (long) np->u.i & 0xFFFFFFFF); + break; + case 8: + printf("%lld", (long long) np->u.i); + break; + default: + abort(); + } +} + +static void +emittree(Node *np) +{ + if (!np) + return; + + switch (np->op) { + case OSTRING: + pprint(np->u.s); + free(np->u.s); + np->u.s = NULL; + break; + case OCONST: + emitconst(np); + break; + case OADDR: + emittree(np->left); + break; + case OMEM: + fputs(symname(np->u.sym), stdout); + break; + default: + emittree(np->left); + printf(" %c ", np->op); + emittree(np->right); + break; + } +} + +static char * +size2asm(Type *tp) +{ + static char spec[ADDR_LEN]; + + if (tp->flags & STRF) { + return "b"; + } else if (tp->flags & INTF) { + switch (tp->size) { + case 1: + return "b"; + case 2: + return "h"; + case 4: + return "w"; + case 8: + return "l"; + } + } else if (tp->flags & FLOATF) { + if (tp->size == 4) + return "s"; + else if (tp->size == 8) + return "d"; + } + + abort(); +} + +void +defglobal(Symbol *sym) +{ + Type *tp = &sym->type; + + if (sym->kind == SEXTRN) + return; + if (sym->kind == SGLOB) + fputs("export ", stdout); + if ((tp->flags & INITF) == 0) + fputs("common ", stdout); + + printf("data %s = align %d {\n", + symname(sym), + tp->align); + if ((tp->flags & INITF) == 0) + printf("\tz\t%lu\n}\n", tp->size); +} + +void +defpar(Symbol *sym) +{ + if (sym->kind == SREG) + sym->kind = SAUTO; + sym->type.flags |= PARF; +} + +void +defvar(Symbol *sym) +{ + if (sym->kind == SREG) + sym->kind = SAUTO; +} + +void +data(Node *np) +{ + printf("\t%s\t", size2asm(&np->type)); + emittree(np); + putchar(','); + putchar('\n'); +} + +static char * +size2stack(Type *tp) +{ + static char spec[ADDR_LEN]; + + if (tp->flags & INTF) { + switch (tp->size) { + case 1: + case 2: + case 4: + return "w"; + case 8: + return "l"; + } + } else if (tp->flags & FLOATF) { + if (tp->size == 4) + return "s"; + else if (tp->size == 8) + return "d"; + } else if (tp->flags & (ARRF|AGGRF)) { + sprintf(spec, ":.%u", tp->id); + return spec; + } else if (tp->size == 0) { + return "w"; + } + abort(); +} + +void +deftype(Type *tp) +{ + printf("type :.%u = align %d { %lu }\n", + tp->id, tp->align, tp->size); +} + +void +writeout(void) +{ + Symbol *p; + Type *tp; + char *sep; + int haslabel = 0; + + if (!curfun) + return; + if (curfun->kind == SGLOB) + fputs("export ", stdout); + printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun)); + + /* declare formal parameters */ + sep = ""; + for (p = locals; p; p = p->next) { + if ((p->type.flags & PARF) == 0) + continue; + printf("%s%s %s%s", + sep, size2stack(&p->type), + symname(p), + (p->type.flags & AGGRF) ? "" : ".val"); + sep = ","; + } + printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : ""); + + /* emit assembler instructions */ + for (pc = prog; pc; pc = pc->next) { + if (pc->label) { + haslabel = 1; + printf("%s\n", symname(pc->label)); + } + if (pc->op == ASLABEL) + continue; + if (pc->flags&BBENTRY && !haslabel) + printf("%s\n", symname(newlabel())); + (*optbl[pc->op].fun)(); + if (!pc->label) + haslabel = 0; + } + + puts("}"); +} + +static char * +addr2txt(Addr *a) +{ + switch (a->kind) { + case SCONST: + sprintf(buff, "%llu", (unsigned long long) a->u.i); + return buff; + case SAUTO: + case SLABEL: + case STMP: + case SGLOB: + case SEXTRN: + case SPRIV: + case SLOCAL: + return symname(a->u.sym); + default: + abort(); + } +} + +static void +binary(void) +{ + struct opdata *p = &optbl[pc->op]; + char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from1, addr2txt(&pc->from1)); + strcpy(from2, addr2txt(&pc->from2)); + printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2); +} + +static void +blit(void) +{ + Type *tp = &pc->to.u.sym->type; + char to[ADDR_LEN], from[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from, addr2txt(&pc->from1)); + printf("\t\tblit\t%s,%s,%lu\n", from, to, tp->size); +} + +static void +store(void) +{ + struct opdata *p = &optbl[pc->op]; + char to[ADDR_LEN], from[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from, addr2txt(&pc->from1)); + printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to); +} + +static void +unary(void) +{ + struct opdata *p = &optbl[pc->op]; + char to[ADDR_LEN], from[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from, addr2txt(&pc->from1)); + printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from); +} + +static void +call(void) +{ + char to[ADDR_LEN], from[ADDR_LEN]; + Symbol *sym = pc->to.u.sym; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from, addr2txt(&pc->from1)); + printf("\t%s =%s\tcall\t%s(", + to, size2stack(&sym->type), from); +} + +static void +param(void) +{ + Symbol *sym = pc->from2.u.sym; + + printf(optbl[pc->op].txt, + size2stack(&sym->type), addr2txt(&pc->from1)); +} + +static void +ecall(void) +{ + struct opdata *p = &optbl[pc->op]; + + puts(p->txt); +} + +static void +ret(void) +{ + if (pc->from1.kind == SNONE) + puts("\t\tret"); + else + printf("\t\tret\t%s\n", addr2txt(&pc->from1)); +} + +static void +jmp(void) +{ + printf("\t\tjmp\t%s\n", addr2txt(&pc->from1)); +} + +static void +branch(void) +{ + char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from1, addr2txt(&pc->from1)); + strcpy(from2, addr2txt(&pc->from2)); + printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2); +} + +static void +vastart(void) +{ + printf("\t\tvastart %s\n", addr2txt(&pc->from1)); +} + +static void +vaarg(void) +{ + Symbol *sym = pc->to.u.sym; + Type *tp = &sym->type; + char to[ADDR_LEN], from[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from, addr2txt(&pc->from1)); + printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from); +} + +static void +asalloc(void) +{ + Symbol *sym = pc->to.u.sym; + Type *tp = &sym->type; + extern Type ptrtype; + + printf("\t%s =%s\talloc%lu\t%lu\n", + symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size); +} + +static void +form2local(void) +{ + Symbol *sym = pc->to.u.sym; + Type *tp = &sym->type; + char *name = symname(sym); + + printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name); +} + +void +endinit(void) +{ + puts("}"); +} + +void +getbblocks(void) +{ + Inst *i; + + if (!prog) + return; + + prog->flags |= BBENTRY; + for (pc = prog; pc; pc = pc->next) { + switch (pc->op) { + case ASBRANCH: + i = pc->from2.u.sym->u.inst; + i->flags |= BBENTRY; + case ASJMP: + i = pc->from1.u.sym->u.inst; + i->flags |= BBENTRY; + case ASRET: + if (pc->next) + pc->next->flags |= BBENTRY; + break; + } + } +} diff --git a/src/cmd/scc-cc/cc2/qbe/optm.c b/src/cmd/scc-cc/cc2/qbe/optm.c @@ -0,0 +1,56 @@ +#include <stddef.h> + +#include <scc/scc.h> + +#include "../cc2.h" + +Node * +optm_dep(Node *np) +{ + int op = np->op; + Node *p, *dst, *next = np->next; + Symbol *sym, *osym; + + switch (op) { + case OEFUN: + /* + * In QBE we need at the end of a basic block + * a jump, so we have to ensure that the last + * statement of the function is a ret, a jmp + * or a branch. In the same way, QBE does + * not accept labels at the end of a function + * (ONOP is used for labels) so we have to add + * a ret there, and in the case of branches + * we need a label for the next statement + */ + op = (np->prev) ? np->prev->op : 0; + if (!op || op == ONOP || op == OBRANCH || (op != ORET && op != OJMP)) + addstmt(node(ORET), KEEPCUR); + break; + case OBRANCH: + if (!next->label) { + sym = getsym(TMPSYM); + sym->kind = SLABEL; + next->label = sym; + } + case OJMP: + for (;;) { + dst = np->u.sym->u.stmt; + if (dst->op != OJMP) + break; + np->u.sym = dst->u.sym; + } + for (p = np->next; p; p = p->next) { + if (p == dst) + return NULL; + if (p->op == ONOP || + p->op == OBLOOP || + p->op == OELOOP) { + continue; + } + break; + } + break; + } + return np; +} diff --git a/src/cmd/scc-cc/cc2/qbe_amd64-sysv/target.mk b/src/cmd/scc-cc/cc2/qbe_amd64-sysv/target.mk @@ -0,0 +1,9 @@ +OBJ-qbe_amd64-sysv = $(OBJS) \ + qbe/cgen.o \ + qbe/optm.o \ + qbe/code.o \ + amd64-sysv/types.o + +cc2-qbe_amd64-sysv: $(LIBSCC) $(OBJ-qbe_amd64-sysv) + $(CC) $(PROJ_LDFLAGS) $(OBJ-qbe_amd64-sysv) -lscc $(PROJ_LDLIBS) -o $@ + cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-cc/cc2/qbe_arm64-sysv/target.mk b/src/cmd/scc-cc/cc2/qbe_arm64-sysv/target.mk @@ -0,0 +1,9 @@ +OBJ-qbe_arm64-sysv = $(OBJS) \ + qbe/cgen.o \ + qbe/optm.o \ + qbe/code.o \ + arm64-sysv/types.o \ + +cc2-qbe_arm64-sysv: $(LIBSCC) $(OBJ-qbe_arm64-sysv) + $(CC) $(PROJ_LDFLAGS) $(OBJ-qbe_arm64-sysv) -lscc $(PROJ_LDLIBS) -o $@ + cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-cc/cc2/target/amd64-sysv/cgen.c b/src/cmd/scc-cc/cc2/target/amd64-sysv/cgen.c @@ -1,13 +0,0 @@ -#include "arch.h" -#include <scc/scc.h> -#include "../../cc2.h" - -Node * -cgen(Node *np) -{ -} - -Node * -sethi(Node *np) -{ -} diff --git a/src/cmd/scc-cc/cc2/target/amd64-sysv/code.c b/src/cmd/scc-cc/cc2/target/amd64-sysv/code.c @@ -1,214 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -#include <scc/cstd.h> -#include <scc/scc.h> - -#include "arch.h" -#include "../../cc2.h" - -enum segment { - CODESEG, - DATASEG, - BSSSEG, - NOSEG -}; - -static int curseg = NOSEG; - -static void -segment(int seg) -{ - static char *txt[] = { - [CODESEG] = "\t.text\n", - [DATASEG] = "\t.data\n", - [BSSSEG] = "\t.bss\n", - }; - - if (seg == curseg) - return; - fputs(txt[seg], stdout); - curseg = seg; -} - -static char * -symname(Symbol *sym) -{ - static char name[INTIDENTSIZ+1]; - - if (sym->name) { - switch (sym->kind) { - case SEXTRN: - case SGLOB: - case SPRIV: - return sym->name; - } - } - - sprintf(name, ".L%d", sym->numid); - - return name; -} - -static void -emitconst(Node *np) -{ - switch (np->type.size) { - case 1: - printf("%d", (int) np->u.i & 0xFF); - break; - case 2: - printf("%d", (int) np->u.i & 0xFFFF); - break; - case 4: - printf("%ld", (long) np->u.i & 0xFFFFFFFF); - break; - case 8: - printf("%lld", (long long) np->u.i & 0xFFFFFFFF); - break; - default: - abort(); - } -} - -static void -emittree(Node *np) -{ - if (!np) - return; - - switch (np->op) { - case OSTRING: - pprint(np->u.s); - free(np->u.s); - np->u.s = NULL; - break; - case OCONST: - emitconst(np); - break; - case OADDR: - emittree(np->left); - break; - case OMEM: - fputs(symname(np->u.sym), stdout); - break; - default: - emittree(np->left); - printf(" %c ", np->op); - emittree(np->right); - break; - } -} -static void -size2asm(Type *tp) -{ - char *s; - - if (tp->flags & STRF) { - s = "\t.ascii\t"; - } else { - switch (tp->size) { - case 1: - s = "\t.byte\t"; - break; - case 2: - s = "\t.short\t"; - break; - case 4: - s = "\t.long\t"; - break; - case 8: - s = "\t.quad\t"; - break; - default: - s = "\t.space\t%lu,"; - break; - } - } - printf(s, tp->size); -} - - -void -data(Node *np) -{ - size2asm(&np->type); - emittree(np); - putchar('\n'); -} - -static void -label(Symbol *sym) -{ - int seg; - char *name = symname(sym); - Type *tp = &sym->type; - - if (sym->type.flags & FUNF) - seg = CODESEG; - else if (sym->type.flags & INITF) - seg = DATASEG; - else - seg = BSSSEG; - segment(seg); - - switch (sym->kind) { - case SEXTRN: - printf("\t.extern\t%s\n", name); - case SLOCAL: - return; - case SGLOB: - printf("\t.global\t%s\n", name); - if (seg == BSSSEG) - printf("\t.comm\t%s,%lu\n", name, tp->size); - break; - } - if (sym->type.align != 1) - printf("\t.align\t%lu\n", sym->type.align ); - printf("%s:\n", name); -} - -void -defglobal(Symbol *sym) -{ - label(sym); - if (sym->kind == SEXTRN || (sym->type.flags & INITF)) - return; - size2asm(&sym->type); - puts("0"); -} - -void -deftype(Type *tp) -{ -} - -void -defvar(Symbol *sym) -{ -} - -void -defpar(Symbol *sym) -{ -} - -void -newfun(void) -{ -} - -void -writeout(void) -{ -} - -void -endinit(void) -{ -} - -void -getbblocks(void) -{ -} diff --git a/src/cmd/scc-cc/cc2/target/amd64-sysv/optm.c b/src/cmd/scc-cc/cc2/target/amd64-sysv/optm.c @@ -1,9 +0,0 @@ -#include <scc/scc.h> - -#include "../../cc2.h" - -Node * -optm_dep(Node *np) -{ - return np; -} diff --git a/src/cmd/scc-cc/cc2/target/amd64-sysv/target.mk b/src/cmd/scc-cc/cc2/target/amd64-sysv/target.mk @@ -1,9 +0,0 @@ -OBJ-amd64-sysv = $(OBJS) \ - target/amd64-sysv/cgen.o \ - target/amd64-sysv/optm.o \ - target/amd64-sysv/code.o \ - target/amd64-sysv/types.o - -cc2-amd64-sysv: $(LIBSCC) $(OBJ-amd64-sysv) - $(CC) $(PROJ_LDFLAGS) $(OBJ-amd64-sysv) -lscc $(PROJ_LDLIBS) -o $@ - cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-cc/cc2/target/amd64-sysv/types.c b/src/cmd/scc-cc/cc2/target/amd64-sysv/types.c @@ -1,93 +0,0 @@ -#include <scc/scc.h> - -#include "../../cc2.h" - - -Type int8type = { - .flags = SIGNF | INTF, - .size = 1, - .align = 1 -}; - -Type int16type = { - .flags = SIGNF | INTF, - .size = 2, - .align = 2 -}; - -Type int32type = { - .flags = SIGNF | INTF, - .size = 4, - .align = 4 -}; - -Type int64type = { - .flags = SIGNF | INTF, - .size = 8, - .align = 8 -}; - -Type uint8type = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type uint16type = { - .flags = INTF, - .size = 2, - .align = 2 -}; - -Type uint32type = { - .flags = INTF, - .size = 4, - .align = 4 -}; - -Type uint64type = { - .flags = INTF, - .size = 8, - .align = 8 -}; - -Type ptrtype = { - .flags = INTF, - .size = 8, - .align = 8 -}; - -Type booltype = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type float32type = { - .flags = FLOATF, - .size = 4, - .align = 4 -}; - -Type float64type = { - .flags = FLOATF, - .size = 8, - .align = 8 -}; - -Type float80type = { - .flags = FLOATF, - .size = 16, - .align = 16 -}; - -Type voidtype = { - .size = 0, - .align = 0 -}; - -Type arg_type = { - .flags = ARRF, - .size = 24, - .align = 8 -}; diff --git a/src/cmd/scc-cc/cc2/target/arm64-sysv/types.c b/src/cmd/scc-cc/cc2/target/arm64-sysv/types.c @@ -1,93 +0,0 @@ -#include <scc/scc.h> - -#include "../../cc2.h" - - -Type int8type = { - .flags = SIGNF | INTF, - .size = 1, - .align = 1 -}; - -Type int16type = { - .flags = SIGNF | INTF, - .size = 2, - .align = 2 -}; - -Type int32type = { - .flags = SIGNF | INTF, - .size = 4, - .align = 4 -}; - -Type int64type = { - .flags = SIGNF | INTF, - .size = 8, - .align = 8 -}; - -Type uint8type = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type uint16type = { - .flags = INTF, - .size = 2, - .align = 2 -}; - -Type uint32type = { - .flags = INTF, - .size = 4, - .align = 4 -}; - -Type uint64type = { - .flags = INTF, - .size = 8, - .align = 8 -}; - -Type ptrtype = { - .flags = INTF, - .size = 8, - .align = 8 -}; - -Type booltype = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type float32type = { - .flags = FLOATF, - .size = 4, - .align = 4 -}; - -Type float64type = { - .flags = FLOATF, - .size = 8, - .align = 8 -}; - -Type float80type = { - .flags = FLOATF, - .size = 16, - .align = 16 -}; - -Type voidtype = { - .size = 0, - .align = 0 -}; - -Type arg_type = { - .flags = ARRF, - .size = 24, - .align = 8 -}; diff --git a/src/cmd/scc-cc/cc2/target/i386-sysv/cgen.c b/src/cmd/scc-cc/cc2/target/i386-sysv/cgen.c @@ -1,14 +0,0 @@ -#include <scc/scc.h> - -#include "arch.h" -#include "../../cc2.h" - -Node * -cgen(Node *np) -{ -} - -Node * -sethi(Node *np) -{ -} diff --git a/src/cmd/scc-cc/cc2/target/i386-sysv/code.c b/src/cmd/scc-cc/cc2/target/i386-sysv/code.c @@ -1,213 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -#include <scc/cstd.h> -#include <scc/scc.h> - -#include "arch.h" -#include "../../cc2.h" - -enum segment { - CODESEG, - DATASEG, - BSSSEG, - NOSEG -}; - -static int curseg = NOSEG; - -static void -segment(int seg) -{ - static char *txt[] = { - [CODESEG] = "\t.text\n", - [DATASEG] = "\t.data\n", - [BSSSEG] = "\t.bss\n", - }; - - if (seg == curseg) - return; - fputs(txt[seg], stdout); - curseg = seg; -} - -static char * -symname(Symbol *sym) -{ - static char name[INTIDENTSIZ+1]; - - if (sym->name) { - switch (sym->kind) { - case SEXTRN: - case SGLOB: - case SPRIV: - return sym->name; - } - } - - sprintf(name, ".L%d", sym->numid); - - return name; -} - -static void -emitconst(Node *np) -{ - switch (np->type.size) { - case 1: - printf("%d", (int) np->u.i & 0xFF); - break; - case 2: - printf("%d", (int) np->u.i & 0xFFFF); - break; - case 4: - printf("%ld", (long) np->u.i & 0xFFFFFFFF); - break; - case 8: - printf("%lld", (long long) np->u.i & 0xFFFFFFFF); - break; - default: - abort(); - } -} - -static void -emittree(Node *np) -{ - if (!np) - return; - - switch (np->op) { - case OSTRING: - pprint(np->u.s); - free(np->u.s); - np->u.s = NULL; - break; - case OCONST: - emitconst(np); - break; - case OADDR: - emittree(np->left); - break; - case OMEM: - fputs(symname(np->u.sym), stdout); - break; - default: - emittree(np->left); - printf(" %c ", np->op); - emittree(np->right); - break; - } -} -static void -size2asm(Type *tp) -{ - char *s; - - if (tp->flags & STRF) { - s = "\t.ascii\t"; - } else { - switch (tp->size) { - case 1: - s = "\t.byte\t"; - break; - case 2: - s = "\t.short\t"; - break; - case 4: - s = "\t.long\t"; - break; - case 8: - s = "\t.quad\t"; - break; - default: - s = "\t.space\t%lu,"; - break; - } - } - printf(s, tp->size); -} - -void -data(Node *np) -{ - size2asm(&np->type); - emittree(np); - putchar('\n'); -} - -static void -label(Symbol *sym) -{ - int seg; - char *name = symname(sym); - Type *tp = &sym->type; - - if (sym->type.flags & FUNF) - seg = CODESEG; - else if (sym->type.flags & INITF) - seg = DATASEG; - else - seg = BSSSEG; - segment(seg); - - switch (sym->kind) { - case SEXTRN: - printf("\t.extern\t%s\n", name); - case SLOCAL: - return; - case SGLOB: - printf("\t.global\t%s\n", name); - if (seg == BSSSEG) - printf("\t.comm\t%s,%lu\n", name, tp->size); - break; - } - if (sym->type.align != 1) - printf("\t.align\t%lu\n", sym->type.align ); - printf("%s:\n", name); -} - -void -defglobal(Symbol *sym) -{ - label(sym); - if (sym->kind == SEXTRN || (sym->type.flags & INITF)) - return; - size2asm(&sym->type); - puts("0"); -} - -void -deftype(Type *tp) -{ -} - -void -defpar(Symbol *sym) -{ -} - -void -defvar(Symbol *sym) -{ -} - -void -newfun(void) -{ -} - -void -writeout(void) -{ -} - -void -endinit(void) -{ -} - -void -getbblocks(void) -{ -} diff --git a/src/cmd/scc-cc/cc2/target/i386-sysv/optm.c b/src/cmd/scc-cc/cc2/target/i386-sysv/optm.c @@ -1,9 +0,0 @@ -#include <scc/scc.h> - -#include "../../cc2.h" - -Node * -optm_dep(Node *np) -{ - return np; -} diff --git a/src/cmd/scc-cc/cc2/target/i386-sysv/target.mk b/src/cmd/scc-cc/cc2/target/i386-sysv/target.mk @@ -1,9 +0,0 @@ -OBJ-i386-sysv = $(OBJS) \ - target/i386-sysv/cgen.o \ - target/i386-sysv/optm.o \ - target/i386-sysv/code.o \ - target/i386-sysv/types.o - -cc2-i386-sysv: $(LIBSCC) $(OBJ-i386-sysv) - $(CC) $(PROJ_LDFLAGS) $(OBJ-i386-sysv) -lscc $(PROJ_LDLIBS) -o $@ - cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-cc/cc2/target/i386-sysv/types.c b/src/cmd/scc-cc/cc2/target/i386-sysv/types.c @@ -1,92 +0,0 @@ -#include <scc/scc.h> - -#include "../../cc2.h" - - -Type int8type = { - .flags = SIGNF | INTF, - .size = 1, - .align = 1 -}; - -Type int16type = { - .flags = SIGNF | INTF, - .size = 2, - .align = 2 -}; - -Type int32type = { - .flags = SIGNF | INTF, - .size = 4, - .align = 4 -}; - -Type int64type = { - .flags = SIGNF | INTF, - .size = 8, - .align = 4 -}; - -Type uint8type = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type uint16type = { - .flags = INTF, - .size = 2, - .align = 2 -}; - -Type uint32type = { - .flags = INTF, - .size = 4, - .align = 2 -}; - -Type uint64type = { - .flags = INTF, - .size = 8, - .align = 4 -}; - -Type ptrtype = { - .flags = INTF, - .size = 4, - .align = 4 -}; - -Type booltype = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type float32type = { - .flags = FLOATF, - .size = 4, - .align = 4 -}; - -Type float64type = { - .flags = FLOATF, - .size = 8, - .align = 4 -}; - -Type float80type = { - .flags = FLOATF, - .size = 12, - .align = 4 -}; - -Type voidtype = { - .size = 0, - .align = 0 -}; - -Type arg_type = { - .size = 4, - .align = 4 -}; diff --git a/src/cmd/scc-cc/cc2/target/qbe/cgen.c b/src/cmd/scc-cc/cc2/target/qbe/cgen.c @@ -1,782 +0,0 @@ -#include <assert.h> -#include <stdlib.h> - -#include <scc/cstd.h> -#include <scc/scc.h> - -#include "arch.h" -#include "../../cc2.h" - -#define I1BYTES 0 -#define I2BYTES 1 -#define I4BYTES 2 -#define I8BYTES 3 - -static unsigned char opasmw[][2] = { - [OADD] = {ASADDW, ASADDW}, - [OSUB] = {ASSUBW, ASSUBW}, - [OMUL] = {ASMULW, ASMULW}, - [OMOD] = {ASMODW, ASUMODW}, - [ODIV] = {ASDIVW, ASUDIVW}, - [OSHL] = {ASSHLW, ASSHLW}, - [OSHR] = {ASSHRW, ASUSHRW}, - [OLT] = {ASLTW, ASULTW}, - [OGT] = {ASGTW, ASUGTW}, - [OLE] = {ASLEW, ASULEW}, - [OGE] = {ASGEW, ASUGEW}, - [OEQ] = {ASEQW, ASEQW}, - [ONE] = {ASNEW, ASNEW}, - [OBAND] = {ASBANDW, ASBANDW}, - [OBOR] = {ASBORW, ASBORW}, - [OBXOR] = {ASBXORW, ASBXORW}, -}; - -static unsigned char opasml[][2] = { - [OADD] = {ASADDL, ASADDL}, - [OSUB] = {ASSUBL, ASSUBL}, - [OMUL] = {ASMULL, ASMULL}, - [OMOD] = {ASMODL, ASUMODL}, - [ODIV] = {ASDIVL, ASUDIVL}, - [OSHL] = {ASSHLL, ASSHLL}, - [OSHR] = {ASSHRL, ASUSHRL}, - [OLT] = {ASLTL, ASULTL}, - [OGT] = {ASGTL, ASUGTL}, - [OLE] = {ASLEL, ASULEL}, - [OGE] = {ASGEL, ASUGEL}, - [OEQ] = {ASEQL, ASEQL}, - [ONE] = {ASNEL, ASNEL}, - [OBAND] = {ASBANDL, ASBANDL}, - [OBOR] = {ASBORL, ASBORL}, - [OBXOR] = {ASBXORL, ASBXORL}, -}; - -static unsigned char opasms[][2] = { - [OADD] = {ASADDS, ASADDS}, - [OSUB] = {ASSUBS, ASSUBS}, - [OMUL] = {ASMULS, ASMULS}, - [ODIV] = {ASDIVS, ASDIVS}, - [OLT] = {ASLTS, ASLTS}, - [OGT] = {ASGTS, ASGTS}, - [OLE] = {ASLES, ASLES}, - [OGE] = {ASGES, ASGES}, - [OEQ] = {ASEQS, ASEQS}, - [ONE] = {ASNES, ASNES}, -}; - -static unsigned char opasmd[][2] = { - [OADD] = {ASADDD, ASADDD}, - [OSUB] = {ASSUBD, ASSUBD}, - [OMUL] = {ASMULD, ASMULD}, - [ODIV] = {ASDIVD, ASDIVD}, - [OLT] = {ASLTD, ASLTD}, - [OGT] = {ASGTD, ASGTD}, - [OLE] = {ASLED, ASLED}, - [OGE] = {ASGED, ASGED}, - [OEQ] = {ASEQD, ASEQD}, - [ONE] = {ASNED, ASNED}, -}; - -static unsigned char (*opbin[][2])[2] = { - {opasmw, opasml}, - {opasms, opasmd}, -}; - -static unsigned char i2i_conv[4][4][2] = { - [I1BYTES] = { - [I4BYTES] = {ASEXTBW, ASUEXTBW}, - [I8BYTES] = {ASEXTBL, ASUEXTBL}, - }, - [I2BYTES] = { - [I4BYTES] = {ASEXTHW, ASUEXTHW}, - [I8BYTES] = {ASEXTHL, ASUEXTHL}, - }, - [I4BYTES] = { - [I8BYTES] = {ASEXTWL, ASUEXTWL}, - } -}; - -static unsigned char f2i_conv[4][4][2] = { - [I4BYTES] = { - [I4BYTES] = {ASSTOW, ASSTOUW}, - [I8BYTES] = {ASSTOL, ASDTOUL}, - }, - [I8BYTES] = { - [I4BYTES] = {ASDTOW, ASDTOUW}, - [I8BYTES] = {ASDTOL, ASDTOUL}, - } -}; - -static unsigned char i2f_conv[4][4][2] = { - [I4BYTES] = { - [I4BYTES] = {ASSWTOS, ASUWTOS}, - [I8BYTES] = {ASSWTOD, ASUWTOD}, - }, - [I8BYTES] = { - [I4BYTES] = {ASSLTOS, ASULTOS}, - [I8BYTES] = {ASSLTOD, ASULTOD}, - } -}; - -extern Type int32type, uint32type, ptrtype; - -/* - * This is strongly influenced by - * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps) - * calculate addresability as follows - * AUTO => 11 value+fp - * REG => 11 reg - * STATIC => 11 (value) - * CONST => 11 $value - * These values of addressability are not used in the code generation. - * They are only used to calculate the Sethi-Ullman numbers. Since - * QBE is AMD64 targered we could do a better job there, and try to - * detect some of the complex addressing modes of these processors. - */ -static Node * -complex(Node *np) -{ - Node *lp = np->left, *rp = np->right; - - if (np->address > 10) - return np; - if (lp) - np->complex = lp->complex; - if (rp) { - int d = np->complex - rp->complex; - - if (d == 0) - ++np->complex; - else if (d < 0) - np->complex = rp->complex; - } - if (np->complex == 0) - ++np->complex; - - return np; -} - -Node * -sethi(Node *np) -{ - Node *lp, *rp; - - if (!np) - return np; - - np->complex = 0; - np->address = 0; - lp = np->left; - rp = np->right; - - switch (np->op) { - case OAUTO: - case OREG: - case OMEM: - case OCONST: - np->address = 11; - break; - case OASSIG: - assert(lp->op != OCAST); - goto binary; - case OCPL: - assert(np->type.flags & INTF); - np->op = OBXOR; - rp = constnode(NULL, ~(TUINT) 0, &np->type); - goto binary; - case OSNEG: - np->op = OSUB; - rp = lp; - lp = constnode(NULL, 0, &np->type); - if ((np->type.flags & INTF) == 0) - lp->u.f = 0.0; - default: - binary: - lp = sethi(lp); - rp = sethi(rp); - break; - } - np->left = lp; - np->right = rp; - - return complex(np); -} - -static int -bytes2idx(int nbytes) -{ - if (nbytes== 1) - return I1BYTES; - else if (nbytes == 2) - return I2BYTES; - else if (nbytes == 4) - return I4BYTES; - else if (nbytes == 8) - return I8BYTES; - else - abort(); -} - -static Node * -load(Type *tp, Node *np) -{ - int op; - Node *new; - int flags = tp->flags; - - if (flags & (AGGRF|FUNF|ARRF|PTRF)) - return np; - - switch (tp->size) { - case 1: - op = ASLDSB; - break; - case 2: - op = ASLDSH; - break; - case 4: - op = (flags & FLOATF) ? ASLDS : ASLDSW; - break; - case 8: - op = (flags & FLOATF) ? ASLDD : ASLDL; - break; - default: - abort(); - } - /* - * unsigned version of operations are always +1 the - * signed version - */ - if ((flags & (INTF|SIGNF)) == INTF && tp->size < 8) - ++op; - - new = tmpnode(tp); - code(op, new, np, NULL); - - return new; -} - -static Node *rhs(Node *np); - -static Node * -cast(Type *td, Node *np) -{ - Type *ts; - Node *tmp; - int op, d_isint, s_isint, sidx, didx, sign; - - ts = &np->type; - d_isint = (td->flags & INTF) != 0; - s_isint = (ts->flags & INTF) != 0; - - sidx = bytes2idx(ts->size); - didx = bytes2idx(td->size); - - sign = (ts->flags & SIGNF) == 0; - - if (d_isint && s_isint) { - /* conversion from int to int */ - if (didx < I4BYTES) - didx = bytes2idx(4); - - if (didx <= sidx) { - np->type = *td; - return np; - } - - op = i2i_conv[sidx][didx][sign]; - } else if (d_isint) { - /* conversion from float to int */ - if (didx < I4BYTES) - didx = bytes2idx(4); - - op = f2i_conv[sidx][didx][sign]; - } else if (s_isint) { - /* conversion from int to float */ - if (sidx == I1BYTES || sidx == I2BYTES) { - ts = (ts->flags&SIGNF) ? &int32type : &uint32type; - np = cast(ts, np); - } - op = i2f_conv[sidx][didx][sign]; - } else { - /* conversion from float to float */ - op = (didx == I4BYTES) ? ASEXTS : ASTRUNCD; - } - - assert(op != 0); - tmp = tmpnode(td); - code(op, tmp, np, NULL); - - return tmp; -} - -static Node * -call(Node *np, Node *fun) -{ - int n, op; - Type *tp; - Node **q, *tmp, *p, *pars[NR_FUNPARAM]; - - for (n = 0, p = np->right; p; p = p->right) - pars[n++] = rhs(p->left); - - tp = &np->type; - tmp = tmpnode(tp); - code(ASCALL, tmp, fun, NULL); - - for (q = pars; q < &pars[n]; ++q) { - op = (q == &pars[n-1]) ? ASPARE : ASPAR; - code(op, NULL, *q, tmpnode(&(*q)->type)); - } - code((np->op == OCALL) ? ASCALLE : ASCALLEX, NULL, NULL, NULL); - - return tmp; -} - -static Node * -copy(Type *tp, Node *to, Node *from) -{ - int op; - - switch (tp->size) { - case 0: - return from; - case 1: - op = ASCOPYB; - break; - case 2: - op = ASCOPYH; - break; - case 4: - op = (tp->flags & FLOATF) ? ASCOPYS : ASCOPYW; - break; - case 8: - op = (tp->flags & FLOATF) ? ASCOPYD : ASCOPYL; - break; - default: - abort(); - } - code(op, to, from, NULL); - return from; -} - -static Node * -field(Node *np, int islhs) -{ - Node *tmp, *addr; - TUINT offset = np->right->u.sym->u.off; - - addr = rhs(np->left); - tmp = node(OADD); - tmp->type = ptrtype; - tmp->left = addr; - tmp->right = constnode(NULL, offset, &ptrtype); - addr = rhs(tmp); - - if (!islhs) - addr = load(&np->type, addr); - return addr; -} - -static Node * -lhs(Node *np) -{ - switch (np->op) { - case OREG: - case OMEM: - case OAUTO: - return np; - case OPTR: - return rhs(np->left); - case OFIELD: - return field(np, 1); - default: - abort(); - } -} - -static void -bool(Node *np, Symbol *true, Symbol *false) -{ - Node *l = np->left, *r = np->right; - Node ret, ifyes, ifno; - Symbol *label; - - switch (np->op) { - case ONEG: - bool(l, false, true); - break; - case OAND: - label = newlabel(); - bool(l, label, false); - setlabel(label); - bool(r, true, false); - break; - case OOR: - label = newlabel(); - bool(l, true, label); - setlabel(label); - bool(r, true, false); - break; - default: - label2node(&ifyes, true); - label2node(&ifno, false); - code(ASBRANCH, rhs(np), &ifyes, &ifno); - break; - } -} - -static Node * -ternary(Node *np) -{ - Node ifyes, ifno, phi, *colon, *tmp; - - tmp = tmpnode(&np->type); - label2node(&ifyes, NULL); - label2node(&ifno, NULL); - label2node(&phi, NULL); - - colon = np->right; - code(ASBRANCH, rhs(np->left), &ifyes, &ifno); - - setlabel(ifyes.u.sym); - copy(&tmp->type, tmp, rhs(colon->left)); - code(ASJMP, NULL, &phi, NULL); - - setlabel(ifno.u.sym); - copy(&tmp->type, tmp, rhs(colon->right)); - setlabel(phi.u.sym); - - return tmp; -} - -static Node * -function(void) -{ - Node aux; - Symbol *p; - - /* allocate stack space for parameters */ - for (p = locals; p; p = p->next) { - if ((p->type.flags & PARF) == 0) - continue; - if ((p->type.flags & AGGRF) != 0) - continue; - code(ASALLOC, label2node(&aux, p), NULL, NULL); - } - - /* allocate stack space for local variables) */ - for (p = locals; p; p = p->next) { - if ((p->type.flags & PARF) != 0) - continue; - if (p->kind != SAUTO || p->id == TMPSYM) - continue; - code(ASALLOC, label2node(&aux, p), NULL, NULL); - } - - /* store formal parameters in parameters */ - for (p = locals; p; p = p->next) { - if ((p->type.flags & PARF) == 0) - continue; - if ((p->type.flags & AGGRF) != 0) - continue; - if ((p->type.flags & (ARRF|AGGRF)) == 0) - code(ASFORM, label2node(&aux, p), NULL, NULL); - } - return NULL; -} - -static void -swtch_if(Node *idx) -{ - Node aux1, aux2, *np; - Symbol *deflabel = NULL; - - for (;;) { - np = delstmt(); - setlabel(np->label); - - switch (np->op) { - case OESWITCH: - if (!deflabel) - deflabel = np->u.sym; - aux1.op = OJMP; - aux1.label = NULL; - aux1.u.sym = deflabel; - cgen(&aux1); - return; - case OCASE: - aux1 = *np; - aux1.op = OBRANCH; - aux1.label = NULL; - aux1.left = &aux2; - - aux2.op = OEQ; - aux2.type = idx->type; - aux2.left = np->left; - aux2.right = idx; - - cgen(&aux1); - break; - case ODEFAULT: - deflabel = np->u.sym; - break; - default: - abort(); - } - } -} - -static int -assignop(Type *tp) -{ - int flags = tp->flags; - - if (flags & (AGGRF|FUNF|ARRF)) - return ASSTM; - - switch (tp->size) { - case 1: - return ASSTB; - case 2: - return ASSTH; - case 4: - return (tp->flags & FLOATF) ? ASSTS : ASSTW; - case 8: - return (tp->flags & FLOATF) ? ASSTD : ASSTL; - default: - abort(); - } -} - -static void -rhs_rhs(Node **lp, Node **rp) -{ - Node *l = *lp, *r = *rp; - - if (l->complex >= r->complex) { - l = rhs(l); - r = rhs(r); - } else { - r = rhs(r); - l = rhs(l); - } - - *lp = l, *rp = r; -} - -static void -lhs_rhs(Node **lp, Node **rp) -{ - Node *l = *lp, *r = *rp; - - if (l->complex >= r->complex) { - l = lhs(l); - r = rhs(r); - } else { - r = rhs(r); - l = lhs(l); - } - - *lp = l, *rp = r; -} - -static Node * -assign(Node *np) -{ - Node *ret, aux; - Node *l = np->left, *r = np->right; - int op; - - switch (np->u.subop) { - break; - case OINC: - op = OADD; - goto post_oper; - case ODEC: - op = OSUB; - post_oper: - lhs_rhs(&l, &r); - ret = load(&l->type, l); - aux.op = op; - aux.left = ret; - aux.right = r; - aux.type = np->type; - r = rhs(sethi(&aux)); - break; - default: - /* assign abbreviation */ - assert(l->type.size == r->type.size); - if (r->type.size < 4) { - lhs_rhs(&l, &r); - aux.op = np->u.subop; - aux.left = load(&r->type, l); - aux.right = r; - aux.type = int32type; - aux.address = np->address; - ret = r = sethi(rhs(&aux)); - break; - } - - aux.op = np->u.subop; - aux.left = l; - aux.right = r; - aux.type = np->type; - aux.address = np->address; - r = sethi(&aux); - case 0: - lhs_rhs(&l, &r); - ret = r; - break; - } - - code(assignop(&np->type), l, r, NULL); - return ret; -} - -static Node * -rhs(Node *np) -{ - Node *tmp, aux1, aux2; - Node *phi, *l = np->left, *r = np->right; - Type *tp; - int sign, size, isfloat, op; - Symbol *true, *false; - - tp = &np->type; - - switch (np->op) { - case OBFUN: - return function(); - case ONOP: - case OBLOOP: - case OELOOP: - case OEFUN: - return NULL; - case OTMP: - case OCONST: - return np; - case OMEM: - case OREG: - case OAUTO: - return load(tp, np); - case ONEG: - case OAND: - case OOR: - true = newlabel(); - false = newlabel(); - phi = label2node(&aux1, NULL); - tmp = tmpnode(&int32type); - - bool(np, true, false); - - setlabel(true); - code(ASCOPYW, tmp, constnode(&aux2, 1, &int32type), NULL); - code(ASJMP, NULL, phi, NULL); - - setlabel(false); - code(ASCOPYW, tmp, constnode(&aux2, 0, &int32type), NULL); - - setlabel(phi->u.sym); - return tmp; - case OMOD: - case OSHL: - case OBAND: - case OBOR: - case OBXOR: - case OSHR: - assert(tp->flags & INTF); - case ODIV: - case OLT: - case OGT: - case OLE: - case OGE: - case OADD: - case OSUB: - case OMUL: - case OEQ: - case ONE: - assert(tp->size == 4 || tp->size == 8); - - sign = (tp->flags & SIGNF) == 0; - size = tp->size == 8; - isfloat = (tp->flags & FLOATF) != 0; - op = opbin[isfloat][size][np->op][sign]; - rhs_rhs(&l, &r); - tmp = tmpnode(tp); - code(op, tmp, l, r); - return tmp; - case OCALL: - case OCALLE: - if (l->op == OPTR) - l = rhs(l); - return call(np, l); - case OCAST: - return cast(tp, rhs(l)); - case OASSIG: - return assign(np); - case OASK: - return ternary(np); - case OCOMMA: - rhs(l); - return rhs(r); - case OPTR: - return load(tp, rhs(l)); - case OADDR: - l = lhs(l); - l->type = *tp; - l->type.flags |= PTRF; - return l; - case OFIELD: - return field(np, 0); - case OBUILTIN: - switch (np->u.subop) { - case BVA_START: - l = rhs(l); - code(ASVSTAR, NULL, l, NULL); - case BVA_END: - return NULL; - case BVA_ARG: - l = rhs(l); - tmp = tmpnode(tp); - code(ASVARG, tmp, l, NULL); - return tmp; - default: - abort(); - } - default: - abort(); - } - abort(); -} - -Node * -cgen(Node *np) -{ - Node aux, *p, *next; - - setlabel(np->label); - switch (np->op) { - case OJMP: - label2node(&aux, np->u.sym); - code(ASJMP, NULL, &aux, NULL); - break; - case OBRANCH: - next = np->next; - if (!next->label) - next->label = newlabel(); - bool(np->left, np->u.sym, next->label); - break; - case ORET: - p = (np->left) ? rhs(np->left) : NULL; - code(ASRET, NULL, p, NULL); - break; - case OBSWITCH: - p = rhs(np->left); - swtch_if(p); - break; - default: - rhs(np); - break; - } - return NULL; -} diff --git a/src/cmd/scc-cc/cc2/target/qbe/code.c b/src/cmd/scc-cc/cc2/target/qbe/code.c @@ -1,605 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <scc/cstd.h> -#include <scc/scc.h> - -#include "arch.h" -#include "../../cc2.h" - -#define ADDR_LEN (INTIDENTSIZ+64) - -static void binary(void), unary(void), store(void), jmp(void), ret(void), - branch(void), call(void), ecall(void), param(void), - asalloc(void), form2local(void), blit(void), vastart(void), - vaarg(void); - -static struct opdata { - void (*fun)(void); - char *txt; - char letter; -} optbl [] = { - [ASLDSB] = {.fun = unary, .txt = "loadsb", .letter = 'w'}, - [ASLDUB] = {.fun = unary, .txt = "loadub", .letter = 'w'}, - [ASLDSH] = {.fun = unary, .txt = "loadsh", .letter = 'w'}, - [ASLDUH] = {.fun = unary, .txt = "loaduh", .letter = 'w'}, - [ASLDSW] = {.fun = unary, .txt = "loadsw", .letter = 'w'}, - [ASLDUW] = {.fun = unary, .txt = "loaduw", .letter = 'w'}, - [ASLDL] = {.fun = unary, .txt = "loadl", .letter = 'l'}, - [ASLDS] = {.fun = unary, .txt = "loads", .letter = 's'}, - [ASLDD] = {.fun = unary, .txt = "loadd", .letter = 'd'}, - - [ASCOPYB] = {.fun = unary, .txt = "copy", .letter = 'b'}, - [ASCOPYH] = {.fun = unary, .txt = "copy", .letter = 'h'}, - [ASCOPYW] = {.fun = unary, .txt = "copy", .letter = 'w'}, - [ASCOPYL] = {.fun = unary, .txt = "copy", .letter = 'l'}, - [ASCOPYS] = {.fun = unary, .txt = "copy", .letter = 's'}, - [ASCOPYD] = {.fun = unary, .txt = "copy", .letter = 'd'}, - - [ASSTB] = {.fun = store, .txt = "store", .letter = 'b'}, - [ASSTH] = {.fun = store, .txt = "store", .letter = 'h'}, - [ASSTW] = {.fun = store, .txt = "store", .letter = 'w'}, - [ASSTL] = {.fun = store, .txt = "store", .letter = 'l'}, - [ASSTM] = {.fun = blit}, - [ASSTS] = {.fun = store, .txt = "store", .letter = 's'}, - [ASSTD] = {.fun = store, .txt = "store", .letter = 'd'}, - - [ASADDW] = {.fun = binary, .txt = "add", .letter = 'w'}, - [ASSUBW] = {.fun = binary, .txt = "sub", .letter = 'w'}, - [ASMULW] = {.fun = binary, .txt = "mul", .letter = 'w'}, - [ASMODW] = {.fun = binary, .txt = "rem", .letter = 'w'}, - [ASUMODW] = {.fun = binary, .txt = "urem", .letter = 'w'}, - [ASDIVW] = {.fun = binary, .txt = "div", .letter = 'w'}, - [ASUDIVW] = {.fun = binary, .txt = "udiv", .letter = 'w'}, - [ASSHLW] = {.fun = binary, .txt = "shl", .letter = 'w'}, - [ASSHRW] = {.fun = binary, .txt = "sar", .letter = 'w'}, - [ASUSHRW] = {.fun = binary, .txt = "shr", .letter = 'w'}, - [ASLTW] = {.fun = binary, .txt = "csltw", .letter = 'w'}, - [ASULTW] = {.fun = binary, .txt = "cultw", .letter = 'w'}, - [ASGTW] = {.fun = binary, .txt = "csgtw", .letter = 'w'}, - [ASUGTW] = {.fun = binary, .txt = "cugtw", .letter = 'w'}, - [ASLEW] = {.fun = binary, .txt = "cslew", .letter = 'w'}, - [ASULEW] = {.fun = binary, .txt = "culew", .letter = 'w'}, - [ASGEW] = {.fun = binary, .txt = "csgew", .letter = 'w'}, - [ASUGEW] = {.fun = binary, .txt = "cugew", .letter = 'w'}, - [ASEQW] = {.fun = binary, .txt = "ceqw", .letter = 'w'}, - [ASNEW] = {.fun = binary, .txt = "cnew", .letter = 'w'}, - [ASBANDW] = {.fun = binary, .txt = "and", .letter = 'w'}, - [ASBORW] = {.fun = binary, .txt = "or", .letter = 'w'}, - [ASBXORW] = {.fun = binary, .txt = "xor", .letter = 'w'}, - - [ASADDL] = {.fun = binary, .txt = "add", .letter = 'l'}, - [ASSUBL] = {.fun = binary, .txt = "sub", .letter = 'l'}, - [ASMULL] = {.fun = binary, .txt = "mul", .letter = 'l'}, - [ASMODL] = {.fun = binary, .txt = "rem", .letter = 'l'}, - [ASUMODL] = {.fun = binary, .txt = "urem", .letter = 'l'}, - [ASDIVL] = {.fun = binary, .txt = "div", .letter = 'l'}, - [ASUDIVL] = {.fun = binary, .txt = "udiv", .letter = 'l'}, - [ASSHLL] = {.fun = binary, .txt = "shl", .letter = 'l'}, - [ASSHRL] = {.fun = binary, .txt = "sar", .letter = 'l'}, - [ASUSHRL] = {.fun = binary, .txt = "shr", .letter = 'l'}, - [ASLTL] = {.fun = binary, .txt = "csltl", .letter = 'w'}, - [ASULTL] = {.fun = binary, .txt = "cultl", .letter = 'w'}, - [ASGTL] = {.fun = binary, .txt = "csgtl", .letter = 'w'}, - [ASUGTL] = {.fun = binary, .txt = "cugtl", .letter = 'w'}, - [ASLEL] = {.fun = binary, .txt = "cslel", .letter = 'w'}, - [ASULEL] = {.fun = binary, .txt = "culel", .letter = 'w'}, - [ASGEL] = {.fun = binary, .txt = "csgel", .letter = 'w'}, - [ASUGEL] = {.fun = binary, .txt = "cugel", .letter = 'w'}, - [ASEQL] = {.fun = binary, .txt = "ceql", .letter = 'w'}, - [ASNEL] = {.fun = binary, .txt = "cnel", .letter = 'w'}, - [ASBANDL] = {.fun = binary, .txt = "and", .letter = 'l'}, - [ASBORL] = {.fun = binary, .txt = "or", .letter = 'l'}, - [ASBXORL] = {.fun = binary, .txt = "xor", .letter = 'l'}, - - [ASADDS] = {.fun = binary, .txt = "add", .letter = 's'}, - [ASSUBS] = {.fun = binary, .txt = "sub", .letter = 's'}, - [ASMULS] = {.fun = binary, .txt = "mul", .letter = 's'}, - [ASDIVS] = {.fun = binary, .txt = "div", .letter = 's'}, - [ASLTS] = {.fun = binary, .txt = "clts", .letter = 'w'}, - [ASGTS] = {.fun = binary, .txt = "cgts", .letter = 'w'}, - [ASLES] = {.fun = binary, .txt = "cles", .letter = 'w'}, - [ASGES] = {.fun = binary, .txt = "cges", .letter = 'w'}, - [ASEQS] = {.fun = binary, .txt = "ceqs", .letter = 'w'}, - [ASNES] = {.fun = binary, .txt = "cnes", .letter = 'w'}, - - [ASADDD] = {.fun = binary, .txt = "add", .letter = 'd'}, - [ASSUBD] = {.fun = binary, .txt = "sub", .letter = 'd'}, - [ASMULD] = {.fun = binary, .txt = "mul", .letter = 'd'}, - [ASDIVD] = {.fun = binary, .txt = "div", .letter = 'd'}, - [ASLTD] = {.fun = binary, .txt = "cltd", .letter = 'w'}, - [ASGTD] = {.fun = binary, .txt = "cgtd", .letter = 'w'}, - [ASLED] = {.fun = binary, .txt = "cled", .letter = 'w'}, - [ASGED] = {.fun = binary, .txt = "cged", .letter = 'w'}, - [ASEQD] = {.fun = binary, .txt = "ceqd", .letter = 'w'}, - [ASNED] = {.fun = binary, .txt = "cned", .letter = 'w'}, - - [ASEXTBW] = {.fun = unary, .txt = "extsb", .letter = 'w'}, - [ASUEXTBW]= {.fun = unary, .txt = "extub", .letter = 'w'}, - [ASEXTBL] = {.fun = unary, .txt = "extsb", .letter = 'l'}, - [ASUEXTBL]= {.fun = unary, .txt = "extub", .letter = 'l'}, - [ASEXTHW] = {.fun = unary, .txt = "extsh", .letter = 'w'}, - [ASUEXTHW]= {.fun = unary, .txt = "extuh", .letter = 'w'}, - [ASEXTHL] = {.fun = unary, .txt = "extsh", .letter = 'l'}, - [ASUEXTHL]= {.fun = unary, .txt = "extuh", .letter = 'l'}, - [ASEXTWL] = {.fun = unary, .txt = "extsw", .letter = 'l'}, - [ASUEXTWL]= {.fun = unary, .txt = "extuw", .letter = 'l'}, - - [ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'}, - [ASSTOUL] = {.fun = unary, .txt = "stoui", .letter = 'l'}, - [ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'}, - [ASSTOUW] = {.fun = unary, .txt = "stoui", .letter = 'w'}, - [ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'}, - [ASDTOUL] = {.fun = unary, .txt = "dtoui", .letter = 'l'}, - [ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'}, - [ASDTOUW] = {.fun = unary, .txt = "dtoui", .letter = 'w'}, - - [ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'}, - [ASUWTOD] = {.fun = unary, .txt = "uwtof", .letter = 'd'}, - [ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'}, - [ASUWTOS] = {.fun = unary, .txt = "uwtof", .letter = 's'}, - [ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'}, - [ASULTOD] = {.fun = unary, .txt = "ultof", .letter = 'd'}, - [ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'}, - [ASULTOS] = {.fun = unary, .txt = "ultof", .letter = 's'}, - - [ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'}, - [ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'}, - - [ASBRANCH] = {.fun = branch}, - [ASJMP] = {.fun = jmp}, - [ASRET] = {.fun = ret}, - [ASCALL] = {.fun = call}, - [ASCALLE] = {.fun = ecall, .txt = ")"}, - [ASCALLEX] = {.fun = ecall, .txt = ", ...)"}, - [ASPAR] = {.fun = param, .txt = "%s %s, "}, - [ASPARE] = {.fun = param, .txt = "%s %s"}, - [ASALLOC] = {.fun = asalloc}, - [ASFORM] = {.fun = form2local}, - - [ASVSTAR] = {.fun = vastart}, - [ASVARG] = {.fun = vaarg}, -}; - -static char buff[ADDR_LEN]; -/* - * : is for user-defined Aggregate Types - * $ is for globals (represented by a pointer) - * % is for function-scope temporaries - * @ is for block labels - */ -static char -sigil(Symbol *sym) -{ - switch (sym->kind) { - case SEXTRN: - case SGLOB: - case SPRIV: - case SLOCAL: - return '$'; - case SAUTO: - case STMP: - return '%'; - case SLABEL: - return '@'; - default: - abort(); - } -} - -static char * -symname(Symbol *sym) -{ - char c = sigil(sym); - - if (sym->name) { - switch (sym->kind) { - case SEXTRN: - case SGLOB: - sprintf(buff, "%c%s", c, sym->name); - return buff; - case SLOCAL: - case SPRIV: - case SAUTO: - sprintf(buff, "%c%s.L%u", c, sym->name, sym->id); - return buff; - default: - abort(); - } - } - sprintf(buff, "%c.L%u", c, sym->numid); - - return buff; -} - -static void -emitconst(Node *np) -{ - switch (np->type.size) { - case 1: - printf("%d", (int) np->u.i & 0xFF); - break; - case 2: - printf("%d", (int) np->u.i & 0xFFFF); - break; - case 4: - printf("%ld", (long) np->u.i & 0xFFFFFFFF); - break; - case 8: - printf("%lld", (long long) np->u.i); - break; - default: - abort(); - } -} - -static void -emittree(Node *np) -{ - if (!np) - return; - - switch (np->op) { - case OSTRING: - pprint(np->u.s); - free(np->u.s); - np->u.s = NULL; - break; - case OCONST: - emitconst(np); - break; - case OADDR: - emittree(np->left); - break; - case OMEM: - fputs(symname(np->u.sym), stdout); - break; - default: - emittree(np->left); - printf(" %c ", np->op); - emittree(np->right); - break; - } -} - -static char * -size2asm(Type *tp) -{ - static char spec[ADDR_LEN]; - - if (tp->flags & STRF) { - return "b"; - } else if (tp->flags & INTF) { - switch (tp->size) { - case 1: - return "b"; - case 2: - return "h"; - case 4: - return "w"; - case 8: - return "l"; - } - } else if (tp->flags & FLOATF) { - if (tp->size == 4) - return "s"; - else if (tp->size == 8) - return "d"; - } - - abort(); -} - -void -defglobal(Symbol *sym) -{ - Type *tp = &sym->type; - - if (sym->kind == SEXTRN) - return; - if (sym->kind == SGLOB) - fputs("export ", stdout); - if ((tp->flags & INITF) == 0) - fputs("common ", stdout); - - printf("data %s = align %d {\n", - symname(sym), - tp->align); - if ((tp->flags & INITF) == 0) - printf("\tz\t%lu\n}\n", tp->size); -} - -void -defpar(Symbol *sym) -{ - if (sym->kind == SREG) - sym->kind = SAUTO; - sym->type.flags |= PARF; -} - -void -defvar(Symbol *sym) -{ - if (sym->kind == SREG) - sym->kind = SAUTO; -} - -void -data(Node *np) -{ - printf("\t%s\t", size2asm(&np->type)); - emittree(np); - putchar(','); - putchar('\n'); -} - -static char * -size2stack(Type *tp) -{ - static char spec[ADDR_LEN]; - - if (tp->flags & INTF) { - switch (tp->size) { - case 1: - case 2: - case 4: - return "w"; - case 8: - return "l"; - } - } else if (tp->flags & FLOATF) { - if (tp->size == 4) - return "s"; - else if (tp->size == 8) - return "d"; - } else if (tp->flags & (ARRF|AGGRF)) { - sprintf(spec, ":.%u", tp->id); - return spec; - } else if (tp->size == 0) { - return "w"; - } - abort(); -} - -void -deftype(Type *tp) -{ - printf("type :.%u = align %d { %lu }\n", - tp->id, tp->align, tp->size); -} - -void -writeout(void) -{ - Symbol *p; - Type *tp; - char *sep; - int haslabel = 0; - - if (!curfun) - return; - if (curfun->kind == SGLOB) - fputs("export ", stdout); - printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun)); - - /* declare formal parameters */ - sep = ""; - for (p = locals; p; p = p->next) { - if ((p->type.flags & PARF) == 0) - continue; - printf("%s%s %s%s", - sep, size2stack(&p->type), - symname(p), - (p->type.flags & AGGRF) ? "" : ".val"); - sep = ","; - } - printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : ""); - - /* emit assembler instructions */ - for (pc = prog; pc; pc = pc->next) { - if (pc->label) { - haslabel = 1; - printf("%s\n", symname(pc->label)); - } - if (pc->op == ASLABEL) - continue; - if (pc->flags&BBENTRY && !haslabel) - printf("%s\n", symname(newlabel())); - (*optbl[pc->op].fun)(); - if (!pc->label) - haslabel = 0; - } - - puts("}"); -} - -static char * -addr2txt(Addr *a) -{ - switch (a->kind) { - case SCONST: - sprintf(buff, "%llu", (unsigned long long) a->u.i); - return buff; - case SAUTO: - case SLABEL: - case STMP: - case SGLOB: - case SEXTRN: - case SPRIV: - case SLOCAL: - return symname(a->u.sym); - default: - abort(); - } -} - -static void -binary(void) -{ - struct opdata *p = &optbl[pc->op]; - char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN]; - - strcpy(to, addr2txt(&pc->to)); - strcpy(from1, addr2txt(&pc->from1)); - strcpy(from2, addr2txt(&pc->from2)); - printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2); -} - -static void -blit(void) -{ - Type *tp = &pc->to.u.sym->type; - char to[ADDR_LEN], from[ADDR_LEN]; - - strcpy(to, addr2txt(&pc->to)); - strcpy(from, addr2txt(&pc->from1)); - printf("\t\tblit\t%s,%s,%lu\n", from, to, tp->size); -} - -static void -store(void) -{ - struct opdata *p = &optbl[pc->op]; - char to[ADDR_LEN], from[ADDR_LEN]; - - strcpy(to, addr2txt(&pc->to)); - strcpy(from, addr2txt(&pc->from1)); - printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to); -} - -static void -unary(void) -{ - struct opdata *p = &optbl[pc->op]; - char to[ADDR_LEN], from[ADDR_LEN]; - - strcpy(to, addr2txt(&pc->to)); - strcpy(from, addr2txt(&pc->from1)); - printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from); -} - -static void -call(void) -{ - char to[ADDR_LEN], from[ADDR_LEN]; - Symbol *sym = pc->to.u.sym; - - strcpy(to, addr2txt(&pc->to)); - strcpy(from, addr2txt(&pc->from1)); - printf("\t%s =%s\tcall\t%s(", - to, size2stack(&sym->type), from); -} - -static void -param(void) -{ - Symbol *sym = pc->from2.u.sym; - - printf(optbl[pc->op].txt, - size2stack(&sym->type), addr2txt(&pc->from1)); -} - -static void -ecall(void) -{ - struct opdata *p = &optbl[pc->op]; - - puts(p->txt); -} - -static void -ret(void) -{ - if (pc->from1.kind == SNONE) - puts("\t\tret"); - else - printf("\t\tret\t%s\n", addr2txt(&pc->from1)); -} - -static void -jmp(void) -{ - printf("\t\tjmp\t%s\n", addr2txt(&pc->from1)); -} - -static void -branch(void) -{ - char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN]; - - strcpy(to, addr2txt(&pc->to)); - strcpy(from1, addr2txt(&pc->from1)); - strcpy(from2, addr2txt(&pc->from2)); - printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2); -} - -static void -vastart(void) -{ - printf("\t\tvastart %s\n", addr2txt(&pc->from1)); -} - -static void -vaarg(void) -{ - Symbol *sym = pc->to.u.sym; - Type *tp = &sym->type; - char to[ADDR_LEN], from[ADDR_LEN]; - - strcpy(to, addr2txt(&pc->to)); - strcpy(from, addr2txt(&pc->from1)); - printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from); -} - -static void -asalloc(void) -{ - Symbol *sym = pc->to.u.sym; - Type *tp = &sym->type; - extern Type ptrtype; - - printf("\t%s =%s\talloc%lu\t%lu\n", - symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size); -} - -static void -form2local(void) -{ - Symbol *sym = pc->to.u.sym; - Type *tp = &sym->type; - char *name = symname(sym); - - printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name); -} - -void -endinit(void) -{ - puts("}"); -} - -void -getbblocks(void) -{ - Inst *i; - - if (!prog) - return; - - prog->flags |= BBENTRY; - for (pc = prog; pc; pc = pc->next) { - switch (pc->op) { - case ASBRANCH: - i = pc->from2.u.sym->u.inst; - i->flags |= BBENTRY; - case ASJMP: - i = pc->from1.u.sym->u.inst; - i->flags |= BBENTRY; - case ASRET: - if (pc->next) - pc->next->flags |= BBENTRY; - break; - } - } -} diff --git a/src/cmd/scc-cc/cc2/target/qbe/optm.c b/src/cmd/scc-cc/cc2/target/qbe/optm.c @@ -1,56 +0,0 @@ -#include <stddef.h> - -#include <scc/scc.h> - -#include "../../cc2.h" - -Node * -optm_dep(Node *np) -{ - int op = np->op; - Node *p, *dst, *next = np->next; - Symbol *sym, *osym; - - switch (op) { - case OEFUN: - /* - * In QBE we need at the end of a basic block - * a jump, so we have to ensure that the last - * statement of the function is a ret, a jmp - * or a branch. In the same way, QBE does - * not accept labels at the end of a function - * (ONOP is used for labels) so we have to add - * a ret there, and in the case of branches - * we need a label for the next statement - */ - op = (np->prev) ? np->prev->op : 0; - if (!op || op == ONOP || op == OBRANCH || (op != ORET && op != OJMP)) - addstmt(node(ORET), KEEPCUR); - break; - case OBRANCH: - if (!next->label) { - sym = getsym(TMPSYM); - sym->kind = SLABEL; - next->label = sym; - } - case OJMP: - for (;;) { - dst = np->u.sym->u.stmt; - if (dst->op != OJMP) - break; - np->u.sym = dst->u.sym; - } - for (p = np->next; p; p = p->next) { - if (p == dst) - return NULL; - if (p->op == ONOP || - p->op == OBLOOP || - p->op == OELOOP) { - continue; - } - break; - } - break; - } - return np; -} diff --git a/src/cmd/scc-cc/cc2/target/qbe_amd64-sysv/target.mk b/src/cmd/scc-cc/cc2/target/qbe_amd64-sysv/target.mk @@ -1,9 +0,0 @@ -OBJ-qbe_amd64-sysv = $(OBJS) \ - target/qbe/cgen.o \ - target/qbe/optm.o \ - target/qbe/code.o \ - target/amd64-sysv/types.o - -cc2-qbe_amd64-sysv: $(LIBSCC) $(OBJ-qbe_amd64-sysv) - $(CC) $(PROJ_LDFLAGS) $(OBJ-qbe_amd64-sysv) -lscc $(PROJ_LDLIBS) -o $@ - cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-cc/cc2/target/qbe_arm64-sysv/target.mk b/src/cmd/scc-cc/cc2/target/qbe_arm64-sysv/target.mk @@ -1,9 +0,0 @@ -OBJ-qbe_arm64-sysv = $(OBJS) \ - target/qbe/cgen.o \ - target/qbe/optm.o \ - target/qbe/code.o \ - target/arm64-sysv/types.o \ - -cc2-qbe_arm64-sysv: $(LIBSCC) $(OBJ-qbe_arm64-sysv) - $(CC) $(PROJ_LDFLAGS) $(OBJ-qbe_arm64-sysv) -lscc $(PROJ_LDLIBS) -o $@ - cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-cc/cc2/target/z80-scc/cgen.c b/src/cmd/scc-cc/cc2/target/z80-scc/cgen.c @@ -1,159 +0,0 @@ -#include <stdlib.h> - -#include <scc/scc.h> - -#include "arch.h" -#include "../../cc2.h" - -static void -swtch(Node *idx) -{ -} - -static Node * -rhs(Node *np, Node *ret) -{ -} - -static Node * -field(Node *np, Node *ret, int islhs) -{ -} - -static Node * -lhs(Node *np, Node *new) -{ - switch (np->op) { - case OMEM: - case OAUTO: - *new = *np; - return new; - case OPTR: - return rhs(np->left, new); - case OFIELD: - return field(np, new, 1); - default: - abort(); - } -} - -static void -bool(Node *np, Symbol *true, Symbol *false) -{ - Node *l = np->left, *r = np->right; - Node ret, ifyes, ifno; - Symbol *label; - - switch (np->op) { - case ONEG: - bool(l, false, true); - break; - case OAND: - label = newlabel(); - bool(l, label, false); - setlabel(label); - bool(r, true, false); - break; - case OOR: - label = newlabel(); - bool(l, true, label); - setlabel(label); - bool(r, true, false); - break; - default: - label2node(&ifyes, true); - label2node(&ifno, false); - code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno); - break; - } -} - -Node * -cgen(Node *np) -{ - Node aux, *p, *next; - - setlabel(np->label); - switch (np->op) { - case OJMP: - label2node(&aux, np->u.sym); - code(ASJMP, NULL, &aux, NULL); - break; - case OBRANCH: - next = np->next; - if (!next->label) - next->label = newlabel(); - bool(np->left, np->u.sym, next->label); - break; - case ORET: - p = np->left; - if (p) - p = rhs(np->left, &aux); - code(ASRET, NULL, p, NULL); - break; - case OBSWITCH: - swtch(rhs(np->left, &aux)); - break; - default: - rhs(np, &aux); - break; - } - return NULL; -} - -/* - * This is strongly influenced by - * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps) - * calculate addresability as follows - * AUTO => 11 value+fp - * REG => 13 reg - * STATIC => 12 (value) - * CONST => 20 $value - */ -Node * -sethi(Node *np) -{ - Node *lp, *rp; - - if (!np) - return np; - - np->complex = 0; - np->address = 0; - lp = np->left; - rp = np->right; - switch (np->op) { - case OAUTO: - np->address = 11; - break; - case OREG: - np->address = 13; - break; - case OMEM: - np->address = 12; - break; - case OCONST: - np->address = 20; - break; - default: - sethi(lp); - sethi(rp); - break; - } - - if (np->address > 10) - return np; - if (lp) - np->complex = lp->complex; - if (rp) { - int d = np->complex - rp->complex; - - if (d == 0) - ++np->complex; - else if (d < 0) - np->complex = rp->complex; - } - if (np->complex == 0) - ++np->complex; - return np; -} diff --git a/src/cmd/scc-cc/cc2/target/z80-scc/code.c b/src/cmd/scc-cc/cc2/target/z80-scc/code.c @@ -1,232 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -#include <scc/cstd.h> -#include <scc/scc.h> - -#include "arch.h" -#include "../../cc2.h" - -enum segment { - CODESEG, - DATASEG, - BSSSEG, - NOSEG -}; - -static int curseg = NOSEG; -static unsigned long offpar, offvar; - -static void -segment(int seg) -{ - static char *txt[] = { - [CODESEG] = "\tCSEG\n", - [DATASEG] = "\tDSEG\n", - [BSSSEG] = "\tASEG\n", - }; - - if (seg == curseg) - return; - fputs(txt[seg], stdout); - curseg = seg; -} - -static char * -symname(Symbol *sym) -{ - static char name[INTIDENTSIZ+1]; - - if (sym->name) { - switch (sym->kind) { - case SGLOB: - case SEXTRN: - snprintf(name, sizeof(name), "_%s", sym->name); - return name; - case SPRIV: - return sym->name; - } - } - - sprintf(name, ".%d", sym->numid); - - return name; -} - -static void -label(Symbol *sym) -{ - int seg; - char *name = symname(sym); - - if (sym->type.flags & FUNF) - seg = CODESEG; - else if (sym->type.flags & INITF) - seg = DATASEG; - else - seg = BSSSEG; - segment(seg); - - switch (sym->kind) { - case SEXTRN: - printf("\tEXTRN\t%s\n", name); - return; - case SGLOB: - printf("\tPUBLIC\t%s\n", name); - break; - } - - printf("%s:\n", name); -} - -static void -emitconst(Node *np) -{ - switch (np->type.size) { - case 1: - printf("%d", (int) np->u.i & 0xFF); - break; - case 2: - printf("%d", (int) np->u.i & 0xFFFF); - break; - case 4: - printf("%ld", (long) np->u.i & 0xFFFFFFFF); - break; - default: - abort(); - } -} - -static void -emittree(Node *np) -{ - if (!np) - return; - - switch (np->op) { - case OSTRING: - pprint(np->u.s); - free(np->u.s); - np->u.s = NULL; - break; - case OCONST: - emitconst(np); - break; - case OADDR: - emittree(np->left); - break; - case OMEM: - fputs(symname(np->u.sym), stdout); - break; - default: - emittree(np->left); - printf(" %c ", np->op); - emittree(np->right); - break; - } -} - -static void -size2asm(Type *tp) -{ - char *s; - - /* - * In z80 we can ignore the alignment - */ - if (tp->flags & STRF) { - s = "\tDB\t"; - } else { - switch (tp->size) { - case 1: - s = "\tDB\t"; - break; - case 2: - s = "\tDW\t"; - break; - case 4: - s = "\tDD\t"; - break; - default: - s = "\tDS\t%lu,"; - break; - } - } - printf(s, tp->size); -} - -void -newfun() -{ - offpar = offvar = 0; -} - -void -defpar(Symbol *sym) -{ - unsigned long align, size; - - if (sym->kind != SREG && sym->kind != SAUTO) - return; - align = sym->type.align; - size = sym->type.size; - - offpar -= align-1 & ~align; - sym->u.off = offpar; - offpar -= size; - sym->kind = SAUTO; -} - -void -defvar(Symbol *sym) -{ - unsigned long align, size; - - if (sym->kind != SREG && sym->kind != SAUTO) - return; - align = sym->type.align; - size = sym->type.size; - - offvar += align-1 & ~align; - sym->u.off = offvar; - offvar += size; - sym->kind = SAUTO; -} - -void -deftype(Type *tp) -{ -} - -void -defglobal(Symbol *sym) -{ - label(sym); - if (sym->kind == SEXTRN || (sym->type.flags & INITF)) - return; - size2asm(&sym->type); - puts("0"); -} - -void -data(Node *np) -{ - size2asm(&np->type); - emittree(np); - putchar('\n'); -} - -void -writeout(void) -{ -} - -void -endinit(void) -{ -} - -void -getbblocks(void) -{ -} diff --git a/src/cmd/scc-cc/cc2/target/z80-scc/optm.c b/src/cmd/scc-cc/cc2/target/z80-scc/optm.c @@ -1,9 +0,0 @@ -#include <scc/scc.h> - -#include "../../cc2.h" - -Node * -optm_dep(Node *np) -{ - return np; -} diff --git a/src/cmd/scc-cc/cc2/target/z80-scc/target.mk b/src/cmd/scc-cc/cc2/target/z80-scc/target.mk @@ -1,9 +0,0 @@ -OBJ-z80-scc = $(OBJS) \ - target/z80-scc/cgen.o \ - target/z80-scc/optm.o \ - target/z80-scc/code.o \ - target/z80-scc/types.o \ - -cc2-z80-scc: $(LIBSCC) $(OBJ-z80-scc) - $(CC) $(PROJ_LDFLAGS) $(OBJ-z80-scc) -lscc $(PROJ_LDLIBS) -o $@ - cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-cc/cc2/target/z80-scc/types.c b/src/cmd/scc-cc/cc2/target/z80-scc/types.c @@ -1,92 +0,0 @@ -#include <scc/scc.h> - -#include "../../cc2.h" - - -Type int8type = { - .flags = SIGNF | INTF, - .size = 1, - .align = 1 -}; - -Type int16type = { - .flags = SIGNF | INTF, - .size = 2, - .align = 1 -}; - -Type int32type = { - .flags = SIGNF | INTF, - .size = 4, - .align = 1 -}; - -Type int64type = { - .flags = SIGNF | INTF, - .size = 8, - .align = 1 -}; - -Type uint8type = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type uint16type = { - .flags = INTF, - .size = 2, - .align = 1 -}; - -Type uint32type = { - .flags = INTF, - .size = 4, - .align = 1 -}; - -Type uint64type = { - .flags = INTF, - .size = 8, - .align = 1 -}; - -Type ptrtype = { - .flags = INTF, - .size = 2, - .align = 1 -}; - -Type booltype = { - .flags = INTF, - .size = 1, - .align = 1 -}; - -Type float32type = { - .flags = FLOATF, - .size = 4, - .align = 1 -}; - -Type float64type = { - .flags = FLOATF, - .size = 4, - .align = 1 -}; - -Type float80type = { - .flags = FLOATF, - .size = 4, - .align = 1 -}; - -Type voidtype = { - .size = 0, - .align = 0 -}; - -Type arg_type = { - .size = 2, - .align = 1 -}; diff --git a/src/cmd/scc-cc/cc2/target/z80-scc/arch.h b/src/cmd/scc-cc/cc2/z80-scc/arch.h diff --git a/src/cmd/scc-cc/cc2/z80-scc/cgen.c b/src/cmd/scc-cc/cc2/z80-scc/cgen.c @@ -0,0 +1,159 @@ +#include <stdlib.h> + +#include <scc/scc.h> + +#include "arch.h" +#include "../cc2.h" + +static void +swtch(Node *idx) +{ +} + +static Node * +rhs(Node *np, Node *ret) +{ +} + +static Node * +field(Node *np, Node *ret, int islhs) +{ +} + +static Node * +lhs(Node *np, Node *new) +{ + switch (np->op) { + case OMEM: + case OAUTO: + *new = *np; + return new; + case OPTR: + return rhs(np->left, new); + case OFIELD: + return field(np, new, 1); + default: + abort(); + } +} + +static void +bool(Node *np, Symbol *true, Symbol *false) +{ + Node *l = np->left, *r = np->right; + Node ret, ifyes, ifno; + Symbol *label; + + switch (np->op) { + case ONEG: + bool(l, false, true); + break; + case OAND: + label = newlabel(); + bool(l, label, false); + setlabel(label); + bool(r, true, false); + break; + case OOR: + label = newlabel(); + bool(l, true, label); + setlabel(label); + bool(r, true, false); + break; + default: + label2node(&ifyes, true); + label2node(&ifno, false); + code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno); + break; + } +} + +Node * +cgen(Node *np) +{ + Node aux, *p, *next; + + setlabel(np->label); + switch (np->op) { + case OJMP: + label2node(&aux, np->u.sym); + code(ASJMP, NULL, &aux, NULL); + break; + case OBRANCH: + next = np->next; + if (!next->label) + next->label = newlabel(); + bool(np->left, np->u.sym, next->label); + break; + case ORET: + p = np->left; + if (p) + p = rhs(np->left, &aux); + code(ASRET, NULL, p, NULL); + break; + case OBSWITCH: + swtch(rhs(np->left, &aux)); + break; + default: + rhs(np, &aux); + break; + } + return NULL; +} + +/* + * This is strongly influenced by + * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps) + * calculate addresability as follows + * AUTO => 11 value+fp + * REG => 13 reg + * STATIC => 12 (value) + * CONST => 20 $value + */ +Node * +sethi(Node *np) +{ + Node *lp, *rp; + + if (!np) + return np; + + np->complex = 0; + np->address = 0; + lp = np->left; + rp = np->right; + switch (np->op) { + case OAUTO: + np->address = 11; + break; + case OREG: + np->address = 13; + break; + case OMEM: + np->address = 12; + break; + case OCONST: + np->address = 20; + break; + default: + sethi(lp); + sethi(rp); + break; + } + + if (np->address > 10) + return np; + if (lp) + np->complex = lp->complex; + if (rp) { + int d = np->complex - rp->complex; + + if (d == 0) + ++np->complex; + else if (d < 0) + np->complex = rp->complex; + } + if (np->complex == 0) + ++np->complex; + return np; +} diff --git a/src/cmd/scc-cc/cc2/z80-scc/code.c b/src/cmd/scc-cc/cc2/z80-scc/code.c @@ -0,0 +1,232 @@ +#include <stdio.h> +#include <stdlib.h> + +#include <scc/cstd.h> +#include <scc/scc.h> + +#include "arch.h" +#include "../cc2.h" + +enum segment { + CODESEG, + DATASEG, + BSSSEG, + NOSEG +}; + +static int curseg = NOSEG; +static unsigned long offpar, offvar; + +static void +segment(int seg) +{ + static char *txt[] = { + [CODESEG] = "\tCSEG\n", + [DATASEG] = "\tDSEG\n", + [BSSSEG] = "\tASEG\n", + }; + + if (seg == curseg) + return; + fputs(txt[seg], stdout); + curseg = seg; +} + +static char * +symname(Symbol *sym) +{ + static char name[INTIDENTSIZ+1]; + + if (sym->name) { + switch (sym->kind) { + case SGLOB: + case SEXTRN: + snprintf(name, sizeof(name), "_%s", sym->name); + return name; + case SPRIV: + return sym->name; + } + } + + sprintf(name, ".%d", sym->numid); + + return name; +} + +static void +label(Symbol *sym) +{ + int seg; + char *name = symname(sym); + + if (sym->type.flags & FUNF) + seg = CODESEG; + else if (sym->type.flags & INITF) + seg = DATASEG; + else + seg = BSSSEG; + segment(seg); + + switch (sym->kind) { + case SEXTRN: + printf("\tEXTRN\t%s\n", name); + return; + case SGLOB: + printf("\tPUBLIC\t%s\n", name); + break; + } + + printf("%s:\n", name); +} + +static void +emitconst(Node *np) +{ + switch (np->type.size) { + case 1: + printf("%d", (int) np->u.i & 0xFF); + break; + case 2: + printf("%d", (int) np->u.i & 0xFFFF); + break; + case 4: + printf("%ld", (long) np->u.i & 0xFFFFFFFF); + break; + default: + abort(); + } +} + +static void +emittree(Node *np) +{ + if (!np) + return; + + switch (np->op) { + case OSTRING: + pprint(np->u.s); + free(np->u.s); + np->u.s = NULL; + break; + case OCONST: + emitconst(np); + break; + case OADDR: + emittree(np->left); + break; + case OMEM: + fputs(symname(np->u.sym), stdout); + break; + default: + emittree(np->left); + printf(" %c ", np->op); + emittree(np->right); + break; + } +} + +static void +size2asm(Type *tp) +{ + char *s; + + /* + * In z80 we can ignore the alignment + */ + if (tp->flags & STRF) { + s = "\tDB\t"; + } else { + switch (tp->size) { + case 1: + s = "\tDB\t"; + break; + case 2: + s = "\tDW\t"; + break; + case 4: + s = "\tDD\t"; + break; + default: + s = "\tDS\t%lu,"; + break; + } + } + printf(s, tp->size); +} + +void +newfun() +{ + offpar = offvar = 0; +} + +void +defpar(Symbol *sym) +{ + unsigned long align, size; + + if (sym->kind != SREG && sym->kind != SAUTO) + return; + align = sym->type.align; + size = sym->type.size; + + offpar -= align-1 & ~align; + sym->u.off = offpar; + offpar -= size; + sym->kind = SAUTO; +} + +void +defvar(Symbol *sym) +{ + unsigned long align, size; + + if (sym->kind != SREG && sym->kind != SAUTO) + return; + align = sym->type.align; + size = sym->type.size; + + offvar += align-1 & ~align; + sym->u.off = offvar; + offvar += size; + sym->kind = SAUTO; +} + +void +deftype(Type *tp) +{ +} + +void +defglobal(Symbol *sym) +{ + label(sym); + if (sym->kind == SEXTRN || (sym->type.flags & INITF)) + return; + size2asm(&sym->type); + puts("0"); +} + +void +data(Node *np) +{ + size2asm(&np->type); + emittree(np); + putchar('\n'); +} + +void +writeout(void) +{ +} + +void +endinit(void) +{ +} + +void +getbblocks(void) +{ +} diff --git a/src/cmd/scc-cc/cc2/z80-scc/optm.c b/src/cmd/scc-cc/cc2/z80-scc/optm.c @@ -0,0 +1,9 @@ +#include <scc/scc.h> + +#include "../cc2.h" + +Node * +optm_dep(Node *np) +{ + return np; +} diff --git a/src/cmd/scc-cc/cc2/z80-scc/target.mk b/src/cmd/scc-cc/cc2/z80-scc/target.mk @@ -0,0 +1,9 @@ +OBJ-z80-scc = $(OBJS) \ + z80-scc/cgen.o \ + z80-scc/optm.o \ + z80-scc/code.o \ + z80-scc/types.o \ + +cc2-z80-scc: $(LIBSCC) $(OBJ-z80-scc) + $(CC) $(PROJ_LDFLAGS) $(OBJ-z80-scc) -lscc $(PROJ_LDLIBS) -o $@ + cp $@ $(LIBEXEC)/scc diff --git a/src/cmd/scc-cc/cc2/z80-scc/types.c b/src/cmd/scc-cc/cc2/z80-scc/types.c @@ -0,0 +1,92 @@ +#include <scc/scc.h> + +#include "../cc2.h" + + +Type int8type = { + .flags = SIGNF | INTF, + .size = 1, + .align = 1 +}; + +Type int16type = { + .flags = SIGNF | INTF, + .size = 2, + .align = 1 +}; + +Type int32type = { + .flags = SIGNF | INTF, + .size = 4, + .align = 1 +}; + +Type int64type = { + .flags = SIGNF | INTF, + .size = 8, + .align = 1 +}; + +Type uint8type = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type uint16type = { + .flags = INTF, + .size = 2, + .align = 1 +}; + +Type uint32type = { + .flags = INTF, + .size = 4, + .align = 1 +}; + +Type uint64type = { + .flags = INTF, + .size = 8, + .align = 1 +}; + +Type ptrtype = { + .flags = INTF, + .size = 2, + .align = 1 +}; + +Type booltype = { + .flags = INTF, + .size = 1, + .align = 1 +}; + +Type float32type = { + .flags = FLOATF, + .size = 4, + .align = 1 +}; + +Type float64type = { + .flags = FLOATF, + .size = 4, + .align = 1 +}; + +Type float80type = { + .flags = FLOATF, + .size = 4, + .align = 1 +}; + +Type voidtype = { + .size = 0, + .align = 0 +}; + +Type arg_type = { + .size = 2, + .align = 1 +};