redeclarations of variables in the same block.

half-step toward multivalued map indexing

SVN=124019
This commit is contained in:
Ken Thompson 2008-06-21 15:11:29 -07:00
parent a77f7b2497
commit 54abac678a
9 changed files with 395 additions and 102 deletions

View file

@ -234,6 +234,11 @@ agen(Node *n, Node *res)
ulong w, lno;
Type *t;
if(debug['g']) {
dump("\nagen-res", res);
dump("agen-r", n);
}
if(n == N || n->type == T)
return;
@ -267,6 +272,21 @@ agen(Node *n, Node *res)
// regfree(&n1);
// break;
case OCALLMETH:
cgen_callmeth(n);
cgen_aret(n, res);
break;
case OCALLINTER:
cgen_callinter(n, res);
cgen_aret(n, res);
break;
case OCALL:
cgen_call(n);
cgen_aret(n, res);
break;
case OINDEXPTR:
w = n->type->width;
if(nr->addable)
@ -388,6 +408,9 @@ bgen(Node *n, int true, Prog *to)
Node n1, n2, tmp;
Prog *p1, *p2;
if(debug['g']) {
dump("\nbgen", n);
}
if(n == N)
n = booltrue;
@ -554,6 +577,10 @@ sgen(Node *n, Node *ns, ulong w)
Node nodl, nodr;
long c;
if(debug['g']) {
dump("\nsgen-res", ns);
dump("sgen-r", n);
}
if(w == 0)
return;
if(n->ullman >= UINF && ns->ullman >= UINF) {
@ -570,7 +597,6 @@ sgen(Node *n, Node *ns, ulong w)
agen(ns, &nodl);
agen(n, &nodr);
}
gins(ACLD, N, N); // clear direction flag
c = w / 8;

View file

@ -658,7 +658,7 @@ cgen_callret(Node *n, Node *res)
fp = structfirst(&flist, getoutarg(t));
if(fp == T)
fatal("cgen_callret: nil");
fatal("cgen_aret: nil");
memset(&nod, 0, sizeof(nod));
nod.op = OINDREG;
@ -670,6 +670,39 @@ cgen_callret(Node *n, Node *res)
cgen_as(res, &nod, 0);
}
void
cgen_aret(Node *n, Node *res)
{
Node nod1, nod2;
Type *fp, *t;
Iter flist;
fatal("cgen_aret");
t = n->left->type;
if(t->etype == TPTR32 || t->etype == TPTR64)
t = t->type;
fp = structfirst(&flist, getoutarg(t));
if(fp == T)
fatal("cgen_aret: nil");
/* gins LEA */
memset(&nod1, 0, sizeof(nod1));
nod1.op = OINDREG;
nod1.val.vval = D_SP;
nod1.addable = 1;
nod1.xoffset = fp->width;
nod1.type = fp->type;
memset(&nod2, 0, sizeof(nod2));
nod2.op = OADDR;
nod2.left = &nod1;
nod2.addable = 1;
cgen_as(res, &nod2, 0);
}
void
cgen_ret(Node *n)
{

View file

@ -1098,20 +1098,20 @@ naddr(Node *n, Addr *a)
fatal("naddr: const %lT", n->type);
break;
// case OADDR:
// naddr(n->left, a);
// if(a->type >= D_INDIR) {
// a->type -= D_INDIR;
// break;
// }
// if(a->type == D_EXTERN || a->type == D_STATIC ||
// a->type == D_AUTO || a->type == D_PARAM)
// if(a->index == D_NONE) {
// a->index = a->type;
// a->type = D_ADDR;
// break;
// }
// goto bad;
case OADDR:
naddr(n->left, a);
if(a->type >= D_INDIR) {
a->type -= D_INDIR;
break;
}
if(a->type == D_EXTERN || a->type == D_STATIC ||
a->type == D_AUTO || a->type == D_PARAM)
if(a->index == D_NONE) {
a->index = a->type;
a->type = D_ADDR;
break;
}
fatal("naddr: OADDR\n");
// case OADD:
// if(n->right->op == OLITERAL) {

View file

@ -489,6 +489,8 @@ dcopy(Sym *a, Sym *b)
a->lexical = b->lexical;
a->undef = b->undef;
a->vargen = b->vargen;
a->vblock = b->vblock;
a->tblock = b->tblock;
}
Sym*
@ -533,6 +535,7 @@ popdcl(char *why)
if(strcmp(why, d->package) != 0)
fatal("popdcl: pushed as %s poped as %s", d->package, why);
dclstack = d->link;
block = d->vblock;
}
void
@ -560,6 +563,10 @@ markdcl(char *why)
d = push();
d->name = nil; // used as a mark in fifo
d->package = why; // diagnostic for unmatched
d->vblock = block;
blockgen++;
block = blockgen;
// if(dflag())
// print("markdcl\n");
}
@ -628,25 +635,20 @@ addvar(Node *n, Type *t, int ctxt)
r = autodcl;
if(ctxt == PEXTERN) {
on = s->oname;
if(on != N) {
if(eqtype(t, on->type, 0)) {
warn("%S redeclared", s);
return;
}
yyerror("%S redeclared (%T %T)", s,
on->type, t);
}
r = externdcl;
gen = 0;
}
if(s->vblock == block)
yyerror("var %S redeclared in this block %d", s, block);
if(ctxt != PEXTERN)
pushdcl(s);
s->vargen = gen;
s->oname = n;
s->offset = 0;
s->vblock = block;
n->type = t;
n->vargen = gen;
@ -692,16 +694,13 @@ addtyp(Type *n, Type *t, int ctxt)
s->otype = t;
return;
}
if(eqtype(t, ot, 0)) {
warn("%S redeclared", s);
return;
}
yyerror("%S redeclared (%T %T)", s,
ot, t);
}
r = externdcl;
}
if(s->tblock == block)
yyerror("type %S redeclared in this block %d", s, block);
if(ctxt != PEXTERN)
pushdcl(s);
@ -712,6 +711,7 @@ addtyp(Type *n, Type *t, int ctxt)
s->vargen = vargen;
s->otype = t;
s->lexical = LATYPE;
s->tblock = block;
t->sym = s;
t->vargen = vargen;
@ -784,9 +784,11 @@ oldname(Sym *s)
n = s->oname;
if(n == N) {
yyerror("%S undefined", s);
n = newname(s);
dodclvar(n, types[TINT32]);
n = nod(ONONAME, N, N);
n->sym = s;
n->type = T;
n->addable = 1;
n->ullman = 0;
}
return n;
}

View file

@ -71,10 +71,16 @@ typedef struct Type Type;
struct Type
{
int etype;
int chan;
uchar etype;
uchar chan;
uchar recur; // to detect loops
uchar trecur; // to detect loops
// TFUNCT
uchar thistuple;
uchar outtuple;
uchar intuple;
Sym* sym;
long vargen; // unique name for OTYPE/ONAME
@ -94,10 +100,6 @@ struct Type
Type* argin;
Node* nname;
uchar thistuple;
uchar outtuple;
uchar intuple;
// TARRAY
long bound;
};
@ -105,7 +107,13 @@ struct Type
struct Node
{
int op;
uchar op;
uchar ullman; // sethi/ullman number
uchar addable; // type of addressability - 0 is not addressable
uchar trecur; // to detect loops
uchar etype; // op for OASOP, etype for OTYPE, exclam for export
uchar class; // PPARAM, PAUTO, PEXTERN, PSTATIC
uchar method; // OCALLMETH name
// most nodes
Node* left;
@ -134,12 +142,6 @@ struct Node
Sym* fsym; // import
Sym* psym; // import
Sym* sym; // various
uchar ullman; // sethi/ullman number
uchar addable; // type of addressability - 0 is not addressable
uchar trecur; // to detect loops
uchar etype; // op for OASOP, etype for OTYPE, exclam for export
uchar class; // PPARAM, PAUTO, PEXTERN, PSTATIC
uchar method; // OCALLMETH name
long vargen; // unique name for OTYPE/ONAME
ulong lineno;
vlong xoffset;
@ -148,6 +150,14 @@ struct Node
struct Sym
{
ushort tblock;
ushort vblock;
uchar undef; // a diagnostic has been generated
uchar export; // marked as export
uchar exported; // has been exported
uchar sym; // huffman encoding in object file
char* opackage; // original package name
char* package; // package name
char* name; // variable name
@ -159,10 +169,6 @@ struct Sym
vlong offset; // stack location if automatic
long lexical;
long vargen; // unique variable number
uchar undef; // a diagnostic has been generated
uchar export; // marked as export
uchar exported; // has been exported
uchar sym; // huffman encoding in object file
Sym* link;
};
#define S ((Sym*)0)
@ -170,7 +176,7 @@ struct Sym
typedef struct Dcl Dcl;
struct Dcl
{
int op;
uchar op;
Sym* dsym; // for printing only
Node* dnode; // oname
Type* dtype; // otype
@ -207,7 +213,7 @@ enum
OTYPE, OCONST, OVAR, OEXPORT, OIMPORT,
ONAME,
ONAME, ONONAME,
ODOT, ODOTPTR, ODOTMETH, ODOTINTER,
ODCLFUNC, ODCLFIELD, ODCLARG,
OLIST, OCMP,
@ -392,6 +398,8 @@ EXTERN long vargen;
EXTERN long exportgen;
EXTERN long maxarg;
EXTERN long stksize;
EXTERN ushort blockgen; // max block number
EXTERN ushort block; // current block number
EXTERN Node* retnil;
EXTERN Node* fskel;
@ -570,6 +578,7 @@ Node* stringop(Node*, int);
Node* mapop(Node*, int);
Node* convas(Node*);
void arrayconv(Type*, Node*);
Node* colas(Node*, Node*);
Node* reorder1(Node*);
Node* reorder2(Node*);
Node* reorder3(Node*);

View file

@ -28,7 +28,8 @@
%type <sym> sym laconst lname latype
%type <lint> chandir
%type <node> xdcl xdcl_list_r oxdcl_list common_dcl
%type <node> xdcl xdcl_list_r oxdcl_list
%type <node> common_dcl Acommon_dcl Bcommon_dcl
%type <node> oarg_type_list arg_type_list_r arg_type
%type <node> else_stmt1 else_stmt2 inc_stmt noninc_stmt
%type <node> complex_stmt compound_stmt ostmt_list
@ -40,17 +41,19 @@
%type <node> simple_stmt osimple_stmt semi_stmt
%type <node> expr uexpr pexpr expr_list oexpr oexpr_list expr_list_r
%type <node> name name_name new_name new_name_list_r
%type <node> vardcl_list_r vardcl
%type <node> vardcl_list_r vardcl Avardcl Bvardcl
%type <node> interfacedcl_list_r interfacedcl
%type <node> structdcl_list_r structdcl
%type <node> export_list_r export
%type <node> hidden_importsym_list_r ohidden_importsym_list hidden_importsym isym
%type <node> hidden_importfield_list_r ohidden_importfield_list hidden_importfield
%type <node> fnbody
%type <node> fnres fnliteral xfndcl fndcl
%type <node> fnres Afnres Bfnres fnliteral xfndcl fndcl
%type <node> keyval_list_r keyval
%type <node> typedcl Atypedcl Btypedcl
%type <type> type fntypeh fntype fnlitdcl intype new_type typeconv
%type <type> fntype fnlitdcl intype new_type typeconv
%type <type> type Atype Btype fntypeh Afntypeh Bfntypeh
%left LOROR
%left LANDAND
@ -147,7 +150,11 @@ xdcl:
}
common_dcl:
LVAR vardcl
Acommon_dcl
| Bcommon_dcl
Acommon_dcl:
LVAR Avardcl
{
$$ = $2;
}
@ -155,17 +162,12 @@ common_dcl:
{
$$ = rev($3);
}
| LCONST constdcl
{
$$ = N;
iota = 0;
}
| LCONST '(' constdcl_list_r osemi ')'
{
$$ = N;
iota = 0;
}
| LTYPE typedcl
| LTYPE Atypedcl
{
$$ = N;
}
@ -174,8 +176,36 @@ common_dcl:
$$ = N;
}
Bcommon_dcl:
LVAR Bvardcl
{
$$ = $2;
}
| LCONST constdcl
{
$$ = N;
iota = 0;
}
| LTYPE Btypedcl
{
$$ = N;
}
vardcl:
new_name_list_r type
Avardcl
| Bvardcl
Avardcl:
new_name_list_r Atype
{
$$ = rev($1);
dodclvar($$, $2);
$$ = nod(OAS, $$, N);
}
Bvardcl:
new_name_list_r Btype
{
$$ = rev($1);
dodclvar($$, $2);
@ -214,7 +244,17 @@ constdcl:
}
typedcl:
new_type type
Atypedcl
| Btypedcl
Atypedcl:
new_type Atype
{
dodcltype($1, $2);
}
Btypedcl:
new_type Btype
{
dodcltype($1, $2);
}
@ -249,13 +289,9 @@ noninc_stmt:
{
$$ = nod(OAS, $1, $3);
}
| new_name LCOLAS expr
| expr_list LCOLAS expr_list
{
walktype($3, Erv); // this is a little harry
defaultlit($3);
dodclvar($1, $3->type);
$$ = nod(OAS, $1, $3);
$$ = nod(OAS, colas($1, $3), $3);
}
inc_stmt:
@ -768,21 +804,25 @@ typeconv:
}
type:
Atype
| Btype
Atype:
latype
{
$$ = oldtype($1);
}
| '[' oexpr ']' type
| '[' oexpr ']' Atype
{
$$ = aindex($2, $4);
}
| LCHAN chandir type
| LCHAN chandir Atype
{
$$ = typ(TCHAN);
$$->type = $3;
$$->chan = $2;
}
| LMAP '[' type ']' type
| LMAP '[' type ']' Atype
{
$$ = typ(TMAP);
$$->down = $3;
@ -805,8 +845,31 @@ type:
{
$$ = dostruct(N, TINTER);
}
| fntypeh
| '*' type
| Afntypeh
| '*' Atype
{
$$ = ptrto($2);
}
Btype:
'[' oexpr ']' Btype
{
$$ = aindex($2, $4);
}
| LCHAN chandir Btype
{
$$ = typ(TCHAN);
$$->type = $3;
$$->chan = $2;
}
| LMAP '[' type ']' Btype
{
$$ = typ(TMAP);
$$->down = $3;
$$->type = $5;
}
| Bfntypeh
| '*' Btype
{
$$ = ptrto($2);
}
@ -874,12 +937,31 @@ fndcl:
}
fntypeh:
LFUNC '(' oarg_type_list ')' fnres
Afntypeh
| Bfntypeh
Afntypeh:
LFUNC '(' oarg_type_list ')' Afnres
{
$$ = functype(N, $3, $5);
funcnam($$, nil);
}
| LFUNC '(' oarg_type_list ')' '.' '(' oarg_type_list ')' fnres
| LFUNC '(' oarg_type_list ')' '.' '(' oarg_type_list ')' Afnres
/* i dont believe that this form is useful for anything */
{
if($3 == N || $3->op == OLIST)
yyerror("syntax error in method receiver");
$$ = functype($3, $7, $9);
funcnam($$, nil);
}
Bfntypeh:
LFUNC '(' oarg_type_list ')' Bfnres
{
$$ = functype(N, $3, $5);
funcnam($$, nil);
}
| LFUNC '(' oarg_type_list ')' '.' '(' oarg_type_list ')' Bfnres
/* i dont believe that this form is useful for anything */
{
if($3 == N || $3->op == OLIST)
@ -942,12 +1024,12 @@ fnbody:
{
$$ = N;
}
fnres:
{
$$ = N;
}
| type
Afnres
| Bfnres
Afnres:
Atype
{
$$ = nod(ODCLFIELD, N, N);
$$->type = $1;
@ -958,6 +1040,17 @@ fnres:
$$ = $2;
}
Bfnres:
{
$$ = N;
}
| Btype
{
$$ = nod(ODCLFIELD, N, N);
$$->type = $1;
$$ = cleanidlist($$);
}
/*
* lists of things
* note that they are left recursive
@ -1082,6 +1175,7 @@ arg_type_list_r:
Astmt:
complex_stmt
| compound_stmt
| Acommon_dcl
| ';'
{
$$ = N;
@ -1093,7 +1187,7 @@ Astmt:
*/
Bstmt:
semi_stmt
| common_dcl
| Bcommon_dcl
/*
* need semi in front YES
@ -1154,6 +1248,10 @@ Bstmt_list_r:
stmt_list_r:
Astmt_list_r
| Bstmt_list_r
| error ';'
{
$$ = N;
}
expr_list_r:
expr
@ -1228,6 +1326,7 @@ expr_list:
$$ = rev($1);
}
/*
* optional things
*/

View file

@ -54,6 +54,8 @@ mainlex(int argc, char *argv[])
lexinit();
lineno = 1;
block = 1;
blockgen = 1;
infile = argv[0];
linehist(infile, 0);
@ -770,7 +772,7 @@ loop:
default:
if(c != e)
warn("unknown escape sequence: %c", c);
yyerror("unknown escape sequence: %c", c);
}
*val = c;
return 0;
@ -791,7 +793,7 @@ hex:
l = l*16 + c-'A' + 10;
continue;
}
warn("non-hex character in escape sequence: %c", c);
yyerror("non-hex character in escape sequence: %c", c);
ungetc(c);
break;
}
@ -806,11 +808,11 @@ oct:
l = l*8 + c-'0';
continue;
}
warn("non-oct character in escape sequence: %c", c);
yyerror("non-oct character in escape sequence: %c", c);
ungetc(c);
}
if(l > 255)
warn("oct escape value > 255: %d", l);
yyerror("oct escape value > 255: %d", l);
*val = l;
return 0;

