2009-07-07 12:03:04 -06:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "go.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* runtime interface and reflection data structures
|
|
|
|
*/
|
|
|
|
|
2009-08-04 23:59:23 -06:00
|
|
|
static NodeList* signatlist;
|
|
|
|
static Sym* dtypesym(Type*);
|
2011-03-03 11:17:54 -07:00
|
|
|
static Sym* weaktypesym(Type*);
|
2009-07-07 12:03:04 -06:00
|
|
|
|
|
|
|
static int
|
|
|
|
sigcmp(Sig *a, Sig *b)
|
|
|
|
{
|
2010-01-25 19:23:20 -07:00
|
|
|
int i;
|
|
|
|
|
|
|
|
i = strcmp(a->name, b->name);
|
|
|
|
if(i != 0)
|
|
|
|
return i;
|
|
|
|
if(a->pkg == b->pkg)
|
|
|
|
return 0;
|
|
|
|
if(a->pkg == nil)
|
|
|
|
return -1;
|
|
|
|
if(b->pkg == nil)
|
|
|
|
return +1;
|
|
|
|
return strcmp(a->pkg->path->s, b->pkg->path->s);
|
2009-07-07 12:03:04 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static Sig*
|
|
|
|
lsort(Sig *l, int(*f)(Sig*, Sig*))
|
|
|
|
{
|
|
|
|
Sig *l1, *l2, *le;
|
|
|
|
|
|
|
|
if(l == 0 || l->link == 0)
|
|
|
|
return l;
|
|
|
|
|
|
|
|
l1 = l;
|
|
|
|
l2 = l;
|
|
|
|
for(;;) {
|
|
|
|
l2 = l2->link;
|
|
|
|
if(l2 == 0)
|
|
|
|
break;
|
|
|
|
l2 = l2->link;
|
|
|
|
if(l2 == 0)
|
|
|
|
break;
|
|
|
|
l1 = l1->link;
|
|
|
|
}
|
|
|
|
|
|
|
|
l2 = l1->link;
|
|
|
|
l1->link = 0;
|
|
|
|
l1 = lsort(l, f);
|
|
|
|
l2 = lsort(l2, f);
|
|
|
|
|
|
|
|
/* set up lead element */
|
|
|
|
if((*f)(l1, l2) < 0) {
|
|
|
|
l = l1;
|
|
|
|
l1 = l1->link;
|
|
|
|
} else {
|
|
|
|
l = l2;
|
|
|
|
l2 = l2->link;
|
|
|
|
}
|
|
|
|
le = l;
|
|
|
|
|
|
|
|
for(;;) {
|
|
|
|
if(l1 == 0) {
|
|
|
|
while(l2) {
|
|
|
|
le->link = l2;
|
|
|
|
le = l2;
|
|
|
|
l2 = l2->link;
|
|
|
|
}
|
|
|
|
le->link = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(l2 == 0) {
|
|
|
|
while(l1) {
|
|
|
|
le->link = l1;
|
|
|
|
le = l1;
|
|
|
|
l1 = l1->link;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if((*f)(l1, l2) < 0) {
|
|
|
|
le->link = l1;
|
|
|
|
le = l1;
|
|
|
|
l1 = l1->link;
|
|
|
|
} else {
|
|
|
|
le->link = l2;
|
|
|
|
le = l2;
|
|
|
|
l2 = l2->link;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
le->link = 0;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* f is method type, with receiver.
|
2010-01-25 19:23:20 -07:00
|
|
|
* return function type, receiver as first argument (or not).
|
2009-07-07 12:03:04 -06:00
|
|
|
*/
|
2009-12-18 18:24:58 -07:00
|
|
|
Type*
|
2010-09-28 11:43:50 -06:00
|
|
|
methodfunc(Type *f, Type *receiver)
|
2009-07-07 12:03:04 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
NodeList *in, *out;
|
|
|
|
Node *d;
|
2009-07-07 12:03:04 -06:00
|
|
|
Type *t;
|
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
in = nil;
|
2010-09-28 11:43:50 -06:00
|
|
|
if(receiver) {
|
2009-07-07 12:03:04 -06:00
|
|
|
d = nod(ODCLFIELD, N, N);
|
2010-09-28 11:43:50 -06:00
|
|
|
d->type = receiver;
|
2009-07-07 12:03:04 -06:00
|
|
|
in = list(in, d);
|
|
|
|
}
|
2009-12-18 18:24:58 -07:00
|
|
|
for(t=getinargx(f)->type; t; t=t->down) {
|
2009-07-07 12:03:04 -06:00
|
|
|
d = nod(ODCLFIELD, N, N);
|
|
|
|
d->type = t->type;
|
2010-02-01 11:49:24 -07:00
|
|
|
d->isddd = t->isddd;
|
2009-07-07 12:03:04 -06:00
|
|
|
in = list(in, d);
|
|
|
|
}
|
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
out = nil;
|
2009-12-18 18:24:58 -07:00
|
|
|
for(t=getoutargx(f)->type; t; t=t->down) {
|
2009-07-07 12:03:04 -06:00
|
|
|
d = nod(ODCLFIELD, N, N);
|
|
|
|
d->type = t->type;
|
|
|
|
out = list(out, d);
|
|
|
|
}
|
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
return functype(N, in, out);
|
2009-07-07 12:03:04 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-01-25 19:23:20 -07:00
|
|
|
* return methods of non-interface type t, sorted by name.
|
2009-07-07 12:03:04 -06:00
|
|
|
* generates stub functions as needed.
|
|
|
|
*/
|
|
|
|
static Sig*
|
|
|
|
methods(Type *t)
|
|
|
|
{
|
|
|
|
Type *f, *mt, *it, *this;
|
|
|
|
Sig *a, *b;
|
|
|
|
Sym *method;
|
|
|
|
Prog *oldlist;
|
|
|
|
|
|
|
|
// named method type
|
|
|
|
mt = methtype(t);
|
|
|
|
if(mt == T)
|
|
|
|
return nil;
|
|
|
|
expandmeth(mt->sym, mt);
|
|
|
|
|
|
|
|
// type stored in interface word
|
|
|
|
it = t;
|
|
|
|
if(it->width > widthptr)
|
|
|
|
it = ptrto(t);
|
|
|
|
|
|
|
|
// make list of methods for t,
|
|
|
|
// generating code if necessary.
|
|
|
|
a = nil;
|
|
|
|
oldlist = nil;
|
2009-07-07 17:05:55 -06:00
|
|
|
for(f=mt->xmethod; f; f=f->down) {
|
2009-07-07 12:03:04 -06:00
|
|
|
if(f->type->etype != TFUNC)
|
|
|
|
continue;
|
|
|
|
if(f->etype != TFIELD)
|
|
|
|
fatal("methods: not field");
|
|
|
|
method = f->sym;
|
|
|
|
if(method == nil)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// get receiver type for this particular method.
|
|
|
|
// if pointer receiver but non-pointer t and
|
|
|
|
// this is not an embedded pointer inside a struct,
|
|
|
|
// method does not apply.
|
|
|
|
this = getthisx(f->type)->type->type;
|
2009-07-07 17:05:55 -06:00
|
|
|
if(isptr[this->etype] && this->type == t)
|
|
|
|
continue;
|
2009-07-07 12:03:04 -06:00
|
|
|
if(isptr[this->etype] && !isptr[t->etype]
|
2009-12-18 18:24:58 -07:00
|
|
|
&& f->embedded != 2 && !isifacemethod(f->type))
|
2009-07-07 12:03:04 -06:00
|
|
|
continue;
|
|
|
|
|
|
|
|
b = mal(sizeof(*b));
|
|
|
|
b->link = a;
|
|
|
|
a = b;
|
|
|
|
|
|
|
|
a->name = method->name;
|
2010-07-26 16:25:10 -06:00
|
|
|
a->isym = methodsym(method, it, 1);
|
|
|
|
a->tsym = methodsym(method, t, 0);
|
2010-09-28 11:43:50 -06:00
|
|
|
a->type = methodfunc(f->type, t);
|
|
|
|
a->mtype = methodfunc(f->type, nil);
|
2009-07-07 12:03:04 -06:00
|
|
|
|
2009-08-04 23:59:23 -06:00
|
|
|
if(!(a->isym->flags & SymSiggen)) {
|
|
|
|
a->isym->flags |= SymSiggen;
|
2010-07-26 16:25:10 -06:00
|
|
|
if(!eqtype(this, it) || this->width < types[tptr]->width) {
|
2009-07-07 12:03:04 -06:00
|
|
|
if(oldlist == nil)
|
|
|
|
oldlist = pc;
|
|
|
|
// Is okay to call genwrapper here always,
|
|
|
|
// but we can generate more efficient code
|
|
|
|
// using genembedtramp if all that is necessary
|
|
|
|
// is a pointer adjustment and a JMP.
|
|
|
|
if(isptr[it->etype] && isptr[this->etype]
|
2009-12-18 18:24:58 -07:00
|
|
|
&& f->embedded && !isifacemethod(f->type))
|
2010-07-27 14:43:58 -06:00
|
|
|
genembedtramp(it, f, a->isym, 1);
|
2009-07-07 12:03:04 -06:00
|
|
|
else
|
2010-07-26 16:25:10 -06:00
|
|
|
genwrapper(it, f, a->isym, 1);
|
2009-07-07 12:03:04 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-04 23:59:23 -06:00
|
|
|
if(!(a->tsym->flags & SymSiggen)) {
|
|
|
|
a->tsym->flags |= SymSiggen;
|
2009-07-07 12:03:04 -06:00
|
|
|
if(!eqtype(this, t)) {
|
|
|
|
if(oldlist == nil)
|
|
|
|
oldlist = pc;
|
2009-07-07 17:05:55 -06:00
|
|
|
if(isptr[t->etype] && isptr[this->etype]
|
2009-12-18 18:24:58 -07:00
|
|
|
&& f->embedded && !isifacemethod(f->type))
|
2010-07-27 14:43:58 -06:00
|
|
|
genembedtramp(t, f, a->tsym, 0);
|
2009-07-07 12:03:04 -06:00
|
|
|
else
|
2010-07-26 16:25:10 -06:00
|
|
|
genwrapper(t, f, a->tsym, 0);
|
2009-07-07 12:03:04 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// restore data output
|
|
|
|
if(oldlist) {
|
|
|
|
// old list ended with AEND; change to ANOP
|
|
|
|
// so that the trampolines that follow can be found.
|
|
|
|
nopout(oldlist);
|
|
|
|
|
|
|
|
// start new data list
|
|
|
|
newplist();
|
|
|
|
}
|
|
|
|
|
|
|
|
return lsort(a, sigcmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-01-25 19:23:20 -07:00
|
|
|
* return methods of interface type t, sorted by name.
|
2009-07-07 12:03:04 -06:00
|
|
|
*/
|
2010-06-14 12:24:51 -06:00
|
|
|
static Sig*
|
2009-07-07 12:03:04 -06:00
|
|
|
imethods(Type *t)
|
|
|
|
{
|
2010-01-25 19:23:20 -07:00
|
|
|
Sig *a, *all, *last;
|
2009-07-07 12:03:04 -06:00
|
|
|
Type *f;
|
2010-09-28 11:43:50 -06:00
|
|
|
Sym *method, *isym;
|
|
|
|
Prog *oldlist;
|
2009-07-07 12:03:04 -06:00
|
|
|
|
2010-01-25 19:23:20 -07:00
|
|
|
all = nil;
|
|
|
|
last = nil;
|
2010-09-28 11:43:50 -06:00
|
|
|
oldlist = nil;
|
2009-07-07 12:03:04 -06:00
|
|
|
for(f=t->type; f; f=f->down) {
|
|
|
|
if(f->etype != TFIELD)
|
|
|
|
fatal("imethods: not field");
|
|
|
|
if(f->type->etype != TFUNC || f->sym == nil)
|
|
|
|
continue;
|
2010-09-28 11:43:50 -06:00
|
|
|
method = f->sym;
|
2010-01-25 19:23:20 -07:00
|
|
|
a = mal(sizeof(*a));
|
2010-09-28 11:43:50 -06:00
|
|
|
a->name = method->name;
|
|
|
|
if(!exportname(method->name))
|
|
|
|
a->pkg = method->pkg;
|
2010-01-25 19:23:20 -07:00
|
|
|
a->mtype = f->type;
|
2009-07-07 12:03:04 -06:00
|
|
|
a->offset = 0;
|
2010-09-28 11:43:50 -06:00
|
|
|
a->type = methodfunc(f->type, nil);
|
|
|
|
|
2010-01-25 19:23:20 -07:00
|
|
|
if(last && sigcmp(last, a) >= 0)
|
|
|
|
fatal("sigcmp vs sortinter %s %s", last->name, a->name);
|
|
|
|
if(last == nil)
|
|
|
|
all = a;
|
|
|
|
else
|
|
|
|
last->link = a;
|
|
|
|
last = a;
|
2010-09-28 11:43:50 -06:00
|
|
|
|
|
|
|
// Compiler can only refer to wrappers for
|
|
|
|
// named interface types.
|
|
|
|
if(t->sym == S)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// NOTE(rsc): Perhaps an oversight that
|
|
|
|
// IfaceType.Method is not in the reflect data.
|
|
|
|
// Generate the method body, so that compiled
|
|
|
|
// code can refer to it.
|
|
|
|
isym = methodsym(method, t, 0);
|
|
|
|
if(!(isym->flags & SymSiggen)) {
|
|
|
|
isym->flags |= SymSiggen;
|
|
|
|
if(oldlist == nil)
|
|
|
|
oldlist = pc;
|
|
|
|
genwrapper(t, f, isym, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(oldlist) {
|
|
|
|
// old list ended with AEND; change to ANOP
|
|
|
|
// so that the trampolines that follow can be found.
|
|
|
|
nopout(oldlist);
|
|
|
|
|
|
|
|
// start new data list
|
|
|
|
newplist();
|
2009-07-07 12:03:04 -06:00
|
|
|
}
|
2010-09-28 11:43:50 -06:00
|
|
|
|
2010-01-25 19:23:20 -07:00
|
|
|
return all;
|
2009-07-07 12:03:04 -06:00
|
|
|
}
|
|
|
|
|
2010-01-22 18:06:20 -07:00
|
|
|
static int
|
|
|
|
dgopkgpath(Sym *s, int ot, Pkg *pkg)
|
|
|
|
{
|
|
|
|
if(pkg == nil)
|
|
|
|
return dgostringptr(s, ot, nil);
|
|
|
|
|
2010-01-25 00:33:59 -07:00
|
|
|
// Emit reference to go.importpath.""., which 6l will
|
|
|
|
// rewrite using the correct import path. Every package
|
|
|
|
// that imports this one directly defines the symbol.
|
|
|
|
if(pkg == localpkg) {
|
|
|
|
static Sym *ns;
|
|
|
|
|
|
|
|
if(ns == nil)
|
|
|
|
ns = pkglookup("importpath.\"\".", mkpkg(strlit("go")));
|
|
|
|
return dsymptr(s, ot, ns, 0);
|
|
|
|
}
|
|
|
|
|
2010-01-22 18:06:20 -07:00
|
|
|
return dgostringptr(s, ot, pkg->name);
|
|
|
|
}
|
|
|
|
|
2010-01-25 00:33:59 -07:00
|
|
|
static void
|
|
|
|
dimportpath(Pkg *p)
|
|
|
|
{
|
|
|
|
static Pkg *gopkg;
|
|
|
|
char *nam;
|
|
|
|
Node *n;
|
|
|
|
|
|
|
|
if(gopkg == nil) {
|
|
|
|
gopkg = mkpkg(strlit("go"));
|
|
|
|
gopkg->name = "go";
|
|
|
|
}
|
|
|
|
nam = smprint("importpath.%s.", p->prefix);
|
|
|
|
|
|
|
|
n = nod(ONAME, N, N);
|
|
|
|
n->sym = pkglookup(nam, gopkg);
|
|
|
|
free(nam);
|
|
|
|
n->class = PEXTERN;
|
|
|
|
n->xoffset = 0;
|
|
|
|
|
|
|
|
gdatastring(n, p->path);
|
|
|
|
ggloblsym(n->sym, types[TSTRING]->width, 1);
|
|
|
|
}
|
2010-01-22 18:06:20 -07:00
|
|
|
|
2009-07-07 12:03:04 -06:00
|
|
|
/*
|
|
|
|
* uncommonType
|
|
|
|
* ../../pkg/runtime/type.go:/uncommonType
|
|
|
|
*/
|
2011-04-09 07:44:20 -06:00
|
|
|
static int
|
|
|
|
dextratype(Sym *sym, int off, Type *t, int ptroff)
|
2009-07-07 12:03:04 -06:00
|
|
|
{
|
|
|
|
int ot, n;
|
|
|
|
Sym *s;
|
|
|
|
Sig *a, *m;
|
|
|
|
|
|
|
|
m = methods(t);
|
|
|
|
if(t->sym == nil && m == nil)
|
2011-04-09 07:44:20 -06:00
|
|
|
return off;
|
|
|
|
|
|
|
|
// fill in *extraType pointer in header
|
|
|
|
dsymptr(sym, ptroff, sym, off);
|
2009-07-07 12:03:04 -06:00
|
|
|
|
|
|
|
n = 0;
|
|
|
|
for(a=m; a; a=a->link) {
|
|
|
|
dtypesym(a->type);
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
|
2011-04-09 07:44:20 -06:00
|
|
|
ot = off;
|
|
|
|
s = sym;
|
2009-07-07 12:03:04 -06:00
|
|
|
if(t->sym) {
|
|
|
|
ot = dgostringptr(s, ot, t->sym->name);
|
|
|
|
if(t != types[t->etype])
|
2010-01-22 18:06:20 -07:00
|
|
|
ot = dgopkgpath(s, ot, t->sym->pkg);
|
2009-07-07 12:03:04 -06:00
|
|
|
else
|
|
|
|
ot = dgostringptr(s, ot, nil);
|
|
|
|
} else {
|
|
|
|
ot = dgostringptr(s, ot, nil);
|
|
|
|
ot = dgostringptr(s, ot, nil);
|
|
|
|
}
|
|
|
|
|
|
|
|
// slice header
|
|
|
|
ot = dsymptr(s, ot, s, ot + widthptr + 2*4);
|
|
|
|
ot = duint32(s, ot, n);
|
|
|
|
ot = duint32(s, ot, n);
|
|
|
|
|
|
|
|
// methods
|
|
|
|
for(a=m; a; a=a->link) {
|
|
|
|
// method
|
|
|
|
// ../../pkg/runtime/type.go:/method
|
|
|
|
ot = dgostringptr(s, ot, a->name);
|
2010-01-22 18:06:20 -07:00
|
|
|
ot = dgopkgpath(s, ot, a->pkg);
|
2010-01-25 19:23:20 -07:00
|
|
|
ot = dsymptr(s, ot, dtypesym(a->mtype), 0);
|
2009-07-07 12:03:04 -06:00
|
|
|
ot = dsymptr(s, ot, dtypesym(a->type), 0);
|
|
|
|
if(a->isym)
|
|
|
|
ot = dsymptr(s, ot, a->isym, 0);
|
|
|
|
else
|
|
|
|
ot = duintptr(s, ot, 0);
|
|
|
|
if(a->tsym)
|
|
|
|
ot = dsymptr(s, ot, a->tsym, 0);
|
|
|
|
else
|
|
|
|
ot = duintptr(s, ot, 0);
|
|
|
|
}
|
|
|
|
|
2011-04-09 07:44:20 -06:00
|
|
|
return ot;
|
2009-07-07 12:03:04 -06:00
|
|
|
}
|
|
|
|
|
2009-12-04 22:44:05 -07:00
|
|
|
enum {
|
|
|
|
KindBool = 1,
|
|
|
|
KindInt,
|
|
|
|
KindInt8,
|
|
|
|
KindInt16,
|
|
|
|
KindInt32,
|
|
|
|
KindInt64,
|
|
|
|
KindUint,
|
|
|
|
KindUint8,
|
|
|
|
KindUint16,
|
|
|
|
KindUint32,
|
|
|
|
KindUint64,
|
|
|
|
KindUintptr,
|
|
|
|
KindFloat32,
|
|
|
|
KindFloat64,
|
2010-06-20 13:16:25 -06:00
|
|
|
KindComplex64,
|
|
|
|
KindComplex128,
|
2009-12-04 22:44:05 -07:00
|
|
|
KindArray,
|
|
|
|
KindChan,
|
|
|
|
KindFunc,
|
|
|
|
KindInterface,
|
|
|
|
KindMap,
|
|
|
|
KindPtr,
|
|
|
|
KindSlice,
|
|
|
|
KindString,
|
|
|
|
KindStruct,
|
|
|
|
KindUnsafePointer,
|
|
|
|
|
|
|
|
KindNoPointers = 1<<7,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
kinds[] =
|
|
|
|
{
|
|
|
|
[TINT] = KindInt,
|
|
|
|
[TUINT] = KindUint,
|
|
|
|
[TINT8] = KindInt8,
|
|
|
|
[TUINT8] = KindUint8,
|
|
|
|
[TINT16] = KindInt16,
|
|
|
|
[TUINT16] = KindUint16,
|
|
|
|
[TINT32] = KindInt32,
|
|
|
|
[TUINT32] = KindUint32,
|
|
|
|
[TINT64] = KindInt64,
|
|
|
|
[TUINT64] = KindUint64,
|
|
|
|
[TUINTPTR] = KindUintptr,
|
|
|
|
[TFLOAT32] = KindFloat32,
|
|
|
|
[TFLOAT64] = KindFloat64,
|
|
|
|
[TBOOL] = KindBool,
|
|
|
|
[TSTRING] = KindString,
|
|
|
|
[TPTR32] = KindPtr,
|
|
|
|
[TPTR64] = KindPtr,
|
|
|
|
[TSTRUCT] = KindStruct,
|
|
|
|
[TINTER] = KindInterface,
|
|
|
|
[TCHAN] = KindChan,
|
|
|
|
[TMAP] = KindMap,
|
|
|
|
[TARRAY] = KindArray,
|
|
|
|
[TFUNC] = KindFunc,
|
2010-06-20 13:16:25 -06:00
|
|
|
[TCOMPLEX64] = KindComplex64,
|
|
|
|
[TCOMPLEX128] = KindComplex128,
|
2011-03-07 13:10:01 -07:00
|
|
|
[TUNSAFEPTR] = KindUnsafePointer,
|
2009-12-04 22:44:05 -07:00
|
|
|
};
|
|
|
|
|
2009-07-07 12:03:04 -06:00
|
|
|
static char*
|
|
|
|
structnames[] =
|
|
|
|
{
|
|
|
|
[TINT] = "*runtime.IntType",
|
|
|
|
[TUINT] = "*runtime.UintType",
|
2010-06-20 13:16:25 -06:00
|
|
|
[TINT8] = "*runtime.IntType",
|
|
|
|
[TUINT8] = "*runtime.UintType",
|
|
|
|
[TINT16] = "*runtime.IntType",
|
|
|
|
[TUINT16] = "*runtime.UintType",
|
|
|
|
[TINT32] = "*runtime.IntType",
|
|
|
|
[TUINT32] = "*runtime.UintType",
|
|
|
|
[TINT64] = "*runtime.IntType",
|
|
|
|
[TUINT64] = "*runtime.UintType",
|
|
|
|
[TUINTPTR] = "*runtime.UintType",
|
|
|
|
[TCOMPLEX64] = "*runtime.ComplexType",
|
|
|
|
[TCOMPLEX128] = "*runtime.ComplexType",
|
|
|
|
[TFLOAT32] = "*runtime.FloatType",
|
|
|
|
[TFLOAT64] = "*runtime.FloatType",
|
2009-07-07 12:03:04 -06:00
|
|
|
[TBOOL] = "*runtime.BoolType",
|
2010-02-17 23:08:30 -07:00
|
|
|
[TSTRING] = "*runtime.StringType",
|
2011-03-07 13:10:01 -07:00
|
|
|
[TUNSAFEPTR] = "*runtime.UnsafePointerType",
|
2009-07-07 12:03:04 -06:00
|
|
|
|
2010-02-17 23:08:30 -07:00
|
|
|
[TPTR32] = "*runtime.PtrType",
|
|
|
|
[TPTR64] = "*runtime.PtrType",
|
2009-07-07 12:03:04 -06:00
|
|
|
[TSTRUCT] = "*runtime.StructType",
|
2010-02-17 23:08:30 -07:00
|
|
|
[TINTER] = "*runtime.InterfaceType",
|
2009-07-07 12:03:04 -06:00
|
|
|
[TCHAN] = "*runtime.ChanType",
|
|
|
|
[TMAP] = "*runtime.MapType",
|
2010-02-17 23:08:30 -07:00
|
|
|
[TARRAY] = "*runtime.ArrayType",
|
2009-07-07 12:03:04 -06:00
|
|
|
[TFUNC] = "*runtime.FuncType",
|
|
|
|
};
|
|
|
|
|
|
|
|
static Sym*
|
|
|
|
typestruct(Type *t)
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
int et;
|
|
|
|
|
|
|
|
et = t->etype;
|
|
|
|
if(et < 0 || et >= nelem(structnames) || (name = structnames[et]) == nil) {
|
|
|
|
fatal("typestruct %lT", t);
|
|
|
|
return nil; // silence gcc
|
|
|
|
}
|
|
|
|
|
|
|
|
if(isslice(t))
|
|
|
|
name = "*runtime.SliceType";
|
|
|
|
|
2010-01-22 18:06:20 -07:00
|
|
|
return pkglookup(name, typepkg);
|
2009-07-07 12:03:04 -06:00
|
|
|
}
|
|
|
|
|
2009-12-04 22:44:05 -07:00
|
|
|
static int
|
|
|
|
haspointers(Type *t)
|
|
|
|
{
|
|
|
|
Type *t1;
|
|
|
|
|
|
|
|
switch(t->etype) {
|
|
|
|
case TINT:
|
|
|
|
case TUINT:
|
|
|
|
case TINT8:
|
|
|
|
case TUINT8:
|
|
|
|
case TINT16:
|
|
|
|
case TUINT16:
|
|
|
|
case TINT32:
|
|
|
|
case TUINT32:
|
|
|
|
case TINT64:
|
|
|
|
case TUINT64:
|
|
|
|
case TUINTPTR:
|
|
|
|
case TFLOAT32:
|
|
|
|
case TFLOAT64:
|
|
|
|
case TBOOL:
|
|
|
|
return 0;
|
|
|
|
case TARRAY:
|
|
|
|
if(t->bound < 0) // slice
|
|
|
|
return 1;
|
|
|
|
return haspointers(t->type);
|
|
|
|
case TSTRUCT:
|
|
|
|
for(t1=t->type; t1!=T; t1=t1->down)
|
|
|
|
if(haspointers(t1->type))
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
case TSTRING:
|
|
|
|
case TPTR32:
|
|
|
|
case TPTR64:
|
2011-03-07 13:10:01 -07:00
|
|
|
case TUNSAFEPTR:
|
2009-12-04 22:44:05 -07:00
|
|
|
case TINTER:
|
|
|
|
case TCHAN:
|
|
|
|
case TMAP:
|
|
|
|
case TFUNC:
|
|
|
|
default:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-07 12:03:04 -06:00
|
|
|
/*
|
|
|
|
* commonType
|
|
|
|
* ../../pkg/runtime/type.go:/commonType
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
dcommontype(Sym *s, int ot, Type *t)
|
|
|
|
{
|
|
|
|
int i;
|
2011-03-03 11:17:54 -07:00
|
|
|
Sym *sptr;
|
2009-07-07 12:03:04 -06:00
|
|
|
char *p;
|
|
|
|
|
2009-08-07 13:50:26 -06:00
|
|
|
dowidth(t);
|
2011-03-03 11:17:54 -07:00
|
|
|
|
|
|
|
sptr = nil;
|
|
|
|
if(t->sym != nil && !isptr[t->etype])
|
|
|
|
sptr = dtypesym(ptrto(t));
|
|
|
|
else
|
|
|
|
sptr = weaktypesym(ptrto(t));
|
|
|
|
|
2009-07-07 12:03:04 -06:00
|
|
|
// empty interface pointing at this type.
|
|
|
|
// all the references that we emit are *interface{};
|
|
|
|
// they point here.
|
|
|
|
ot = rnd(ot, widthptr);
|
|
|
|
ot = dsymptr(s, ot, typestruct(t), 0);
|
|
|
|
ot = dsymptr(s, ot, s, 2*widthptr);
|
|
|
|
|
|
|
|
// ../../pkg/runtime/type.go:/commonType
|
|
|
|
// actual type structure
|
|
|
|
// type commonType struct {
|
|
|
|
// size uintptr;
|
|
|
|
// hash uint32;
|
|
|
|
// alg uint8;
|
|
|
|
// align uint8;
|
|
|
|
// fieldAlign uint8;
|
2010-12-13 08:05:20 -07:00
|
|
|
// kind uint8;
|
2009-07-07 12:03:04 -06:00
|
|
|
// string *string;
|
2011-02-24 15:11:20 -07:00
|
|
|
// *extraType;
|
|
|
|
// ptrToThis *Type
|
2009-07-07 12:03:04 -06:00
|
|
|
// }
|
|
|
|
ot = duintptr(s, ot, t->width);
|
2009-09-02 10:09:32 -06:00
|
|
|
ot = duint32(s, ot, typehash(t));
|
2009-07-07 12:03:04 -06:00
|
|
|
ot = duint8(s, ot, algtype(t));
|
2010-12-13 09:57:41 -07:00
|
|
|
ot = duint8(s, ot, t->align); // align
|
|
|
|
ot = duint8(s, ot, t->align); // fieldAlign
|
2009-12-04 22:44:05 -07:00
|
|
|
i = kinds[t->etype];
|
|
|
|
if(t->etype == TARRAY && t->bound < 0)
|
|
|
|
i = KindSlice;
|
|
|
|
if(!haspointers(t))
|
|
|
|
i |= KindNoPointers;
|
2010-10-05 13:17:16 -06:00
|
|
|
ot = duint8(s, ot, i); // kind
|
2010-01-25 19:23:20 -07:00
|
|
|
longsymnames = 1;
|
|
|
|
p = smprint("%-T", t);
|
|
|
|
longsymnames = 0;
|
2009-07-07 12:03:04 -06:00
|
|
|
ot = dgostringptr(s, ot, p); // string
|
|
|
|
free(p);
|
2011-04-09 07:44:20 -06:00
|
|
|
|
|
|
|
// skip pointer to extraType,
|
|
|
|
// which follows the rest of this type structure.
|
|
|
|
// caller will fill in if needed.
|
|
|
|
// otherwise linker will assume 0.
|
|
|
|
ot += widthptr;
|
|
|
|
|
|
|
|
ot = dsymptr(s, ot, sptr, 0); // ptrto type
|
2009-07-07 12:03:04 -06:00
|
|
|
return ot;
|
|
|
|
}
|
|
|
|
|
|
|
|
Sym*
|
|
|
|
typesym(Type *t)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
Sym *s;
|
|
|
|
|
|
|
|
p = smprint("%#-T", t);
|
2010-01-22 18:06:20 -07:00
|
|
|
s = pkglookup(p, typepkg);
|
2009-07-07 12:03:04 -06:00
|
|
|
free(p);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node*
|
|
|
|
typename(Type *t)
|
|
|
|
{
|
|
|
|
Sym *s;
|
|
|
|
Node *n;
|
|
|
|
|
2010-06-27 18:37:01 -06:00
|
|
|
if(t == T || (isptr[t->etype] && t->type == T) || isideal(t))
|
2009-08-13 15:41:42 -06:00
|
|
|
fatal("typename %T", t);
|
2009-07-07 12:03:04 -06:00
|
|
|
s = typesym(t);
|
|
|
|
if(s->def == N) {
|
|
|
|
n = nod(ONAME, N, N);
|
|
|
|
n->sym = s;
|
|
|
|
n->type = types[TUINT8];
|
|
|
|
n->addable = 1;
|
|
|
|
n->ullman = 1;
|
|
|
|
n->class = PEXTERN;
|
|
|
|
n->xoffset = 0;
|
|
|
|
s->def = n;
|
|
|
|
|
2009-08-04 23:59:23 -06:00
|
|
|
signatlist = list(signatlist, typenod(t));
|
2009-07-07 12:03:04 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
n = nod(OADDR, s->def, N);
|
|
|
|
n->type = ptrto(s->def->type);
|
|
|
|
n->addable = 1;
|
|
|
|
n->ullman = 2;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2011-03-03 11:17:54 -07:00
|
|
|
static Sym*
|
|
|
|
weaktypesym(Type *t)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
Sym *s;
|
|
|
|
static Pkg *weak;
|
|
|
|
|
|
|
|
if(weak == nil) {
|
|
|
|
weak = mkpkg(strlit("weak.type"));
|
|
|
|
weak->name = "weak.type";
|
|
|
|
weak->prefix = "weak.type"; // not weak%2etype
|
|
|
|
}
|
|
|
|
|
|
|
|
p = smprint("%#-T", t);
|
|
|
|
s = pkglookup(p, weak);
|
|
|
|
free(p);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2009-12-27 10:32:30 -07:00
|
|
|
static Sym*
|
2009-07-07 12:03:04 -06:00
|
|
|
dtypesym(Type *t)
|
|
|
|
{
|
2011-04-09 07:44:20 -06:00
|
|
|
int ot, xt, n, isddd, dupok;
|
2009-07-07 12:03:04 -06:00
|
|
|
Sym *s, *s1, *s2;
|
|
|
|
Sig *a, *m;
|
2010-12-13 08:05:20 -07:00
|
|
|
Type *t1, *tbase;
|
2009-08-27 12:16:34 -06:00
|
|
|
|
2009-09-21 16:45:55 -06:00
|
|
|
if(isideal(t))
|
|
|
|
fatal("dtypesym %T", t);
|
2009-07-07 12:03:04 -06:00
|
|
|
|
|
|
|
s = typesym(t);
|
2009-08-04 23:59:23 -06:00
|
|
|
if(s->flags & SymSiggen)
|
2009-07-07 12:03:04 -06:00
|
|
|
return s;
|
2009-08-04 23:59:23 -06:00
|
|
|
s->flags |= SymSiggen;
|
2009-07-07 12:03:04 -06:00
|
|
|
|
|
|
|
// special case (look for runtime below):
|
|
|
|
// when compiling package runtime,
|
|
|
|
// emit the type structures for int, float, etc.
|
2010-12-13 08:05:20 -07:00
|
|
|
tbase = t;
|
|
|
|
if(isptr[t->etype] && t->sym == S && t->type->sym != S)
|
|
|
|
tbase = t->type;
|
|
|
|
dupok = tbase->sym == S;
|
2009-07-07 12:03:04 -06:00
|
|
|
|
2011-03-07 13:10:01 -07:00
|
|
|
if(compiling_runtime && tbase == types[tbase->etype]) // int, float, etc
|
|
|
|
goto ok;
|
2009-07-07 12:03:04 -06:00
|
|
|
|
2010-12-13 08:05:20 -07:00
|
|
|
// named types from other files are defined only by those files
|
|
|
|
if(tbase->sym && !tbase->local)
|
2009-07-07 12:03:04 -06:00
|
|
|
return s;
|
2010-12-13 08:05:20 -07:00
|
|
|
if(isforw[tbase->etype])
|
2009-07-07 12:03:04 -06:00
|
|
|
return s;
|
|
|
|
|
|
|
|
ok:
|
|
|
|
ot = 0;
|
2011-04-09 07:44:20 -06:00
|
|
|
xt = 0;
|
2009-07-07 12:03:04 -06:00
|
|
|
switch(t->etype) {
|
|
|
|
default:
|
|
|
|
ot = dcommontype(s, ot, t);
|
2011-04-09 07:44:20 -06:00
|
|
|
xt = ot - 2*widthptr;
|
2009-07-07 12:03:04 -06:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TARRAY:
|
|
|
|
// ../../pkg/runtime/type.go:/ArrayType
|
|
|
|
s1 = dtypesym(t->type);
|
|
|
|
ot = dcommontype(s, ot, t);
|
2011-04-09 07:44:20 -06:00
|
|
|
xt = ot - 2*widthptr;
|
2009-07-07 12:03:04 -06:00
|
|
|
ot = dsymptr(s, ot, s1, 0);
|
|
|
|
if(t->bound < 0)
|
|
|
|
ot = duintptr(s, ot, -1);
|
|
|
|
else
|
|
|
|
ot = duintptr(s, ot, t->bound);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TCHAN:
|
|
|
|
// ../../pkg/runtime/type.go:/ChanType
|
|
|
|
s1 = dtypesym(t->type);
|
|
|
|
ot = dcommontype(s, ot, t);
|
2011-04-09 07:44:20 -06:00
|
|
|
xt = ot - 2*widthptr;
|
2009-07-07 12:03:04 -06:00
|
|
|
ot = dsymptr(s, ot, s1, 0);
|
|
|
|
ot = duintptr(s, ot, t->chan);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TFUNC:
|
|
|
|
for(t1=getthisx(t)->type; t1; t1=t1->down)
|
|
|
|
dtypesym(t1->type);
|
2010-02-01 01:25:59 -07:00
|
|
|
isddd = 0;
|
|
|
|
for(t1=getinargx(t)->type; t1; t1=t1->down) {
|
|
|
|
isddd = t1->isddd;
|
2009-07-07 12:03:04 -06:00
|
|
|
dtypesym(t1->type);
|
2010-02-01 01:25:59 -07:00
|
|
|
}
|
2009-07-07 12:03:04 -06:00
|
|
|
for(t1=getoutargx(t)->type; t1; t1=t1->down)
|
|
|
|
dtypesym(t1->type);
|
|
|
|
|
|
|
|
ot = dcommontype(s, ot, t);
|
2011-04-09 07:44:20 -06:00
|
|
|
xt = ot - 2*widthptr;
|
2010-02-01 01:25:59 -07:00
|
|
|
ot = duint8(s, ot, isddd);
|
2009-07-07 12:03:04 -06:00
|
|
|
|
|
|
|
// two slice headers: in and out.
|
2010-02-01 01:25:59 -07:00
|
|
|
ot = rnd(ot, widthptr);
|
2009-07-07 12:03:04 -06:00
|
|
|
ot = dsymptr(s, ot, s, ot+2*(widthptr+2*4));
|
|
|
|
n = t->thistuple + t->intuple;
|
|
|
|
ot = duint32(s, ot, n);
|
|
|
|
ot = duint32(s, ot, n);
|
|
|
|
ot = dsymptr(s, ot, s, ot+1*(widthptr+2*4)+n*widthptr);
|
|
|
|
ot = duint32(s, ot, t->outtuple);
|
|
|
|
ot = duint32(s, ot, t->outtuple);
|
|
|
|
|
|
|
|
// slice data
|
|
|
|
for(t1=getthisx(t)->type; t1; t1=t1->down, n++)
|
|
|
|
ot = dsymptr(s, ot, dtypesym(t1->type), 0);
|
|
|
|
for(t1=getinargx(t)->type; t1; t1=t1->down, n++)
|
|
|
|
ot = dsymptr(s, ot, dtypesym(t1->type), 0);
|
|
|
|
for(t1=getoutargx(t)->type; t1; t1=t1->down, n++)
|
|
|
|
ot = dsymptr(s, ot, dtypesym(t1->type), 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TINTER:
|
|
|
|
m = imethods(t);
|
|
|
|
n = 0;
|
|
|
|
for(a=m; a; a=a->link) {
|
|
|
|
dtypesym(a->type);
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ../../pkg/runtime/type.go:/InterfaceType
|
|
|
|
ot = dcommontype(s, ot, t);
|
2011-04-09 07:44:20 -06:00
|
|
|
xt = ot - 2*widthptr;
|
2009-07-07 12:03:04 -06:00
|
|
|
ot = dsymptr(s, ot, s, ot+widthptr+2*4);
|
|
|
|
ot = duint32(s, ot, n);
|
|
|
|
ot = duint32(s, ot, n);
|
|
|
|
for(a=m; a; a=a->link) {
|
|
|
|
// ../../pkg/runtime/type.go:/imethod
|
|
|
|
ot = dgostringptr(s, ot, a->name);
|
2010-01-22 18:06:20 -07:00
|
|
|
ot = dgopkgpath(s, ot, a->pkg);
|
2009-07-07 12:03:04 -06:00
|
|
|
ot = dsymptr(s, ot, dtypesym(a->type), 0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TMAP:
|
|
|
|
// ../../pkg/runtime/type.go:/MapType
|
|
|
|
s1 = dtypesym(t->down);
|
|
|
|
s2 = dtypesym(t->type);
|
|
|
|
ot = dcommontype(s, ot, t);
|
2011-04-09 07:44:20 -06:00
|
|
|
xt = ot - 2*widthptr;
|
2009-07-07 12:03:04 -06:00
|
|
|
ot = dsymptr(s, ot, s1, 0);
|
|
|
|
ot = dsymptr(s, ot, s2, 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TPTR32:
|
|
|
|
case TPTR64:
|
|
|
|
if(t->type->etype == TANY) {
|
2010-12-13 08:05:20 -07:00
|
|
|
// ../../pkg/runtime/type.go:/UnsafePointerType
|
2009-07-07 12:03:04 -06:00
|
|
|
ot = dcommontype(s, ot, t);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// ../../pkg/runtime/type.go:/PtrType
|
|
|
|
s1 = dtypesym(t->type);
|
|
|
|
ot = dcommontype(s, ot, t);
|
2011-04-09 07:44:20 -06:00
|
|
|
xt = ot - 2*widthptr;
|
2009-07-07 12:03:04 -06:00
|
|
|
ot = dsymptr(s, ot, s1, 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TSTRUCT:
|
|
|
|
// ../../pkg/runtime/type.go:/StructType
|
|
|
|
// for security, only the exported fields.
|
|
|
|
n = 0;
|
|
|
|
for(t1=t->type; t1!=T; t1=t1->down) {
|
|
|
|
dtypesym(t1->type);
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
ot = dcommontype(s, ot, t);
|
2011-04-09 07:44:20 -06:00
|
|
|
xt = ot - 2*widthptr;
|
2009-07-07 12:03:04 -06:00
|
|
|
ot = dsymptr(s, ot, s, ot+widthptr+2*4);
|
|
|
|
ot = duint32(s, ot, n);
|
|
|
|
ot = duint32(s, ot, n);
|
|
|
|
for(t1=t->type; t1!=T; t1=t1->down) {
|
|
|
|
// ../../pkg/runtime/type.go:/structField
|
2009-07-28 18:01:46 -06:00
|
|
|
if(t1->sym && !t1->embedded) {
|
2009-07-07 12:03:04 -06:00
|
|
|
ot = dgostringptr(s, ot, t1->sym->name);
|
|
|
|
if(exportname(t1->sym->name))
|
|
|
|
ot = dgostringptr(s, ot, nil);
|
|
|
|
else
|
2010-01-22 18:06:20 -07:00
|
|
|
ot = dgopkgpath(s, ot, t1->sym->pkg);
|
2009-07-07 12:03:04 -06:00
|
|
|
} else {
|
|
|
|
ot = dgostringptr(s, ot, nil);
|
|
|
|
ot = dgostringptr(s, ot, nil);
|
|
|
|
}
|
|
|
|
ot = dsymptr(s, ot, dtypesym(t1->type), 0);
|
|
|
|
ot = dgostrlitptr(s, ot, t1->note);
|
|
|
|
ot = duintptr(s, ot, t1->width); // field offset
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-04-09 07:44:20 -06:00
|
|
|
ot = dextratype(s, ot, t, xt);
|
2010-12-13 08:05:20 -07:00
|
|
|
ggloblsym(s, ot, dupok);
|
2009-07-07 12:03:04 -06:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dumptypestructs(void)
|
|
|
|
{
|
|
|
|
int i;
|
2009-08-04 23:59:23 -06:00
|
|
|
NodeList *l;
|
|
|
|
Node *n;
|
2009-07-07 12:03:04 -06:00
|
|
|
Type *t;
|
2010-01-25 00:33:59 -07:00
|
|
|
Pkg *p;
|
2009-07-07 12:03:04 -06:00
|
|
|
|
|
|
|
// copy types from externdcl list to signatlist
|
2009-08-04 23:59:23 -06:00
|
|
|
for(l=externdcl; l; l=l->next) {
|
|
|
|
n = l->n;
|
|
|
|
if(n->op != OTYPE)
|
2009-07-07 12:03:04 -06:00
|
|
|
continue;
|
2009-08-04 23:59:23 -06:00
|
|
|
signatlist = list(signatlist, n);
|
2009-07-07 12:03:04 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// process signatlist
|
2009-08-04 23:59:23 -06:00
|
|
|
for(l=signatlist; l; l=l->next) {
|
|
|
|
n = l->n;
|
|
|
|
if(n->op != OTYPE)
|
2009-07-07 12:03:04 -06:00
|
|
|
continue;
|
2009-08-04 23:59:23 -06:00
|
|
|
t = n->type;
|
2009-07-07 12:03:04 -06:00
|
|
|
dtypesym(t);
|
2010-12-13 08:05:20 -07:00
|
|
|
if(t->sym)
|
2009-07-07 12:03:04 -06:00
|
|
|
dtypesym(ptrto(t));
|
|
|
|
}
|
|
|
|
|
2010-01-25 00:33:59 -07:00
|
|
|
// generate import strings for imported packages
|
|
|
|
for(i=0; i<nelem(phash); i++)
|
|
|
|
for(p=phash[i]; p; p=p->link)
|
|
|
|
if(p->direct)
|
|
|
|
dimportpath(p);
|
|
|
|
|
2009-08-13 15:41:42 -06:00
|
|
|
// do basic types if compiling package runtime.
|
2009-07-07 12:03:04 -06:00
|
|
|
// they have to be in at least one package,
|
2010-01-25 00:33:59 -07:00
|
|
|
// and runtime is always loaded implicitly,
|
2009-07-07 12:03:04 -06:00
|
|
|
// so this is as good as any.
|
|
|
|
// another possible choice would be package main,
|
|
|
|
// but using runtime means fewer copies in .6 files.
|
2010-01-25 00:33:59 -07:00
|
|
|
if(compiling_runtime) {
|
2009-07-07 12:03:04 -06:00
|
|
|
for(i=1; i<=TBOOL; i++)
|
2009-10-19 19:47:37 -06:00
|
|
|
dtypesym(ptrto(types[i]));
|
2009-07-07 12:03:04 -06:00
|
|
|
dtypesym(ptrto(types[TSTRING]));
|
2011-03-07 13:10:01 -07:00
|
|
|
dtypesym(ptrto(types[TUNSAFEPTR]));
|
2010-01-25 00:33:59 -07:00
|
|
|
|
|
|
|
// add paths for runtime and main, which 6l imports implicitly.
|
|
|
|
dimportpath(runtimepkg);
|
|
|
|
dimportpath(mkpkg(strlit("main")));
|
2009-07-07 12:03:04 -06:00
|
|
|
}
|
|
|
|
}
|