github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/cmd/gc/sinit.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 /* 6 * static initialization 7 */ 8 9 #include <u.h> 10 #include <libc.h> 11 #include "go.h" 12 13 enum 14 { 15 InitNotStarted = 0, 16 InitDone = 1, 17 InitPending = 2, 18 }; 19 20 static void initplan(Node*); 21 static NodeList *initlist; 22 static void init2(Node*, NodeList**); 23 static void init2list(NodeList*, NodeList**); 24 static int staticinit(Node*, NodeList**); 25 static Node *staticname(Type*, int); 26 27 // init1 walks the AST starting at n, and accumulates in out 28 // the list of definitions needing init code in dependency order. 29 static void 30 init1(Node *n, NodeList **out) 31 { 32 NodeList *l; 33 Node *nv; 34 35 if(n == N) 36 return; 37 init1(n->left, out); 38 init1(n->right, out); 39 for(l=n->list; l; l=l->next) 40 init1(l->n, out); 41 42 if(n->left && n->type && n->left->op == OTYPE && n->class == PFUNC) { 43 // Methods called as Type.Method(receiver, ...). 44 // Definitions for method expressions are stored in type->nname. 45 init1(n->type->nname, out); 46 } 47 48 if(n->op != ONAME) 49 return; 50 switch(n->class) { 51 case PEXTERN: 52 case PFUNC: 53 break; 54 default: 55 if(isblank(n) && n->curfn == N && n->defn != N && n->defn->initorder == InitNotStarted) { 56 // blank names initialization is part of init() but not 57 // when they are inside a function. 58 break; 59 } 60 return; 61 } 62 63 if(n->initorder == InitDone) 64 return; 65 if(n->initorder == InitPending) { 66 // Since mutually recursive sets of functions are allowed, 67 // we don't necessarily raise an error if n depends on a node 68 // which is already waiting for its dependencies to be visited. 69 // 70 // initlist contains a cycle of identifiers referring to each other. 71 // If this cycle contains a variable, then this variable refers to itself. 72 // Conversely, if there exists an initialization cycle involving 73 // a variable in the program, the tree walk will reach a cycle 74 // involving that variable. 75 if(n->class != PFUNC) { 76 nv = n; 77 goto foundinitloop; 78 } 79 for(l=initlist; l->n!=n; l=l->next) { 80 if(l->n->class != PFUNC) { 81 nv = l->n; 82 goto foundinitloop; 83 } 84 } 85 // The loop involves only functions, ok. 86 return; 87 88 foundinitloop: 89 // if there have already been errors printed, 90 // those errors probably confused us and 91 // there might not be a loop. let the user 92 // fix those first. 93 flusherrors(); 94 if(nerrors > 0) 95 errorexit(); 96 97 // There is a loop involving nv. We know about 98 // n and initlist = n1 <- ... <- nv <- ... <- n <- ... 99 print("%L: initialization loop:\n", nv->lineno); 100 // Build back pointers in initlist. 101 for(l=initlist; l; l=l->next) 102 if(l->next != nil) 103 l->next->end = l; 104 // Print nv -> ... -> n1 -> n. 105 for(l=initlist; l->n!=nv; l=l->next); 106 for(; l; l=l->end) 107 print("\t%L %S refers to\n", l->n->lineno, l->n->sym); 108 // Print n -> ... -> nv. 109 for(l=initlist; l->n!=n; l=l->next); 110 for(; l->n != nv; l=l->end) 111 print("\t%L %S refers to\n", l->n->lineno, l->n->sym); 112 print("\t%L %S\n", nv->lineno, nv->sym); 113 errorexit(); 114 } 115 116 // reached a new unvisited node. 117 n->initorder = InitPending; 118 l = malloc(sizeof *l); 119 if(l == nil) { 120 flusherrors(); 121 yyerror("out of memory"); 122 errorexit(); 123 } 124 l->next = initlist; 125 l->n = n; 126 l->end = nil; 127 initlist = l; 128 129 // make sure that everything n depends on is initialized. 130 // n->defn is an assignment to n 131 if(n->defn != N) { 132 switch(n->defn->op) { 133 default: 134 goto bad; 135 136 case ODCLFUNC: 137 init2list(n->defn->nbody, out); 138 break; 139 140 case OAS: 141 if(n->defn->left != n) 142 goto bad; 143 if(isblank(n->defn->left) && candiscard(n->defn->right)) { 144 n->defn->op = OEMPTY; 145 n->defn->left = N; 146 n->defn->right = N; 147 break; 148 } 149 150 init2(n->defn->right, out); 151 if(debug['j']) 152 print("%S\n", n->sym); 153 if(isblank(n) || !staticinit(n, out)) { 154 if(debug['%']) 155 dump("nonstatic", n->defn); 156 *out = list(*out, n->defn); 157 } 158 break; 159 160 case OAS2FUNC: 161 case OAS2MAPR: 162 case OAS2DOTTYPE: 163 case OAS2RECV: 164 if(n->defn->initorder != InitNotStarted) 165 break; 166 n->defn->initorder = InitDone; 167 for(l=n->defn->rlist; l; l=l->next) 168 init1(l->n, out); 169 if(debug['%']) dump("nonstatic", n->defn); 170 *out = list(*out, n->defn); 171 break; 172 } 173 } 174 l = initlist; 175 initlist = l->next; 176 if(l->n != n) 177 fatal("bad initlist"); 178 free(l); 179 n->initorder = InitDone; 180 return; 181 182 bad: 183 dump("defn", n->defn); 184 fatal("init1: bad defn"); 185 } 186 187 // recurse over n, doing init1 everywhere. 188 static void 189 init2(Node *n, NodeList **out) 190 { 191 if(n == N || n->initorder == InitDone) 192 return; 193 194 if(n->op == ONAME && n->ninit) 195 fatal("name %S with ninit: %+N\n", n->sym, n); 196 197 init1(n, out); 198 init2(n->left, out); 199 init2(n->right, out); 200 init2(n->ntest, out); 201 init2list(n->ninit, out); 202 init2list(n->list, out); 203 init2list(n->rlist, out); 204 init2list(n->nbody, out); 205 init2list(n->nelse, out); 206 207 if(n->op == OCLOSURE) 208 init2list(n->closure->nbody, out); 209 if(n->op == ODOTMETH || n->op == OCALLPART) 210 init2(n->type->nname, out); 211 } 212 213 static void 214 init2list(NodeList *l, NodeList **out) 215 { 216 for(; l; l=l->next) 217 init2(l->n, out); 218 } 219 220 static void 221 initreorder(NodeList *l, NodeList **out) 222 { 223 Node *n; 224 225 for(; l; l=l->next) { 226 n = l->n; 227 switch(n->op) { 228 case ODCLFUNC: 229 case ODCLCONST: 230 case ODCLTYPE: 231 continue; 232 } 233 initreorder(n->ninit, out); 234 n->ninit = nil; 235 init1(n, out); 236 } 237 } 238 239 // initfix computes initialization order for a list l of top-level 240 // declarations and outputs the corresponding list of statements 241 // to include in the init() function body. 242 NodeList* 243 initfix(NodeList *l) 244 { 245 NodeList *lout; 246 int lno; 247 248 lout = nil; 249 lno = lineno; 250 initreorder(l, &lout); 251 lineno = lno; 252 return lout; 253 } 254 255 /* 256 * compilation of top-level (static) assignments 257 * into DATA statements if at all possible. 258 */ 259 260 static int staticassign(Node*, Node*, NodeList**); 261 262 static int 263 staticinit(Node *n, NodeList **out) 264 { 265 Node *l, *r; 266 267 if(n->op != ONAME || n->class != PEXTERN || n->defn == N || n->defn->op != OAS) 268 fatal("staticinit"); 269 270 lineno = n->lineno; 271 l = n->defn->left; 272 r = n->defn->right; 273 return staticassign(l, r, out); 274 } 275 276 // like staticassign but we are copying an already 277 // initialized value r. 278 static int 279 staticcopy(Node *l, Node *r, NodeList **out) 280 { 281 int i; 282 InitEntry *e; 283 InitPlan *p; 284 Node *a, *ll, *rr, *orig, n1; 285 286 if(r->op != ONAME || r->class != PEXTERN || r->sym->pkg != localpkg) 287 return 0; 288 if(r->defn == N) // probably zeroed but perhaps supplied externally and of unknown value 289 return 0; 290 if(r->defn->op != OAS) 291 return 0; 292 orig = r; 293 r = r->defn->right; 294 295 switch(r->op) { 296 case ONAME: 297 if(staticcopy(l, r, out)) 298 return 1; 299 *out = list(*out, nod(OAS, l, r)); 300 return 1; 301 302 case OLITERAL: 303 if(iszero(r)) 304 return 1; 305 gdata(l, r, l->type->width); 306 return 1; 307 308 case OADDR: 309 switch(r->left->op) { 310 case ONAME: 311 gdata(l, r, l->type->width); 312 return 1; 313 } 314 break; 315 316 case OPTRLIT: 317 switch(r->left->op) { 318 default: 319 //dump("not static addr", r); 320 break; 321 case OARRAYLIT: 322 case OSTRUCTLIT: 323 case OMAPLIT: 324 // copy pointer 325 gdata(l, nod(OADDR, r->nname, N), l->type->width); 326 return 1; 327 } 328 break; 329 330 case OARRAYLIT: 331 if(isslice(r->type)) { 332 // copy slice 333 a = r->nname; 334 n1 = *l; 335 n1.xoffset = l->xoffset + Array_array; 336 gdata(&n1, nod(OADDR, a, N), widthptr); 337 n1.xoffset = l->xoffset + Array_nel; 338 gdata(&n1, r->right, widthint); 339 n1.xoffset = l->xoffset + Array_cap; 340 gdata(&n1, r->right, widthint); 341 return 1; 342 } 343 // fall through 344 case OSTRUCTLIT: 345 p = r->initplan; 346 n1 = *l; 347 for(i=0; i<p->len; i++) { 348 e = &p->e[i]; 349 n1.xoffset = l->xoffset + e->xoffset; 350 n1.type = e->expr->type; 351 if(e->expr->op == OLITERAL) 352 gdata(&n1, e->expr, n1.type->width); 353 else { 354 ll = nod(OXXX, N, N); 355 *ll = n1; 356 ll->orig = ll; // completely separate copy 357 if(!staticassign(ll, e->expr, out)) { 358 // Requires computation, but we're 359 // copying someone else's computation. 360 rr = nod(OXXX, N, N); 361 *rr = *orig; 362 rr->orig = rr; // completely separate copy 363 rr->type = ll->type; 364 rr->xoffset += e->xoffset; 365 *out = list(*out, nod(OAS, ll, rr)); 366 } 367 } 368 } 369 return 1; 370 } 371 return 0; 372 } 373 374 static int 375 staticassign(Node *l, Node *r, NodeList **out) 376 { 377 Node *a, n1, nam; 378 Type *ta; 379 InitPlan *p; 380 InitEntry *e; 381 int i; 382 Strlit *sval; 383 384 switch(r->op) { 385 default: 386 //dump("not static", r); 387 break; 388 389 case ONAME: 390 if(r->class == PEXTERN && r->sym->pkg == localpkg) 391 return staticcopy(l, r, out); 392 break; 393 394 case OLITERAL: 395 if(iszero(r)) 396 return 1; 397 gdata(l, r, l->type->width); 398 return 1; 399 400 case OADDR: 401 if(stataddr(&nam, r->left)) { 402 n1 = *r; 403 n1.left = &nam; 404 gdata(l, &n1, l->type->width); 405 return 1; 406 } 407 408 case OPTRLIT: 409 switch(r->left->op) { 410 default: 411 //dump("not static ptrlit", r); 412 break; 413 414 case OARRAYLIT: 415 case OMAPLIT: 416 case OSTRUCTLIT: 417 // Init pointer. 418 a = staticname(r->left->type, 1); 419 r->nname = a; 420 gdata(l, nod(OADDR, a, N), l->type->width); 421 // Init underlying literal. 422 if(!staticassign(a, r->left, out)) 423 *out = list(*out, nod(OAS, a, r->left)); 424 return 1; 425 } 426 break; 427 428 case OSTRARRAYBYTE: 429 if(l->class == PEXTERN && r->left->op == OLITERAL) { 430 sval = r->left->val.u.sval; 431 slicebytes(l, sval->s, sval->len); 432 return 1; 433 } 434 break; 435 436 case OARRAYLIT: 437 initplan(r); 438 if(isslice(r->type)) { 439 // Init slice. 440 ta = typ(TARRAY); 441 ta->type = r->type->type; 442 ta->bound = mpgetfix(r->right->val.u.xval); 443 a = staticname(ta, 1); 444 r->nname = a; 445 n1 = *l; 446 n1.xoffset = l->xoffset + Array_array; 447 gdata(&n1, nod(OADDR, a, N), widthptr); 448 n1.xoffset = l->xoffset + Array_nel; 449 gdata(&n1, r->right, widthint); 450 n1.xoffset = l->xoffset + Array_cap; 451 gdata(&n1, r->right, widthint); 452 // Fall through to init underlying array. 453 l = a; 454 } 455 // fall through 456 case OSTRUCTLIT: 457 initplan(r); 458 p = r->initplan; 459 n1 = *l; 460 for(i=0; i<p->len; i++) { 461 e = &p->e[i]; 462 n1.xoffset = l->xoffset + e->xoffset; 463 n1.type = e->expr->type; 464 if(e->expr->op == OLITERAL) 465 gdata(&n1, e->expr, n1.type->width); 466 else { 467 a = nod(OXXX, N, N); 468 *a = n1; 469 a->orig = a; // completely separate copy 470 if(!staticassign(a, e->expr, out)) 471 *out = list(*out, nod(OAS, a, e->expr)); 472 } 473 } 474 return 1; 475 476 case OMAPLIT: 477 // TODO: Table-driven map insert. 478 break; 479 } 480 return 0; 481 } 482 483 /* 484 * from here down is the walk analysis 485 * of composite literals. 486 * most of the work is to generate 487 * data statements for the constant 488 * part of the composite literal. 489 */ 490 491 static void structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init); 492 static void arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init); 493 static void slicelit(int ctxt, Node *n, Node *var, NodeList **init); 494 static void maplit(int ctxt, Node *n, Node *var, NodeList **init); 495 496 static Node* 497 staticname(Type *t, int ctxt) 498 { 499 Node *n; 500 501 snprint(namebuf, sizeof(namebuf), "statictmp_%.4d", statuniqgen); 502 statuniqgen++; 503 n = newname(lookup(namebuf)); 504 if(!ctxt) 505 n->readonly = 1; 506 addvar(n, t, PEXTERN); 507 return n; 508 } 509 510 static int 511 isliteral(Node *n) 512 { 513 if(n->op == OLITERAL) 514 if(n->val.ctype != CTNIL) 515 return 1; 516 return 0; 517 } 518 519 static int 520 simplename(Node *n) 521 { 522 if(n->op != ONAME) 523 goto no; 524 if(!n->addable) 525 goto no; 526 if(n->class & PHEAP) 527 goto no; 528 if(n->class == PPARAMREF) 529 goto no; 530 return 1; 531 532 no: 533 return 0; 534 } 535 536 static void 537 litas(Node *l, Node *r, NodeList **init) 538 { 539 Node *a; 540 541 a = nod(OAS, l, r); 542 typecheck(&a, Etop); 543 walkexpr(&a, init); 544 *init = list(*init, a); 545 } 546 547 enum 548 { 549 MODEDYNAM = 1, 550 MODECONST = 2, 551 }; 552 553 static int 554 getdyn(Node *n, int top) 555 { 556 NodeList *nl; 557 Node *value; 558 int mode; 559 560 mode = 0; 561 switch(n->op) { 562 default: 563 if(isliteral(n)) 564 return MODECONST; 565 return MODEDYNAM; 566 case OARRAYLIT: 567 if(!top && n->type->bound < 0) 568 return MODEDYNAM; 569 case OSTRUCTLIT: 570 break; 571 } 572 573 for(nl=n->list; nl; nl=nl->next) { 574 value = nl->n->right; 575 mode |= getdyn(value, 0); 576 if(mode == (MODEDYNAM|MODECONST)) 577 break; 578 } 579 return mode; 580 } 581 582 static void 583 structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init) 584 { 585 Node *r, *a; 586 NodeList *nl; 587 Node *index, *value; 588 589 for(nl=n->list; nl; nl=nl->next) { 590 r = nl->n; 591 if(r->op != OKEY) 592 fatal("structlit: rhs not OKEY: %N", r); 593 index = r->left; 594 value = r->right; 595 596 switch(value->op) { 597 case OARRAYLIT: 598 if(value->type->bound < 0) { 599 if(pass == 1 && ctxt != 0) { 600 a = nod(ODOT, var, newname(index->sym)); 601 slicelit(ctxt, value, a, init); 602 } else 603 if(pass == 2 && ctxt == 0) { 604 a = nod(ODOT, var, newname(index->sym)); 605 slicelit(ctxt, value, a, init); 606 } else 607 if(pass == 3) 608 break; 609 continue; 610 } 611 a = nod(ODOT, var, newname(index->sym)); 612 arraylit(ctxt, pass, value, a, init); 613 continue; 614 615 case OSTRUCTLIT: 616 a = nod(ODOT, var, newname(index->sym)); 617 structlit(ctxt, pass, value, a, init); 618 continue; 619 } 620 621 if(isliteral(value)) { 622 if(pass == 2) 623 continue; 624 } else 625 if(pass == 1) 626 continue; 627 628 // build list of var.field = expr 629 a = nod(ODOT, var, newname(index->sym)); 630 a = nod(OAS, a, value); 631 typecheck(&a, Etop); 632 if(pass == 1) { 633 walkexpr(&a, init); // add any assignments in r to top 634 if(a->op != OAS) 635 fatal("structlit: not as"); 636 a->dodata = 2; 637 } else { 638 orderstmtinplace(&a); 639 walkstmt(&a); 640 } 641 *init = list(*init, a); 642 } 643 } 644 645 static void 646 arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init) 647 { 648 Node *r, *a; 649 NodeList *l; 650 Node *index, *value; 651 652 for(l=n->list; l; l=l->next) { 653 r = l->n; 654 if(r->op != OKEY) 655 fatal("arraylit: rhs not OKEY: %N", r); 656 index = r->left; 657 value = r->right; 658 659 switch(value->op) { 660 case OARRAYLIT: 661 if(value->type->bound < 0) { 662 if(pass == 1 && ctxt != 0) { 663 a = nod(OINDEX, var, index); 664 slicelit(ctxt, value, a, init); 665 } else 666 if(pass == 2 && ctxt == 0) { 667 a = nod(OINDEX, var, index); 668 slicelit(ctxt, value, a, init); 669 } else 670 if(pass == 3) 671 break; 672 continue; 673 } 674 a = nod(OINDEX, var, index); 675 arraylit(ctxt, pass, value, a, init); 676 continue; 677 678 case OSTRUCTLIT: 679 a = nod(OINDEX, var, index); 680 structlit(ctxt, pass, value, a, init); 681 continue; 682 } 683 684 if(isliteral(index) && isliteral(value)) { 685 if(pass == 2) 686 continue; 687 } else 688 if(pass == 1) 689 continue; 690 691 // build list of var[index] = value 692 a = nod(OINDEX, var, index); 693 a = nod(OAS, a, value); 694 typecheck(&a, Etop); 695 if(pass == 1) { 696 walkexpr(&a, init); 697 if(a->op != OAS) 698 fatal("arraylit: not as"); 699 a->dodata = 2; 700 } else { 701 orderstmtinplace(&a); 702 walkstmt(&a); 703 } 704 *init = list(*init, a); 705 } 706 } 707 708 static void 709 slicelit(int ctxt, Node *n, Node *var, NodeList **init) 710 { 711 Node *r, *a; 712 NodeList *l; 713 Type *t; 714 Node *vstat, *vauto; 715 Node *index, *value; 716 int mode; 717 718 // make an array type 719 t = shallow(n->type); 720 t->bound = mpgetfix(n->right->val.u.xval); 721 t->width = 0; 722 t->sym = nil; 723 t->haspointers = 0; 724 dowidth(t); 725 726 if(ctxt != 0) { 727 // put everything into static array 728 vstat = staticname(t, ctxt); 729 arraylit(ctxt, 1, n, vstat, init); 730 arraylit(ctxt, 2, n, vstat, init); 731 732 // copy static to slice 733 a = nod(OSLICE, vstat, nod(OKEY, N, N)); 734 a = nod(OAS, var, a); 735 typecheck(&a, Etop); 736 a->dodata = 2; 737 *init = list(*init, a); 738 return; 739 } 740 741 // recipe for var = []t{...} 742 // 1. make a static array 743 // var vstat [...]t 744 // 2. assign (data statements) the constant part 745 // vstat = constpart{} 746 // 3. make an auto pointer to array and allocate heap to it 747 // var vauto *[...]t = new([...]t) 748 // 4. copy the static array to the auto array 749 // *vauto = vstat 750 // 5. assign slice of allocated heap to var 751 // var = [0:]*auto 752 // 6. for each dynamic part assign to the slice 753 // var[i] = dynamic part 754 // 755 // an optimization is done if there is no constant part 756 // 3. var vauto *[...]t = new([...]t) 757 // 5. var = [0:]*auto 758 // 6. var[i] = dynamic part 759 760 // if the literal contains constants, 761 // make static initialized array (1),(2) 762 vstat = N; 763 mode = getdyn(n, 1); 764 if(mode & MODECONST) { 765 vstat = staticname(t, ctxt); 766 arraylit(ctxt, 1, n, vstat, init); 767 } 768 769 // make new auto *array (3 declare) 770 vauto = temp(ptrto(t)); 771 772 // set auto to point at new temp or heap (3 assign) 773 if(n->alloc != N) { 774 // temp allocated during order.c for dddarg 775 n->alloc->type = t; 776 if(vstat == N) { 777 a = nod(OAS, n->alloc, N); 778 typecheck(&a, Etop); 779 *init = list(*init, a); // zero new temp 780 } 781 a = nod(OADDR, n->alloc, N); 782 } else if(n->esc == EscNone) { 783 a = temp(t); 784 if(vstat == N) { 785 a = nod(OAS, temp(t), N); 786 typecheck(&a, Etop); 787 *init = list(*init, a); // zero new temp 788 a = a->left; 789 } 790 a = nod(OADDR, a, N); 791 } else { 792 a = nod(ONEW, N, N); 793 a->list = list1(typenod(t)); 794 } 795 a = nod(OAS, vauto, a); 796 typecheck(&a, Etop); 797 walkexpr(&a, init); 798 *init = list(*init, a); 799 800 if(vstat != N) { 801 // copy static to heap (4) 802 a = nod(OIND, vauto, N); 803 a = nod(OAS, a, vstat); 804 typecheck(&a, Etop); 805 walkexpr(&a, init); 806 *init = list(*init, a); 807 } 808 809 // make slice out of heap (5) 810 a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N))); 811 typecheck(&a, Etop); 812 orderstmtinplace(&a); 813 walkstmt(&a); 814 *init = list(*init, a); 815 816 // put dynamics into slice (6) 817 for(l=n->list; l; l=l->next) { 818 r = l->n; 819 if(r->op != OKEY) 820 fatal("slicelit: rhs not OKEY: %N", r); 821 index = r->left; 822 value = r->right; 823 a = nod(OINDEX, var, index); 824 a->bounded = 1; 825 // TODO need to check bounds? 826 827 switch(value->op) { 828 case OARRAYLIT: 829 if(value->type->bound < 0) 830 break; 831 arraylit(ctxt, 2, value, a, init); 832 continue; 833 834 case OSTRUCTLIT: 835 structlit(ctxt, 2, value, a, init); 836 continue; 837 } 838 839 if(isliteral(index) && isliteral(value)) 840 continue; 841 842 // build list of var[c] = expr 843 a = nod(OAS, a, value); 844 typecheck(&a, Etop); 845 orderstmtinplace(&a); 846 walkstmt(&a); 847 *init = list(*init, a); 848 } 849 } 850 851 static void 852 maplit(int ctxt, Node *n, Node *var, NodeList **init) 853 { 854 Node *r, *a; 855 NodeList *l; 856 int nerr; 857 int64 b; 858 Type *t, *tk, *tv, *t1; 859 Node *vstat, *index, *value, *key, *val; 860 Sym *syma, *symb; 861 862 USED(ctxt); 863 ctxt = 0; 864 865 // make the map var 866 nerr = nerrors; 867 868 a = nod(OMAKE, N, N); 869 a->list = list1(typenod(n->type)); 870 litas(var, a, init); 871 872 // count the initializers 873 b = 0; 874 for(l=n->list; l; l=l->next) { 875 r = l->n; 876 877 if(r->op != OKEY) 878 fatal("maplit: rhs not OKEY: %N", r); 879 index = r->left; 880 value = r->right; 881 882 if(isliteral(index) && isliteral(value)) 883 b++; 884 } 885 886 if(b != 0) { 887 // build type [count]struct { a Tindex, b Tvalue } 888 t = n->type; 889 tk = t->down; 890 tv = t->type; 891 892 symb = lookup("b"); 893 t = typ(TFIELD); 894 t->type = tv; 895 t->sym = symb; 896 897 syma = lookup("a"); 898 t1 = t; 899 t = typ(TFIELD); 900 t->type = tk; 901 t->sym = syma; 902 t->down = t1; 903 904 t1 = t; 905 t = typ(TSTRUCT); 906 t->type = t1; 907 908 t1 = t; 909 t = typ(TARRAY); 910 t->bound = b; 911 t->type = t1; 912 913 dowidth(t); 914 915 // make and initialize static array 916 vstat = staticname(t, ctxt); 917 b = 0; 918 for(l=n->list; l; l=l->next) { 919 r = l->n; 920 921 if(r->op != OKEY) 922 fatal("maplit: rhs not OKEY: %N", r); 923 index = r->left; 924 value = r->right; 925 926 if(isliteral(index) && isliteral(value)) { 927 // build vstat[b].a = key; 928 a = nodintconst(b); 929 a = nod(OINDEX, vstat, a); 930 a = nod(ODOT, a, newname(syma)); 931 a = nod(OAS, a, index); 932 typecheck(&a, Etop); 933 walkexpr(&a, init); 934 a->dodata = 2; 935 *init = list(*init, a); 936 937 // build vstat[b].b = value; 938 a = nodintconst(b); 939 a = nod(OINDEX, vstat, a); 940 a = nod(ODOT, a, newname(symb)); 941 a = nod(OAS, a, value); 942 typecheck(&a, Etop); 943 walkexpr(&a, init); 944 a->dodata = 2; 945 *init = list(*init, a); 946 947 b++; 948 } 949 } 950 951 // loop adding structure elements to map 952 // for i = 0; i < len(vstat); i++ { 953 // map[vstat[i].a] = vstat[i].b 954 // } 955 index = temp(types[TINT]); 956 957 a = nod(OINDEX, vstat, index); 958 a->bounded = 1; 959 a = nod(ODOT, a, newname(symb)); 960 961 r = nod(OINDEX, vstat, index); 962 r->bounded = 1; 963 r = nod(ODOT, r, newname(syma)); 964 r = nod(OINDEX, var, r); 965 966 r = nod(OAS, r, a); 967 968 a = nod(OFOR, N, N); 969 a->nbody = list1(r); 970 971 a->ninit = list1(nod(OAS, index, nodintconst(0))); 972 a->ntest = nod(OLT, index, nodintconst(t->bound)); 973 a->nincr = nod(OAS, index, nod(OADD, index, nodintconst(1))); 974 975 typecheck(&a, Etop); 976 walkstmt(&a); 977 *init = list(*init, a); 978 } 979 980 // put in dynamic entries one-at-a-time 981 key = nil; 982 val = nil; 983 for(l=n->list; l; l=l->next) { 984 r = l->n; 985 986 if(r->op != OKEY) 987 fatal("maplit: rhs not OKEY: %N", r); 988 index = r->left; 989 value = r->right; 990 991 if(isliteral(index) && isliteral(value)) 992 continue; 993 994 // build list of var[c] = expr. 995 // use temporary so that mapassign1 can have addressable key, val. 996 if(key == nil) { 997 key = temp(var->type->down); 998 val = temp(var->type->type); 999 } 1000 a = nod(OAS, key, r->left); 1001 typecheck(&a, Etop); 1002 walkstmt(&a); 1003 *init = list(*init, a); 1004 a = nod(OAS, val, r->right); 1005 typecheck(&a, Etop); 1006 walkstmt(&a); 1007 *init = list(*init, a); 1008 1009 a = nod(OAS, nod(OINDEX, var, key), val); 1010 typecheck(&a, Etop); 1011 walkstmt(&a); 1012 *init = list(*init, a); 1013 1014 if(nerr != nerrors) 1015 break; 1016 } 1017 1018 if(key != nil) { 1019 a = nod(OVARKILL, key, N); 1020 typecheck(&a, Etop); 1021 *init = list(*init, a); 1022 a = nod(OVARKILL, val, N); 1023 typecheck(&a, Etop); 1024 *init = list(*init, a); 1025 } 1026 } 1027 1028 void 1029 anylit(int ctxt, Node *n, Node *var, NodeList **init) 1030 { 1031 Type *t; 1032 Node *a, *vstat, *r; 1033 1034 t = n->type; 1035 switch(n->op) { 1036 default: 1037 fatal("anylit: not lit"); 1038 1039 case OPTRLIT: 1040 if(!isptr[t->etype]) 1041 fatal("anylit: not ptr"); 1042 1043 if(n->right != N) { 1044 r = nod(OADDR, n->right, N); 1045 typecheck(&r, Erv); 1046 } else { 1047 r = nod(ONEW, N, N); 1048 r->typecheck = 1; 1049 r->type = t; 1050 r->esc = n->esc; 1051 } 1052 walkexpr(&r, init); 1053 a = nod(OAS, var, r); 1054 1055 typecheck(&a, Etop); 1056 *init = list(*init, a); 1057 1058 var = nod(OIND, var, N); 1059 typecheck(&var, Erv | Easgn); 1060 anylit(ctxt, n->left, var, init); 1061 break; 1062 1063 case OSTRUCTLIT: 1064 if(t->etype != TSTRUCT) 1065 fatal("anylit: not struct"); 1066 1067 if(simplename(var) && count(n->list) > 4) { 1068 1069 if(ctxt == 0) { 1070 // lay out static data 1071 vstat = staticname(t, ctxt); 1072 structlit(ctxt, 1, n, vstat, init); 1073 1074 // copy static to var 1075 a = nod(OAS, var, vstat); 1076 typecheck(&a, Etop); 1077 walkexpr(&a, init); 1078 *init = list(*init, a); 1079 1080 // add expressions to automatic 1081 structlit(ctxt, 2, n, var, init); 1082 break; 1083 } 1084 structlit(ctxt, 1, n, var, init); 1085 structlit(ctxt, 2, n, var, init); 1086 break; 1087 } 1088 1089 // initialize of not completely specified 1090 if(simplename(var) || count(n->list) < structcount(t)) { 1091 a = nod(OAS, var, N); 1092 typecheck(&a, Etop); 1093 walkexpr(&a, init); 1094 *init = list(*init, a); 1095 } 1096 structlit(ctxt, 3, n, var, init); 1097 break; 1098 1099 case OARRAYLIT: 1100 if(t->etype != TARRAY) 1101 fatal("anylit: not array"); 1102 if(t->bound < 0) { 1103 slicelit(ctxt, n, var, init); 1104 break; 1105 } 1106 1107 if(simplename(var) && count(n->list) > 4) { 1108 1109 if(ctxt == 0) { 1110 // lay out static data 1111 vstat = staticname(t, ctxt); 1112 arraylit(1, 1, n, vstat, init); 1113 1114 // copy static to automatic 1115 a = nod(OAS, var, vstat); 1116 typecheck(&a, Etop); 1117 walkexpr(&a, init); 1118 *init = list(*init, a); 1119 1120 // add expressions to automatic 1121 arraylit(ctxt, 2, n, var, init); 1122 break; 1123 } 1124 arraylit(ctxt, 1, n, var, init); 1125 arraylit(ctxt, 2, n, var, init); 1126 break; 1127 } 1128 1129 // initialize of not completely specified 1130 if(simplename(var) || count(n->list) < t->bound) { 1131 a = nod(OAS, var, N); 1132 typecheck(&a, Etop); 1133 walkexpr(&a, init); 1134 *init = list(*init, a); 1135 } 1136 arraylit(ctxt, 3, n, var, init); 1137 break; 1138 1139 case OMAPLIT: 1140 if(t->etype != TMAP) 1141 fatal("anylit: not map"); 1142 maplit(ctxt, n, var, init); 1143 break; 1144 } 1145 } 1146 1147 int 1148 oaslit(Node *n, NodeList **init) 1149 { 1150 int ctxt; 1151 1152 if(n->left == N || n->right == N) 1153 goto no; 1154 if(n->left->type == T || n->right->type == T) 1155 goto no; 1156 if(!simplename(n->left)) 1157 goto no; 1158 if(!eqtype(n->left->type, n->right->type)) 1159 goto no; 1160 1161 // context is init() function. 1162 // implies generated data executed 1163 // exactly once and not subject to races. 1164 ctxt = 0; 1165 // if(n->dodata == 1) 1166 // ctxt = 1; 1167 1168 switch(n->right->op) { 1169 default: 1170 goto no; 1171 1172 case OSTRUCTLIT: 1173 case OARRAYLIT: 1174 case OMAPLIT: 1175 if(vmatch1(n->left, n->right)) 1176 goto no; 1177 anylit(ctxt, n->right, n->left, init); 1178 break; 1179 } 1180 n->op = OEMPTY; 1181 return 1; 1182 1183 no: 1184 // not a special composit literal assignment 1185 return 0; 1186 } 1187 1188 static int 1189 getlit(Node *lit) 1190 { 1191 if(smallintconst(lit)) 1192 return mpgetfix(lit->val.u.xval); 1193 return -1; 1194 } 1195 1196 int 1197 stataddr(Node *nam, Node *n) 1198 { 1199 int l; 1200 1201 if(n == N) 1202 goto no; 1203 1204 switch(n->op) { 1205 1206 case ONAME: 1207 *nam = *n; 1208 return n->addable; 1209 1210 case ODOT: 1211 if(!stataddr(nam, n->left)) 1212 break; 1213 nam->xoffset += n->xoffset; 1214 nam->type = n->type; 1215 return 1; 1216 1217 case OINDEX: 1218 if(n->left->type->bound < 0) 1219 break; 1220 if(!stataddr(nam, n->left)) 1221 break; 1222 l = getlit(n->right); 1223 if(l < 0) 1224 break; 1225 // Check for overflow. 1226 if(n->type->width != 0 && MAXWIDTH/n->type->width <= l) 1227 break; 1228 nam->xoffset += l*n->type->width; 1229 nam->type = n->type; 1230 return 1; 1231 } 1232 1233 no: 1234 return 0; 1235 } 1236 1237 int 1238 gen_as_init(Node *n) 1239 { 1240 Node *nr, *nl; 1241 Node nam, nod1; 1242 1243 if(n->dodata == 0) 1244 goto no; 1245 1246 nr = n->right; 1247 nl = n->left; 1248 if(nr == N) { 1249 if(!stataddr(&nam, nl)) 1250 goto no; 1251 if(nam.class != PEXTERN) 1252 goto no; 1253 goto yes; 1254 } 1255 1256 if(nr->type == T || !eqtype(nl->type, nr->type)) 1257 goto no; 1258 1259 if(!stataddr(&nam, nl)) 1260 goto no; 1261 1262 if(nam.class != PEXTERN) 1263 goto no; 1264 1265 switch(nr->op) { 1266 default: 1267 goto no; 1268 1269 case OCONVNOP: 1270 nr = nr->left; 1271 if(nr == N || nr->op != OSLICEARR) 1272 goto no; 1273 // fall through 1274 1275 case OSLICEARR: 1276 if(nr->right->op == OKEY && nr->right->left == N && nr->right->right == N) { 1277 nr = nr->left; 1278 goto slice; 1279 } 1280 goto no; 1281 1282 case OLITERAL: 1283 break; 1284 } 1285 1286 switch(nr->type->etype) { 1287 default: 1288 goto no; 1289 1290 case TBOOL: 1291 case TINT8: 1292 case TUINT8: 1293 case TINT16: 1294 case TUINT16: 1295 case TINT32: 1296 case TUINT32: 1297 case TINT64: 1298 case TUINT64: 1299 case TINT: 1300 case TUINT: 1301 case TUINTPTR: 1302 case TPTR32: 1303 case TPTR64: 1304 case TFLOAT32: 1305 case TFLOAT64: 1306 gdata(&nam, nr, nr->type->width); 1307 break; 1308 1309 case TCOMPLEX64: 1310 case TCOMPLEX128: 1311 gdatacomplex(&nam, nr->val.u.cval); 1312 break; 1313 1314 case TSTRING: 1315 gdatastring(&nam, nr->val.u.sval); 1316 break; 1317 } 1318 1319 yes: 1320 return 1; 1321 1322 slice: 1323 gused(N); // in case the data is the dest of a goto 1324 nl = nr; 1325 if(nr == N || nr->op != OADDR) 1326 goto no; 1327 nr = nr->left; 1328 if(nr == N || nr->op != ONAME) 1329 goto no; 1330 1331 // nr is the array being converted to a slice 1332 if(nr->type == T || nr->type->etype != TARRAY || nr->type->bound < 0) 1333 goto no; 1334 1335 nam.xoffset += Array_array; 1336 gdata(&nam, nl, types[tptr]->width); 1337 1338 nam.xoffset += Array_nel-Array_array; 1339 nodconst(&nod1, types[TINT], nr->type->bound); 1340 gdata(&nam, &nod1, widthint); 1341 1342 nam.xoffset += Array_cap-Array_nel; 1343 gdata(&nam, &nod1, widthint); 1344 1345 goto yes; 1346 1347 no: 1348 if(n->dodata == 2) { 1349 dump("\ngen_as_init", n); 1350 fatal("gen_as_init couldnt make data statement"); 1351 } 1352 return 0; 1353 } 1354 1355 static int isvaluelit(Node*); 1356 static InitEntry* entry(InitPlan*); 1357 static void addvalue(InitPlan*, vlong, Node*, Node*); 1358 1359 static void 1360 initplan(Node *n) 1361 { 1362 InitPlan *p; 1363 Node *a; 1364 NodeList *l; 1365 1366 if(n->initplan != nil) 1367 return; 1368 p = mal(sizeof *p); 1369 n->initplan = p; 1370 switch(n->op) { 1371 default: 1372 fatal("initplan"); 1373 case OARRAYLIT: 1374 for(l=n->list; l; l=l->next) { 1375 a = l->n; 1376 if(a->op != OKEY || !smallintconst(a->left)) 1377 fatal("initplan arraylit"); 1378 addvalue(p, n->type->type->width*mpgetfix(a->left->val.u.xval), N, a->right); 1379 } 1380 break; 1381 case OSTRUCTLIT: 1382 for(l=n->list; l; l=l->next) { 1383 a = l->n; 1384 if(a->op != OKEY || a->left->type == T) 1385 fatal("initplan structlit"); 1386 addvalue(p, a->left->type->width, N, a->right); 1387 } 1388 break; 1389 case OMAPLIT: 1390 for(l=n->list; l; l=l->next) { 1391 a = l->n; 1392 if(a->op != OKEY) 1393 fatal("initplan maplit"); 1394 addvalue(p, -1, a->left, a->right); 1395 } 1396 break; 1397 } 1398 } 1399 1400 static void 1401 addvalue(InitPlan *p, vlong xoffset, Node *key, Node *n) 1402 { 1403 int i; 1404 InitPlan *q; 1405 InitEntry *e; 1406 1407 USED(key); 1408 1409 // special case: zero can be dropped entirely 1410 if(iszero(n)) { 1411 p->zero += n->type->width; 1412 return; 1413 } 1414 1415 // special case: inline struct and array (not slice) literals 1416 if(isvaluelit(n)) { 1417 initplan(n); 1418 q = n->initplan; 1419 for(i=0; i<q->len; i++) { 1420 e = entry(p); 1421 *e = q->e[i]; 1422 e->xoffset += xoffset; 1423 } 1424 return; 1425 } 1426 1427 // add to plan 1428 if(n->op == OLITERAL) 1429 p->lit += n->type->width; 1430 else 1431 p->expr += n->type->width; 1432 1433 e = entry(p); 1434 e->xoffset = xoffset; 1435 e->expr = n; 1436 } 1437 1438 int 1439 iszero(Node *n) 1440 { 1441 NodeList *l; 1442 1443 switch(n->op) { 1444 case OLITERAL: 1445 switch(n->val.ctype) { 1446 default: 1447 dump("unexpected literal", n); 1448 fatal("iszero"); 1449 1450 case CTNIL: 1451 return 1; 1452 1453 case CTSTR: 1454 return n->val.u.sval == nil || n->val.u.sval->len == 0; 1455 1456 case CTBOOL: 1457 return n->val.u.bval == 0; 1458 1459 case CTINT: 1460 case CTRUNE: 1461 return mpcmpfixc(n->val.u.xval, 0) == 0; 1462 1463 case CTFLT: 1464 return mpcmpfltc(n->val.u.fval, 0) == 0; 1465 1466 case CTCPLX: 1467 return mpcmpfltc(&n->val.u.cval->real, 0) == 0 && mpcmpfltc(&n->val.u.cval->imag, 0) == 0; 1468 } 1469 break; 1470 case OARRAYLIT: 1471 if(isslice(n->type)) 1472 break; 1473 // fall through 1474 case OSTRUCTLIT: 1475 for(l=n->list; l; l=l->next) 1476 if(!iszero(l->n->right)) 1477 return 0; 1478 return 1; 1479 } 1480 return 0; 1481 } 1482 1483 static int 1484 isvaluelit(Node *n) 1485 { 1486 return (n->op == OARRAYLIT && isfixedarray(n->type)) || n->op == OSTRUCTLIT; 1487 } 1488 1489 static InitEntry* 1490 entry(InitPlan *p) 1491 { 1492 if(p->len >= p->cap) { 1493 if(p->cap == 0) 1494 p->cap = 4; 1495 else 1496 p->cap *= 2; 1497 p->e = realloc(p->e, p->cap*sizeof p->e[0]); 1498 if(p->e == nil) 1499 fatal("out of memory"); 1500 } 1501 return &p->e[p->len++]; 1502 }