View file

@ -615,6 +615,7 @@ opnames[] =
[OMOD] = "MOD",
[OMUL] = "MUL",
[ONAME] = "NAME",
[ONONAME] = "NONAME",
[ONE] = "NE",
[ONOT] = "NOT",
[OOROR] = "OROR",
@ -998,6 +999,7 @@ Nconv(Fmt *fp)
break;
case ONAME:
case ONONAME:
if(n->sym == S) {
snprint(buf, sizeof(buf), "%O%J", n->op, n);
break;

View file

@ -38,7 +38,7 @@ walktype(Node *n, int top)
lno = dynlineno;
if(top == Exxx || top == Eyyy) {
dump("", n);
fatal("walktype: top=%d", top);
fatal("walktype: bad top=%d", top);
}
loop:
@ -79,6 +79,17 @@ loop:
ullmancalc(n);
goto ret;
case ONONAME:
s = n->sym;
if(s->undef == 0) {
s->undef = 1;
yyerror("%S: undefined", s);
goto ret;
}
if(top == Etop)
goto nottop;
goto ret;
case ONAME:
if(top == Etop)
goto nottop;
@ -200,6 +211,9 @@ loop:
case OCALLMETH:
// add this-pointer to the arg list
// this is bad - if not a simple
// should make a temp copy rather
// than recalculate it.
l = ascompatte(n->op, getinarg(t), &n->right, 0);
r = ascompatte(n->op, getthis(t), &n->left->left, 0);
if(l != N)
@ -461,9 +475,6 @@ loop:
goto badt;
case TMAP:
print("top=%d type %lT", top, t);
dump("index", n);
// right side must map type
if(n->right->type == T) {
convlit(n->right, t->down);
@ -477,7 +488,7 @@ dump("index", n);
n->op = OINDEX;
n->type = t->type;
if(top == Erv)
*n = *mapop(n, top);
*n = *mapop(n, top);
break;
case TSTRING:
@ -493,7 +504,7 @@ dump("index", n);
goto badt;
*n = *stringop(n, top);
break;
case TARRAY:
case TDARRAY:
// right side must be an int
@ -746,7 +757,6 @@ casebody(Node *n)
Node *oc, *ot, *t;
Iter save;
/*
* look to see if statements at top level have
* case labels attached to them. convert the illegal
@ -912,7 +922,6 @@ print("%L walkdot %O %d\n", n->op, top);
}
}
Node*
ascompatee(int op, Node **nl, Node **nr)
{
@ -927,7 +936,6 @@ ascompatee(int op, Node **nl, Node **nr)
l = listfirst(&savel, nl);
r = listfirst(&saver, nr);
nn = N;
loop:
if(l == N || r == N) {
@ -1382,7 +1390,6 @@ mapop(Node *n, int top)
case OINDEX:
if(top != Erv)
goto nottop;
dump("access start", n);
// mapaccess1(hmap *map[any]any, key any) (val any);
t = fixmap(n->left->type);
@ -1415,7 +1422,6 @@ dump("access start", n);
r = nod(OCALL, on, r);
walktype(r, Erv);
r->type = t->type;
dump("access finish", r);
break;
// mapaccess2(hmap *map[any]any, key any) (val any, pres bool);
@ -1515,7 +1521,6 @@ dump("access finish", r);
break;
}
//dump("mapop return", r);
dynlineno = lno;
return r;
@ -1544,7 +1549,7 @@ convas(Node *n)
Type *lt, *rt;
if(n->op != OAS)
fatal("convas: not as %O", n->op);
fatal("convas: not OAS %O", n->op);
ullmancalc(n);
l = n->left;
@ -1631,6 +1636,121 @@ loop:
goto loop;
}
Node*
old2new(Node *n, Type *t)
{
Node *l;
if(n->op != ONAME && n->op != ONONAME) {
yyerror("left side of := must be a name");
return n;
}
l = newname(n->sym);
dodclvar(l, t);
return l;
}
Node*
colas(Node *nl, Node *nr)
{
Iter savel, saver;
Node *l, *r, *a, *n;
Type *t;
int cl, cr;
/* nl is an expression list.
* nr is an expression list.
* return a newname-list from
* the types from the rhs.
*/
n = N;
cr = listcount(nr);
cl = listcount(nl);
if(cl != cr) {
if(cr == 1)
goto multi;
goto badt;
}
l = listfirst(&savel, &nl);
r = listfirst(&saver, &nr);
loop:
if(l == N)
return n;
walktype(r, Erv);
defaultlit(r);
a = old2new(l, r->type);
if(n == N)
n = a;
else
n = nod(OLIST, n, a);
l = listnext(&savel);
r = listnext(&saver);
goto loop;
multi:
/*
* there is a list on the left
* and a mono on the right.
* go into the right to get
* individual types for the left.
*/
switch(nr->op) {
default:
goto badt;
case OCALLMETH:
case OCALLINTER:
case OCALL:
walktype(nr->left, Erv);
t = nr->left->type;
if(t == T || t->etype != TFUNC)
goto badt;
if(t->outtuple != cl)
goto badt;
l = listfirst(&savel, &nl);
t = structfirst(&saver, getoutarg(t));
while(l != N) {
a = old2new(l, t);
if(n == N)
n = a;
else
n = nod(OLIST, n, a);
l = listnext(&savel);
t = structnext(&saver);
}
break;
case OINDEX:
case OINDEXPTR:
// check if rhs is a map index.
// if so, types are bool,maptype
if(cl != 2)
goto badt;
walktype(nr->left, Elv);
t = nr->left->type;
if(t != T && isptr[t->etype])
t = t->type;
if(t == T || t->etype != TMAP)
goto badt;
a = old2new(nl->left, types[TBOOL]);
n = a;
a = old2new(nl->right, t->type);
n = nod(OLIST, n, a);
break;
}
return n;
badt:
yyerror("shape error across :=");
return nl;
}
Node*
reorder1(Node *n)
{