mirror of https://github.com/golang/go.git
x[lo:] - gc and runtime.
* add runtime sliceslice1 for x[lo:] * remove runtime arraytoslice, rewriting &arr into arr[0:len(arr)]. * port cgen_inline into 8g, 5g. * use native memmove in maps R=ken2 https://golang.org/cl/157106
This commit is contained in:
parent
688ffc1dc1
commit
652f55672d
|
|
@ -61,6 +61,7 @@ EXTERN Node* newproc;
|
||||||
EXTERN Node* deferproc;
|
EXTERN Node* deferproc;
|
||||||
EXTERN Node* deferreturn;
|
EXTERN Node* deferreturn;
|
||||||
EXTERN Node* throwindex;
|
EXTERN Node* throwindex;
|
||||||
|
EXTERN Node* throwslice;
|
||||||
EXTERN Node* throwreturn;
|
EXTERN Node* throwreturn;
|
||||||
EXTERN long unmappedzero;
|
EXTERN long unmappedzero;
|
||||||
EXTERN int maxstksize;
|
EXTERN int maxstksize;
|
||||||
|
|
@ -78,6 +79,7 @@ void cgen_callinter(Node*, Node*, int);
|
||||||
void cgen_proc(Node*, int);
|
void cgen_proc(Node*, int);
|
||||||
void cgen_callret(Node*, Node*);
|
void cgen_callret(Node*, Node*);
|
||||||
void cgen_dcl(Node*);
|
void cgen_dcl(Node*);
|
||||||
|
int cgen_inline(Node*, Node*);
|
||||||
int needconvert(Type*, Type*);
|
int needconvert(Type*, Type*);
|
||||||
void genconv(Type*, Type*);
|
void genconv(Type*, Type*);
|
||||||
void allocparams(void);
|
void allocparams(void);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ compile(Node *fn)
|
||||||
deferproc = sysfunc("deferproc");
|
deferproc = sysfunc("deferproc");
|
||||||
deferreturn = sysfunc("deferreturn");
|
deferreturn = sysfunc("deferreturn");
|
||||||
throwindex = sysfunc("throwindex");
|
throwindex = sysfunc("throwindex");
|
||||||
|
throwslice = sysfunc("throwslice");
|
||||||
throwreturn = sysfunc("throwreturn");
|
throwreturn = sysfunc("throwreturn");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -685,3 +686,382 @@ clearfat(Node *nl)
|
||||||
regfree(&nz);
|
regfree(&nz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
regcmp(const void *va, const void *vb)
|
||||||
|
{
|
||||||
|
Node *ra, *rb;
|
||||||
|
|
||||||
|
ra = (Node*)va;
|
||||||
|
rb = (Node*)vb;
|
||||||
|
return ra->local - rb->local;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Prog* throwpc;
|
||||||
|
|
||||||
|
void
|
||||||
|
getargs(NodeList *nn, Node *reg, int n)
|
||||||
|
{
|
||||||
|
NodeList *l;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
throwpc = nil;
|
||||||
|
|
||||||
|
l = nn;
|
||||||
|
for(i=0; i<n; i++) {
|
||||||
|
if(!smallintconst(l->n->right) && !isslice(l->n->right->type)) {
|
||||||
|
regalloc(reg+i, l->n->right->type, N);
|
||||||
|
cgen(l->n->right, reg+i);
|
||||||
|
} else
|
||||||
|
reg[i] = *l->n->right;
|
||||||
|
if(reg[i].local != 0)
|
||||||
|
yyerror("local used");
|
||||||
|
reg[i].local = l->n->left->xoffset;
|
||||||
|
l = l->next;
|
||||||
|
}
|
||||||
|
qsort((void*)reg, n, sizeof(*reg), regcmp);
|
||||||
|
for(i=0; i<n; i++)
|
||||||
|
reg[i].local = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cmpandthrow(Node *nl, Node *nr)
|
||||||
|
{
|
||||||
|
vlong cl, cr;
|
||||||
|
Prog *p1;
|
||||||
|
int op;
|
||||||
|
Node *c, n1, n2;
|
||||||
|
|
||||||
|
op = OLE;
|
||||||
|
if(smallintconst(nl)) {
|
||||||
|
cl = mpgetfix(nl->val.u.xval);
|
||||||
|
if(cl == 0)
|
||||||
|
return;
|
||||||
|
if(smallintconst(nr)) {
|
||||||
|
cr = mpgetfix(nr->val.u.xval);
|
||||||
|
if(cl > cr) {
|
||||||
|
if(throwpc == nil) {
|
||||||
|
throwpc = pc;
|
||||||
|
ginscall(throwslice, 0);
|
||||||
|
} else
|
||||||
|
patch(gbranch(AB, T), throwpc);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// put the constant on the right
|
||||||
|
op = brrev(op);
|
||||||
|
c = nl;
|
||||||
|
nl = nr;
|
||||||
|
nr = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
n1.op = OXXX;
|
||||||
|
if(nr->op != OREGISTER) {
|
||||||
|
regalloc(&n1, types[TUINT32], N);
|
||||||
|
gmove(nr, &n1);
|
||||||
|
nr = &n1;
|
||||||
|
}
|
||||||
|
n2.op = OXXX;
|
||||||
|
if(nl->op != OREGISTER) {
|
||||||
|
regalloc(&n2, types[TUINT32], N);
|
||||||
|
gmove(nl, &n2);
|
||||||
|
nl = &n2;
|
||||||
|
}
|
||||||
|
gcmp(optoas(OCMP, types[TUINT32]), nl, nr);
|
||||||
|
if(nr == &n1)
|
||||||
|
regfree(&n1);
|
||||||
|
if(nl == &n2)
|
||||||
|
regfree(&n2);
|
||||||
|
if(throwpc == nil) {
|
||||||
|
p1 = gbranch(optoas(op, types[TUINT32]), T);
|
||||||
|
throwpc = pc;
|
||||||
|
ginscall(throwslice, 0);
|
||||||
|
patch(p1, pc);
|
||||||
|
} else {
|
||||||
|
op = brcom(op);
|
||||||
|
p1 = gbranch(optoas(op, types[TUINT32]), T);
|
||||||
|
patch(p1, throwpc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sleasy(Node *n)
|
||||||
|
{
|
||||||
|
if(n->op != ONAME)
|
||||||
|
return 0;
|
||||||
|
if(!n->addable)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate inline code for
|
||||||
|
// slicearray
|
||||||
|
// sliceslice
|
||||||
|
// arraytoslice
|
||||||
|
int
|
||||||
|
cgen_inline(Node *n, Node *res)
|
||||||
|
{
|
||||||
|
Node nodes[5];
|
||||||
|
Node n1, n2, n3, nres, nnode0, ntemp;
|
||||||
|
vlong v;
|
||||||
|
int i, narg, bad;
|
||||||
|
|
||||||
|
if(n->op != OCALLFUNC)
|
||||||
|
goto no;
|
||||||
|
if(!n->left->addable)
|
||||||
|
goto no;
|
||||||
|
if(strcmp(n->left->sym->package, "runtime") != 0)
|
||||||
|
goto no;
|
||||||
|
if(strcmp(n->left->sym->name, "slicearray") == 0)
|
||||||
|
goto slicearray;
|
||||||
|
if(strcmp(n->left->sym->name, "sliceslice") == 0) {
|
||||||
|
narg = 4;
|
||||||
|
goto sliceslice;
|
||||||
|
}
|
||||||
|
if(strcmp(n->left->sym->name, "sliceslice1") == 0) {
|
||||||
|
narg = 3;
|
||||||
|
goto sliceslice;
|
||||||
|
}
|
||||||
|
goto no;
|
||||||
|
|
||||||
|
slicearray:
|
||||||
|
if(!sleasy(res))
|
||||||
|
goto no;
|
||||||
|
getargs(n->list, nodes, 5);
|
||||||
|
|
||||||
|
// if(hb[3] > nel[1]) goto throw
|
||||||
|
cmpandthrow(&nodes[3], &nodes[1]);
|
||||||
|
|
||||||
|
// if(lb[2] > hb[3]) goto throw
|
||||||
|
cmpandthrow(&nodes[2], &nodes[3]);
|
||||||
|
|
||||||
|
// len = hb[3] - lb[2] (destroys hb)
|
||||||
|
n2 = *res;
|
||||||
|
n2.type = types[TUINT32];
|
||||||
|
n2.xoffset += Array_nel;
|
||||||
|
|
||||||
|
if(smallintconst(&nodes[3]) && smallintconst(&nodes[2])) {
|
||||||
|
v = mpgetfix(nodes[3].val.u.xval) -
|
||||||
|
mpgetfix(nodes[2].val.u.xval);
|
||||||
|
nodconst(&n1, types[TUINT32], v);
|
||||||
|
gmove(&n1, &n2);
|
||||||
|
} else {
|
||||||
|
regalloc(&n1, types[TUINT32], &nodes[3]);
|
||||||
|
gmove(&nodes[3], &n1);
|
||||||
|
if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
|
||||||
|
gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
|
||||||
|
gmove(&n1, &n2);
|
||||||
|
regfree(&n1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cap = nel[1] - lb[2] (destroys nel)
|
||||||
|
n2 = *res;
|
||||||
|
n2.type = types[TUINT32];
|
||||||
|
n2.xoffset += Array_cap;
|
||||||
|
|
||||||
|
if(smallintconst(&nodes[1]) && smallintconst(&nodes[2])) {
|
||||||
|
v = mpgetfix(nodes[1].val.u.xval) -
|
||||||
|
mpgetfix(nodes[2].val.u.xval);
|
||||||
|
nodconst(&n1, types[TUINT32], v);
|
||||||
|
gmove(&n1, &n2);
|
||||||
|
} else {
|
||||||
|
regalloc(&n1, types[TUINT32], &nodes[1]);
|
||||||
|
gmove(&nodes[1], &n1);
|
||||||
|
if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
|
||||||
|
gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
|
||||||
|
gmove(&n1, &n2);
|
||||||
|
regfree(&n1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if slice could be too big, dereference to
|
||||||
|
// catch nil array pointer.
|
||||||
|
if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
|
||||||
|
n2 = nodes[0];
|
||||||
|
n2.xoffset = 0;
|
||||||
|
n2.op = OINDREG;
|
||||||
|
n2.type = types[TUINT8];
|
||||||
|
regalloc(&n1, types[TUINT32], N);
|
||||||
|
gins(AMOVB, &n2, &n1);
|
||||||
|
regfree(&n1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ary = old[0] + (lb[2] * width[4]) (destroys old)
|
||||||
|
n2 = *res;
|
||||||
|
n2.type = types[tptr];
|
||||||
|
n2.xoffset += Array_array;
|
||||||
|
|
||||||
|
if(smallintconst(&nodes[2]) && smallintconst(&nodes[4])) {
|
||||||
|
v = mpgetfix(nodes[2].val.u.xval) *
|
||||||
|
mpgetfix(nodes[4].val.u.xval);
|
||||||
|
if(v != 0) {
|
||||||
|
nodconst(&n1, types[tptr], v);
|
||||||
|
gins(optoas(OADD, types[tptr]), &n1, &nodes[0]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
regalloc(&n1, types[tptr], &nodes[2]);
|
||||||
|
gmove(&nodes[2], &n1);
|
||||||
|
if(!smallintconst(&nodes[4]) || mpgetfix(nodes[4].val.u.xval) != 1) {
|
||||||
|
regalloc(&n3, types[tptr], N);
|
||||||
|
gmove(&nodes[4], &n3);
|
||||||
|
gins(optoas(OMUL, types[tptr]), &n3, &n1);
|
||||||
|
regfree(&n3);
|
||||||
|
}
|
||||||
|
gins(optoas(OADD, types[tptr]), &n1, &nodes[0]);
|
||||||
|
regfree(&n1);
|
||||||
|
}
|
||||||
|
gmove(&nodes[0], &n2);
|
||||||
|
|
||||||
|
for(i=0; i<5; i++) {
|
||||||
|
if(nodes[i].op == OREGISTER)
|
||||||
|
regfree(&nodes[i]);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
sliceslice:
|
||||||
|
getargs(n->list, nodes, narg);
|
||||||
|
|
||||||
|
nres = *res; // result
|
||||||
|
nnode0 = nodes[0]; // input slice
|
||||||
|
if(!sleasy(res) || !sleasy(&nodes[0])) {
|
||||||
|
bad = 0;
|
||||||
|
if(res->ullman >= UINF)
|
||||||
|
bad = 1;
|
||||||
|
for(i=0; i<narg; i++) {
|
||||||
|
if(nodes[i].ullman >= UINF)
|
||||||
|
bad = 1;
|
||||||
|
if(nodes[i].op == OREGISTER)
|
||||||
|
regfree(&nodes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bad)
|
||||||
|
goto no;
|
||||||
|
|
||||||
|
tempname(&ntemp, res->type);
|
||||||
|
if(!sleasy(&nodes[0])) {
|
||||||
|
cgen(&nodes[0], &ntemp);
|
||||||
|
nnode0 = ntemp;
|
||||||
|
}
|
||||||
|
getargs(n->list, nodes, narg);
|
||||||
|
if(!sleasy(res))
|
||||||
|
nres = ntemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(narg == 3) { // old[lb:]
|
||||||
|
// move width to where it would be for old[lb:hb]
|
||||||
|
nodes[3] = nodes[2];
|
||||||
|
nodes[2].op = OXXX;
|
||||||
|
|
||||||
|
// if(lb[1] > old.nel[0]) goto throw;
|
||||||
|
n2 = nnode0;
|
||||||
|
n2.xoffset += Array_nel;
|
||||||
|
n2.type = types[TUINT32];
|
||||||
|
cmpandthrow(&nodes[1], &n2);
|
||||||
|
|
||||||
|
// ret.nel = old.nel[0]-lb[1];
|
||||||
|
n2 = nnode0;
|
||||||
|
n2.type = types[TUINT32];
|
||||||
|
n2.xoffset += Array_nel;
|
||||||
|
|
||||||
|
regalloc(&n1, types[TUINT32], N);
|
||||||
|
gmove(&n2, &n1);
|
||||||
|
if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
|
||||||
|
gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
|
||||||
|
|
||||||
|
n2 = nres;
|
||||||
|
n2.type = types[TUINT32];
|
||||||
|
n2.xoffset += Array_nel;
|
||||||
|
gmove(&n1, &n2);
|
||||||
|
regfree(&n1);
|
||||||
|
} else { // old[lb:hb]
|
||||||
|
// if(hb[2] > old.cap[0]) goto throw;
|
||||||
|
n2 = nnode0;
|
||||||
|
n2.xoffset += Array_cap;
|
||||||
|
n2.type = types[TUINT32];
|
||||||
|
cmpandthrow(&nodes[2], &n2);
|
||||||
|
|
||||||
|
// if(lb[1] > hb[2]) goto throw;
|
||||||
|
cmpandthrow(&nodes[1], &nodes[2]);
|
||||||
|
|
||||||
|
// ret.len = hb[2]-lb[1]; (destroys hb[2])
|
||||||
|
n2 = nres;
|
||||||
|
n2.type = types[TUINT32];
|
||||||
|
n2.xoffset += Array_nel;
|
||||||
|
|
||||||
|
if(smallintconst(&nodes[2]) && smallintconst(&nodes[1])) {
|
||||||
|
v = mpgetfix(nodes[2].val.u.xval) -
|
||||||
|
mpgetfix(nodes[1].val.u.xval);
|
||||||
|
nodconst(&n1, types[TUINT32], v);
|
||||||
|
gmove(&n1, &n2);
|
||||||
|
} else {
|
||||||
|
regalloc(&n1, types[TUINT32], &nodes[2]);
|
||||||
|
gmove(&nodes[2], &n1);
|
||||||
|
if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
|
||||||
|
gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
|
||||||
|
gmove(&n1, &n2);
|
||||||
|
regfree(&n1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
|
||||||
|
n2 = nnode0;
|
||||||
|
n2.type = types[TUINT32];
|
||||||
|
n2.xoffset += Array_cap;
|
||||||
|
|
||||||
|
regalloc(&n1, types[TUINT32], &nodes[2]);
|
||||||
|
gmove(&n2, &n1);
|
||||||
|
if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
|
||||||
|
gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
|
||||||
|
|
||||||
|
n2 = nres;
|
||||||
|
n2.type = types[TUINT32];
|
||||||
|
n2.xoffset += Array_cap;
|
||||||
|
gmove(&n1, &n2);
|
||||||
|
regfree(&n1);
|
||||||
|
|
||||||
|
// ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
|
||||||
|
n2 = nnode0;
|
||||||
|
n2.type = types[tptr];
|
||||||
|
n2.xoffset += Array_array;
|
||||||
|
regalloc(&n3, types[tptr], N);
|
||||||
|
gmove(&n2, &n3);
|
||||||
|
|
||||||
|
regalloc(&n1, types[tptr], &nodes[1]);
|
||||||
|
if(smallintconst(&nodes[1]) && smallintconst(&nodes[3])) {
|
||||||
|
gmove(&n2, &n1);
|
||||||
|
v = mpgetfix(nodes[1].val.u.xval) *
|
||||||
|
mpgetfix(nodes[3].val.u.xval);
|
||||||
|
if(v != 0) {
|
||||||
|
nodconst(&n2, types[tptr], v);
|
||||||
|
gins(optoas(OADD, types[tptr]), &n3, &n1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gmove(&nodes[1], &n1);
|
||||||
|
if(!smallintconst(&nodes[3]) || mpgetfix(nodes[3].val.u.xval) != 1) {
|
||||||
|
regalloc(&n2, types[tptr], N);
|
||||||
|
gmove(&nodes[3], &n2);
|
||||||
|
gins(optoas(OMUL, types[tptr]), &n2, &n1);
|
||||||
|
regfree(&n2);
|
||||||
|
}
|
||||||
|
gins(optoas(OADD, types[tptr]), &n3, &n1);
|
||||||
|
}
|
||||||
|
regfree(&n3);
|
||||||
|
|
||||||
|
n2 = nres;
|
||||||
|
n2.type = types[tptr];
|
||||||
|
n2.xoffset += Array_array;
|
||||||
|
gmove(&n1, &n2);
|
||||||
|
regfree(&n1);
|
||||||
|
|
||||||
|
for(i=0; i<4; i++) {
|
||||||
|
if(nodes[i].op == OREGISTER)
|
||||||
|
regfree(&nodes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!sleasy(res)) {
|
||||||
|
cgen(&nres, res);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
no:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1131,7 +1131,7 @@ cgen_inline(Node *n, Node *res)
|
||||||
Node nodes[5];
|
Node nodes[5];
|
||||||
Node n1, n2, nres, nnode0, ntemp;
|
Node n1, n2, nres, nnode0, ntemp;
|
||||||
vlong v;
|
vlong v;
|
||||||
int i, bad;
|
int i, narg, bad;
|
||||||
|
|
||||||
if(n->op != OCALLFUNC)
|
if(n->op != OCALLFUNC)
|
||||||
goto no;
|
goto no;
|
||||||
|
|
@ -1141,10 +1141,14 @@ cgen_inline(Node *n, Node *res)
|
||||||
goto no;
|
goto no;
|
||||||
if(strcmp(n->left->sym->name, "slicearray") == 0)
|
if(strcmp(n->left->sym->name, "slicearray") == 0)
|
||||||
goto slicearray;
|
goto slicearray;
|
||||||
if(strcmp(n->left->sym->name, "sliceslice") == 0)
|
if(strcmp(n->left->sym->name, "sliceslice") == 0) {
|
||||||
|
narg = 4;
|
||||||
goto sliceslice;
|
goto sliceslice;
|
||||||
if(strcmp(n->left->sym->name, "arraytoslice") == 0)
|
}
|
||||||
goto arraytoslice;
|
if(strcmp(n->left->sym->name, "sliceslice1") == 0) {
|
||||||
|
narg = 3;
|
||||||
|
goto sliceslice;
|
||||||
|
}
|
||||||
goto no;
|
goto no;
|
||||||
|
|
||||||
slicearray:
|
slicearray:
|
||||||
|
|
@ -1231,44 +1235,8 @@ slicearray:
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
arraytoslice:
|
|
||||||
if(!sleasy(res))
|
|
||||||
goto no;
|
|
||||||
getargs(n->list, nodes, 2);
|
|
||||||
|
|
||||||
// ret.len = nel[1];
|
|
||||||
n2 = *res;
|
|
||||||
n2.xoffset += Array_nel;
|
|
||||||
gins(optoas(OAS, types[TUINT32]), &nodes[1], &n2);
|
|
||||||
|
|
||||||
// ret.cap = nel[1];
|
|
||||||
n2 = *res;
|
|
||||||
n2.xoffset += Array_cap;
|
|
||||||
gins(optoas(OAS, types[TUINT32]), &nodes[1], &n2);
|
|
||||||
|
|
||||||
// ret.array = old[0];
|
|
||||||
n2 = *res;
|
|
||||||
n2.xoffset += Array_array;
|
|
||||||
gins(optoas(OAS, types[tptr]), &nodes[0], &n2);
|
|
||||||
|
|
||||||
// if slice could be too big, dereference to
|
|
||||||
// catch nil array pointer.
|
|
||||||
if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
|
|
||||||
n2 = nodes[0];
|
|
||||||
n2.xoffset = 0;
|
|
||||||
n2.op = OINDREG;
|
|
||||||
n2.type = types[TUINT8];
|
|
||||||
gins(ATESTB, nodintconst(0), &n2);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0; i<2; i++) {
|
|
||||||
if(nodes[i].op == OREGISTER)
|
|
||||||
regfree(&nodes[i]);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
sliceslice:
|
sliceslice:
|
||||||
getargs(n->list, nodes, 4);
|
getargs(n->list, nodes, narg);
|
||||||
|
|
||||||
nres = *res; // result
|
nres = *res; // result
|
||||||
nnode0 = nodes[0]; // input slice
|
nnode0 = nodes[0]; // input slice
|
||||||
|
|
@ -1276,7 +1244,7 @@ sliceslice:
|
||||||
bad = 0;
|
bad = 0;
|
||||||
if(res->ullman >= UINF)
|
if(res->ullman >= UINF)
|
||||||
bad = 1;
|
bad = 1;
|
||||||
for(i=0; i<4; i++) {
|
for(i=0; i<narg; i++) {
|
||||||
if(nodes[i].ullman >= UINF)
|
if(nodes[i].ullman >= UINF)
|
||||||
bad = 1;
|
bad = 1;
|
||||||
if(nodes[i].op == OREGISTER)
|
if(nodes[i].op == OREGISTER)
|
||||||
|
|
@ -1291,35 +1259,60 @@ sliceslice:
|
||||||
cgen(&nodes[0], &ntemp);
|
cgen(&nodes[0], &ntemp);
|
||||||
nnode0 = ntemp;
|
nnode0 = ntemp;
|
||||||
}
|
}
|
||||||
getargs(n->list, nodes, 4);
|
getargs(n->list, nodes, narg);
|
||||||
if(!sleasy(res))
|
if(!sleasy(res))
|
||||||
nres = ntemp;
|
nres = ntemp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(narg == 3) { // old[lb:]
|
||||||
|
// move width to where it would be for old[lb:hb]
|
||||||
|
nodes[3] = nodes[2];
|
||||||
|
nodes[2].op = OXXX;
|
||||||
|
|
||||||
|
// if(lb[1] > old.nel[0]) goto throw;
|
||||||
|
n2 = nnode0;
|
||||||
|
n2.xoffset += Array_nel;
|
||||||
|
cmpandthrow(&nodes[1], &n2);
|
||||||
|
|
||||||
// if(hb[2] > old.cap[0]) goto throw;
|
// ret.nel = old.nel[0]-lb[1];
|
||||||
n2 = nnode0;
|
n2 = nnode0;
|
||||||
n2.xoffset += Array_cap;
|
n2.xoffset += Array_nel;
|
||||||
cmpandthrow(&nodes[2], &n2);
|
|
||||||
|
regalloc(&n1, types[TUINT32], N);
|
||||||
// if(lb[1] > hb[2]) goto throw;
|
gins(optoas(OAS, types[TUINT32]), &n2, &n1);
|
||||||
cmpandthrow(&nodes[1], &nodes[2]);
|
|
||||||
|
|
||||||
// ret.len = hb[2]-lb[1]; (destroys hb[2])
|
|
||||||
n2 = nres;
|
|
||||||
n2.xoffset += Array_nel;
|
|
||||||
|
|
||||||
if(smallintconst(&nodes[2]) && smallintconst(&nodes[1])) {
|
|
||||||
v = mpgetfix(nodes[2].val.u.xval) -
|
|
||||||
mpgetfix(nodes[1].val.u.xval);
|
|
||||||
nodconst(&n1, types[TUINT32], v);
|
|
||||||
gins(optoas(OAS, types[TUINT32]), &n1, &n2);
|
|
||||||
} else {
|
|
||||||
regalloc(&n1, types[TUINT32], &nodes[2]);
|
|
||||||
gmove(&nodes[2], &n1);
|
|
||||||
if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
|
if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
|
||||||
gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
|
gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
|
||||||
|
|
||||||
|
n2 = nres;
|
||||||
|
n2.xoffset += Array_nel;
|
||||||
gins(optoas(OAS, types[TUINT32]), &n1, &n2);
|
gins(optoas(OAS, types[TUINT32]), &n1, &n2);
|
||||||
regfree(&n1);
|
regfree(&n1);
|
||||||
|
} else { // old[lb:hb]
|
||||||
|
// if(hb[2] > old.cap[0]) goto throw;
|
||||||
|
n2 = nnode0;
|
||||||
|
n2.xoffset += Array_cap;
|
||||||
|
cmpandthrow(&nodes[2], &n2);
|
||||||
|
|
||||||
|
// if(lb[1] > hb[2]) goto throw;
|
||||||
|
cmpandthrow(&nodes[1], &nodes[2]);
|
||||||
|
|
||||||
|
// ret.len = hb[2]-lb[1]; (destroys hb[2])
|
||||||
|
n2 = nres;
|
||||||
|
n2.xoffset += Array_nel;
|
||||||
|
|
||||||
|
if(smallintconst(&nodes[2]) && smallintconst(&nodes[1])) {
|
||||||
|
v = mpgetfix(nodes[2].val.u.xval) -
|
||||||
|
mpgetfix(nodes[1].val.u.xval);
|
||||||
|
nodconst(&n1, types[TUINT32], v);
|
||||||
|
gins(optoas(OAS, types[TUINT32]), &n1, &n2);
|
||||||
|
} else {
|
||||||
|
regalloc(&n1, types[TUINT32], &nodes[2]);
|
||||||
|
gmove(&nodes[2], &n1);
|
||||||
|
if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
|
||||||
|
gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
|
||||||
|
gins(optoas(OAS, types[TUINT32]), &n1, &n2);
|
||||||
|
regfree(&n1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
|
// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,10 @@ cgen(Node *n, Node *res)
|
||||||
if(res == N || res->type == T)
|
if(res == N || res->type == T)
|
||||||
fatal("cgen: res nil");
|
fatal("cgen: res nil");
|
||||||
|
|
||||||
|
// inline slices
|
||||||
|
if(cgen_inline(n, res))
|
||||||
|
return;
|
||||||
|
|
||||||
while(n->op == OCONVNOP)
|
while(n->op == OCONVNOP)
|
||||||
n = n->left;
|
n = n->left;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ EXTERN Node* newproc;
|
||||||
EXTERN Node* deferproc;
|
EXTERN Node* deferproc;
|
||||||
EXTERN Node* deferreturn;
|
EXTERN Node* deferreturn;
|
||||||
EXTERN Node* throwindex;
|
EXTERN Node* throwindex;
|
||||||
|
EXTERN Node* throwslice;
|
||||||
EXTERN Node* throwreturn;
|
EXTERN Node* throwreturn;
|
||||||
EXTERN int maxstksize;
|
EXTERN int maxstksize;
|
||||||
extern uint32 unmappedzero;
|
extern uint32 unmappedzero;
|
||||||
|
|
@ -106,6 +107,7 @@ Prog* gins(int, Node*, Node*);
|
||||||
int samaddr(Node*, Node*);
|
int samaddr(Node*, Node*);
|
||||||
void naddr(Node*, Addr*, int);
|
void naddr(Node*, Addr*, int);
|
||||||
void cgen_aret(Node*, Node*);
|
void cgen_aret(Node*, Node*);
|
||||||
|
int cgen_inline(Node*, Node*);
|
||||||
Node* ncon(uint32);
|
Node* ncon(uint32);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ compile(Node *fn)
|
||||||
deferproc = sysfunc("deferproc");
|
deferproc = sysfunc("deferproc");
|
||||||
deferreturn = sysfunc("deferreturn");
|
deferreturn = sysfunc("deferreturn");
|
||||||
throwindex = sysfunc("throwindex");
|
throwindex = sysfunc("throwindex");
|
||||||
|
throwslice = sysfunc("throwslice");
|
||||||
throwreturn = sysfunc("throwreturn");
|
throwreturn = sysfunc("throwreturn");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -740,4 +741,348 @@ cgen_bmul(int op, Node *nl, Node *nr, Node *res)
|
||||||
regfree(&n2b);
|
regfree(&n2b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
regcmp(const void *va, const void *vb)
|
||||||
|
{
|
||||||
|
Node *ra, *rb;
|
||||||
|
|
||||||
|
ra = (Node*)va;
|
||||||
|
rb = (Node*)vb;
|
||||||
|
return ra->local - rb->local;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Prog* throwpc;
|
||||||
|
|
||||||
|
void
|
||||||
|
getargs(NodeList *nn, Node *reg, int n)
|
||||||
|
{
|
||||||
|
NodeList *l;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
throwpc = nil;
|
||||||
|
|
||||||
|
l = nn;
|
||||||
|
for(i=0; i<n; i++) {
|
||||||
|
if(!smallintconst(l->n->right) && !isslice(l->n->right->type)) {
|
||||||
|
if(i < 3) // AX CX DX
|
||||||
|
nodreg(reg+i, l->n->right->type, D_AX+i);
|
||||||
|
else
|
||||||
|
reg[i].op = OXXX;
|
||||||
|
regalloc(reg+i, l->n->right->type, reg+i);
|
||||||
|
cgen(l->n->right, reg+i);
|
||||||
|
} else
|
||||||
|
reg[i] = *l->n->right;
|
||||||
|
if(reg[i].local != 0)
|
||||||
|
yyerror("local used");
|
||||||
|
reg[i].local = l->n->left->xoffset;
|
||||||
|
l = l->next;
|
||||||
|
}
|
||||||
|
qsort((void*)reg, n, sizeof(*reg), regcmp);
|
||||||
|
for(i=0; i<n; i++)
|
||||||
|
reg[i].local = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cmpandthrow(Node *nl, Node *nr)
|
||||||
|
{
|
||||||
|
vlong cl, cr;
|
||||||
|
Prog *p1;
|
||||||
|
int op;
|
||||||
|
Node *c;
|
||||||
|
|
||||||
|
op = OLE;
|
||||||
|
if(smallintconst(nl)) {
|
||||||
|
cl = mpgetfix(nl->val.u.xval);
|
||||||
|
if(cl == 0)
|
||||||
|
return;
|
||||||
|
if(smallintconst(nr)) {
|
||||||
|
cr = mpgetfix(nr->val.u.xval);
|
||||||
|
if(cl > cr) {
|
||||||
|
if(throwpc == nil) {
|
||||||
|
throwpc = pc;
|
||||||
|
ginscall(throwslice, 0);
|
||||||
|
} else
|
||||||
|
patch(gbranch(AJMP, T), throwpc);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// put the constant on the right
|
||||||
|
op = brrev(op);
|
||||||
|
c = nl;
|
||||||
|
nl = nr;
|
||||||
|
nr = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
gins(optoas(OCMP, types[TUINT32]), nl, nr);
|
||||||
|
if(throwpc == nil) {
|
||||||
|
p1 = gbranch(optoas(op, types[TUINT32]), T);
|
||||||
|
throwpc = pc;
|
||||||
|
ginscall(throwslice, 0);
|
||||||
|
patch(p1, pc);
|
||||||
|
} else {
|
||||||
|
op = brcom(op);
|
||||||
|
p1 = gbranch(optoas(op, types[TUINT32]), T);
|
||||||
|
patch(p1, throwpc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sleasy(Node *n)
|
||||||
|
{
|
||||||
|
if(n->op != ONAME)
|
||||||
|
return 0;
|
||||||
|
if(!n->addable)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate inline code for
|
||||||
|
// slicearray
|
||||||
|
// sliceslice
|
||||||
|
// arraytoslice
|
||||||
|
int
|
||||||
|
cgen_inline(Node *n, Node *res)
|
||||||
|
{
|
||||||
|
Node nodes[5];
|
||||||
|
Node n1, n2, nres, nnode0, ntemp;
|
||||||
|
vlong v;
|
||||||
|
int i, narg, bad;
|
||||||
|
|
||||||
|
if(n->op != OCALLFUNC)
|
||||||
|
goto no;
|
||||||
|
if(!n->left->addable)
|
||||||
|
goto no;
|
||||||
|
if(strcmp(n->left->sym->package, "runtime") != 0)
|
||||||
|
goto no;
|
||||||
|
if(strcmp(n->left->sym->name, "slicearray") == 0)
|
||||||
|
goto slicearray;
|
||||||
|
if(strcmp(n->left->sym->name, "sliceslice") == 0) {
|
||||||
|
narg = 4;
|
||||||
|
goto sliceslice;
|
||||||
|
}
|
||||||
|
if(strcmp(n->left->sym->name, "sliceslice1") == 0) {
|
||||||
|
narg = 3;
|
||||||
|
goto sliceslice;
|
||||||
|
}
|
||||||
|
goto no;
|
||||||
|
|
||||||
|
slicearray:
|
||||||
|
if(!sleasy(res))
|
||||||
|
goto no;
|
||||||
|
getargs(n->list, nodes, 5);
|
||||||
|
|
||||||
|
// if(hb[3] > nel[1]) goto throw
|
||||||
|
cmpandthrow(&nodes[3], &nodes[1]);
|
||||||
|
|
||||||
|
// if(lb[2] > hb[3]) goto throw
|
||||||
|
cmpandthrow(&nodes[2], &nodes[3]);
|
||||||
|
|
||||||
|
// len = hb[3] - lb[2] (destroys hb)
|
||||||
|
n2 = *res;
|
||||||
|
n2.xoffset += Array_nel;
|
||||||
|
|
||||||
|
if(smallintconst(&nodes[3]) && smallintconst(&nodes[2])) {
|
||||||
|
v = mpgetfix(nodes[3].val.u.xval) -
|
||||||
|
mpgetfix(nodes[2].val.u.xval);
|
||||||
|
nodconst(&n1, types[TUINT32], v);
|
||||||
|
gins(optoas(OAS, types[TUINT32]), &n1, &n2);
|
||||||
|
} else {
|
||||||
|
regalloc(&n1, types[TUINT32], &nodes[3]);
|
||||||
|
gmove(&nodes[3], &n1);
|
||||||
|
if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
|
||||||
|
gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
|
||||||
|
gins(optoas(OAS, types[TUINT32]), &n1, &n2);
|
||||||
|
regfree(&n1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cap = nel[1] - lb[2] (destroys nel)
|
||||||
|
n2 = *res;
|
||||||
|
n2.xoffset += Array_cap;
|
||||||
|
|
||||||
|
if(smallintconst(&nodes[1]) && smallintconst(&nodes[2])) {
|
||||||
|
v = mpgetfix(nodes[1].val.u.xval) -
|
||||||
|
mpgetfix(nodes[2].val.u.xval);
|
||||||
|
nodconst(&n1, types[TUINT32], v);
|
||||||
|
gins(optoas(OAS, types[TUINT32]), &n1, &n2);
|
||||||
|
} else {
|
||||||
|
regalloc(&n1, types[TUINT32], &nodes[1]);
|
||||||
|
gmove(&nodes[1], &n1);
|
||||||
|
if(!smallintconst(&nodes[2]) || mpgetfix(nodes[2].val.u.xval) != 0)
|
||||||
|
gins(optoas(OSUB, types[TUINT32]), &nodes[2], &n1);
|
||||||
|
gins(optoas(OAS, types[TUINT32]), &n1, &n2);
|
||||||
|
regfree(&n1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if slice could be too big, dereference to
|
||||||
|
// catch nil array pointer.
|
||||||
|
if(nodes[0].op == OREGISTER && nodes[0].type->type->width >= unmappedzero) {
|
||||||
|
n2 = nodes[0];
|
||||||
|
n2.xoffset = 0;
|
||||||
|
n2.op = OINDREG;
|
||||||
|
n2.type = types[TUINT8];
|
||||||
|
gins(ATESTB, nodintconst(0), &n2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ary = old[0] + (lb[2] * width[4]) (destroys old)
|
||||||
|
n2 = *res;
|
||||||
|
n2.xoffset += Array_array;
|
||||||
|
|
||||||
|
if(smallintconst(&nodes[2]) && smallintconst(&nodes[4])) {
|
||||||
|
v = mpgetfix(nodes[2].val.u.xval) *
|
||||||
|
mpgetfix(nodes[4].val.u.xval);
|
||||||
|
if(v != 0) {
|
||||||
|
nodconst(&n1, types[tptr], v);
|
||||||
|
gins(optoas(OADD, types[tptr]), &n1, &nodes[0]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
regalloc(&n1, types[tptr], &nodes[2]);
|
||||||
|
gmove(&nodes[2], &n1);
|
||||||
|
if(!smallintconst(&nodes[4]) || mpgetfix(nodes[4].val.u.xval) != 1)
|
||||||
|
gins(optoas(OMUL, types[tptr]), &nodes[4], &n1);
|
||||||
|
gins(optoas(OADD, types[tptr]), &n1, &nodes[0]);
|
||||||
|
regfree(&n1);
|
||||||
|
}
|
||||||
|
gins(optoas(OAS, types[tptr]), &nodes[0], &n2);
|
||||||
|
|
||||||
|
for(i=0; i<5; i++) {
|
||||||
|
if(nodes[i].op == OREGISTER)
|
||||||
|
regfree(&nodes[i]);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
sliceslice:
|
||||||
|
getargs(n->list, nodes, narg);
|
||||||
|
|
||||||
|
nres = *res; // result
|
||||||
|
nnode0 = nodes[0]; // input slice
|
||||||
|
ntemp.op = OXXX;
|
||||||
|
if(!sleasy(res) || !sleasy(&nodes[0])) {
|
||||||
|
bad = 0;
|
||||||
|
if(res->ullman >= UINF)
|
||||||
|
bad = 1;
|
||||||
|
for(i=0; i<narg; i++) {
|
||||||
|
if(nodes[i].ullman >= UINF)
|
||||||
|
bad = 1;
|
||||||
|
if(nodes[i].op == OREGISTER)
|
||||||
|
regfree(&nodes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bad)
|
||||||
|
goto no;
|
||||||
|
|
||||||
|
tempalloc(&ntemp, res->type);
|
||||||
|
if(!sleasy(&nodes[0])) {
|
||||||
|
cgen(&nodes[0], &ntemp);
|
||||||
|
nnode0 = ntemp;
|
||||||
|
}
|
||||||
|
getargs(n->list, nodes, narg);
|
||||||
|
if(!sleasy(res))
|
||||||
|
nres = ntemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(narg == 3) { // old[lb:]
|
||||||
|
// move width to where it would be for old[lb:hb]
|
||||||
|
nodes[3] = nodes[2];
|
||||||
|
nodes[2].op = OXXX;
|
||||||
|
|
||||||
|
// if(lb[1] > old.nel[0]) goto throw;
|
||||||
|
n2 = nnode0;
|
||||||
|
n2.xoffset += Array_nel;
|
||||||
|
cmpandthrow(&nodes[1], &n2);
|
||||||
|
|
||||||
|
// ret.nel = old.nel[0]-lb[1];
|
||||||
|
n2 = nnode0;
|
||||||
|
n2.xoffset += Array_nel;
|
||||||
|
|
||||||
|
regalloc(&n1, types[TUINT32], N);
|
||||||
|
gins(optoas(OAS, types[TUINT32]), &n2, &n1);
|
||||||
|
if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
|
||||||
|
gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
|
||||||
|
|
||||||
|
n2 = nres;
|
||||||
|
n2.xoffset += Array_nel;
|
||||||
|
gins(optoas(OAS, types[TUINT32]), &n1, &n2);
|
||||||
|
regfree(&n1);
|
||||||
|
} else { // old[lb:hb]
|
||||||
|
// if(hb[2] > old.cap[0]) goto throw;
|
||||||
|
n2 = nnode0;
|
||||||
|
n2.xoffset += Array_cap;
|
||||||
|
cmpandthrow(&nodes[2], &n2);
|
||||||
|
|
||||||
|
// if(lb[1] > hb[2]) goto throw;
|
||||||
|
cmpandthrow(&nodes[1], &nodes[2]);
|
||||||
|
|
||||||
|
// ret.len = hb[2]-lb[1]; (destroys hb[2])
|
||||||
|
n2 = nres;
|
||||||
|
n2.xoffset += Array_nel;
|
||||||
|
|
||||||
|
if(smallintconst(&nodes[2]) && smallintconst(&nodes[1])) {
|
||||||
|
v = mpgetfix(nodes[2].val.u.xval) -
|
||||||
|
mpgetfix(nodes[1].val.u.xval);
|
||||||
|
nodconst(&n1, types[TUINT32], v);
|
||||||
|
gins(optoas(OAS, types[TUINT32]), &n1, &n2);
|
||||||
|
} else {
|
||||||
|
regalloc(&n1, types[TUINT32], &nodes[2]);
|
||||||
|
gmove(&nodes[2], &n1);
|
||||||
|
if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
|
||||||
|
gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
|
||||||
|
gins(optoas(OAS, types[TUINT32]), &n1, &n2);
|
||||||
|
regfree(&n1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
|
||||||
|
n2 = nnode0;
|
||||||
|
n2.xoffset += Array_cap;
|
||||||
|
|
||||||
|
regalloc(&n1, types[TUINT32], &nodes[2]);
|
||||||
|
gins(optoas(OAS, types[TUINT32]), &n2, &n1);
|
||||||
|
if(!smallintconst(&nodes[1]) || mpgetfix(nodes[1].val.u.xval) != 0)
|
||||||
|
gins(optoas(OSUB, types[TUINT32]), &nodes[1], &n1);
|
||||||
|
|
||||||
|
n2 = nres;
|
||||||
|
n2.xoffset += Array_cap;
|
||||||
|
gins(optoas(OAS, types[TUINT32]), &n1, &n2);
|
||||||
|
regfree(&n1);
|
||||||
|
|
||||||
|
// ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
|
||||||
|
n2 = nnode0;
|
||||||
|
n2.xoffset += Array_array;
|
||||||
|
|
||||||
|
regalloc(&n1, types[tptr], &nodes[1]);
|
||||||
|
if(smallintconst(&nodes[1]) && smallintconst(&nodes[3])) {
|
||||||
|
gins(optoas(OAS, types[tptr]), &n2, &n1);
|
||||||
|
v = mpgetfix(nodes[1].val.u.xval) *
|
||||||
|
mpgetfix(nodes[3].val.u.xval);
|
||||||
|
if(v != 0) {
|
||||||
|
nodconst(&n2, types[tptr], v);
|
||||||
|
gins(optoas(OADD, types[tptr]), &n2, &n1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gmove(&nodes[1], &n1);
|
||||||
|
if(!smallintconst(&nodes[3]) || mpgetfix(nodes[3].val.u.xval) != 1)
|
||||||
|
gins(optoas(OMUL, types[tptr]), &nodes[3], &n1);
|
||||||
|
gins(optoas(OADD, types[tptr]), &n2, &n1);
|
||||||
|
}
|
||||||
|
|
||||||
|
n2 = nres;
|
||||||
|
n2.xoffset += Array_array;
|
||||||
|
gins(optoas(OAS, types[tptr]), &n1, &n2);
|
||||||
|
regfree(&n1);
|
||||||
|
|
||||||
|
for(i=0; i<4; i++) {
|
||||||
|
if(nodes[i].op == OREGISTER)
|
||||||
|
regfree(&nodes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!sleasy(res)) {
|
||||||
|
cgen(&nres, res);
|
||||||
|
}
|
||||||
|
if(ntemp.op != OXXX)
|
||||||
|
tempfree(&ntemp);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
no:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,9 +64,9 @@ char *runtimeimport =
|
||||||
"func runtime.selectdefault (sel *uint8) (selected bool)\n"
|
"func runtime.selectdefault (sel *uint8) (selected bool)\n"
|
||||||
"func runtime.selectgo (sel *uint8)\n"
|
"func runtime.selectgo (sel *uint8)\n"
|
||||||
"func runtime.makeslice (nel int, cap int, width int) (ary []any)\n"
|
"func runtime.makeslice (nel int, cap int, width int) (ary []any)\n"
|
||||||
|
"func runtime.sliceslice1 (old []any, lb int, width int) (ary []any)\n"
|
||||||
"func runtime.sliceslice (old []any, lb int, hb int, width int) (ary []any)\n"
|
"func runtime.sliceslice (old []any, lb int, hb int, width int) (ary []any)\n"
|
||||||
"func runtime.slicearray (old *any, nel int, lb int, hb int, width int) (ary []any)\n"
|
"func runtime.slicearray (old *any, nel int, lb int, hb int, width int) (ary []any)\n"
|
||||||
"func runtime.arraytoslice (old *any, nel int) (ary []any)\n"
|
|
||||||
"func runtime.closure ()\n"
|
"func runtime.closure ()\n"
|
||||||
"func runtime.int64div (? int64, ? int64) (? int64)\n"
|
"func runtime.int64div (? int64, ? int64) (? int64)\n"
|
||||||
"func runtime.uint64div (? uint64, ? uint64) (? uint64)\n"
|
"func runtime.uint64div (? uint64, ? uint64) (? uint64)\n"
|
||||||
|
|
|
||||||
|
|
@ -831,9 +831,13 @@ pexpr:
|
||||||
{
|
{
|
||||||
$$ = nod(OINDEX, $1, $3);
|
$$ = nod(OINDEX, $1, $3);
|
||||||
}
|
}
|
||||||
| pexpr '[' keyval ']'
|
| pexpr '[' expr ':' ']'
|
||||||
{
|
{
|
||||||
$$ = nod(OSLICE, $1, $3);
|
$$ = nod(OSLICE, $1, nod(OKEY, $3, N));
|
||||||
|
}
|
||||||
|
| pexpr '[' expr ':' expr ']'
|
||||||
|
{
|
||||||
|
$$ = nod(OSLICE, $1, nod(OKEY, $3, $5));
|
||||||
}
|
}
|
||||||
| pseudocall
|
| pseudocall
|
||||||
| convtype '(' expr ')'
|
| convtype '(' expr ')'
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,9 @@ func selectdefault(sel *byte) (selected bool)
|
||||||
func selectgo(sel *byte)
|
func selectgo(sel *byte)
|
||||||
|
|
||||||
func makeslice(nel int, cap int, width int) (ary []any)
|
func makeslice(nel int, cap int, width int) (ary []any)
|
||||||
|
func sliceslice1(old []any, lb int, width int) (ary []any)
|
||||||
func sliceslice(old []any, lb int, hb int, width int) (ary []any)
|
func sliceslice(old []any, lb int, hb int, width int) (ary []any)
|
||||||
func slicearray(old *any, nel int, lb int, hb int, width int) (ary []any)
|
func slicearray(old *any, nel int, lb int, hb int, width int) (ary []any)
|
||||||
func arraytoslice(old *any, nel int) (ary []any)
|
|
||||||
|
|
||||||
func closure() // has args, but compiler fills in
|
func closure() // has args, but compiler fills in
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -587,7 +587,7 @@ reswitch:
|
||||||
defaultlit(&n->right->left, types[TUINT]);
|
defaultlit(&n->right->left, types[TUINT]);
|
||||||
defaultlit(&n->right->right, types[TUINT]);
|
defaultlit(&n->right->right, types[TUINT]);
|
||||||
implicitstar(&n->left);
|
implicitstar(&n->left);
|
||||||
if(n->right->left == N || n->right->right == N) {
|
if(n->right->left == N) {
|
||||||
yyerror("missing slice bounds?");
|
yyerror("missing slice bounds?");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
@ -597,11 +597,13 @@ reswitch:
|
||||||
yyerror("invalid slice index %#N (type %T)", n->right->left, t);
|
yyerror("invalid slice index %#N (type %T)", n->right->left, t);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if((t = n->right->right->type) == T)
|
if(n->right->right != N) {
|
||||||
goto error;
|
if((t = n->right->right->type) == T)
|
||||||
if(!isint[t->etype]) {
|
goto error;
|
||||||
yyerror("invalid slice index %#N (type %T)", n->right->right, t);
|
if(!isint[t->etype]) {
|
||||||
goto error;
|
yyerror("invalid slice index %#N (type %T)", n->right->right, t);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
l = n->left;
|
l = n->left;
|
||||||
if((t = l->type) == T)
|
if((t = l->type) == T)
|
||||||
|
|
|
||||||
|
|
@ -808,15 +808,26 @@ walkexpr(Node **np, NodeList **init)
|
||||||
walkexpr(&n->right->right, init);
|
walkexpr(&n->right->right, init);
|
||||||
// dynamic slice
|
// dynamic slice
|
||||||
// sliceslice(old []any, lb int, hb int, width int) (ary []any)
|
// sliceslice(old []any, lb int, hb int, width int) (ary []any)
|
||||||
|
// sliceslice1(old []any, lb int, width int) (ary []any)
|
||||||
t = n->type;
|
t = n->type;
|
||||||
fn = syslook("sliceslice", 1);
|
if(n->right->right != N) {
|
||||||
argtype(fn, t->type); // any-1
|
fn = syslook("sliceslice", 1);
|
||||||
argtype(fn, t->type); // any-2
|
argtype(fn, t->type); // any-1
|
||||||
n = mkcall1(fn, t, init,
|
argtype(fn, t->type); // any-2
|
||||||
n->left,
|
n = mkcall1(fn, t, init,
|
||||||
conv(n->right->left, types[TINT]),
|
n->left,
|
||||||
conv(n->right->right, types[TINT]),
|
conv(n->right->left, types[TINT]),
|
||||||
nodintconst(t->type->width));
|
conv(n->right->right, types[TINT]),
|
||||||
|
nodintconst(t->type->width));
|
||||||
|
} else {
|
||||||
|
fn = syslook("sliceslice1", 1);
|
||||||
|
argtype(fn, t->type); // any-1
|
||||||
|
argtype(fn, t->type); // any-2
|
||||||
|
n = mkcall1(fn, t, init,
|
||||||
|
n->left,
|
||||||
|
conv(n->right->left, types[TINT]),
|
||||||
|
nodintconst(t->type->width));
|
||||||
|
}
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OSLICEARR:
|
case OSLICEARR:
|
||||||
|
|
@ -829,13 +840,29 @@ walkexpr(Node **np, NodeList **init)
|
||||||
fn = syslook("slicearray", 1);
|
fn = syslook("slicearray", 1);
|
||||||
argtype(fn, n->left->type); // any-1
|
argtype(fn, n->left->type); // any-1
|
||||||
argtype(fn, t->type); // any-2
|
argtype(fn, t->type); // any-2
|
||||||
|
if(n->right->right == N)
|
||||||
|
r = nodintconst(n->left->type->bound);
|
||||||
|
else
|
||||||
|
r = conv(n->right->right, types[TINT]);
|
||||||
n = mkcall1(fn, t, init,
|
n = mkcall1(fn, t, init,
|
||||||
nod(OADDR, n->left, N), nodintconst(n->left->type->bound),
|
nod(OADDR, n->left, N), nodintconst(n->left->type->bound),
|
||||||
conv(n->right->left, types[TINT]),
|
conv(n->right->left, types[TINT]),
|
||||||
conv(n->right->right, types[TINT]),
|
r,
|
||||||
nodintconst(t->type->width));
|
nodintconst(t->type->width));
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
|
case OCONVSLICE:
|
||||||
|
// slicearray(old *any, nel int, lb int, hb int, width int) (ary []any)
|
||||||
|
fn = syslook("slicearray", 1);
|
||||||
|
argtype(fn, n->left->type->type); // any-1
|
||||||
|
argtype(fn, n->type->type); // any-2
|
||||||
|
n = mkcall1(fn, n->type, init, n->left,
|
||||||
|
nodintconst(n->left->type->type->bound),
|
||||||
|
nodintconst(0),
|
||||||
|
nodintconst(n->left->type->type->bound),
|
||||||
|
nodintconst(n->type->type->width));
|
||||||
|
goto ret;
|
||||||
|
|
||||||
case OADDR:;
|
case OADDR:;
|
||||||
Node *nvar, *nstar;
|
Node *nvar, *nstar;
|
||||||
|
|
||||||
|
|
@ -1014,14 +1041,6 @@ walkexpr(Node **np, NodeList **init)
|
||||||
n = ifacecvt(n->type, n->left, n->etype, init);
|
n = ifacecvt(n->type, n->left, n->etype, init);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OCONVSLICE:
|
|
||||||
// arraytoslice(old *any, nel int) (ary []any)
|
|
||||||
fn = syslook("arraytoslice", 1);
|
|
||||||
argtype(fn, n->left->type->type); // any-1
|
|
||||||
argtype(fn, n->type->type); // any-2
|
|
||||||
n = mkcall1(fn, n->type, init, n->left, nodintconst(n->left->type->type->bound));
|
|
||||||
goto ret;
|
|
||||||
|
|
||||||
case OCLOSURE:
|
case OCLOSURE:
|
||||||
n = walkclosure(n, init);
|
n = walkclosure(n, init);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,6 @@
|
||||||
#define free(a) USED(a)
|
#define free(a) USED(a)
|
||||||
#define offsetof(s,m) (uint32)(&(((s*)0)->m))
|
#define offsetof(s,m) (uint32)(&(((s*)0)->m))
|
||||||
#define memset(a,b,c) runtime·memclr((byte*)(a), (uint32)(c))
|
#define memset(a,b,c) runtime·memclr((byte*)(a), (uint32)(c))
|
||||||
#define memmove(a,b,c) mmov((byte*)(a),(byte*)(b),(uint32)(c))
|
|
||||||
#define memcpy(a,b,c) mcpy((byte*)(a),(byte*)(b),(uint32)(c))
|
#define memcpy(a,b,c) mcpy((byte*)(a),(byte*)(b),(uint32)(c))
|
||||||
#define assert(a) if(!(a)) throw("assert")
|
#define assert(a) if(!(a)) throw("assert")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,28 +104,6 @@ mcmp(byte *s1, byte *s2, uint32 n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
mmov(byte *t, byte *f, uint32 n)
|
|
||||||
{
|
|
||||||
if(t < f) {
|
|
||||||
while(n > 0) {
|
|
||||||
*t = *f;
|
|
||||||
t++;
|
|
||||||
f++;
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t += n;
|
|
||||||
f += n;
|
|
||||||
while(n > 0) {
|
|
||||||
t--;
|
|
||||||
f--;
|
|
||||||
*t = *f;
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte*
|
byte*
|
||||||
mchr(byte *p, byte c, byte *ep)
|
mchr(byte *p, byte c, byte *ep)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -342,7 +342,7 @@ void printf(int8*, ...);
|
||||||
byte* mchr(byte*, byte, byte*);
|
byte* mchr(byte*, byte, byte*);
|
||||||
void mcpy(byte*, byte*, uint32);
|
void mcpy(byte*, byte*, uint32);
|
||||||
int32 mcmp(byte*, byte*, uint32);
|
int32 mcmp(byte*, byte*, uint32);
|
||||||
void mmov(byte*, byte*, uint32);
|
void memmove(void*, void*, uint32);
|
||||||
void* mal(uint32);
|
void* mal(uint32);
|
||||||
uint32 cmpstring(String, String);
|
uint32 cmpstring(String, String);
|
||||||
String gostring(byte*);
|
String gostring(byte*);
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ throwslice(uint32 lb, uint32 hb, uint32 n)
|
||||||
void
|
void
|
||||||
runtime·sliceslice(Slice old, uint32 lb, uint32 hb, uint32 width, Slice ret)
|
runtime·sliceslice(Slice old, uint32 lb, uint32 hb, uint32 width, Slice ret)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(hb > old.cap || lb > hb) {
|
if(hb > old.cap || lb > hb) {
|
||||||
if(debug) {
|
if(debug) {
|
||||||
prints("runtime·sliceslice: old=");
|
prints("runtime·sliceslice: old=");
|
||||||
|
|
@ -75,7 +74,7 @@ runtime·sliceslice(Slice old, uint32 lb, uint32 hb, uint32 width, Slice ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
// new array is inside old array
|
// new array is inside old array
|
||||||
ret.len = hb-lb;
|
ret.len = hb - lb;
|
||||||
ret.cap = old.cap - lb;
|
ret.cap = old.cap - lb;
|
||||||
ret.array = old.array + lb*width;
|
ret.array = old.array + lb*width;
|
||||||
|
|
||||||
|
|
@ -96,6 +95,49 @@ runtime·sliceslice(Slice old, uint32 lb, uint32 hb, uint32 width, Slice ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sliceslice1(old []any, lb int, width int) (ary []any);
|
||||||
|
void
|
||||||
|
runtime·sliceslice1(Slice old, uint32 lb, uint32 width, Slice ret)
|
||||||
|
{
|
||||||
|
if(lb > old.len) {
|
||||||
|
if(debug) {
|
||||||
|
prints("runtime·sliceslice: old=");
|
||||||
|
runtime·printslice(old);
|
||||||
|
prints("; lb=");
|
||||||
|
runtime·printint(lb);
|
||||||
|
prints("; width=");
|
||||||
|
runtime·printint(width);
|
||||||
|
prints("\n");
|
||||||
|
|
||||||
|
prints("oldarray: nel=");
|
||||||
|
runtime·printint(old.len);
|
||||||
|
prints("; cap=");
|
||||||
|
runtime·printint(old.cap);
|
||||||
|
prints("\n");
|
||||||
|
}
|
||||||
|
throwslice(lb, old.len, old.cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
// new array is inside old array
|
||||||
|
ret.len = old.len - lb;
|
||||||
|
ret.cap = old.cap - lb;
|
||||||
|
ret.array = old.array + lb*width;
|
||||||
|
|
||||||
|
FLUSH(&ret);
|
||||||
|
|
||||||
|
if(debug) {
|
||||||
|
prints("runtime·sliceslice: old=");
|
||||||
|
runtime·printslice(old);
|
||||||
|
prints("; lb=");
|
||||||
|
runtime·printint(lb);
|
||||||
|
prints("; width=");
|
||||||
|
runtime·printint(width);
|
||||||
|
prints("; ret=");
|
||||||
|
runtime·printslice(ret);
|
||||||
|
prints("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// slicearray(old *any, nel int, lb int, hb int, width int) (ary []any);
|
// slicearray(old *any, nel int, lb int, hb int, width int) (ary []any);
|
||||||
void
|
void
|
||||||
runtime·slicearray(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, Slice ret)
|
runtime·slicearray(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, Slice ret)
|
||||||
|
|
@ -149,34 +191,6 @@ runtime·slicearray(byte* old, uint32 nel, uint32 lb, uint32 hb, uint32 width, S
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// arraytoslice(old *any, nel int) (ary []any)
|
|
||||||
void
|
|
||||||
runtime·arraytoslice(byte* old, uint32 nel, Slice ret)
|
|
||||||
{
|
|
||||||
if(nel > 0 && old == nil) {
|
|
||||||
// crash if old == nil.
|
|
||||||
// could give a better message
|
|
||||||
// but this is consistent with all the in-line checks
|
|
||||||
// that the compiler inserts for other uses.
|
|
||||||
*old = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// new dope to old array
|
|
||||||
ret.len = nel;
|
|
||||||
ret.cap = nel;
|
|
||||||
ret.array = old;
|
|
||||||
|
|
||||||
FLUSH(&ret);
|
|
||||||
|
|
||||||
if(debug) {
|
|
||||||
prints("runtime·slicearrayp: old=");
|
|
||||||
runtime·printpointer(old);
|
|
||||||
prints("; ret=");
|
|
||||||
runtime·printslice(ret);
|
|
||||||
prints("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// slicecopy(to any, fr any, wid uint32) int
|
// slicecopy(to any, fr any, wid uint32) int
|
||||||
void
|
void
|
||||||
runtime·slicecopy(Slice to, Slice fm, uintptr width, int32 ret)
|
runtime·slicecopy(Slice to, Slice fm, uintptr width, int32 ret)
|
||||||
|
|
|
||||||
|
|
@ -26,14 +26,18 @@ main()
|
||||||
lb = 0; hb = 10;
|
lb = 0; hb = 10;
|
||||||
by = bx[lb:hb]; tstb();
|
by = bx[lb:hb]; tstb();
|
||||||
by = bx[lb:10]; tstb();
|
by = bx[lb:10]; tstb();
|
||||||
|
by = bx[lb:]; tstb();
|
||||||
by = bx[0:hb]; tstb();
|
by = bx[0:hb]; tstb();
|
||||||
by = bx[0:10]; tstb();
|
by = bx[0:10]; tstb();
|
||||||
|
by = bx[0:]; tstb();
|
||||||
|
|
||||||
lb = 2; hb = 10;
|
lb = 2; hb = 10;
|
||||||
by = bx[lb:hb]; tstb();
|
by = bx[lb:hb]; tstb();
|
||||||
by = bx[lb:10]; tstb();
|
by = bx[lb:10]; tstb();
|
||||||
|
by = bx[lb:]; tstb();
|
||||||
by = bx[2:hb]; tstb();
|
by = bx[2:hb]; tstb();
|
||||||
by = bx[2:10]; tstb();
|
by = bx[2:10]; tstb();
|
||||||
|
by = bx[2:]; tstb();
|
||||||
|
|
||||||
lb = 0; hb = 8;
|
lb = 0; hb = 8;
|
||||||
by = bx[lb:hb]; tstb();
|
by = bx[lb:hb]; tstb();
|
||||||
|
|
@ -51,14 +55,18 @@ main()
|
||||||
lb = 0; hb = 10;
|
lb = 0; hb = 10;
|
||||||
fy = fx[lb:hb]; tstf();
|
fy = fx[lb:hb]; tstf();
|
||||||
fy = fx[lb:10]; tstf();
|
fy = fx[lb:10]; tstf();
|
||||||
|
fy = fx[lb:]; tstf();
|
||||||
fy = fx[0:hb]; tstf();
|
fy = fx[0:hb]; tstf();
|
||||||
fy = fx[0:10]; tstf();
|
fy = fx[0:10]; tstf();
|
||||||
|
fy = fx[0:]; tstf();
|
||||||
|
|
||||||
lb = 2; hb = 10;
|
lb = 2; hb = 10;
|
||||||
fy = fx[lb:hb]; tstf();
|
fy = fx[lb:hb]; tstf();
|
||||||
fy = fx[lb:10]; tstf();
|
fy = fx[lb:10]; tstf();
|
||||||
|
fy = fx[lb:]; tstf();
|
||||||
fy = fx[2:hb]; tstf();
|
fy = fx[2:hb]; tstf();
|
||||||
fy = fx[2:10]; tstf();
|
fy = fx[2:10]; tstf();
|
||||||
|
fy = fx[2:]; tstf();
|
||||||
|
|
||||||
lb = 0; hb = 8;
|
lb = 0; hb = 8;
|
||||||
fy = fx[lb:hb]; tstf();
|
fy = fx[lb:hb]; tstf();
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,18 @@ main()
|
||||||
lb = 0; hb = 10;
|
lb = 0; hb = 10;
|
||||||
by = bx[lb:hb]; tstb();
|
by = bx[lb:hb]; tstb();
|
||||||
by = bx[lb:10]; tstb();
|
by = bx[lb:10]; tstb();
|
||||||
|
by = bx[lb:]; tstb();
|
||||||
by = bx[0:hb]; tstb();
|
by = bx[0:hb]; tstb();
|
||||||
by = bx[0:10]; tstb();
|
by = bx[0:10]; tstb();
|
||||||
|
by = bx[0:]; tstb();
|
||||||
|
|
||||||
lb = 2; hb = 10;
|
lb = 2; hb = 10;
|
||||||
by = bx[lb:hb]; tstb();
|
by = bx[lb:hb]; tstb();
|
||||||
by = bx[lb:10]; tstb();
|
by = bx[lb:10]; tstb();
|
||||||
|
by = bx[lb:]; tstb();
|
||||||
by = bx[2:hb]; tstb();
|
by = bx[2:hb]; tstb();
|
||||||
by = bx[2:10]; tstb();
|
by = bx[2:10]; tstb();
|
||||||
|
by = bx[2:]; tstb();
|
||||||
|
|
||||||
lb = 0; hb = 8;
|
lb = 0; hb = 8;
|
||||||
by = bx[lb:hb]; tstb();
|
by = bx[lb:hb]; tstb();
|
||||||
|
|
@ -46,14 +50,18 @@ main()
|
||||||
lb = 0; hb = 10;
|
lb = 0; hb = 10;
|
||||||
fy = fx[lb:hb]; tstf();
|
fy = fx[lb:hb]; tstf();
|
||||||
fy = fx[lb:10]; tstf();
|
fy = fx[lb:10]; tstf();
|
||||||
|
fy = fx[lb:]; tstf();
|
||||||
fy = fx[0:hb]; tstf();
|
fy = fx[0:hb]; tstf();
|
||||||
fy = fx[0:10]; tstf();
|
fy = fx[0:10]; tstf();
|
||||||
|
fy = fx[0:]; tstf();
|
||||||
|
|
||||||
lb = 2; hb = 10;
|
lb = 2; hb = 10;
|
||||||
fy = fx[lb:hb]; tstf();
|
fy = fx[lb:hb]; tstf();
|
||||||
fy = fx[lb:10]; tstf();
|
fy = fx[lb:10]; tstf();
|
||||||
|
fy = fx[lb:]; tstf();
|
||||||
fy = fx[2:hb]; tstf();
|
fy = fx[2:hb]; tstf();
|
||||||
fy = fx[2:10]; tstf();
|
fy = fx[2:10]; tstf();
|
||||||
|
fy = fx[2:]; tstf();
|
||||||
|
|
||||||
lb = 0; hb = 8;
|
lb = 0; hb = 8;
|
||||||
fy = fx[lb:hb]; tstf();
|
fy = fx[lb:hb]; tstf();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue