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