ref: e1dd87b2721b7b42e252d83330798e73daf48a27
parent: 0f342c47db402a0b4ba021dab79414941180c1f0
author: Ori Bernstein <[email protected]>
date: Wed Jan 15 14:00:03 EST 2014
Fix writing constant struct literals We had alignment and padding issues. Fixed.
--- a/6/asm.h
+++ b/6/asm.h
@@ -227,3 +227,6 @@
int floatnode(Node *n);
void breakhere();
void dumpasm(Isel *s, FILE *fd);
+
+size_t tyalign(size_t sz, size_t eltsz);
+
--- a/6/isel.c
+++ b/6/isel.c
@@ -35,7 +35,7 @@
/* forward decls */
Loc *selexpr(Isel *s, Node *n);
-static void writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *blob);
+static size_t writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *blob);
/* used to decide which operator is appropriate
* for implementing various conditional operators */
@@ -988,10 +988,11 @@
}
}
-static void writelit(FILE *fd, Htab *strtab, Node *v, size_t sz)
+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",
@@ -1006,6 +1007,7 @@
} 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;
@@ -1036,22 +1038,17 @@
die("Can't generate literal labels, ffs. They're not data.");
break;
}
+ return sz;
}
-static void writepad(FILE *fd, size_t sz)
+static size_t writepad(FILE *fd, size_t sz)
{
- fprintf(fd, "\t.fill %zd,1,0\n", sz);
+ assert((ssize_t)sz >= 0);
+ if (sz > 0)
+ fprintf(fd, "\t.fill %zd,1,0\n", sz);
+ return sz;
}
-static void writeexprs(FILE *fd, Htab *globls, Htab *strtab, Node **e, size_t n)
-{
- size_t i;
-
- for (i = 0; i < n; i++) {
- writeblob(fd, globls, strtab, e[i]);
- }
-}
-
static size_t getintlit(Node *n, char *failmsg)
{
if (exprop(n) != Olit)
@@ -1062,7 +1059,7 @@
return n->lit.intval;
}
-static void writeslice(FILE *fd, Htab *globls, Htab *strtab, Node *n)
+static size_t writeslice(FILE *fd, Htab *globls, Htab *strtab, Node *n)
{
Node *base, *lo, *hi;
ssize_t loval, hival, sz;
@@ -1084,21 +1081,60 @@
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 void writeblob(FILE *fd, Htab *globls, Htab *strtab, Node *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, 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++) {
+ sz += writepad(fd, tyalign(sz, size(dcl[i])) - 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 = sz;
+ for (i = 0; i < ndcl; i++)
+ end = tyalign(end, size(dcl[i]));
+ 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:
- writeexprs(fd, globls, strtab, n->expr.args, n->expr.nargs);
+ sz = writestruct(fd, globls, strtab, n);
break;
case Olit:
- writelit(fd, strtab, n->expr.args[0], size(n));
+ sz = writelit(fd, strtab, n->expr.args[0], exprtype(n));
break;
case Oslice:
- writeslice(fd, globls, strtab, n);
+ sz = writeslice(fd, globls, strtab, n);
break;
default:
dump(n, stdout);
@@ -1105,6 +1141,7 @@
die("Nonliteral initializer for global");
break;
}
+ return sz;
}
void genblob(FILE *fd, Node *blob, Htab *globls, Htab *strtab)
--- a/6/simp.c
+++ b/6/simp.c
@@ -71,7 +71,7 @@
static Type *tyword;
static Type *tyvoid;
-static size_t tyalign(size_t sz, size_t eltsz)
+size_t tyalign(size_t sz, size_t eltsz)
{
return align(sz, min(eltsz, Ptrsz));
}
--- a/libstd/strjoin.myr
+++ b/libstd/strjoin.myr
@@ -4,14 +4,14 @@
pkg std =
const strcat : (a : byte[:], b : byte[:] -> byte[:])
- const strjoin : (strings : byte[:][:] -> byte[:])
+ const strjoin : (strings : byte[:][:], delim : byte[:] -> byte[:])
;;
const strcat = {a, b
- -> strjoin([a, b][:])
+ -> strjoin([a, b][:], "")
}
-const strjoin = {strings
+const strjoin = {strings, delim
var len, off
var i
var s
@@ -20,6 +20,9 @@
for i = 0; i < strings.len; i++
len += strings[i].len
;;
+ if strings.len > 0
+ len += (strings.len - 1)*delim.len
+ ;;
s = slalloc(len)
off = 0
@@ -26,6 +29,11 @@
for i = 0; i < strings.len; i++
slcp(s[off:off + strings[i].len], strings[i])
off += strings[i].len
+ /* we don't want to terminate the last string with delim */
+ if i != strings.len - 1
+ slcp(s[off:off + delim.len], delim)
+ off += delim.len
+ ;;
;;
-> s
}
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -146,6 +146,7 @@
%type <node> castexpr
%type <ucon> unionelt
%type <node> blkbody
+%type <node> implstmt
%type <nodelist> arglist argdefs params matches
%type <nodelist> structbody structelts arrayelts
@@ -205,6 +206,7 @@
{puttype(file->file.globls, mkname($1.line, $1.name), $1.type);
installucons(file->file.globls, $1.type);}
| traitdef
+ | implstmt
| /* empty */
;
@@ -278,6 +280,7 @@
| tydef {puttype(file->file.exports, mkname($1.line, $1.name), $1.type);
installucons(file->file.exports, $1.type);}
| traitdef
+ | implstmt
| visdef {die("Unimplemented visdef");}
| /* empty */
;
@@ -302,6 +305,8 @@
| Tident Tdot name
{$$ = $3; setns($3, $1->str);}
;
+
+implstmt: Timpl name type
traitdef: Ttrait Tident generictype Tasn traitbody endlns Tendblk
{$$ = mktrait($1->line, mkname($2->line, $2->str), $5.nl, $5.nn, NULL, 0);}
--- a/test/data/strjoin-expected
+++ b/test/data/strjoin-expected
@@ -1,2 +1,3 @@
foo;bar
xyzw
+x:y:z:w
--- a/test/strjoin.myr
+++ b/test/strjoin.myr
@@ -8,5 +8,6 @@
"w"
]
std.put("%s\n", std.strcat("foo;", "bar"))
- std.put("%s\n", std.strjoin(strings[:]))
+ std.put("%s\n", std.strjoin(strings[:], ""))
+ std.put("%s\n", std.strjoin(strings[:], ":"))
}