Commit 8231e945 authored by Ken Thompson's avatar Ken Thompson

now method/interface code

R=r
OCL=15627
CL=15627
parent 128f0528
......@@ -154,10 +154,6 @@ cgen(Node *n, Node *res)
regfree(&n1);
break;
case OS2I:
case OI2I:
case OI2S:
case OINDEXPTR:
case OINDEX:
case ODOT:
......@@ -345,12 +341,6 @@ agen(Node *n, Node *res)
cgen_aret(n, res);
break;
case OS2I:
case OI2I:
case OI2S:
agen_inter(n, res);
break;
case OINDEXPTR:
w = n->type->width;
if(nr->addable)
......@@ -678,10 +668,10 @@ int32
stkof(Node *n)
{
switch(n->op) {
case OS2I:
return 2*widthptr;
case OI2I:
return 1*widthptr;
// case OS2I:
// return 2*widthptr;
// case OI2I:
// return 1*widthptr;
case OINDREG:
return n->xoffset;
}
......
......@@ -373,7 +373,7 @@ agen_inter(Node *n, Node *res)
default:
fatal("agen_inter %O\n", n->op);
case OS2I:
// case OS2I:
// ifaces2i(*sigi, *sigs, i.map, i.s)
// i.s is input
// (i.map, i.s) is output
......@@ -398,7 +398,7 @@ agen_inter(Node *n, Node *res)
o = 2*widthptr;
break;
case OI2I:
// case OI2I:
// ifacei2i(*sigi, i.map, i.s)
// (i.map, i.s) is input
// (i.map, i.s) is output
......@@ -424,7 +424,7 @@ agen_inter(Node *n, Node *res)
o = 1*widthptr;
break;
case OI2S:
// case OI2S:
// ifacei2s(*sigs, i.map, i.s)
// (i.map, i.s) is input
// i.s is output
......
......@@ -294,45 +294,6 @@ nodconst(Node *n, Type *t, vlong v)
}
}
Sym*
signame(Type *t)
{
Sym *s;
char *e;
loop:
if(t == T)
fatal("signame: nil type");
switch(t->etype) {
default:
e = "sigs";
break;
case TPTR32:
case TPTR64:
t = t->type;
goto loop;
case TSTRUCT:
case TINTER:
e = "sigi";
break;
}
s = t->sym;
if(s == S)
fatal("signame: no sym for type");
// mark it as used so signature will be generated
if(s->local == 1)
s->local = 2;
snprint(namebuf, sizeof(namebuf), "%s_%s", e, s->name);
s = pkglookup(namebuf, s->opackage);
return s;
}
void
nodtypesig(Node *n, Type *t)
{
......@@ -1055,8 +1016,10 @@ naddr(Node *n, Addr *a)
a->etype = n->etype;
a->offset = n->xoffset;
a->sym = n->sym;
if(a->sym == S)
if(a->sym == S) {
a->sym = lookup(".noname");
fatal("noname");
}
if(n->method) {
if(n->type != T)
if(n->type->sym != S)
......
......@@ -161,8 +161,6 @@ dumpobj(void)
}
}
Bterm(bout);
return;
Bterm(bout);
}
Bputdot(Biobuf *b)
......@@ -477,31 +475,14 @@ dumpsignatures(void)
if(t == T)
continue;
et = t->etype;
if(t->method == T && et != TINTER)
continue;
s = d->dsym;
s = signame(t);
if(s == S)
continue;
if(s->name[0] == '_')
continue;
// if it was imported
if(s->local == 0)
continue;
// until i can figure out
// when/if it is used, do them all
// // if not used and not exported
// if(s->local == 1 && !s->export)
// continue;
x = mal(sizeof(*d));
x->op = OTYPE;
x->dsym = s;
x->dtype = t;
x->dsym = d->dsym;
x->dtype = d->dtype;
x->forw = signatlist;
signatlist = x;
}
......@@ -548,10 +529,16 @@ dumpsignatures(void)
continue;
t = d->dtype;
et = t->etype;
if(t->method == T && et != TINTER)
at.sym = signame(t);
if(at.sym == S)
continue;
if(!at.sym->local)
continue;
//print("SIGNAME = %lS\n", at.sym);
et = t->etype;
s = d->dsym;
if(s == S)
continue;
......@@ -562,14 +549,13 @@ dumpsignatures(void)
if(strcmp(s->opackage, package) != 0)
continue;
at.sym = signame(t);
a = nil;
o = 0;
f = t->type;
if(et != TINTER)
f = t->method;
f = t->method;
if(et == TINTER)
f = t->type;
for(; f!=T; f=f->down) {
if(f->type->etype != TFUNC)
......
......@@ -260,7 +260,7 @@ enum
ODCLFUNC, ODCLFIELD, ODCLARG,
OLIST, OCMP,
OPTR, OARRAY,
ORETURN, OFOR, OIF, OSWITCH, OI2S, OS2I, OI2I,
ORETURN, OFOR, OIF, OSWITCH,
OAS, OASOP, OCASE, OXCASE, OFALL, OXFALL,
OGOTO, OPROC, ONEW, OEMPTY, OSELECT,
OLEN, OCAP, OPANIC, OPRINT, OTYPEOF,
......@@ -564,6 +564,7 @@ int isptrarray(Type*);
int isptrdarray(Type*);
int isinter(Type*);
int ismethod(Type*);
Sym* signame(Type*);
int bytearraysz(Type*);
int eqtype(Type*, Type*, int);
void argtype(Node*, Type*);
......@@ -692,7 +693,8 @@ Node* mapop(Node*, int);
Type* fixchan(Type*);
Node* chanop(Node*, int);
Node* arrayop(Node*, int);
Node* isandss(Type*, Node*);
Node* ifaceop(Type*, Node*, int);
int isandss(Type*, Node*);
Node* convas(Node*);
void arrayconv(Type*, Node*);
Node* colas(Node*, Node*);
......
......@@ -644,9 +644,6 @@ opnames[] =
[OPTR] = "PTR",
[ORETURN] = "RETURN",
[ORSH] = "RSH",
[OI2S] = "I2S",
[OS2I] = "S2I",
[OI2I] = "I2I",
[OSLICE] = "SLICE",
[OSUB] = "SUB",
[OSELECT] = "SELECT",
......@@ -1238,6 +1235,58 @@ ismethod(Type *t)
return 0;
}
Sym*
signame(Type *t)
{
Sym *s, *ss;
char *e;
loop:
if(t == T) {
print("signame: nil type\n");
goto bad;
}
switch(t->etype) {
default:
e = "sigs";
break;
case TPTR32:
case TPTR64:
t = t->type;
goto loop;
case TINTER:
e = "sigi";
break;
}
s = t->sym;
if(s == S) {
print("signame: no type name\n");
goto bad;
}
if(s->name[0] == '_') {
// print("signame: temp type name %S\n", s);
goto bad;
}
snprint(namebuf, sizeof(namebuf), "%s_%s", e, s->name);
ss = pkglookup(namebuf, s->opackage);
if(ss->oname == N) {
ss->oname = newname(ss);
ss->oname->type = types[TUINT8];
ss->oname->class = PEXTERN;
ss->local = s->local;
//print("signame: %d %lS\n", ss->local, ss);
}
return ss;
bad:
return S;
}
int
bytearraysz(Type *t)
{
......@@ -1620,9 +1669,6 @@ ullmancalc(Node *n)
case ONAME:
ul = 0;
goto out;
case OS2I:
case OI2S:
case OI2I:
case OCALL:
case OCALLMETH:
case OCALLINTER:
......
......@@ -23,7 +23,10 @@ func slicestring(string, int32, int32) string;
func indexstring(string, int32) byte;
func intstring(int64) string;
func byteastring(*byte, int32) string;
func mkiface(*byte, *byte, *struct{}) interface{};
func ifaceT2I(sigi *byte, sigt *byte, elem any) (ret interface{});
func ifaceI2T(sigt *byte, iface interface{}) (ret any);
func ifaceI2I(sigi *byte, iface any) (ret any);
func argc() int32;
func envc() int32;
......@@ -95,7 +98,11 @@ export
indexstring
intstring
byteastring
mkiface
// interface
ifaceT2I
ifaceI2T
ifaceI2I
// args
argc
......
This diff is collapsed.
......@@ -10,6 +10,14 @@ static Type* sw3(Node*, Type*);
static Node* curfn;
static Node* addtop;
enum
{
Inone,
I2T,
I2I,
T2I
};
// can this code branch reach the end
// without an undcontitional RETURN
// this is hard, so it is conservative
......@@ -494,15 +502,6 @@ loop:
case OINDREG:
goto ret;
case OS2I:
case OI2S:
case OI2I:
if(top != Erv)
goto nottop;
n->addable = 0;
walktype(n->left, Erv);
goto ret;
case OCONV:
if(top == Etop)
goto nottop;
......@@ -551,9 +550,9 @@ loop:
goto ret;
// interface and structure
r = isandss(n->type, l);
if(r != N) {
indir(n, r);
et = isandss(n->type, l);
if(et != Inone) {
indir(n, ifaceop(n->type, l, et));
goto ret;
}
......@@ -2454,18 +2453,7 @@ arrayop(Node *n, int top)
return r;
}
void
diagnamed(Type *t)
{
if(isinter(t))
if(t->sym == S)
yyerror("interface type must be named");
if(ismethod(t))
if(t->type == T || t->type->sym == S)
yyerror("structure type must be named");
}
Node*
int
isandss(Type *lt, Node *r)
{
Type *rt;
......@@ -2474,32 +2462,98 @@ isandss(Type *lt, Node *r)
rt = r->type;
if(isinter(lt)) {
if(ismethod(rt)) {
o = OS2I;
goto ret;
}
if(isinter(rt)) {
o = OI2I;
goto ret;
}
if(ismethod(rt))
return T2I;
if(isinter(rt) && !eqtype(rt, lt, 0))
return I2I;
}
if(ismethod(lt)) {
if(isinter(rt)) {
o = OI2S;
goto ret;
}
if(isinter(rt))
return I2T;
}
return N;
return Inone;
}
ret:
diagnamed(lt);
diagnamed(rt);
Node*
ifaceop(Type *tl, Node *n, int op)
{
Type *tr;
Node *r, *a, *on;
Sym *s;
n = nod(o, r, N);
n->type = lt;
return n;
tr = n->type;
switch(op) {
default:
fatal("ifaceop: unknown op %d\n", op);
case I2T:
// ifaceI2T(sigt *byte, iface interface{}) (ret any);
a = n; // interface
r = a;
s = signame(tl); // sigi
if(s == S)
fatal("ifaceop: signame I2T");
a = s->oname;
a = nod(OADDR, a, N);
r = list(a, r);
on = syslook("ifaceI2T", 1);
argtype(on, tl);
break;
case T2I:
// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret interface{});
a = n; // elem
r = a;
s = signame(tr); // sigt
if(s == S)
fatal("ifaceop: signame-1 T2I: %lT", tr);
a = s->oname;
a = nod(OADDR, a, N);
r = list(a, r);
s = signame(tl); // sigi
if(s == S) {
fatal("ifaceop: signame-2 T2I: %lT", tl);
}
a = s->oname;
a = nod(OADDR, a, N);
r = list(a, r);
on = syslook("ifaceT2I", 1);
argtype(on, tr);
break;
case I2I:
// ifaceI2I(sigi *byte, iface any-1) (ret any-2);
a = n; // interface
r = a;
s = signame(tr); // sigi
if(s == S)
fatal("ifaceop: signame I2I");
a = s->oname;
a = nod(OADDR, a, N);
r = list(a, r);
on = syslook("ifaceI2I", 1);
argtype(on, n->type);
argtype(on, tr);
break;
}
r = nod(OCALL, on, r);
walktype(r, Erv);
return r;
}
Node*
......@@ -2507,6 +2561,7 @@ convas(Node *n)
{
Node *l, *r;
Type *lt, *rt;
int et;
if(n->op != OAS)
fatal("convas: not OAS %O", n->op);
......@@ -2542,10 +2597,9 @@ convas(Node *n)
if(eqtype(lt, rt, 0))
goto out;
r = isandss(lt, r);
if(r != N) {
n->right = r;
walktype(n, Etop);
et = isandss(lt, r);
if(et != Inone) {
n->right = ifaceop(lt, r, et);
goto out;
}
......@@ -2994,11 +3048,15 @@ arraylit(Node *n)
fatal("arraylit: not array");
if(t->bound < 0) {
// make a shallow copy
t = typ(0);
*t = *n->type;
n->type = t;
// make it a closed array
r = listfirst(&saver, &n->left);
for(idx=0; r!=N; idx++)
r = listnext(&saver);
t = deep(t);
t->bound = idx;
}
......
......@@ -20,6 +20,7 @@ LIBOFILES=\
runtime.$O\
map.$O\
chan.$O\
iface.$O\
array.$O\
print.$O\
rune.$O\
......
// 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 "runtime.h"
typedef struct Sigt Sigt;
typedef struct Sigi Sigi;
typedef struct Map Map;
struct Sigt
{
byte* name;
uint32 hash;
void (*fun)(void);
};
struct Sigi
{
byte* name;
uint32 hash;
uint32 offset;
};
struct Map
{
Sigi* sigi;
Sigt* sigt;
Map* link;
int32 bad;
int32 unused;
void (*fun[])(void);
};
static Map* hash[1009];
static int32 debug = 0;
static Map*
hashmap(Sigi *si, Sigt *ss)
{
int32 ns, ni;
uint32 ihash, h;
byte *sname, *iname;
Map *m;
h = ((uint32)(uint64)si + (uint32)(uint64)ss) % nelem(hash);
for(m=hash[h]; m!=nil; m=m->link) {
if(m->sigi == si && m->sigt == ss) {
if(m->bad) {
throw("bad hashmap");
m = nil;
}
// prints("old hashmap\n");
return m;
}
}
ni = si[0].offset; // first word has size
m = mal(sizeof(*m) + ni*sizeof(m->fun[0]));
m->sigi = si;
m->sigt = ss;
ni = 1; // skip first word
ns = 0;
loop1:
// pick up next name from
// interface signature
iname = si[ni].name;
if(iname == nil) {
m->link = hash[h];
hash[h] = m;
// prints("new hashmap\n");
return m;
}
ihash = si[ni].hash;
loop2:
// pick up and comapre next name
// from structure signature
sname = ss[ns].name;
if(sname == nil) {
prints((int8*)iname);
prints(": ");
throw("hashmap: failed to find method");
m->bad = 1;
m->link = hash[h];
hash[h] = m;
return nil;
}
if(ihash != ss[ns].hash ||
strcmp(sname, iname) != 0) {
ns++;
goto loop2;
}
m->fun[si[ni].offset] = ss[ns].fun;
ni++;
goto loop1;
}
static void
printsigi(Sigi *si)
{
sys·printpointer(si);
}
static void
printsigt(Sigt *st)
{
sys·printpointer(st);
}
static void
printiface(Map *im, void *it)
{
prints("(");
sys·printpointer(im);
prints(",");
sys·printpointer(it);
prints(")");
}
// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret interface{});
void
sys·ifaceT2I(Sigi *si, Sigt *st, void *elem, Map *retim, void *retit)
{
if(debug) {
prints("T2I sigi=");
printsigi(si);
prints(" sigt=");
printsigt(st);
prints(" elem=");
sys·printpointer(elem);
prints("\n");
}
retim = hashmap(si, st);
retit = elem;
if(debug) {
prints("T2I ret=");
printiface(retim, retit);
prints("\n");
}
FLUSH(&retim);
}
// ifaceI2T(sigt *byte, iface interface{}) (ret any);
void
sys·ifaceI2T(Sigt *st, Map *im, void *it, void *ret)
{
if(debug) {
prints("I2T sigt=");
printsigt(st);
prints(" iface=");
printiface(im, it);
prints("\n");
}
if(im == nil)
throw("ifaceI2T: nil map");
if(im->sigt != st)
throw("ifaceI2T: wrong type");
ret = it;
if(debug) {
prints("I2T ret=");
sys·printpointer(ret);
prints("\n");
}
FLUSH(&ret);
}
// ifaceI2I(sigi *byte, iface interface{}) (ret interface{});
void
sys·ifaceI2I(Sigi *si, Map *im, void *it, Map *retim, void *retit)
{
if(debug) {
prints("I2I sigi=");
sys·printpointer(si);
prints(" iface=");
printiface(im, it);
prints("\n");
}
if(im == nil) {
throw("ifaceI2I: nil map");
return;
}
retit = it;
retim = im;
if(im->sigi != si)
retim = hashmap(si, im->sigt);
if(debug) {
prints("I2I ret=");
printiface(retim, retit);
prints("\n");
}
FLUSH(&retim);
}
......@@ -4,7 +4,6 @@
#include "runtime.h"
int32 debug = 0;
int32 panicking = 0;
void
......@@ -146,175 +145,6 @@ sys·mal(uint32 n, uint8 *ret)
FLUSH(&ret);
}
static Map* hash[1009];
static Map*
hashmap(Sigi *si, Sigs *ss)
{
int32 ns, ni;
uint32 ihash, h;
byte *sname, *iname;
Map *m;
h = ((uint32)(uint64)si + (uint32)(uint64)ss) % nelem(hash);
for(m=hash[h]; m!=nil; m=m->link) {
if(m->si == si && m->ss == ss) {
if(m->bad) {
throw("bad hashmap");
m = nil;
}
// prints("old hashmap\n");
return m;
}
}
ni = si[0].offset; // first word has size
m = mal(sizeof(*m) + ni*sizeof(m->fun[0]));
m->si = si;
m->ss = ss;
ni = 1; // skip first word
ns = 0;
loop1:
// pick up next name from
// interface signature
iname = si[ni].name;
if(iname == nil) {
m->link = hash[h];
hash[h] = m;
// prints("new hashmap\n");
return m;
}
ihash = si[ni].hash;
loop2:
// pick up and comapre next name
// from structure signature
sname = ss[ns].name;
if(sname == nil) {
prints((int8*)iname);
prints(": ");
throw("hashmap: failed to find method");
m->bad = 1;
m->link = hash[h];
hash[h] = m;
return nil;
}
if(ihash != ss[ns].hash ||
strcmp(sname, iname) != 0) {
ns++;
goto loop2;
}
m->fun[si[ni].offset] = ss[ns].fun;
ni++;
goto loop1;
}
void
sys·ifaces2i(Sigi *si, Sigs *ss, Map *m, void *s)
{
if(debug) {
prints("s2i sigi=");
sys·printpointer(si);
prints(" sigs=");
sys·printpointer(ss);
prints(" s=");
sys·printpointer(s);
}
if(s == nil) {
throw("ifaces2i: nil pointer");
m = nil;
FLUSH(&m);
return;
}
m = hashmap(si, ss);
if(debug) {
prints(" returning m=");
sys·printpointer(m);
prints(" s=");
sys·printpointer(s);
prints("\n");
dump((byte*)m, 64);
}
FLUSH(&m);
}
void
sys·ifacei2i(Sigi *si, Map *m, void *s)
{
if(debug) {
prints("i2i sigi=");
sys·printpointer(si);
prints(" m=");
sys·printpointer(m);
prints(" s=");
sys·printpointer(s);
}
if(m == nil) {
throw("ifacei2i: nil map");
s = nil;
FLUSH(&s);
return;
}
if(m->si == nil) {
throw("ifacei2i: nil pointer");
return;
}
if(m->si != si) {
m = hashmap(si, m->ss);
FLUSH(&m);
}
if(debug) {
prints(" returning m=");
sys·printpointer(m);
prints(" s=");
sys·printpointer(s);
prints("\n");
dump((byte*)m, 64);
}
}
void
sys·ifacei2s(Sigs *ss, Map *m, void *s)
{
if(debug) {
prints("i2s m=");
sys·printpointer(m);
prints(" s=");
sys·printpointer(s);
prints("\n");
}
if(m == nil) {
throw("ifacei2s: nil map");
s = nil;
FLUSH(&s);
return;
}
if(m->ss != ss) {
dump((byte*)m, 64);
throw("ifacei2s: wrong pointer");
s = nil;
FLUSH(&s);
return;
}
}
enum
{
NANEXP = 2047<<20,
......
......@@ -34,9 +34,6 @@ typedef double float64;
typedef uint8 bool;
typedef uint8 byte;
typedef struct String *string;
typedef struct Sigs Sigs;
typedef struct Sigi Sigi;
typedef struct Map Map;
typedef struct Array Array;
typedef struct Gobuf Gobuf;
typedef struct G G;
......@@ -95,18 +92,6 @@ struct String
int32 len;
byte str[1];
};
struct Sigs
{
byte* name;
uint32 hash;
void (*fun)(void);
};
struct Sigi
{
byte* name;
uint32 hash;
uint32 offset;
};
struct Array
{ // must not move anything
......@@ -115,15 +100,6 @@ struct Array
uint32 cap; // allocate3d number of elements
byte b[8]; // actual array - may not be contig
};
struct Map
{
Sigi* si;
Sigs* ss;
Map* link;
int32 bad;
int32 unused;
void (*fun[])(void);
};
struct Gobuf
{
byte* SP;
......@@ -305,9 +281,6 @@ void sys·cmpstring(string, string, int32);
void sys·slicestring(string, int32, int32, string);
void sys·indexstring(string, int32, byte);
void sys·intstring(int64, string);
void sys·ifaces2i(Sigi*, Sigs*, Map*, void*);
void sys·ifacei2i(Sigi*, Map*, void*);
void sys·ifacei2s(Sigs*, Map*, void*);
/*
* User go-called
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment