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