ref: 6e6db2755b917179743b1f7649aa8b71a7dac8fc
parent: 8addbdbc991cb4718e15bf16ce7f203faa1227f6
parent: 56a192ced907bcc27405b85e120abb3005f9d981
author: Ori Bernstein <[email protected]>
date: Fri Oct 10 00:04:09 EDT 2014
Merge branch 'master' of git+ssh://mimir.eigenstate.org/git/ori/mc
--- a/6/Makefile
+++ b/6/Makefile
@@ -1,9 +1,12 @@
INSTBIN=6m
-OBJ=isel.o \
- locs.o \
- main.o \
- ra.o \
- simp.o \
+OBJ= \
+ gen.o \
+ isel.o \
+ locs.o \
+ main.o \
+ ra.o \
+ simp.o \
+ typeinfo.o \
DEPS=../parse/libparse.a ../opt/libmi.a
--- a/6/asm.h
+++ b/6/asm.h
@@ -185,15 +185,18 @@
Bitset *initial; /* initial set of locations used by this fn */
};
+/* globals */
extern char *modenames[];
+extern Type *tyintptr;
+extern Type *tyword;
+extern Type *tyvoid;
+extern Node *abortoob;
/* options */
extern int extracheck;
-/* entry points */
-void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab);
-void genasm(FILE *fd, Func *fn, Htab *globls, Htab *strtab);
-void genstrings(FILE *fd, Htab *strtab);
+void simpglobl(Node *dcl, Htab *globls, Func ***fn, size_t *nfn, Node ***blob, size_t *nblob);
+void selfunc(Isel *is, Func *fn, Htab *globls, Htab *strtab);
void gen(Node *file, char *out);
/* location generation */
@@ -212,15 +215,15 @@
Loc *locmemls(char *disp, Loc *base, Loc *idx, int scale, Mode mode);
Loc *loclit(long val, Mode m);
Loc *loclitl(char *lbl);
+char *asmname(Node *n);
Loc *coreg(Reg r, Mode m);
int isfloatmode(Mode m);
int isintmode(Mode m);
-void locprint(FILE *fd, Loc *l, char spec);
-void iprintf(FILE *fd, Insn *insn);
-
/* emitting instructions */
Insn *mkinsn(AsmOp op, ...);
+void iprintf(FILE *fd, Insn *insn);
+void locprint(FILE *fd, Loc *l, char spec);
/* register allocation */
extern char *regnames[]; /* name table */
@@ -233,6 +236,8 @@
/* useful functions */
size_t tysize(Type *t);
size_t size(Node *n);
+size_t tyoffset(Type *ty, Node *memb);
+size_t offset(Node *aggr, Node *memb);
int stacktype(Type *t);
int floattype(Type *t);
int stacknode(Node *n);
--- /dev/null
+++ b/6/gen.c
@@ -1,0 +1,524 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+#include "opt.h"
+#include "asm.h"
+#include "../config.h"
+
+/* string tables */
+char *insnfmts[] = {
+#define Insn(val, fmt, use, def) fmt,
+#include "insns.def"
+#undef Insn
+};
+
+char* modenames[] = {
+ [ModeB] = "b",
+ [ModeW] = "w",
+ [ModeL] = "l",
+ [ModeQ] = "q",
+ [ModeF] = "s",
+ [ModeD] = "d"
+};
+
+
+static size_t writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *blob);
+
+static void fillglobls(Stab *st, Htab *globls)
+{
+ void **k;
+ size_t i, nk;
+ Stab *stab;
+ Node *s;
+
+ k = htkeys(st->dcl, &nk);
+ for (i = 0; i < nk; i++) {
+ s = htget(st->dcl, k[i]);
+ htput(globls, s, asmname(s->decl.name));
+ }
+ free(k);
+
+ k = htkeys(st->ns, &nk);
+ for (i = 0; i < nk; i++) {
+ stab = htget(st->ns, k[i]);
+ fillglobls(stab, globls);
+ }
+ free(k);
+}
+
+static void initconsts(Htab *globls)
+{
+ Type *ty;
+ Node *name;
+ Node *dcl;
+
+ tyintptr = mktype(Zloc, Tyuint64);
+ tyword = mktype(Zloc, Tyuint);
+ tyvoid = mktype(Zloc, Tyvoid);
+
+ ty = mktyfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid));
+ name = mknsname(Zloc, "_rt", "abort_oob");
+ dcl = mkdecl(Zloc, name, ty);
+ dcl->decl.isconst = 1;
+ dcl->decl.isextern = 1;
+ htput(globls, dcl, asmname(dcl->decl.name));
+
+ abortoob = mkexpr(Zloc, Ovar, name, NULL);
+ abortoob->expr.type = ty;
+ abortoob->expr.did = dcl->decl.did;
+ abortoob->expr.isconst = 1;
+}
+
+void locprint(FILE *fd, Loc *l, char spec)
+{
+ assert(l->mode);
+ switch (l->type) {
+ case Loclitl:
+ assert(spec == 'i' || spec == 'x' || spec == 'u');
+ fprintf(fd, "$%s", l->lbl);
+ break;
+ case Loclbl:
+ assert(spec == 'm' || spec == 'v' || spec == 'x');
+ fprintf(fd, "%s", l->lbl);
+ break;
+ case Locreg:
+ assert((spec == 'r' && isintmode(l->mode)) ||
+ (spec == 'f' && isfloatmode(l->mode)) ||
+ spec == 'v' ||
+ spec == 'x' ||
+ spec == 'u');
+ if (l->reg.colour == Rnone)
+ fprintf(fd, "%%P.%zd%s", l->reg.id, modenames[l->mode]);
+ else
+ fprintf(fd, "%s", regnames[l->reg.colour]);
+ break;
+ case Locmem:
+ case Locmeml:
+ assert(spec == 'm' || spec == 'v' || spec == 'x');
+ if (l->type == Locmem) {
+ if (l->mem.constdisp)
+ fprintf(fd, "%ld", l->mem.constdisp);
+ } else {
+ if (l->mem.lbldisp)
+ fprintf(fd, "%s", l->mem.lbldisp);
+ }
+ if (l->mem.base) {
+ fprintf(fd, "(");
+ locprint(fd, l->mem.base, 'r');
+ if (l->mem.idx) {
+ fprintf(fd, ",");
+ locprint(fd, l->mem.idx, 'r');
+ }
+ if (l->mem.scale > 1)
+ fprintf(fd, ",%d", l->mem.scale);
+ if (l->mem.base)
+ fprintf(fd, ")");
+ } else if (l->type != Locmeml) {
+ die("Only locmeml can have unspecified base reg");
+ }
+ break;
+ case Loclit:
+ assert(spec == 'i' || spec == 'x' || spec == 'u');
+ fprintf(fd, "$%ld", l->lit);
+ break;
+ case Locnone:
+ die("Bad location in locprint()");
+ break;
+ }
+}
+
+static int issubreg(Loc *a, Loc *b)
+{
+ return rclass(a) == rclass(b) && a->mode != b->mode;
+}
+
+void iprintf(FILE *fd, Insn *insn)
+{
+ char *p;
+ int i;
+ int modeidx;
+
+ /* x64 has a quirk; it has no movzlq because mov zero extends. This
+ * means that we need to do a movl when we really want a movzlq. Since
+ * we don't know the name of the reg to use, we need to sub it in when
+ * writing... */
+ switch (insn->op) {
+ case Imovzx:
+ if (insn->args[0]->mode == ModeL && insn->args[1]->mode == ModeQ) {
+ if (insn->args[1]->reg.colour) {
+ insn->op = Imov;
+ insn->args[1] = coreg(insn->args[1]->reg.colour, ModeL);
+ }
+ }
+ break;
+ case Imovs:
+ if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
+ break;
+ /* moving a reg to itself is dumb. */
+ if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
+ return;
+ break;
+ case Imov:
+ assert(!isfloatmode(insn->args[0]->mode));
+ if (insn->args[0]->type != Locreg || insn->args[1]->type != Locreg)
+ break;
+ if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
+ break;
+ /* if one reg is a subreg of another, we can just use the right
+ * mode to move between them. */
+ if (issubreg(insn->args[0], insn->args[1]))
+ insn->args[0] = coreg(insn->args[0]->reg.colour, insn->args[1]->mode);
+ /* moving a reg to itself is dumb. */
+ if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
+ return;
+ break;
+ default:
+ break;
+ }
+ p = insnfmts[insn->op];
+ i = 0;
+ modeidx = 0;
+ for (; *p; p++) {
+ if (*p != '%') {
+ fputc(*p, fd);
+ continue;
+ }
+
+ /* %-formating */
+ p++;
+ switch (*p) {
+ case '\0':
+ goto done; /* skip the final p++ */
+ case 'r': /* int register */
+ case 'f': /* float register */
+ case 'm': /* memory */
+ case 'i': /* imm */
+ case 'v': /* reg/mem */
+ case 'u': /* reg/imm */
+ case 'x': /* reg/mem/imm */
+ locprint(fd, insn->args[i], *p);
+ i++;
+ break;
+ case 't':
+ default:
+ /* the asm description uses 1-based indexing, so that 0
+ * can be used as a sentinel. */
+ if (isdigit(*p))
+ modeidx = strtol(p, &p, 10) - 1;
+
+ if (*p == 't')
+ fputs(modenames[insn->args[modeidx]->mode], fd);
+ else
+ die("Invalid %%-specifier '%c'", *p);
+ break;
+ }
+ }
+done:
+ return;
+}
+
+
+static void writebytes(FILE *fd, char *p, size_t sz)
+{
+ size_t i;
+
+ for (i = 0; i < sz; i++) {
+ if (i % 60 == 0)
+ fprintf(fd, "\t.ascii \"");
+ if (p[i] == '"' || p[i] == '\\')
+ fprintf(fd, "\\");
+ if (isprint(p[i]))
+ fprintf(fd, "%c", p[i]);
+ else
+ fprintf(fd, "\\%03o", (uint8_t)p[i] & 0xff);
+ /* line wrapping for readability */
+ if (i % 60 == 59 || i == sz - 1)
+ fprintf(fd, "\"\n");
+ }
+}
+
+static size_t writelit(FILE *fd, Htab *strtab, Node *v, Type *ty)
+{
+ char buf[128];
+ char *lbl;
+ size_t sz;
+ char *intsz[] = {
+ [1] = ".byte",
+ [2] = ".short",
+ [4] = ".long",
+ [8] = ".quad"
+ };
+ union {
+ float fv;
+ double dv;
+ uint64_t qv;
+ uint32_t lv;
+ } u;
+
+ assert(v->type == Nlit);
+ sz = tysize(ty);
+ switch (v->lit.littype) {
+ case Lint: fprintf(fd, "\t%s %lld\n", intsz[sz], v->lit.intval); break;
+ case Lbool: fprintf(fd, "\t.byte %d\n", v->lit.boolval); break;
+ case Lchr: fprintf(fd, "\t.long %d\n", v->lit.chrval); break;
+ case Lflt:
+ if (tybase(v->lit.type)->type == Tyflt32) {
+ u.fv = v->lit.fltval;
+ fprintf(fd, "\t.long 0x%" PRIx32 "\n", u.lv);
+ } else if (tybase(v->lit.type)->type == Tyflt64) {
+ u.dv = v->lit.fltval;
+ fprintf(fd, "\t.quad 0x%" PRIx64 "\n", u.qv);
+ }
+ break;
+ case Lstr:
+ if (hthas(strtab, v->lit.strval)) {
+ lbl = htget(strtab, v->lit.strval);
+ } else {
+ lbl = genlblstr(buf, sizeof buf);
+ htput(strtab, v->lit.strval, strdup(lbl));
+ }
+ fprintf(fd, "\t.quad %s\n", lbl);
+ fprintf(fd, "\t.quad %zd\n", strlen(v->lit.strval));
+ break;
+ case Lfunc:
+ die("Generating this shit ain't ready yet ");
+ break;
+ case Llbl:
+ die("Can't generate literal labels, ffs. They're not data.");
+ break;
+ }
+ return sz;
+}
+
+static size_t writepad(FILE *fd, size_t sz)
+{
+ assert((ssize_t)sz >= 0);
+ if (sz > 0)
+ fprintf(fd, "\t.fill %zd,1,0\n", sz);
+ return sz;
+}
+
+static size_t getintlit(Node *n, char *failmsg)
+{
+ if (exprop(n) != Olit)
+ fatal(n, "%s", failmsg);
+ n = n->expr.args[0];
+ if (n->lit.littype != Lint)
+ fatal(n, "%s", failmsg);
+ return n->lit.intval;
+}
+
+static size_t writeslice(FILE *fd, Htab *globls, Htab *strtab, Node *n)
+{
+ Node *base, *lo, *hi;
+ ssize_t loval, hival, sz;
+ char *lbl;
+
+ base = n->expr.args[0];
+ lo = n->expr.args[1];
+ hi = n->expr.args[2];
+
+ /* by this point, all slicing operations should have had their bases
+ * pulled out, and we should have vars with their pseudo-decls in their
+ * place */
+ if (exprop(base) != Ovar || !base->expr.isconst)
+ fatal(base, "slice base is not a constant value");
+ loval = getintlit(lo, "lower bound in slice is not constant literal");
+ hival = getintlit(hi, "upper bound in slice is not constant literal");
+ sz = tysize(tybase(exprtype(base))->sub[0]);
+
+ lbl = htget(globls, base);
+ fprintf(fd, "\t.quad %s + (%zd*%zd)\n", lbl, loval, sz);
+ fprintf(fd, "\t.quad %zd\n", (hival - loval));
+ return size(n);
+}
+
+static size_t writestruct(FILE *fd, Htab *globls, Htab *strtab, Node *n)
+{
+ Type *t;
+ Node **dcl;
+ int found;
+ size_t i, j;
+ size_t sz, pad, end;
+ size_t ndcl;
+
+ sz = 0;
+ t = tybase(exprtype(n));
+ assert(t->type == Tystruct);
+ dcl = t->sdecls;
+ ndcl = t->nmemb;
+ for (i = 0; i < ndcl; i++) {
+ pad = alignto(sz, decltype(dcl[i]));
+ sz += writepad(fd, pad - sz);
+ found = 0;
+ for (j = 0; j < n->expr.nargs; j++)
+ if (!strcmp(namestr(n->expr.args[j]->expr.idx), declname(dcl[i]))) {
+ found = 1;
+ sz += writeblob(fd, globls, strtab, n->expr.args[j]);
+ }
+ if (!found)
+ sz += writepad(fd, size(dcl[i]));
+ }
+ end = alignto(sz, t);
+ sz += writepad(fd, end - sz);
+ return sz;
+}
+static size_t writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *n)
+{
+ size_t i, sz;
+
+ switch(exprop(n)) {
+ case Otup:
+ case Oarr:
+ sz = 0;
+ for (i = 0; i < n->expr.nargs; i++)
+ sz += writeblob(fd, globls, strtab, n->expr.args[i]);
+ break;
+ case Ostruct:
+ sz = writestruct(fd, globls, strtab, n);
+ break;
+ case Olit:
+ sz = writelit(fd, strtab, n->expr.args[0], exprtype(n));
+ break;
+ case Oslice:
+ sz = writeslice(fd, globls, strtab, n);
+ break;
+ default:
+ dump(n, stdout);
+ die("Nonliteral initializer for global");
+ break;
+ }
+ return sz;
+}
+
+void genstrings(FILE *fd, Htab *strtab)
+{
+ void **k;
+ size_t i, nk;
+
+ k = htkeys(strtab, &nk);
+ for (i = 0; i < nk; i++) {
+ fprintf(fd, "%s:\n", (char*)htget(strtab, k[i]));
+ writebytes(fd, k[i], strlen(k[i]));
+ }
+}
+
+
+static void writeasm(FILE *fd, Isel *s, Func *fn)
+{
+ size_t i, j;
+
+ if (fn->isexport || !strcmp(fn->name, Symprefix "main"))
+ fprintf(fd, ".globl %s\n", fn->name);
+ fprintf(fd, "%s:\n", fn->name);
+ for (j = 0; j < s->cfg->nbb; j++) {
+ if (!s->bb[j])
+ continue;
+ for (i = 0; i < s->bb[j]->nlbls; i++)
+ fprintf(fd, "%s:\n", s->bb[j]->lbls[i]);
+ for (i = 0; i < s->bb[j]->ni; i++)
+ iprintf(fd, s->bb[j]->il[i]);
+ }
+}
+
+void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab)
+{
+ char *lbl;
+
+ /* lits and such also get wrapped in decls */
+ assert(blob->type == Ndecl);
+
+ lbl = htget(globls, blob);
+ if (blob->decl.vis != Visintern)
+ fprintf(fd, ".globl %s\n", lbl);
+ fprintf(fd, "%s:\n", lbl);
+ if (blob->decl.init)
+ writeblob(fd, globls, strtab, blob->decl.init);
+ else
+ writepad(fd, size(blob));
+}
+
+/* genfunc requires all nodes in 'nl' to map cleanly to operations that are
+ * natively supported, as promised in the output of reduce(). No 64-bit
+ * operations on x32, no structures, and so on. */
+void genfunc(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
+{
+ Isel is = {0,};
+
+ is.reglocs = mkht(varhash, vareq);
+ is.stkoff = fn->stkoff;
+ is.globls = globls;
+ is.ret = fn->ret;
+ is.cfg = fn->cfg;
+
+ selfunc(&is, fn, globls, strtab);
+ if (debugopt['i'])
+ writeasm(stdout, &is, fn);
+ writeasm(fd, &is, fn);
+}
+
+void gen(Node *file, char *out)
+{
+ Htab *globls, *strtab;
+ Node *n, **blob;
+ Func **fn;
+ size_t nfn, nblob;
+ size_t i;
+ FILE *fd;
+
+ /* ensure that all physical registers have a loc created before any
+ * other locs, so that locmap[Physreg] maps to the Loc for the physreg
+ * in question */
+ for (i = 0; i < Nreg; i++)
+ locphysreg(i);
+
+ fn = NULL;
+ nfn = 0;
+ blob = NULL;
+ nblob = 0;
+ globls = mkht(varhash, vareq);
+ initconsts(globls);
+
+ /* We need to define all global variables before use */
+ fillglobls(file->file.globls, globls);
+
+ pushstab(file->file.globls);
+ for (i = 0; i < file->file.nstmts; i++) {
+ n = file->file.stmts[i];
+ switch (n->type) {
+ case Nuse: /* nothing to do */
+ case Nimpl:
+ break;
+ case Ndecl:
+ simpglobl(n, globls, &fn, &nfn, &blob, &nblob);
+ break;
+ default:
+ die("Bad node %s in toplevel", nodestr(n->type));
+ break;
+ }
+ }
+ popstab();
+
+ fd = fopen(out, "w");
+ if (!fd)
+ die("Couldn't open fd %s", out);
+
+ strtab = mkht(strhash, streq);
+ fprintf(fd, ".data\n");
+ for (i = 0; i < nblob; i++)
+ genblob(fd, blob[i], globls, strtab);
+ fprintf(fd, ".text\n");
+ for (i = 0; i < nfn; i++)
+ genfunc(fd, fn[i], globls, strtab);
+ genstrings(fd, strtab);
+ fclose(fd);
+}
--- a/6/isel.c
+++ b/6/isel.c
@@ -16,25 +16,8 @@
#include "asm.h"
#include "../config.h"
-/* string tables */
-char *insnfmts[] = {
-#define Insn(val, fmt, use, def) fmt,
-#include "insns.def"
-#undef Insn
-};
-
-char* modenames[] = {
- [ModeB] = "b",
- [ModeW] = "w",
- [ModeL] = "l",
- [ModeQ] = "q",
- [ModeF] = "s",
- [ModeD] = "d"
-};
-
/* forward decls */
Loc *selexpr(Isel *s, Node *n);
-static size_t writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *blob);
/* used to decide which operator is appropriate
* for implementing various conditional operators */
@@ -157,7 +140,7 @@
return i;
}
-void g(Isel *s, AsmOp op, ...)
+static void g(Isel *s, AsmOp op, ...)
{
va_list ap;
Insn *i;
@@ -768,154 +751,6 @@
return r;
}
-void locprint(FILE *fd, Loc *l, char spec)
-{
- assert(l->mode);
- switch (l->type) {
- case Loclitl:
- assert(spec == 'i' || spec == 'x' || spec == 'u');
- fprintf(fd, "$%s", l->lbl);
- break;
- case Loclbl:
- assert(spec == 'm' || spec == 'v' || spec == 'x');
- fprintf(fd, "%s", l->lbl);
- break;
- case Locreg:
- assert((spec == 'r' && isintmode(l->mode)) ||
- (spec == 'f' && isfloatmode(l->mode)) ||
- spec == 'v' ||
- spec == 'x' ||
- spec == 'u');
- if (l->reg.colour == Rnone)
- fprintf(fd, "%%P.%zd%s", l->reg.id, modenames[l->mode]);
- else
- fprintf(fd, "%s", regnames[l->reg.colour]);
- break;
- case Locmem:
- case Locmeml:
- assert(spec == 'm' || spec == 'v' || spec == 'x');
- if (l->type == Locmem) {
- if (l->mem.constdisp)
- fprintf(fd, "%ld", l->mem.constdisp);
- } else {
- if (l->mem.lbldisp)
- fprintf(fd, "%s", l->mem.lbldisp);
- }
- if (l->mem.base) {
- fprintf(fd, "(");
- locprint(fd, l->mem.base, 'r');
- if (l->mem.idx) {
- fprintf(fd, ",");
- locprint(fd, l->mem.idx, 'r');
- }
- if (l->mem.scale > 1)
- fprintf(fd, ",%d", l->mem.scale);
- if (l->mem.base)
- fprintf(fd, ")");
- } else if (l->type != Locmeml) {
- die("Only locmeml can have unspecified base reg");
- }
- break;
- case Loclit:
- assert(spec == 'i' || spec == 'x' || spec == 'u');
- fprintf(fd, "$%ld", l->lit);
- break;
- case Locnone:
- die("Bad location in locprint()");
- break;
- }
-}
-
-int subreg(Loc *a, Loc *b)
-{
- return rclass(a) == rclass(b) && a->mode != b->mode;
-}
-
-void iprintf(FILE *fd, Insn *insn)
-{
- char *p;
- int i;
- int modeidx;
-
- /* x64 has a quirk; it has no movzlq because mov zero extends. This
- * means that we need to do a movl when we really want a movzlq. Since
- * we don't know the name of the reg to use, we need to sub it in when
- * writing... */
- switch (insn->op) {
- case Imovzx:
- if (insn->args[0]->mode == ModeL && insn->args[1]->mode == ModeQ) {
- if (insn->args[1]->reg.colour) {
- insn->op = Imov;
- insn->args[1] = coreg(insn->args[1]->reg.colour, ModeL);
- }
- }
- break;
- case Imovs:
- if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
- break;
- /* moving a reg to itself is dumb. */
- if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
- return;
- break;
- case Imov:
- assert(!isfloatmode(insn->args[0]->mode));
- if (insn->args[0]->type != Locreg || insn->args[1]->type != Locreg)
- break;
- if (insn->args[0]->reg.colour == Rnone || insn->args[1]->reg.colour == Rnone)
- break;
- /* if one reg is a subreg of another, we can just use the right
- * mode to move between them. */
- if (subreg(insn->args[0], insn->args[1]))
- insn->args[0] = coreg(insn->args[0]->reg.colour, insn->args[1]->mode);
- /* moving a reg to itself is dumb. */
- if (insn->args[0]->reg.colour == insn->args[1]->reg.colour)
- return;
- break;
- default:
- break;
- }
- p = insnfmts[insn->op];
- i = 0;
- modeidx = 0;
- for (; *p; p++) {
- if (*p != '%') {
- fputc(*p, fd);
- continue;
- }
-
- /* %-formating */
- p++;
- switch (*p) {
- case '\0':
- goto done; /* skip the final p++ */
- case 'r': /* int register */
- case 'f': /* float register */
- case 'm': /* memory */
- case 'i': /* imm */
- case 'v': /* reg/mem */
- case 'u': /* reg/imm */
- case 'x': /* reg/mem/imm */
- locprint(fd, insn->args[i], *p);
- i++;
- break;
- case 't':
- default:
- /* the asm description uses 1-based indexing, so that 0
- * can be used as a sentinel. */
- if (isdigit(*p))
- modeidx = strtol(p, &p, 10) - 1;
-
- if (*p == 't')
- fputs(modenames[insn->args[modeidx]->mode], fd);
- else
- die("Invalid %%-specifier '%c'", *p);
- break;
- }
- }
-done:
- return;
-}
-
static void isel(Isel *s, Node *n)
{
switch (n->type) {
@@ -996,23 +831,6 @@
g(s, Iret, NULL);
}
-static void writeasm(FILE *fd, Isel *s, Func *fn)
-{
- size_t i, j;
-
- if (fn->isexport || !strcmp(fn->name, Symprefix "main"))
- fprintf(fd, ".globl %s\n", fn->name);
- fprintf(fd, "%s:\n", fn->name);
- for (j = 0; j < s->cfg->nbb; j++) {
- if (!s->bb[j])
- continue;
- for (i = 0; i < s->bb[j]->nlbls; i++)
- fprintf(fd, "%s:\n", s->bb[j]->lbls[i]);
- for (i = 0; i < s->bb[j]->ni; i++)
- iprintf(fd, s->bb[j]->il[i]);
- }
-}
-
static Asmbb *mkasmbb(Bb *bb)
{
Asmbb *as;
@@ -1028,226 +846,22 @@
return as;
}
-static void writebytes(FILE *fd, char *p, size_t sz)
+void selfunc(Isel *is, Func *fn, Htab *globls, Htab *strtab)
{
- size_t i;
-
- for (i = 0; i < sz; i++) {
- if (i % 60 == 0)
- fprintf(fd, "\t.ascii \"");
- if (p[i] == '"' || p[i] == '\\')
- fprintf(fd, "\\");
- if (isprint(p[i]))
- fprintf(fd, "%c", p[i]);
- else
- fprintf(fd, "\\%03o", (uint8_t)p[i] & 0xff);
- /* line wrapping for readability */
- if (i % 60 == 59 || i == sz - 1)
- fprintf(fd, "\"\n");
- }
-}
-
-static size_t writelit(FILE *fd, Htab *strtab, Node *v, Type *ty)
-{
- char buf[128];
- char *lbl;
- size_t sz;
- char *intsz[] = {
- [1] = ".byte",
- [2] = ".short",
- [4] = ".long",
- [8] = ".quad"
- };
- union {
- float fv;
- double dv;
- uint64_t qv;
- uint32_t lv;
- } u;
-
- assert(v->type == Nlit);
- sz = tysize(ty);
- switch (v->lit.littype) {
- case Lint: fprintf(fd, "\t%s %lld\n", intsz[sz], v->lit.intval); break;
- case Lbool: fprintf(fd, "\t.byte %d\n", v->lit.boolval); break;
- case Lchr: fprintf(fd, "\t.long %d\n", v->lit.chrval); break;
- case Lflt:
- if (tybase(v->lit.type)->type == Tyflt32) {
- u.fv = v->lit.fltval;
- fprintf(fd, "\t.long 0x%" PRIx32 "\n", u.lv);
- } else if (tybase(v->lit.type)->type == Tyflt64) {
- u.dv = v->lit.fltval;
- fprintf(fd, "\t.quad 0x%" PRIx64 "\n", u.qv);
- }
- break;
- case Lstr:
- if (hthas(strtab, v->lit.strval)) {
- lbl = htget(strtab, v->lit.strval);
- } else {
- lbl = genlblstr(buf, sizeof buf);
- htput(strtab, v->lit.strval, strdup(lbl));
- }
- fprintf(fd, "\t.quad %s\n", lbl);
- fprintf(fd, "\t.quad %zd\n", strlen(v->lit.strval));
- break;
- case Lfunc:
- die("Generating this shit ain't ready yet ");
- break;
- case Llbl:
- die("Can't generate literal labels, ffs. They're not data.");
- break;
- }
- return sz;
-}
-
-static size_t writepad(FILE *fd, size_t sz)
-{
- assert((ssize_t)sz >= 0);
- if (sz > 0)
- fprintf(fd, "\t.fill %zd,1,0\n", sz);
- return sz;
-}
-
-static size_t getintlit(Node *n, char *failmsg)
-{
- if (exprop(n) != Olit)
- fatal(n, "%s", failmsg);
- n = n->expr.args[0];
- if (n->lit.littype != Lint)
- fatal(n, "%s", failmsg);
- return n->lit.intval;
-}
-
-static size_t writeslice(FILE *fd, Htab *globls, Htab *strtab, Node *n)
-{
- Node *base, *lo, *hi;
- ssize_t loval, hival, sz;
- char *lbl;
-
- base = n->expr.args[0];
- lo = n->expr.args[1];
- hi = n->expr.args[2];
-
- /* by this point, all slicing operations should have had their bases
- * pulled out, and we should have vars with their pseudo-decls in their
- * place */
- if (exprop(base) != Ovar || !base->expr.isconst)
- fatal(base, "slice base is not a constant value");
- loval = getintlit(lo, "lower bound in slice is not constant literal");
- hival = getintlit(hi, "upper bound in slice is not constant literal");
- sz = tysize(tybase(exprtype(base))->sub[0]);
-
- lbl = htget(globls, base);
- fprintf(fd, "\t.quad %s + (%zd*%zd)\n", lbl, loval, sz);
- fprintf(fd, "\t.quad %zd\n", (hival - loval));
- return size(n);
-}
-
-static size_t writestruct(FILE *fd, Htab *globls, Htab *strtab, Node *n)
-{
- Type *t;
- Node **dcl;
- int found;
- size_t i, j;
- size_t sz, pad, end;
- size_t ndcl;
-
- sz = 0;
- t = tybase(exprtype(n));
- assert(t->type == Tystruct);
- dcl = t->sdecls;
- ndcl = t->nmemb;
- for (i = 0; i < ndcl; i++) {
- pad = alignto(sz, decltype(dcl[i]));
- sz += writepad(fd, pad - sz);
- found = 0;
- for (j = 0; j < n->expr.nargs; j++)
- if (!strcmp(namestr(n->expr.args[j]->expr.idx), declname(dcl[i]))) {
- found = 1;
- sz += writeblob(fd, globls, strtab, n->expr.args[j]);
- }
- if (!found)
- sz += writepad(fd, size(dcl[i]));
- }
- end = alignto(sz, t);
- sz += writepad(fd, end - sz);
- return sz;
-}
-
-static size_t writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *n)
-{
- size_t i, sz;
-
- switch(exprop(n)) {
- case Otup:
- case Oarr:
- sz = 0;
- for (i = 0; i < n->expr.nargs; i++)
- sz += writeblob(fd, globls, strtab, n->expr.args[i]);
- break;
- case Ostruct:
- sz = writestruct(fd, globls, strtab, n);
- break;
- case Olit:
- sz = writelit(fd, strtab, n->expr.args[0], exprtype(n));
- break;
- case Oslice:
- sz = writeslice(fd, globls, strtab, n);
- break;
- default:
- dump(n, stdout);
- die("Nonliteral initializer for global");
- break;
- }
- return sz;
-}
-
-void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab)
-{
- char *lbl;
-
- /* lits and such also get wrapped in decls */
- assert(blob->type == Ndecl);
-
- lbl = htget(globls, blob);
- if (blob->decl.vis != Visintern)
- fprintf(fd, ".globl %s\n", lbl);
- fprintf(fd, "%s:\n", lbl);
- if (blob->decl.init)
- writeblob(fd, globls, strtab, blob->decl.init);
- else
- writepad(fd, size(blob));
-}
-
-/* genasm requires all nodes in 'nl' to map cleanly to operations that are
- * natively supported, as promised in the output of reduce(). No 64-bit
- * operations on x32, no structures, and so on. */
-void genasm(FILE *fd, Func *fn, Htab *globls, Htab *strtab)
-{
- Isel is = {0,};
Node *n;
Bb *bb;
size_t i, j;
char buf[128];
- is.reglocs = mkht(varhash, vareq);
- is.stkoff = fn->stkoff;
- is.globls = globls;
- is.ret = fn->ret;
- is.cfg = fn->cfg;
- /* ensure that all physical registers have a loc created, so we
- * don't get any surprises referring to them in the allocator */
- for (i = 0; i < Nreg; i++)
- locphysreg(i);
for (i = 0; i < fn->cfg->nbb; i++)
- lappend(&is.bb, &is.nbb, mkasmbb(fn->cfg->bb[i]));
+ lappend(&is->bb, &is->nbb, mkasmbb(fn->cfg->bb[i]));
- is.curbb = is.bb[0];
- prologue(&is, fn->stksz);
+ is->curbb = is->bb[0];
+ prologue(is, fn->stksz);
for (j = 0; j < fn->cfg->nbb - 1; j++) {
- is.curbb = is.bb[j];
- if (!is.bb[j])
+ is->curbb = is->bb[j];
+ if (!is->bb[j])
continue;
bb = fn->cfg->bb[j];
for (i = 0; i < bb->nnl; i++) {
@@ -1255,27 +869,11 @@
n = bb->nl[i];
snprintf(buf, sizeof buf, "\n\t# bb = %ld, bbidx = %ld, %s:%d",
j, i, file->file.files[n->loc.file], n->loc.line);
- g(&is, Ilbl, locstrlbl(buf), NULL);
- isel(&is, fn->cfg->bb[j]->nl[i]);
+ g(is, Ilbl, locstrlbl(buf), NULL);
+ isel(is, fn->cfg->bb[j]->nl[i]);
}
}
- is.curbb = is.bb[is.nbb - 1];
- epilogue(&is);
- regalloc(&is);
-
- if (debugopt['i'])
- writeasm(stdout, &is, fn);
- writeasm(fd, &is, fn);
-}
-
-void genstrings(FILE *fd, Htab *strtab)
-{
- void **k;
- size_t i, nk;
-
- k = htkeys(strtab, &nk);
- for (i = 0; i < nk; i++) {
- fprintf(fd, "%s:\n", (char*)htget(strtab, k[i]));
- writebytes(fd, k[i], strlen(k[i]));
- }
+ is->curbb = is->bb[is->nbb - 1];
+ epilogue(is);
+ regalloc(is);
}
--- a/6/locs.c
+++ b/6/locs.c
@@ -13,6 +13,7 @@
#include "parse.h"
#include "opt.h"
#include "asm.h"
+#include "../config.h"
Mode regmodes[] = {
#define Reg(r, name, mode) mode,
@@ -72,6 +73,33 @@
{
return m == ModeF || m == ModeD;
}
+
+/* For x86, the assembly names are generated as follows:
+ * local symbols: .name
+ * un-namespaced symbols: <symprefix>name
+ * namespaced symbols: <symprefix>namespace$name
+ */
+char *asmname(Node *n)
+{
+ char *s;
+ int len;
+
+ len = strlen(Symprefix);
+ if (n->name.ns)
+ len += strlen(n->name.ns) + 1; /* +1 for separator */
+ len += strlen(n->name.name) + 1;
+
+ s = xalloc(len + 1);
+ s[0] = '\0';
+ if (n->name.ns)
+ snprintf(s, len, "%s%s$%s", Symprefix, n->name.ns, n->name.name);
+ else if (n->name.name[0] == '.')
+ snprintf(s, len, "%s", n->name.name);
+ else
+ snprintf(s, len, "%s%s", Symprefix, n->name.name);
+ return s;
+}
+
char *genlblstr(char *buf, size_t sz)
{
static int nextlbl;
--- a/6/simp.c
+++ b/6/simp.c
@@ -52,7 +52,6 @@
Htab *stkoff;
};
-static char *asmname(Node *n);
static Node *simp(Simp *s, Node *n);
static Node *rval(Simp *s, Node *n, Node *dst);
static Node *lval(Simp *s, Node *n);
@@ -65,10 +64,10 @@
static void matchpattern(Simp *s, Node *pat, Node *val, Type *t, Node *iftrue, Node *iffalse);
/* useful constants */
-static Type *tyintptr;
-static Type *tyword;
-static Type *tyvoid;
-static Node *abortfunc;
+Type *tyintptr;
+Type *tyword;
+Type *tyvoid;
+Node *abortoob;
size_t alignto(size_t sz, Type *t)
{
@@ -286,139 +285,6 @@
return s->decl.isconst && decltype(s)->type == Tyfunc;
}
-/* For x86, the assembly names are generated as follows:
- * local symbols: .name
- * un-namespaced symbols: <symprefix>name
- * namespaced symbols: <symprefix>namespace$name
- */
-static char *asmname(Node *n)
-{
- char *s;
- int len;
-
- len = strlen(Symprefix);
- if (n->name.ns)
- len += strlen(n->name.ns) + 1; /* +1 for separator */
- len += strlen(n->name.name) + 1;
-
- s = xalloc(len + 1);
- s[0] = '\0';
- if (n->name.ns)
- snprintf(s, len, "%s%s$%s", Symprefix, n->name.ns, n->name.name);
- else if (n->name.name[0] == '.')
- snprintf(s, len, "%s", n->name.name);
- else
- snprintf(s, len, "%s%s", Symprefix, n->name.name);
- return s;
-}
-
-size_t tysize(Type *t)
-{
- size_t sz;
- size_t i;
-
- sz = 0;
- if (!t)
- die("size of empty type => bailing.");
- switch (t->type) {
- case Tyvoid:
- die("void has no size");
- return 1;
- case Tybool: case Tyint8:
- case Tybyte: case Tyuint8:
- return 1;
- case Tyint16: case Tyuint16:
- return 2;
- case Tyint: case Tyint32:
- case Tyuint: case Tyuint32:
- case Tychar: /* utf32 */
- return 4;
-
- case Typtr: case Tyfunc:
- case Tyvalist: /* ptr to first element of valist */
- return Ptrsz;
-
- case Tyint64: case Tylong:
- case Tyuint64: case Tyulong:
- return 8;
-
- /*end integer types*/
- case Tyflt32:
- return 4;
- case Tyflt64:
- return 8;
-
- case Tyslice:
- return 2*Ptrsz; /* len; ptr */
- case Tyname:
- return tysize(t->sub[0]);
- case Tyarray:
- t->asize = fold(t->asize, 1);
- assert(exprop(t->asize) == Olit);
- return t->asize->expr.args[0]->lit.intval * tysize(t->sub[0]);
- case Tytuple:
- for (i = 0; i < t->nsub; i++) {
- sz = alignto(sz, t->sub[i]);
- sz += tysize(t->sub[i]);
- }
- sz = alignto(sz, t);
- return sz;
- break;
- case Tystruct:
- for (i = 0; i < t->nmemb; i++) {
- sz = alignto(sz, decltype(t->sdecls[i]));
- sz += size(t->sdecls[i]);
- }
- sz = alignto(sz, t);
- return sz;
- break;
- case Tyunion:
- sz = Wordsz;
- for (i = 0; i < t->nmemb; i++)
- if (t->udecls[i]->etype)
- sz = max(sz, tysize(t->udecls[i]->etype) + Wordsz);
- return align(sz, Ptrsz);
- break;
- case Tybad: case Tyvar: case Typaram: case Tyunres: case Ntypes:
- die("Type %s does not have size; why did it get down to here?", tystr(t));
- break;
- }
- return -1;
-}
-
-size_t size(Node *n)
-{
- Type *t;
-
- if (n->type == Nexpr)
- t = n->expr.type;
- else
- t = n->decl.type;
- return tysize(t);
-}
-
-/* gets the byte offset of 'memb' within the aggregate type 'aggr' */
-static size_t offset(Node *aggr, Node *memb)
-{
- Type *ty;
- size_t i;
- size_t off;
-
- ty = tybase(exprtype(aggr));
- if (ty->type == Typtr)
- ty = tybase(ty->sub[0]);
-
- assert(ty->type == Tystruct);
- off = 0;
- for (i = 0; i < ty->nmemb; i++) {
- off = alignto(off, decltype(ty->sdecls[i]));
- if (!strcmp(namestr(memb), declname(ty->sdecls[i])))
- return off;
- off += size(ty->sdecls[i]);
- }
- die("Could not find member %s in struct", namestr(memb));
- return -1;
-}
static Node *gentemp(Simp *simp, Node *e, Type *ty, Node **dcl)
{
char buf[128];
@@ -879,7 +745,7 @@
cmp->expr.type = mktype(len->loc, Tybool);
ok = genlbl(len->loc);
fail = genlbl(len->loc);
- die = mkexpr(idx->loc, Ocall, abortfunc, NULL);
+ die = mkexpr(idx->loc, Ocall, abortoob, NULL);
die->expr.type = mktype(len->loc, Tyvoid);
/* insert them */
@@ -1764,28 +1630,6 @@
return fn;
}
-static void fillglobls(Stab *st, Htab *globls)
-{
- void **k;
- size_t i, nk;
- Stab *stab;
- Node *s;
-
- k = htkeys(st->dcl, &nk);
- for (i = 0; i < nk; i++) {
- s = htget(st->dcl, k[i]);
- htput(globls, s, asmname(s->decl.name));
- }
- free(k);
-
- k = htkeys(st->ns, &nk);
- for (i = 0; i < nk; i++) {
- stab = htget(st->ns, k[i]);
- fillglobls(stab, globls);
- }
- free(k);
-}
-
static void extractsub(Simp *s, Node ***blobs, size_t *nblobs, Node *e)
{
size_t i;
@@ -1836,7 +1680,7 @@
}
}
-static void simpglobl(Node *dcl, Htab *globls, Func ***fn, size_t *nfn, Node ***blob, size_t *nblob)
+void simpglobl(Node *dcl, Htab *globls, Func ***fn, size_t *nfn, Node ***blob, size_t *nblob)
{
Simp s = {0,};
char *name;
@@ -1859,78 +1703,4 @@
*blob = s.blobs;
*nblob = s.nblobs;
free(name);
-}
-
-static void initconsts(Htab *globls)
-{
- Type *ty;
- Node *name;
- Node *dcl;
-
- tyintptr = mktype(Zloc, Tyuint64);
- tyword = mktype(Zloc, Tyuint);
- tyvoid = mktype(Zloc, Tyvoid);
-
- ty = mktyfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid));
- name = mknsname(Zloc, "_rt", "abort_oob");
- dcl = mkdecl(Zloc, name, ty);
- dcl->decl.isconst = 1;
- dcl->decl.isextern = 1;
- htput(globls, dcl, asmname(dcl->decl.name));
-
- abortfunc = mkexpr(Zloc, Ovar, name, NULL);
- abortfunc->expr.type = ty;
- abortfunc->expr.did = dcl->decl.did;
- abortfunc->expr.isconst = 1;
-}
-
-void gen(Node *file, char *out)
-{
- Htab *globls, *strtab;
- Node *n, **blob;
- Func **fn;
- size_t nfn, nblob;
- size_t i;
- FILE *fd;
-
- fn = NULL;
- nfn = 0;
- blob = NULL;
- nblob = 0;
- globls = mkht(varhash, vareq);
- initconsts(globls);
-
- /* We need to define all global variables before use */
- fillglobls(file->file.globls, globls);
-
- pushstab(file->file.globls);
- for (i = 0; i < file->file.nstmts; i++) {
- n = file->file.stmts[i];
- switch (n->type) {
- case Nuse: /* nothing to do */
- case Nimpl:
- break;
- case Ndecl:
- simpglobl(n, globls, &fn, &nfn, &blob, &nblob);
- break;
- default:
- die("Bad node %s in toplevel", nodestr(n->type));
- break;
- }
- }
- popstab();
-
- fd = fopen(out, "w");
- if (!fd)
- die("Couldn't open fd %s", out);
-
- strtab = mkht(strhash, streq);
- fprintf(fd, ".data\n");
- for (i = 0; i < nblob; i++)
- genblob(fd, blob[i], globls, strtab);
- fprintf(fd, ".text\n");
- for (i = 0; i < nfn; i++)
- genasm(fd, fn[i], globls, strtab);
- genstrings(fd, strtab);
- fclose(fd);
}
--- /dev/null
+++ b/6/typeinfo.c
@@ -1,0 +1,129 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+#include "opt.h"
+#include "asm.h"
+#include "../config.h"
+
+
+size_t tysize(Type *t)
+{
+ size_t sz;
+ size_t i;
+
+ sz = 0;
+ if (!t)
+ die("size of empty type => bailing.");
+ switch (t->type) {
+ case Tyvoid:
+ die("void has no size");
+ return 1;
+ case Tybool: case Tyint8:
+ case Tybyte: case Tyuint8:
+ return 1;
+ case Tyint16: case Tyuint16:
+ return 2;
+ case Tyint: case Tyint32:
+ case Tyuint: case Tyuint32:
+ case Tychar: /* utf32 */
+ return 4;
+
+ case Typtr: case Tyfunc:
+ case Tyvalist: /* ptr to first element of valist */
+ return Ptrsz;
+
+ case Tyint64: case Tylong:
+ case Tyuint64: case Tyulong:
+ return 8;
+
+ /*end integer types*/
+ case Tyflt32:
+ return 4;
+ case Tyflt64:
+ return 8;
+
+ case Tyslice:
+ return 2*Ptrsz; /* len; ptr */
+ case Tyname:
+ return tysize(t->sub[0]);
+ case Tyarray:
+ t->asize = fold(t->asize, 1);
+ assert(exprop(t->asize) == Olit);
+ return t->asize->expr.args[0]->lit.intval * tysize(t->sub[0]);
+ case Tytuple:
+ for (i = 0; i < t->nsub; i++) {
+ sz = alignto(sz, t->sub[i]);
+ sz += tysize(t->sub[i]);
+ }
+ sz = alignto(sz, t);
+ return sz;
+ break;
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++) {
+ sz = alignto(sz, decltype(t->sdecls[i]));
+ sz += size(t->sdecls[i]);
+ }
+ sz = alignto(sz, t);
+ return sz;
+ break;
+ case Tyunion:
+ sz = Wordsz;
+ for (i = 0; i < t->nmemb; i++)
+ if (t->udecls[i]->etype)
+ sz = max(sz, tysize(t->udecls[i]->etype) + Wordsz);
+ return align(sz, Ptrsz);
+ break;
+ case Tybad: case Tyvar: case Typaram: case Tyunres: case Ntypes:
+ die("Type %s does not have size; why did it get down to here?", tystr(t));
+ break;
+ }
+ return -1;
+}
+
+/* gets the byte offset of 'memb' within the aggregate type 'aggr' */
+size_t tyoffset(Type *ty, Node *memb)
+{
+ size_t i;
+ size_t off;
+
+ ty = tybase(ty);
+ if (ty->type == Typtr)
+ ty = tybase(ty->sub[0]);
+
+ assert(ty->type == Tystruct);
+ off = 0;
+ for (i = 0; i < ty->nmemb; i++) {
+ off = alignto(off, decltype(ty->sdecls[i]));
+ if (!strcmp(namestr(memb), declname(ty->sdecls[i])))
+ return off;
+ off += size(ty->sdecls[i]);
+ }
+ die("Could not find member %s in struct", namestr(memb));
+ return -1;
+}
+
+size_t size(Node *n)
+{
+ Type *t;
+
+ if (n->type == Nexpr)
+ t = n->expr.type;
+ else
+ t = n->decl.type;
+ return tysize(t);
+}
+
+size_t offset(Node *aggr, Node *memb)
+{
+ return tyoffset(exprtype(aggr), memb);
+}
+
--- a/libstd/dial.myr
+++ b/libstd/dial.myr
@@ -10,6 +10,7 @@
use "resolve.use"
use "result.use"
use "sleq.use"
+use "strfind.use"
use "sys.use"
use "syswrap.use"
use "utf.use"
@@ -30,10 +31,42 @@
/* takes a plan 9 style dial string */
const dial = {str
var proto, host, port
- var socktype, portnum
var sa : sys.sockaddr_in /* we only support inet sockets right now.. ugh. */
var sock
+ match parsedial(str)
+ | `Ok val: (proto, host, port) = val
+ | `Fail m: -> `Fail m
+ ;;
+
+ match getaddr(host)
+ | `Ipv4 bits:
+ sa.fam = sys.Afinet
+ sa.addr = bits
+ sa.port = hosttonet(port)
+ | `Ipv6 bits:
+ -> `Fail "ipv6 not yet supported"
+ ;;
+
+ sock = sys.socket(sa.fam, proto, 0)
+ if sock < 0
+ -> `Fail "failed to connect to socket"
+ ;;
+ var err
+ err = sys.connect(sock, (&sa) castto(sys.sockaddr#), sizeof(sys.sockaddr_in))
+ if err < 0
+ put("Errno %i\n", -err)
+ sys.close(sock)
+ -> `Fail "Failed to bind socket"
+ ;;
+
+ -> `Ok (sock castto(fd))
+}
+
+const parsedial = {str
+ var proto, host, port
+ var socktype, portnum
+
(proto, str) = nameseg(str)
(host, str) = nameseg(str)
(port, str) = nameseg(str)
@@ -61,28 +94,7 @@
| `None: -> `Fail "bad port"
;;
- match getaddr(host)
- | `Ipv4 bits:
- sa.fam = sys.Afinet
- sa.addr = bits
- sa.port = hosttonet(portnum)
- | `Ipv6 bits:
- -> `Fail "ipv6 not yet supported"
- ;;
-
- sock = sys.socket(sa.fam, socktype, 0)
- if sock < 0
- -> `Fail "failed to connect to socket"
- ;;
- var err
- err = sys.connect(sock, (&sa) castto(sys.sockaddr#), sizeof(sys.sockaddr_in))
- if err < 0
- put("Errno %i\n", -err)
- sys.close(sock)
- -> `Fail "Failed to bind socket"
- ;;
-
- -> `Ok (sock castto(fd))
+ -> `Ok (socktype, host, portnum)
}
const parseport = {port
@@ -120,13 +132,11 @@
}
const nameseg = {str
- var len
-
- for len = 0; len < str.len; len++
- if str[len] == '!' castto(byte)
- -> (str[:len], str[len+1:])
- ;;
+ match strfind(str, "!")
+ | `Some idx:
+ -> (str[:idx], str[idx:])
+ | `None:
+ -> (str, "")
;;
- -> (str[:], str[len:])
}