summaryrefslogtreecommitdiff
path: root/src/cmd/gc/subr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/subr.c')
-rw-r--r--src/cmd/gc/subr.c126
1 files changed, 113 insertions, 13 deletions
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index be99a2afc..a0ef878f1 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -393,10 +393,11 @@ typ(int et)
return t;
}
-Node*
-dobad(void)
+
+Type*
+sortinter(Type *t)
{
- return nod(OBAD, N, N);
+ return t;
}
Node*
@@ -2636,23 +2637,25 @@ NodeList*
structargs(Type **tl, int mustname)
{
Iter savet;
- Node *a;
+ Node *a, *n;
NodeList *args;
Type *t;
- char nam[100];
- int n;
+ char buf[100];
+ int gen;
args = nil;
- n = 0;
+ gen = 0;
for(t = structfirst(&savet, tl); t != T; t = structnext(&savet)) {
+ n = N;
if(t->sym)
- a = nametodcl(newname(t->sym), t->type);
+ n = newname(t->sym);
else if(mustname) {
// have to give it a name so we can refer to it in trampoline
- snprint(nam, sizeof nam, ".anon%d", n++);
- a = nametodcl(newname(lookup(nam)), t->type);
- } else
- a = anondcl(t->type);
+ snprint(buf, sizeof buf, ".anon%d", gen++);
+ n = newname(lookup(buf));
+ }
+ a = nod(ODCLFIELD, n, N);
+ a->type = t->type;
args = list(args, a);
}
return args;
@@ -2694,7 +2697,8 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam)
dclcontext = PEXTERN;
markdcl();
- this = nametodcl(newname(lookup(".this")), rcvr);
+ this = nod(ODCLFIELD, newname(lookup(".this")), N);
+ this->type = rcvr;
in = structargs(getinarg(method->type), 1);
out = structargs(getoutarg(method->type), 0);
@@ -2982,6 +2986,9 @@ liststmt(NodeList *l)
return n;
}
+/*
+ * return nelem of list
+ */
int
count(NodeList *l)
{
@@ -2992,3 +2999,96 @@ count(NodeList *l)
n++;
return n;
}
+
+/*
+ * return nelem of list
+ */
+int
+structcount(Type *t)
+{
+ int v;
+ Iter s;
+
+ v = 0;
+ for(t = structfirst(&s, &t); t != T; t = structnext(&s))
+ v++;
+ return v;
+}
+
+/*
+ * when a type's width should be known, we call checkwidth
+ * to compute it. during a declaration like
+ *
+ * type T *struct { next T }
+ *
+ * it is necessary to defer the calculation of the struct width
+ * until after T has been initialized to be a pointer to that struct.
+ * similarly, during import processing structs may be used
+ * before their definition. in those situations, calling
+ * defercheckwidth() stops width calculations until
+ * resumecheckwidth() is called, at which point all the
+ * checkwidths that were deferred are executed.
+ * sometimes it is okay to
+ */
+typedef struct TypeList TypeList;
+struct TypeList {
+ Type *t;
+ TypeList *next;
+};
+
+static TypeList *tlfree;
+static TypeList *tlq;
+static int defercalc;
+
+void
+checkwidth(Type *t)
+{
+ TypeList *l;
+
+ // function arg structs should not be checked
+ // outside of the enclosing function.
+ if(t->funarg)
+ fatal("checkwidth %T", t);
+
+ if(!defercalc) {
+ dowidth(t);
+ return;
+ }
+
+ l = tlfree;
+ if(l != nil)
+ tlfree = l->next;
+ else
+ l = mal(sizeof *l);
+
+ l->t = t;
+ l->next = tlq;
+ tlq = l;
+}
+
+void
+defercheckwidth(void)
+{
+ // we get out of sync on syntax errors, so don't be pedantic.
+ // if(defercalc)
+ // fatal("defercheckwidth");
+ defercalc = 1;
+}
+
+void
+resumecheckwidth(void)
+{
+ TypeList *l;
+
+ if(!defercalc)
+ fatal("restartcheckwidth");
+ defercalc = 0;
+
+ for(l = tlq; l != nil; l = tlq) {
+ dowidth(l->t);
+ tlq = l->next;
+ l->next = tlfree;
+ tlfree = l;
+ }
+}
+