Commit 4026500d authored by Ken Thompson's avatar Ken Thompson

arrays

R=r
OCL=21564
CL=21564
parent eaa2a364
......@@ -148,8 +148,11 @@ dowidth(Type *t)
w = wptr;
break;
case TARRAY:
if(t->type == T)
break;
dowidth(t->type);
if(t->bound >= 0 && t->type != T)
w = sizeof(Array);
if(t->bound >= 0)
w = t->bound * t->type->width;
break;
......
......@@ -185,7 +185,7 @@ cgen(Node *n, Node *res)
}
regalloc(&n1, nl->type, res);
cgen(nl, &n1);
if(isptrarray(n->type) && isptrdarray(nl->type)) {
if(isptrsarray(n->type) && isptrdarray(nl->type)) {
// convert dynamic array to static array
n2 = n1;
n2.op = OINDREG;
......@@ -193,10 +193,10 @@ cgen(Node *n, Node *res)
n2.type = types[tptr];
gins(AMOVQ, &n2, &n1);
}
if(isptrdarray(n->type) && isptrarray(nl->type)) {
if(isptrdarray(n->type) && isptrsarray(nl->type)) {
// conver static array to dynamic array
// it is assumed that the dope is just before the array
nodconst(&n2, types[tptr], offsetof(Array,b));
nodconst(&n2, types[tptr], sizeof(Array));
gins(ASUBQ, &n2, &n1);
}
gmove(&n1, res);
......@@ -252,6 +252,16 @@ cgen(Node *n, Node *res)
regfree(&n1);
break;
}
if(isdarray(nl->type)) {
regalloc(&n1, types[tptr], res);
agen(nl, &n1);
n1.op = OINDREG;
n1.type = types[TUINT32];
n1.xoffset = offsetof(Array,nel);
gmove(&n1, res);
regfree(&n1);
break;
}
fatal("cgen: OLEN: unknown type %lT", nl->type);
break;
......@@ -266,6 +276,16 @@ cgen(Node *n, Node *res)
regfree(&n1);
break;
}
if(isdarray(nl->type)) {
regalloc(&n1, types[tptr], res);
agen(nl, &n1);
n1.op = OINDREG;
n1.type = types[TUINT32];
n1.xoffset = offsetof(Array,cap);
gmove(&n1, res);
regfree(&n1);
break;
}
fatal("cgen: OCAP: unknown type %lT", nl->type);
break;
......@@ -489,7 +509,7 @@ agen(Node *n, Node *res)
if(v < 0)
yyerror("out of bounds on array");
else
if(isptrarray(nl->type)) {
if(isptrsarray(nl->type)) {
if(v >= nl->type->type->bound)
yyerror("out of bounds on array");
} else
......@@ -523,7 +543,7 @@ agen(Node *n, Node *res)
n1.xoffset = offsetof(Array, nel);
} else {
nodconst(&n1, types[TUINT64], nl->type->bound);
if(isptrarray(nl->type))
if(isptrsarray(nl->type))
nodconst(&n1, types[TUINT64], nl->type->type->bound);
}
gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
......@@ -815,8 +835,9 @@ sgen(Node *n, Node *ns, int32 w)
int32 c, q, odst, osrc;
if(debug['g']) {
dump("\nsgen-res", ns);
dump("sgen-r", n);
print("\nsgen w=%d\n", w);
dump("r", n);
dump("res", ns);
}
if(w == 0)
return;
......@@ -830,9 +851,6 @@ sgen(Node *n, Node *ns, int32 w)
// offset on the stack
osrc = stkof(n);
odst = stkof(ns);
//print("\nnsrc=%N\n", n);
//print("ndst=%N\n", ns);
//print("osrc=%d odst=%d w=%d\n", osrc, odst, w);
nodreg(&nodl, types[tptr], D_DI);
nodreg(&nodr, types[tptr], D_SI);
......
......@@ -484,11 +484,6 @@ loop:
fatal("stotype: oops %N\n", n);
switch(n->type->etype) {
case TARRAY:
if(n->type->bound < 0)
yyerror("type of a structure field cannot be an open array");
break;
case TCHAN:
case TMAP:
case TSTRING:
......
......@@ -69,9 +69,8 @@ typedef struct Array Array;
struct Array
{ // must not move anything
uchar array[8]; // pointer to data
uint32 nel; // number of elements
uint32 cap; // allocated number of elements
uchar b; // actual array - may not be contig
uchar nel[4]; // number of elements
uchar cap[4]; // allocated number of elements
};
/*
......@@ -637,8 +636,10 @@ void dump(char*, Node*);
Type* aindex(Node*, Type*);
int isnil(Node*);
int isptrto(Type*, int);
int isptrarray(Type*);
int isptrsarray(Type*);
int isptrdarray(Type*);
int issarray(Type*);
int isdarray(Type*);
int isinter(Type*);
int isnilinter(Type*);
int isddd(Type*);
......
......@@ -857,12 +857,12 @@ pexpr:
| LNEW '(' type ')'
{
$$ = nod(ONEW, N, N);
$$->type = ptrto($3);
$$->type = $3;
}
| LNEW '(' type ',' expr_list ')'
{
$$ = nod(ONEW, $5, N);
$$->type = ptrto($3);
$$->type = $3;
}
| LCONVERT '(' type ',' keyexpr_list ')'
{
......
......@@ -440,6 +440,7 @@ aindex(Node *b, Type *t)
r = typ(TARRAY);
r->type = t;
r->bound = bound;
dowidth(r);
return r;
}
......@@ -1421,7 +1422,7 @@ isptrto(Type *t, int et)
}
int
isptrarray(Type *t)
isptrsarray(Type *t)
{
if(isptrto(t, TARRAY))
if(t->type->bound >= 0)
......@@ -1438,6 +1439,22 @@ isptrdarray(Type *t)
return 0;
}
int
issarray(Type *t)
{
if(t != T && t->etype == TARRAY && t->bound >= 0)
return 1;
return 0;
}
int
isdarray(Type *t)
{
if(t != T && t->etype == TARRAY && t->bound < 0)
return 1;
return 0;
}
int
isselect(Node *n)
{
......
......@@ -26,7 +26,7 @@ export func slicestring(string, int, int) string;
export func indexstring(string, int) byte;
export func intstring(int64) string;
export func byteastring(*byte, int) string;
export func arraystring(*[]byte) string;
export func arraystring([]byte) string;
export func ifaceT2I(sigi *byte, sigt *byte, elem any) (ret any);
export func ifaceI2T(sigt *byte, iface any) (ret any);
......@@ -79,10 +79,10 @@ export func selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
export func selectdefault(sel *byte) (selected bool);
export func selectgo(sel *byte);
export func newarray(nel int, cap int, width int) (ary *[]any);
export func arraysliced(old *[]any, lb int, hb int, width int) (ary *[]any);
export func arrayslices(old *any, nel int, lb int, hb int, width int) (ary *[]any);
export func arrays2d(old *any, nel int) (ary *[]any);
export func newarray(nel int, cap int, width int) (ary []any);
export func arraysliced(old []any, lb int, hb int, width int) (ary []any);
export func arrayslices(old *any, nel int, lb int, hb int, width int) (ary []any);
export func arrays2d(old *any, nel int) (ary []any);
export func gosched();
export func goexit();
......
......@@ -19,7 +19,7 @@ char *sysimport =
"export func sys.indexstring (? string, ? int) (? uint8)\n"
"export func sys.intstring (? int64) (? string)\n"
"export func sys.byteastring (? *uint8, ? int) (? string)\n"
"export func sys.arraystring (? *[]uint8) (? string)\n"
"export func sys.arraystring (? []uint8) (? string)\n"
"export func sys.ifaceT2I (sigi *uint8, sigt *uint8, elem any) (ret any)\n"
"export func sys.ifaceI2T (sigt *uint8, iface any) (ret any)\n"
"export func sys.ifaceI2T2 (sigt *uint8, iface any) (ret any, ok bool)\n"
......@@ -63,10 +63,10 @@ char *sysimport =
"export func sys.selectrecv (sel *uint8, hchan *chan any, elem *any) (selected bool)\n"
"export func sys.selectdefault (sel *uint8) (selected bool)\n"
"export func sys.selectgo (sel *uint8)\n"
"export func sys.newarray (nel int, cap int, width int) (ary *[]any)\n"
"export func sys.arraysliced (old *[]any, lb int, hb int, width int) (ary *[]any)\n"
"export func sys.arrayslices (old *any, nel int, lb int, hb int, width int) (ary *[]any)\n"
"export func sys.arrays2d (old *any, nel int) (ary *[]any)\n"
"export func sys.newarray (nel int, cap int, width int) (ary []any)\n"
"export func sys.arraysliced (old []any, lb int, hb int, width int) (ary []any)\n"
"export func sys.arrayslices (old *any, nel int, lb int, hb int, width int) (ary []any)\n"
"export func sys.arrays2d (old *any, nel int) (ary []any)\n"
"export func sys.gosched ()\n"
"export func sys.goexit ()\n"
"export func sys.readfile (? string) (? string, ? bool)\n"
......
......@@ -592,7 +592,7 @@ loop:
}
// convert dynamic to static generated by ONEW
if(isptrarray(t) && isptrdarray(l->type))
if(issarray(t) && isdarray(l->type))
goto ret;
// structure literal
......@@ -1882,8 +1882,8 @@ ascompat(Type *t1, Type *t2)
if(ismethod(t1))
return 1;
if(isptrdarray(t1))
if(isptrarray(t2))
if(isdarray(t1))
if(issarray(t2))
return 1;
return 0;
......@@ -1992,28 +1992,32 @@ newcompat(Node *n)
Type *t;
t = n->type;
if(t == T || !isptr[t->etype] || t->type == T)
fatal("newcompat: type should be pointer %lT", t);
if(t == T)
goto bad;
if(isptr[t->etype]) {
if(t->type == T)
goto bad;
t = t->type;
switch(t->etype) {
case TFUNC:
yyerror("cannot make new %T", t);
break;
case TMAP:
r = mapop(n, Erv);
return r;
dowidth(t);
case TCHAN:
r = chanop(n, Erv);
return r;
on = syslook("mal", 1);
argtype(on, t);
case TARRAY:
r = arrayop(n, Erv);
return r;
r = nodintconst(t->width);
r = nod(OCALL, on, r);
walktype(r, Erv);
r->type = n->type;
goto ret;
}
switch(t->etype) {
default:
goto bad;
case TSTRUCT:
if(n->left != N)
yyerror("dont know what new(,e) means");
......@@ -2027,10 +2031,30 @@ newcompat(Node *n)
r = nod(OCALL, on, r);
walktype(r, Erv);
// r = nod(OCONV, r, N);
r->type = n->type;
r->type = ptrto(n->type);
return r;
case TMAP:
n->type = ptrto(n->type);
r = mapop(n, Erv);
break;
case TCHAN:
n->type = ptrto(n->type);
r = chanop(n, Erv);
break;
case TARRAY:
r = arrayop(n, Erv);
break;
}
ret:
return r;
bad:
fatal("cannot make new %T", t);
return n;
}
Node*
......@@ -2119,10 +2143,8 @@ stringop(Node *n, int top)
break;
case OARRAY:
// arraystring(*[]byte) string;
// arraystring([]byte) string;
r = n->left;
if(!isptr[r->type->etype])
r = nod(OADDR, r, N);
on = syslook("arraystring", 0);
r = nod(OCALL, on, r);
break;
......@@ -2557,24 +2579,20 @@ shape:
}
Type*
fixarray(Type *tm)
fixarray(Type *t)
{
Type *t;
t = tm->type;
if(t == T)
goto bad;
if(t->etype != TARRAY)
goto bad;
if(t->type == T)
goto bad;
dowidth(t->type);
dowidth(t);
return t;
bad:
yyerror("not an array: %lT", tm);
yyerror("not an array: %lT", t);
return T;
}
......@@ -2583,7 +2601,7 @@ Node*
arrayop(Node *n, int top)
{
Node *r, *a;
Type *t;
Type *t, *tl;
Node *on;
Iter save;
......@@ -2592,8 +2610,30 @@ arrayop(Node *n, int top)
default:
fatal("darrayop: unknown op %O", n->op);
case OAS:
// arrays2d(old *any, nel int) (ary []any)
t = fixarray(n->right->type);
tl = fixarray(n->left->type);
a = nodintconst(t->bound); // nel
a = nod(OCONV, a, N);
a->type = types[TINT];
r = a;
a = nod(OADDR, n->right, N); // old
r = list(a, r);
on = syslook("arrays2d", 1);
argtype(on, t); // any-1
argtype(on, tl->type); // any-2
r = nod(OCALL, on, r);
walktype(r, top);
n->right = r;
return n;
case ONEW:
// newarray(nel int, max int, width int) (ary *[]any)
// newarray(nel int, max int, width int) (ary []any)
t = fixarray(n->type);
a = nodintconst(t->type->width); // width
......@@ -2624,41 +2664,12 @@ arrayop(Node *n, int top)
r = nod(OCALL, on, r);
walktype(r, top);
if(t->etype == TARRAY) {
// single case when we can convert a dynamic
// array pointer to a static array pointer
// saves making a sys function to alloc a static
r = nod(OCONV, r, N);
r->type = ptrto(t);
}
break;
case OAS:
// arrays2d(old *any, nel int) (ary *[]any)
t = fixarray(n->right->type);
a = nodintconst(t->bound); // nel
a = nod(OCONV, a, N);
a->type = types[TINT];
r = a;
a = n->right; // old
r = list(a, r);
on = syslook("arrays2d", 1);
argtype(on, n->right->type->type); // any-1
argtype(on, t->type); // any-2
r = nod(OCALL, on, r);
walktype(r, top);
n->right = r;
return n;
case OSLICE:
if(isptrarray(n->left->type))
goto slicestatic;
// arrayslices(old any, nel int, lb int, hb int, width int) (ary []any)
// arraysliced(old []any, lb int, hb int, width int) (ary []any)
// arrayslices(old *[]any, lb int, hb int, width int) (ary *[]any)
t = fixarray(n->left->type);
a = nodintconst(t->type->width); // width
......@@ -2674,44 +2685,29 @@ arrayop(Node *n, int top)
a->type = types[TINT];
r = list(a, r);
a = n->left; // old
r = list(a, r);
on = syslook("arraysliced", 1);
argtype(on, t->type); // any-1
argtype(on, t->type); // any-2
r = nod(OCALL, on, r);
walktype(r, top);
break;
slicestatic:
// arrayslices(old *any, nel int, lb int, hb int, width int) (ary *[]any)
t = fixarray(n->left->type);
a = nodintconst(t->type->width); // width
a = nod(OCONV, a, N);
a->type = types[TINT];
r = a;
a = nod(OCONV, n->right->right, N); // hb
a->type = types[TINT];
r = list(a, r);
a = nod(OCONV, n->right->left, N); // lb
a->type = types[TINT];
r = list(a, r);
if(t->bound >= 0) {
// static slice
a = nodintconst(t->bound); // nel
a = nod(OCONV, a, N);
a->type = types[TINT];
r = list(a, r);
a = n->left; // old
a = nod(OADDR, n->left, N); // old
r = list(a, r);
on = syslook("arrayslices", 1);
argtype(on, t); // any-1
argtype(on, t->type); // any-2
} else {
// dynamic slice
a = n->left; // old
r = list(a, r);
on = syslook("arraysliced", 1);
argtype(on, t->type); // any-1
argtype(on, t->type); // any-2
}
r = nod(OCALL, on, r);
walktype(r, top);
break;
......@@ -2899,7 +2895,7 @@ convas(Node *n)
goto out;
}
if(isptrdarray(lt) && isptrarray(rt)) {
if(isdarray(lt) && issarray(rt)) {
if(!eqtype(lt->type->type, rt->type->type, 0))
goto bad;
indir(n, arrayop(n, Etop));
......
......@@ -6,23 +6,20 @@
static int32 debug = 0;
// newarray(nel uint32, cap uint32, width uint32) (ary *[]any);
// newarray(nel int, cap int, width int) (ary []any);
void
sys·newarray(uint32 nel, uint32 cap, uint32 width, Array* ret)
sys·newarray(uint32 nel, uint32 cap, uint32 width, Array ret)
{
Array *d;
uint64 size;
if(cap < nel)
cap = nel;
size = cap*width;
d = mal(sizeof(*d) - sizeof(d->b) + size);
d->nel = nel;
d->cap = cap;
d->array = d->b;
ret.nel = nel;
ret.cap = cap;
ret.array = mal(size);
ret = d;
FLUSH(&ret);
if(debug) {
......@@ -33,7 +30,7 @@ sys·newarray(uint32 nel, uint32 cap, uint32 width, Array* ret)
prints("; width=");
sys·printint(width);
prints("; ret=");
sys·printarray(ret);
sys·printarray(&ret);
prints("\n");
}
}
......@@ -51,16 +48,15 @@ throwslice(uint32 lb, uint32 hb, uint32 n)
throw("array slice");
}
// arraysliced(old *[]any, lb uint32, hb uint32, width uint32) (ary *[]any);
// arraysliced(old []any, lb int, hb int, width int) (ary []any);
void
sys·arraysliced(Array* old, uint32 lb, uint32 hb, uint32 width, Array* ret)
sys·arraysliced(Array old, uint32 lb, uint32 hb, uint32 width, Array ret)
{
Array *d;
if(hb > old->cap || lb > hb) {
if(hb > old.cap || lb > hb) {
if(debug) {
prints("sys·arrayslices: old=");
sys·printpointer(old);
prints("sys·arraysliced: old=");
sys·printarray(&old);
prints("; lb=");
sys·printint(lb);
prints("; hb=");
......@@ -70,26 +66,24 @@ sys·arraysliced(Array* old, uint32 lb, uint32 hb, uint32 width, Array* ret)
prints("\n");
prints("oldarray: nel=");
sys·printint(old->nel);
sys·printint(old.nel);
prints("; cap=");
sys·printint(old->cap);
sys·printint(old.cap);
prints("\n");
}
throwslice(lb, hb, old->cap);
throwslice(lb, hb, old.cap);
}
// new array is inside old array
d = mal(sizeof(*d) - sizeof(d->b));
d->nel = hb-lb;
d->cap = old->cap - lb;
d->array = old->array + lb*width;
ret.nel = hb-lb;
ret.cap = old.cap - lb;
ret.array = old.array + lb*width;
ret = d;
FLUSH(&ret);
if(debug) {
prints("sys·arrayslices: old=");
sys·printarray(old);
prints("sys·arraysliced: old=");
sys·printarray(&old);
prints("; lb=");
sys·printint(lb);
prints("; hb=");
......@@ -97,16 +91,15 @@ sys·arraysliced(Array* old, uint32 lb, uint32 hb, uint32 width, Array* ret)
prints("; width=");
sys·printint(width);
prints("; ret=");
sys·printarray(ret);
sys·printarray(&ret);
prints("\n");
}
}
// arrayslices(old *any, nel uint32, lb uint32, hb uint32, width uint32) (ary *[]any);
// arrayslices(old *any, nel int, lb int, hb int, width int) (ary []any);
void
sys·arrayslices(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, Array* ret)
sys·arrayslices(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, Array ret)
{
Array *d;
if(hb > nel || lb > hb) {
if(debug) {
......@@ -126,12 +119,10 @@ sys·arrayslices(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, Arra
}
// new array is inside old array
d = mal(sizeof(*d) - sizeof(d->b));
d->nel = hb-lb;
d->cap = nel-lb;
d->array = old + lb*width;
ret.nel = hb-lb;
ret.cap = nel-lb;
ret.array = old + lb*width;
ret = d;
FLUSH(&ret);
if(debug) {
......@@ -146,31 +137,28 @@ sys·arrayslices(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, Arra
prints("; width=");
sys·printint(width);
prints("; ret=");
sys·printarray(ret);
sys·printarray(&ret);
prints("\n");
}
}
// arrays2d(old *any, nel uint32) (ary *[]any)
// arrays2d(old *any, nel int) (ary []any)
void
sys·arrays2d(byte* old, uint32 nel, Array* ret)
sys·arrays2d(byte* old, uint32 nel, Array ret)
{
Array *d;
// new dope to old array
d = mal(sizeof(*d) - sizeof(d->b));
d->nel = nel;
d->cap = nel;
d->array = old;
ret.nel = nel;
ret.cap = nel;
ret.array = old;
ret = d;
FLUSH(&ret);
if(debug) {
prints("sys·arrays2d: old=");
sys·printpointer(old);
prints("; ret=");
sys·printarray(ret);
sys·printarray(&ret);
prints("\n");
}
}
......@@ -180,7 +168,7 @@ sys·printarray(Array *a)
{
prints("[");
sys·printint(a->nel);
prints(",");
prints("/");
sys·printint(a->cap);
prints("]");
sys·printpointer(a->array);
......
......@@ -115,7 +115,6 @@ struct Array
byte* array; // actual data
uint32 nel; // number of elements
uint32 cap; // allocated number of elements
byte b[8]; // actual array - may not be contig
};
struct Gobuf
{
......
......@@ -7,7 +7,7 @@
package main
export func
setpd(a *[]int)
setpd(a []int)
{
// print("setpd a=", a, " len=", len(a), " cap=", cap(a), "\n");
for i:=0; i<len(a); i++ {
......@@ -16,7 +16,7 @@ setpd(a *[]int)
}
export func
sumpd(a *[]int) int
sumpd(a []int) int
{
// print("sumpd a=", a, " len=", len(a), " cap=", cap(a), "\n");
t := 0;
......@@ -109,8 +109,8 @@ testpdpf2()
{
var a [80]int;
setpd(&a);
res(sumpd(&a), 0, 80);
setpd(a);
res(sumpd(a), 0, 80);
}
// generate bounds error with ptr dynamic
......
......@@ -6,7 +6,18 @@
package main
import rand "rand"
var randx int;
func
nrand(n int) int
{
randx += 10007;
if randx >= 1000000 {
randx -= 1000000;
}
return randx%n;
}
type Chan
struct
......@@ -31,7 +42,7 @@ init()
}
func
mkchan(c,n int) *[]*Chan
mkchan(c,n int) []*Chan
{
ca := new([]*Chan, n);
for i:=0; i<n; i++ {
......@@ -76,7 +87,7 @@ send(c *Chan)
{
nproc++; // total goroutines running
for {
for r:=rand.nrand(10); r>=0; r-- {
for r:=nrand(10); r>=0; r-- {
sys.gosched();
}
c.sc <- c.sv;
......@@ -107,7 +118,7 @@ recv(c *Chan)
nproc++; // total goroutines running
for {
for r:=rand.nrand(10); r>=0; r-- {
for r:=nrand(10); r>=0; r-- {
sys.gosched();
}
v = <-c.rc;
......@@ -136,7 +147,7 @@ sel(r0,r1,r2,r3, s0,s1,s2,s3 *Chan)
if s3.sc != nil { a++ }
for {
for r:=rand.nrand(5); r>=0; r-- {
for r:=nrand(5); r>=0; r-- {
sys.gosched();
}
......
......@@ -9,7 +9,7 @@ package main
const size = 16;
var a [size]byte;
var p *[]byte;
var p []byte;
var m *map[int]byte;
func
......
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