]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/ld, runtime: emit pointer maps for nosplits identified by the linker
authorCarl Shapiro <cshapiro@google.com>
Thu, 30 May 2013 00:16:57 +0000 (17:16 -0700)
committerCarl Shapiro <cshapiro@google.com>
Thu, 30 May 2013 00:16:57 +0000 (17:16 -0700)
A nosplits was assumed to have no argument information and no
pointer map.  However, nosplits created by the linker often
have both.  This change uses the pointer map size as an
alternate source of argument size when processing a nosplit.

In addition, the symbol table construction pointer map size
and argument size consistency check is strengthened.  If a
nptrs is greater than 0 it must be equal to the number of
argument words.

R=golang-dev, khr, khr
CC=golang-dev
https://golang.org/cl/9666047

src/cmd/gc/pgen.c
src/cmd/ld/lib.c
src/pkg/runtime/symtab.c

index 7fcbf19b1ed27283cea1fc9d16c071dac24c2c10..4d3859d02d288f4bc0e0d427b92edef00dbf16c7 100644 (file)
@@ -296,21 +296,15 @@ pointermap(Node *fn)
                walktype(inargtype, bv);
        if(outargtype != nil)
                walktype(outargtype, bv);
-       if(bvisempty(bv)) {
-               prog = gins(ANPTRS, N, N);
+       prog = gins(ANPTRS, N, N);
+       prog->to.type = D_CONST;
+       prog->to.offset = bv->n;
+       for(i = 0; i < bv->n; i += 32) {
+               prog = gins(APTRS, N, N);
+               prog->from.type = D_CONST;
+               prog->from.offset = i / 32;
                prog->to.type = D_CONST;
-               prog->to.offset = 0;
-       } else {
-               prog = gins(ANPTRS, N, N);
-               prog->to.type = D_CONST;
-               prog->to.offset = bv->n;
-               for(i = 0; i < bv->n; i += 32) {
-                       prog = gins(APTRS, N, N);
-                       prog->from.type = D_CONST;
-                       prog->from.offset = i / 32;
-                       prog->to.type = D_CONST;
-                       prog->to.offset = bv->b[i / 32];
-               }
+               prog->to.offset = bv->b[i / 32];
        }
        free(bv);
 }
index 42448fe09fc4a27f25a16f7012b4035aae604ec7..88c9f6a6074e66137a34b7f1f4c30890c4aef461 100644 (file)
@@ -1914,7 +1914,11 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
                /* frame, locals, args, auto, param and pointers after */
                put(nil, ".frame", 'm', (uint32)s->text->to.offset+PtrSize, 0, 0, 0);
                put(nil, ".locals", 'm', s->locals, 0, 0, 0);
-               if(s->text->textflag & NOSPLIT)
+               if((s->text->textflag & NOSPLIT) && (s->args == 0) && (s->nptrs < 0))
+                       // This might be a vararg function and have no
+                       // predetermined argument size.  This check is
+                       // approximate and will also match 0 argument
+                       // nosplit functions compiled by 6c.
                        put(nil, ".args", 'm', ArgsSizeUnknown, 0, 0, 0);
                else
                        put(nil, ".args", 'm', s->args, 0, 0, 0);
index be06d578d483d0848de9ee36bb217e5ea0e828b7..ffcb8826e6093d1dc63ade7dea4a77066bf9c08e 100644 (file)
@@ -234,8 +234,8 @@ dofunc(Sym *sym)
                        func[nfunc-1].args = sym->value;
                else if(runtime·strcmp(sym->name, (byte*)".nptrs") == 0) {
                        // TODO(cshapiro): use a dense representation for gc information
-                       if(sym->value > func[nfunc-1].args/sizeof(uintptr)) {
-                               runtime·printf("more pointer map entries than argument words\n");
+                       if(sym->value != func[nfunc-1].args/sizeof(uintptr)) {
+                               runtime·printf("pointer map size and argument size disagree\n");
                                runtime·throw("mangled symbol table");
                        }
                        cap = ROUND(sym->value, 32) / 32;