shithub: mc

Download patch

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[:], ":"))
 }